原文:Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- Direct12优化


第一章:向量代数

1、向量计算的时候,使用XMVECTOR(可以利用SIMD优点);类成员变量使用XMFLOAT2 (2D),XMFLOAT3 (3D),和XMFLOAT4 (4D) 。

2、向函数传递参数的时候(XMVECTOR可以直接传递到SSE/SSE2)前三个参数类型要定义为FXMVECTOR; 第四个要定义为GXMVECTOR; 第五个和第六个要定义为HXMVECTOR; 其他参数要定义为CXMVECTOR。


第二章:矩阵代数

1、用以计算的时候使用XMMATRIX类型;类的成员变量使用XMFLOAT4X4;

2、向函数传递参数时,规则和XMVECTOR一样;

3、上述规则对于构造函数是例外,构造函数一直使用CXMMATRIX,并且不要添加XM_CALLCONV。


第三章:变换

1、正交矩阵的逆矩阵和它的转置矩阵相等,所以计算起来更高效;

2、根据矩阵的乘法结合律,我们可以将多个变换矩阵合成为一个变化矩阵。


第四章:Direct 3D初始化

1、为了优化全屏模式下的性能,准确匹配显示模式就很重要,比如刷新频率。


第五章:渲染流水线

1、类成员变量XMCOLOR,计算时使用XMVECTOR;

2、128位颜色用来进行高精度的计算,这样算法上的错误积累就少很多;最终颜色一般保存为32位(在back buffer中也通常是32位),当前的物理显示设备无法体现128位颜色的好处;


第六章:在Direct3D中绘制

1、如果PS上裁切像素,尽可能早clip掉,因为这样像素不会进行后面的PS计算;

2、对于硬件优化,一个像素片段是有可能直接跳过像素着色器,比如(early-z rejection),但是在有些情况下,这个功能会无法使用,比如如果像素着色器中修改了Z值,那么每个像素必须进行像素着色器计算后才能得到最终的Z值;


第七章:在Direct3D中绘制(二)

1、不要在着色器中使用太多的常量缓冲,为了性能[Thibieroz13]建议保持在5个以下;

2、每一个绘制调用都会以当前设置的根参数对象状态来执行。这样可以正常执行,因为硬件会为每一个绘制调用自动保存一份根参数对象的snapshot。也就是说根参数对象会在每次绘制调用中自动进行版本管理。为了性能优化,我们应该尽可能让根签名更小,其中一个原因是每个绘制调用中对根参数对象的自动版本管理,根签名越大,需要的开销就越大。更进一步,SDK文档建议跟参数应该根据改变的频率来排序(从高到低),并且尽可能减少根签名的切换。所以在多个PSO中共享一个根签名是一个不错的主意。所以创建一个“super”根签名在多个着色器程序中共享,即使部分参数在部分着色器中不需要使用,也可以优化性能。但是如果这个“super”根签名太大就会让减少切换获得的好处变小。


第八章:光照

1、全局光照的计算量无法应用到实时程序,游戏中一般使用局部光照。


第九章:贴图

1、我们可以将多个图片放到一个大纹理中(texture atlas),然后应用于多个物体。这样可以避免多次资源加载,减少DrawCall,优化性能;

2、使用DDS格式文件,GPU可以直接原生使用很多它的文件格式;并且它支持压缩,可以让GPU原生解压缩;

3、根据DX11的文档:定义完整类型的格式,可以进行运行时的优化。也就是说为了性能,只有当你真正需要无类型格式,否则都定义成完整类型的格式;


第十章:混合

1、混合操作是需要更多的逐像素计算,所以是消耗较多的性能,所以只有当需要使用的时候打开它,使用完成后就关闭它;

2、Alpha测试会消耗性能,所以只有当我们需要的时候再开启它;


第十一章:模板测试

1、显卡可能会每帧在同一个点上绘制多次,这种覆盖会影响到性能,因为它在重复绘制看不到的点。所以测量深度复杂度对优化分析就很有用;

2、深度测试时在输出合并阶段执行的(像素着色器之后)。所以即使像素后续会被放弃,但是还是会进行很耗时的像素着色器计算。但是现代的显卡提供了一个叫早期Z测试(early z-test)的技术,可以让Z测试在像素着色器之前进行。为了能够得到这个技术带来的重要的好处,你需要在绘制没有混合的物体的时候,进行从前往后的顺序进行绘制,这样最近的物体会先绘制,然后被遮挡的物体会被这个early z-test技术剔除,它会对具有高深度复杂度的场景带来大量的性能提升。对于early z-test技术我们无法使用D3D API进行控制,它完全是由显卡驱动判定控制的。比如如果你的像素着色器中修改了像素的Z值,那么early z-test将无法进行;


第十二章:几何着色器


第十三章:计算着色器

1、所以如果你的GPU有16个多处理器,那么你至少要把你的需求划分为16个线程组,这样你所有的多处理器都可以同时计算。为了有更好的性能,你应该为每个多处理器划分2个线程组,这样就可以切换线程组([Fung10]);

2、硬件把这些线程划分为warps(32个线程为一个warp),然后warps被多处理器以SIMD32来处理。每个CUDA core处理一个线程并且回顾“Fermi”多处理器,有32个CUDA cores。在D3D中你可以用一个不是32的倍数的值指定一个线程组的大小,但是出于性能考虑,最好还是指定为warp大小的倍数([Fung10]);

3、尺寸最好是wavefront的倍数(因为同时也是warp的倍数),这样就可以同时兼容两种显卡;

4、做模糊效果时,对于9x9的矩阵,我们需要81个采样。但是分离到2个1D的时候,我们只需要18个采样。尤其我们是在模糊纹理,纹理提取是很消耗性能的,所以通过分离模糊来减少纹理采样可以提高性能;

5、上面的步骤需要我们先进行正常的渲染流水线,然后切换到CS进行计算,然后切换回渲染流水线。这样的切换是由开销的([NVIDIA10])应当尽可能避免这样的切换;

6、模糊是一个很占用性能的操作,它的运算量主要与纹理的大小相关。一般情况下我们渲染到纹理的时候,可以渲染到一张比后置缓冲小的纹理上。这样可以提高渲染的纹理的速度;因为尺寸减小了,所以提高了模糊的速度;最终绘制到后置缓冲的时候,因为用了放大滤波器,又增加一层模糊效果;

7、线程组提供共享内存,访问它跟访问硬件cache一样快,它可以用来优化或者一些算法的实现。在CS中,它的定义如下:groupshared float4 gCache[N]; 数组大小可以是任意数,但是不能超过32kb,出于性能考虑,它的大小应该不超过16kb,否则不能让2个线程组指定到用一个多处理器;


第十四章:曲面细分阶段

1、D3D11硬件支持的最大细分因子是64。如果所有细分因子都是0,那么当前patch就拒绝进入后面的阶段。它可以帮助我们基于patch在背面消除和视锥体裁切上实现优化;

2、具体裁切多少主要基于需求,不要做不需要的裁切来浪费性能;

3、如果细分因子是1(也就是不细分),走一遍细分阶段流程是浪费GPU开销;

4、因为是基于GPU实现的,不要细分一个覆盖小于8个像素的这种太小的三角形;

5、批量调用具有细分的绘制调用(频繁打开和关闭曲面细分非常浪费性能);

6、曲面细分可以优化内存,也可以减少物理和动画运算(在低模上计算),可以实现LOD(以前只能放到CPU);


第十五章:第一人称摄像机和动态索引

1、最小化descriptors可以让我们的根签名更小,这代表每个绘制调用造成更少的性能开销;


第十六章:实例化和截头锥体裁切


第十七章:拾取

1、为了优化考虑,我们先进行物体包围体检测,只有检测通过的物体再遍历每个三角形检测;


第十八章:立方体贴图

1、在以前,应用通常优先绘制天空,然后使用它替换掉渲染目标,和深度/模板缓冲。但是“ATI Radeon HD 2000 Programming Guide”反对这个做法,原因有下:第一,深度/模板缓冲会为了内部硬件优化被明确的清空掉,对于渲染目标也是一样的;第二,因为大部分天空都是被其他物体比如建筑和地形遮挡的,所以如果我们先绘制天空,会导致很多像素需要重新绘制,这样很浪费性能。所以现在推荐最后再清空和绘制天空;


第十九章:法线贴图

1、如果你要使用压缩纹理格式保存法线贴图,使用BC7 (DXGI_FORMAT_BC7_UNORM)格式是最好的效果,它可以减少由压缩法线贴图造成的错误;


第二十章:阴影贴图

1、目前为止,我们使用4次测试的PCF内核,更大的内核会得到更平滑的边缘,但是会更消耗性能。观察上面的例子,其实只需要在边缘进行PCF,内部是不需要的,根据这个需求,衍生出了其他算法。[Isidoro06b]描述了一种方案,在着色器代码中需要动态分支:只有在边缘进行PCF。这种检测边缘又会带来其他性能开销,所以选择方案的时候要做好利弊分析;

2、这里像素着色器没有返回值,是因为我们只输出深度值。像素着色器只用以裁剪透明的像素片段。如果不需要根据透明度进行裁剪,我们可以设置像素着色器为null,这样可以让性能更高;

3、如果渲染阴影贴图的时候包含曲面细分几何体,我们需要曲面细分要和摄像机渲染时的细分保持一致;也就是说相机与物体的距离和光源与物体的距离要差不多,否则阴影会出现错误。一种优化的方案是,渲染阴影贴图的时候不使用曲面细分。(这种优化用准确性交换速度);

4、构造函数通过分辨率和viewport来创建纹理。分辨率影响了阴影的效果,高分辨率会需要更多性能开销和内存;

5、PCF的缺点在于它需要4次采样,在现代显卡上,采样操作是很费性能的操作之一,因为GPU的内存带宽和延时并没有像它计算能力那样得到提高[Möller08]。幸运的是,DX11图形硬件内置了支持PCF的方法SampleCmpLevelZero;


第二十一章:环境光遮蔽

1、实时程序使用屏幕空间环境光遮蔽(SSAO),无法使用光线追踪环境光遮蔽,因为计算量太大;

2、为了性能,SSAP贴图使用半分辨率;


第二十二章:四元数


第二十三章:角色动画

Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- Direct12优化的更多相关文章

  1. Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 全书总结

    原文:Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 全书总结 本系列文章中可能有很多翻译有问题或者错误的地方:并且有些章节 ...

  2. Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第二十三章:角色动画

    原文:Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第二十三章:角色动画 学习目标 熟悉蒙皮动画的术语: 学习网格层级变换 ...

  3. Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第二十二章:四元数(QUATERNIONS)

    原文:Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第二十二章:四元数(QUATERNIONS) 学习目标 回顾复数,以及 ...

  4. Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第二十一章:环境光遮蔽(AMBIENT OCCLUSION)

    原文:Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第二十一章:环境光遮蔽(AMBIENT OCCLUSION) 学习目标 ...

  5. Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第二十章:阴影贴图

    原文:Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第二十章:阴影贴图 本章介绍一种在游戏和应用中,模拟动态阴影的基本阴影 ...

  6. Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第十九章:法线贴图

    原文:Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第十九章:法线贴图 学习目标 理解为什么需要法线贴图: 学习法线贴图如 ...

  7. Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第十八章:立方体贴图

    原文:Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第十八章:立方体贴图 代码工程地址: https://github.c ...

  8. Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第十七章:拾取

    原文:Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第十七章:拾取 代码工程地址: https://github.com/ ...

  9. Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第十六章:实例化和截头锥体裁切

    原文:Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第十六章:实例化和截头锥体裁切 代码工程地址: https://git ...

随机推荐

  1. js算法之把一个数组按照指定的数组大小分割成若干个数组块

    题目描述:     把一个数组arr按照指定的数组大小size分割成若干个数组块. 例如:   chunk([1,2,3,4],2)=[[1,2],[3,4]];   chunk([1,2,3,4,5 ...

  2. django2.x报错No module named 'django.core.urlresolvers'b

    解决方法就是: from django.urls import reverse 最近从django1.9迁移到django2.0中出现一个意外的报错: 这个报错的原因在stack overflow上有 ...

  3. Simple implementation and results of genetic algorithm.

    This experiment was done for the final assignment of my Professional English class. This part has be ...

  4. 使用Python的requests库作接口测试——请求对象与响应对象

    任何时候调用requests.*()操作接口时,我们都在做两件事情: 1.构建一个Request对象,该对象被发送到服务器去请求或查询一些资源: 2.一旦requests得到一个从服务器返回的响应,就 ...

  5. ubuntn右上角小键盘消失及fictx切换输入法快捷键

    Ubuntu任务栏右上角的小键盘消失,打开系统设置-文本输入-左下角将当前输入法显示在任务栏. 切换输入法快捷键,打开系统设置 > 文件输入 >切换到下一个源(上一个源)的快捷键设置一个不 ...

  6. mac vagrant 虚拟机nfs挂载点

    需求:在mac 上安装了虚拟机,虚拟机系统为centos6.5,现在希望讲虚拟机上点目录通过nfs共享给mac使用 下面主要描述通过nfs共享目录给mac调用的过程 过程参考网址: http://ww ...

  7. bootstrap-fileinput详细说明与使用

    介绍 bootstrap-fileinput是一款非常优秀的HTML5文件上传插件,支持文件预览.多文件上传等一系列特性. 一款非常优秀的HTML5文件上传插件,支持bootstrap 3.x 和4. ...

  8. fastjson 对象和json互转

    list转json List<Openid> openids = od.getAll(session); String json = JSONObject.toJSONString(ope ...

  9. go语言:获取字符串长度

    go语言字符串底层由字节数组实现,使用UTF-8编码,初始化以后不能被修改 获取字符串长度 一.当字符串中所有字符都是单字节字符时,使用 len 函数获取字符串的长度 package main imp ...

  10. day18 15.自定义连接池

    我们写的是连接池吗?Connection对象绝对不能关.现在写的玩意不是连接池.因为现在讲的是JDBC,连接池也是JDBC里面的,人家那是SUN公司定义的标准.标准,你那不是标准.既然是标准,你做连接 ...