文章来源:
CAD
世界网
一般来说, 定位渲染通道瓶颈的方法就是改变渲染通道每个步骤的工作量 , 如果吞吐量也改变了 , 那个步骤就是瓶颈 . 。找到了瓶颈就要想办法消除瓶颈 , 可以减少该步骤的工作量 , 增加其他步骤的工作量。
一般在光栅化之前的瓶颈称作 ”transform bound”, 三角形设置处理后的瓶颈称作 ”fill bound” 定位瓶颈的办法 :
一般来说, 定位渲染通道瓶颈的方法就是改变渲染通道每个步骤的工作量 , 如果吞吐量也改变了 , 那个步骤就是瓶颈 . 。找到了瓶颈就要想办法消除瓶颈 , 可以减少该步骤的工作量 , 增加其他步骤的工作量。
一般在光栅化之前的瓶颈称作 ”transform bound”, 三角形设置处理后的瓶颈称作 ”fill bound” 定位瓶颈的办法 :
·
1.
改变帧缓冲或者渲染目标
(Render Target)
的颜色深度
(16
到
32
位
),
如果帧速改变了
,
那么瓶颈应该在帧缓冲
(RenderTarget)
的填充率上。
·
2.
否则试试改变贴图大小和贴图过滤设置
,
如果帧速变了
,
那么瓶颈应该是在贴图这里。
·
3.
否则改变分辨率
.
如果帧速改变了
,
那么改变一下
pixel shader
的指令数量
,
如果帧速变了
,
那么瓶颈应该就是
pixel shader.
否则瓶颈就在光栅化过程中。
·
4.
否则
,
改变顶点格式的大小
,
如果帧速改变了
,
那么瓶颈应该在显卡带宽上。
·
5.
如果以上都不是
,
那么瓶颈就在
CPU
这一边。
·
优化方法
36
条
:
·
1.
尽量减少无用的顶点数据
,
比如贴图坐标
,
如果有
Object
使用
2
组有的使用
1
组
,
那么不
要将他们放在一个
vertex buffer
中
,
这样可以减少传输的数据量。
·
2.
使用多个
streamsource,
比如
SkinMesh
渲染
,
可以把顶点坐标和法线这些每一帧都要修改的数据放在一个动态
VB
中
,
其它不需要修改的
(
如贴图坐标
)
放到一个静态
VB
中
,
这样就减少了数据传输量。
·
3.
尽量使用
16
位的索引缓冲
,
避免
32
位的
.
一方面浪费带宽
,
一方面也不是所有的显卡都支持
32
位的索引缓冲。
·
4.
可以考虑使用
vertex shader
来计算静态
VB
中的数据
.
比如
SkinMesh
的顶点可以放到
vectex shader
中计算
,
这样就可以避免每一帧都从
AGP
内存中向显存传送数据
.
这样也可以使用静态
VB
了。
·
5.
坚决避免使用
Draw**UP
一族的函数来绘制多边形。
·
6.
在设计程序之前好好规划一下显卡内存的使用
,
确保
framebuffer,
贴图
,
静态
VB
能够正好放入显卡的本地内存中。
·
7.
尽量使顶点格式大小是
32
字节的倍数
.
可以考虑使用压缩过的顶点格式然后用
vertex shader
去解
.
或者留下冗余的部分
,
使顶点大小刚好使
32
字节的倍数。
·
8.
顶点在顶点缓冲中的顺序尽量符合绘制的顺序
,
考虑使用
strips
来代替
list
。
·
9.
如果可能尽量多的使用
static vertex buffer
代替
dynamic vertex buffer
。
·
10.
动态
VB
使用
DISCARD
参数来
lock
更新
,
使用
NOOVERWRITE
来添加
.
尽量不要使用不带参数的
lock
调用
(0)
。
·
11.
尽量减少
lock
的次数
,
有些东西并不一定非要每一帧都更新
VB,
比如人物动画一般每秒钟更新
30
次
VB
基本上就够了。
·
12.
如果是因为需要绘制的顶点数据太多了可以考虑使用
LOD,
但是现在的显卡的绘制能力都很强劲
,
所以需要权衡一下
LOD
是否能够带来相应的好处
,
如果过分的强化
LOD
很可能将瓶颈转移到
CPU
这边。
·
13.
避免过多的顶点计算
,
比如过多的光源
,
过于复杂的光照计算
(
复杂的光照模型
),
纹理自动生成的开启也会增加顶点的计算量
.
如果贴图坐标变换矩阵不是单位矩阵
,
也会造成顶点计算量的增加
,
所以如果纹理变换已经结束
,
记得要将纹理变换矩阵设为单位矩阵同时调整贴图坐标。
·
14.
避免
Vertex shader
指令数量太多或者分支过多
,
尽量减少
vertex shader
的长度和复杂程度
.
尽量使用
swizzling
代替
mov
。
·
15.
如果图象质量方面的计算
(pixel shader)
范围很大
,
并且很复杂
,
可以考虑试试全屏反走样。说不定更快。
·
16.
尽量按照
front – back
的顺序来绘制。
·
17.
在
shader
中判断
Z
值可以避免绘制不可见的象素
,
但是
nvidia
建议简单的
shader
不要这么做
.(Don't do this in a simple shader)
。
·
18.
如果可能
,
尽量使用
vertex shader
来代替
pixel shader.
将计算从逐象素变成逐顶点。
·
19.
尽量降低贴图的大小
.
过大的贴图可能造成贴图
cache
过载
,
从而导致贴图
cache
命中降低
.
过大的贴图会导致显存过载
,
这时候贴图是从系统内存中取的。
·
20.
只要可能就用
16
位色的贴图
,
如环境贴图或者
shadow map.
它们用
32
位色的贴图实在是浪费。
·
21.
考虑使用
DXT
贴图压缩。
·
22.
如果可能
,
使用简单的贴图过滤或者
mip map,
除非必要否则尽量不要使用三线过滤和各项异性过滤
. light map
和
环境贴图基本上都不需要使用它们。
·
23.
只有真正需要修改的贴图才使用
Dynamic,
并且使用
DISCRAD
和
WRITEONLY
来
lock
。
·
24.
太多的帧缓冲读写可以考虑关闭
Z-Writes
如有些多
pass
的渲染中的后续
pass
或者粒子系统等半透明几何物体(如果可以)。
·
25.
可能的话尽量使用
alpha test
代替
alpha blending
。
·
26.
如果不需要
stencil buffer
就尽量使用
16
位的
Z buffer
。
·
27.
减小
RenderTarget
贴图的大小
,
如
shadow map
环境贴图
.
可能根本不需要那么大效果就很好。
·
28.Stencil
和
Z buffer
尽量一起
clear.
他们本来就是一块缓冲。
·
29.
尽量减少渲染状态的切换
,
尽量一次画尽可能多的多边形。(根据显卡性能决定最多画多少,
不过一般再多也不会多到哪里去。
除非你根本不需要贴图和渲染状态的切换)。
·
30.
尽量使用
shader
来代替
Fixed Pipeline
。
·
31.
尽量使用
shader
来实现来取代
Multipass
渲染效果。
·
32.
尽量优先先建立重要的资源
,
如
Render target, shaders,
贴图
, VB, IB
等等
.
以免显存过载的时候它们被创建到系统内存中。
·
33.
坚决不要在渲染循环中调用创建资源。
·
34.
按照
shader
和贴图分组后再渲染
.
先按照
shaders
分组再按贴图。
·
35.Color Stencil Z buffer
尽量在一次
Clear
调用中清除。
·
36.
一个
Vertex buffer
的大小在
2M
-4M
之间最好。