平民程序 - linghuye's blog

天下风云出我辈,一入江湖岁月催。皇图霸业谈笑中,不胜人生一场醉。提剑跨骑挥鬼雨,白骨如山鸟惊飞。尘事如潮人如水,只笑江湖几人回。

随笔 - 221, 文章 - 0, 评论 - 680, 引用 - 0
数据加载中……

优化!优化!优化!

原则
1.以目前计算机的发展阶段而言, 游戏总是CPU Limited.
2.渲染 Batch, Batch, Batch
3.尽力减少图形API调用次数.
4.Minimize data swithing, such as SetStreamSource and SetIndices. Maximize FVF sharing.

认识:
1.DX API消耗Top5:  SetPixelShaderConstant()   SetPixeShader()     SetVertexShaderConstant()   SetVertexShader()   SetTexture()

经验:
1. 过大过多的纹理造成带宽瓶颈,而顶点数据流量一般不足以产生瓶颈.
2.25k batches/s @ 100% 1GHz CPU, 即在PentiumD 2.8G上,令CPU满负荷运转,要保持30FPS,每帧只能渲染25000 * 2.8 / 30 = 2333个batch.经我测试,这只是在最理想状态下,渲染每个大于1000面的静态物体时的数据. 但若渲染的是小于大约130个面的静态物体,可渲染的batch比这高很多,大约2倍左右甚至更高,此时据文档说是CPU在负责计算顶点. 然后,如果渲染的是生物,按GPU计算骨骼运动的标准,最耗的是CPU骨骼层次矩阵计算和SetVertexShaderConst函数,两者都直接和骨骼数量成正比,即骨骼越多可渲染的batch越少.
3.对MMORPG游戏而言,瓶颈总是在CPU上,总是在骨架动作计算和渲染提交Batch次数上.

25k batches/s @ 100% 1GHz CPU



References:
http://ati.amd.com/developer/gdc/2006/GDC06-Advanced_D3D_Tutorial_Day-Huddy-Optimization.pdf

http://developer.download.nvidia.com/GPU_Programming_Guide/GPU_Programming_Guide.pdf
http://developer.nvidia.com/docs/IO/8230/BatchBatchBatch.ppt
http://download.nvidia.com/developer/presentations/GDC_2004/Dx9Optimization.pdf
http://developer.nvidia.com/object/gdc_d3dperf.html

posted on 2008-02-24 21:03 linghuye 阅读(4886) 评论(8)  编辑 收藏 引用 所属分类: 3D图形学研究

评论

# re: 优化!优化!优化!  回复  更多评论   

骨骼层次矩阵计算,是可以做预处理的,即以空间换时间。实际上一般的角色的骨骼数据所占的空间也不会很大,以50根骨骼和1000帧的数据来计算,则所占的空间为: 50 * sizeof(float43) * 1000 = 2,500,000,对于游戏中的主角来说,存储骨骼所要的空间不会超过10M(大多数角色)。有关DX Api调用开销来说,SetVertexShaderConst的开销相对于SetTexture, SetVertexShader,SetStreamSource来说应该是非常小的。
2008-03-09 22:16 | JackWolf

# re: 优化!优化!优化!  回复  更多评论   

1.你说的好像是标准实现, 不明白作了哪些预处理.
2.根据我的测试实践,SetVertexShaderConst在骨骼运动计算整个流程中可以占到30-50%,设置GPU寄存器是很慢的, DX API消耗Top5, 这也是ATI的官方文档提出的. Geometry Instance技术,为了避开设置寄存器,而使用设置顶点数据流的方法,把这些矩阵状态作为顶点流数据传入shader.
2008-03-09 22:49 | linghuye

# re: 优化!优化!优化!  回复  更多评论   

1. "最耗的是CPU骨骼层次矩阵计算" 所谓层次矩阵计算即矩阵的父子关系计算(hierarchy),我指的是这部分的预处理,即不需要再进行层次矩阵计算。
2. “DX API消耗Top5,”不知道您说的这个排行榜是什么地方来的,我在dx sdk文档中没有找到。
另外给出一份dx sdk中关于常用dx api的performace性能参数,在文档中也有明确说明,这些api的调用开销会根据实际情况有不同。

API Call Average number of Cycles
SetVertexDeclaration 6500 - 11250
SetFVF 6400 - 11200
SetVertexShader 3000 - 12100
SetPixelShader 6300 - 7000
SPECULARENABLE 1900 - 11200
SetRenderTarget 6000 - 6250
SetPixelShaderConstant (1 Constant) 1500 - 9000
NORMALIZENORMALS 2200 - 8100
LightEnable 1300 - 9000
SetStreamSource 3700 - 5800
LIGHTING 1700 - 7500
DIFFUSEMATERIALSOURCE 900 - 8300
AMBIENTMATERIALSOURCE 900 - 8200
COLORVERTEX 800 - 7800
SetLight 2200 - 5100
SetTransform 3200 - 3750
SetIndices 900 - 5600
AMBIENT 1150 - 4800
SetTexture 2500 - 3100
SPECULARMATERIALSOURCE 900 - 4600
EMISSIVEMATERIALSOURCE 900 - 4500
SetMaterial 1000 - 3700
ZENABLE 700 - 3900
WRAP0 1600 - 2700
MINFILTER 1700 - 2500
MAGFILTER 1700 - 2400
SetVertexShaderConstant (1 Constant) 1000 - 2700
COLOROP 1500 - 2100
COLORARG2 1300 - 2000
COLORARG1 1300 - 1980
CULLMODE 500 - 2570
CLIPPING 500 - 2550
DrawIndexedPrimitive 1200 - 1400
ADDRESSV 1090 - 1500
ADDRESSU 1070 - 1500
DrawPrimitive 1050 - 1150
SRGBTEXTURE 150 - 1500
STENCILMASK 570 - 700
STENCILZFAIL 500 - 800
STENCILREF 550 - 700
ALPHABLENDENABLE 550 - 700
STENCILFUNC 560 - 680
STENCILWRITEMASK 520 - 700
STENCILFAIL 500 - 750
ZFUNC 510 - 700
ZWRITEENABLE 520 - 680
STENCILENABLE 540 - 650
STENCILPASS 560 - 630
SRCBLEND 500 - 685
Two_Sided_StencilMODE 450 - 590
ALPHATESTENABLE 470 - 525
ALPHAREF 460 - 530
ALPHAFUNC 450 - 540
DESTBLEND 475 - 510
COLORWRITEENABLE 465 - 515
CCW_STENCILFAIL 340 - 560
CCW_STENCILPASS 340 - 545
CCW_STENCILZFAIL 330 - 495
SCISSORTESTENABLE 375 - 440
CCW_STENCILFUNC 250 - 480
SetScissorRect 150 - 340



很久没有看最新的技术文档了,做项目总是要为项目的实际需求服务,真羡慕版主,有机会研究新的技术和成果并实践之,很羡慕。
2008-03-18 19:18 | JackWolf

# re: 优化!优化!优化!  回复  更多评论   

1.预处理层级骨骼计算确实会省很多,但是
a.预处理层级计算后,得到的是一整个Matrix,丢失了平移/旋转/缩放信息,运动帧间只能完成简单的矩阵线性插值,不能做平滑的quat rotation slerp,和Squad淡入淡出过渡, 而且实现动作间过渡时会很容易出错.
b.不做层级处理,不能完成Inverse Kinematics处理,还有其他一些骨骼技术.
所以对于一个正式的完善的骨骼系统,层次关系难以预处理.

2.这种说法来源于
http://ati.amd.com/developer/gdc/2006/GDC06-Advanced_D3D_Tutorial_Day-Huddy-Optimization.pdf

http://download.nvidia.com/developer/presentations/GDC_2004/Dx9Optimization.pdf

dx sdk中所说的开销仅是DirectX Runtime的开销,要实际考量一个API,还要考虑它的driver overhead和hardware overhead.
2008-03-18 22:34 | linghuye

# re: 优化!优化!优化!  回复  更多评论   

1. a 得到的Matrix,是可以分解为T/R/S的,并没有丢失这部分的信息。同样可以做动作帧的Transform,其实不管是线性插值还是quaternion插值,如果两个矩阵差异太大,动作表现上都是变形的。只是无法做Blend。以WoW为例,除了在边移动和边战斗的时候需要Blend以外,很少有动作需要Blend。
1. b 不做层级处理,为什么不能完成IK处理呢?还需要请教

2. ATI网站上的paper是这样提到,甚至把SetVertexShaderConstant和SetTexture并列,这有点吃惊。
2008-03-20 22:00 | JackWolf

# re: 优化!优化!优化!  回复  更多评论   

1.算出Matrix,再分解为T/R/S,分解的消耗是不是大了点?
2.层级处理后得到的是所有父节点和自身的矩阵乘积, 即M =V * M1 * M2 * M3,每个M为 Scale * Rotate * Position, 最后再分解M得出的S,R,P是没有含义的,不能认为就是最终骨骼的S,R,P,这个我实践过的.
3.正是因为矩阵差异太大,可能导致blend错误,所以要在每个层级上做blend,因为一旦矩阵累积了每个层级,差异很大.
4.IK我也只是略知皮毛,记得IK要逆向调整每个层级的骨骼以达到正确的姿势.
5.WoW中最频繁的blend,发生在行进间转身的那个动作,特别是左右跑互换时上半身的过渡, 平滑得让人看不出它做了过渡,但实际上资源中是没有转身这个独立动画的. 这个是我一直想达到的效果.
2008-03-21 09:55 | linghuye

# re: 优化!优化!优化!  回复  更多评论   

1.在我目前参与的项目中,实际上是矩阵缓存和动态计算两套机制同时使用的,因为这两种机制并不冲突。而且矩阵缓存的效率提升是比较明显的。假设在一个场景中,同屏30个怪物,每个怪物50根骨骼,每帧花费在矩阵计算上的CPU开销是比较可观的(50根骨骼的hierachy,矩阵计算的次数可能达到75—100次),即便使用了SSE2指令集针对矩阵计算进行优化也是如此。当然,如果瓶颈是在GPU则另当别论了。
2.在骨骼计算之中,除了做slerp以外,很少会需要使用骨骼的旋转、缩放信息,一般很少会再针对矩阵进行T/S/R的分解,但这部分信息还是保留着的。
3.WOW中的左右跑步就是Transform+Blend同时作用。
2008-03-23 20:24 | JackWolf

# re: 优化!优化!优化!  回复  更多评论   

http://download.nvidia.com/developer/presentations/GDC_2004/Dx9Optimization.pdf

这个URL怎么打不开。。。
2008-03-23 20:25 | JackWolf
只有注册用户登录后才能发表评论。