前几天的BLOG中说了一些我的3D引擎GUI的渲染部分原理,这几天做到ListCtrl控件的时候,当我添加很多Item进去的时候(几乎满屏的12Px汉字,一个汉字两个三角形,相当于上万个三角形了),FPS降得吓人,Debug版只有18FPS,Release版也只有60FPS。。优化、优化、还是优化!优化之后,FPS终于达到了令人满意的500FPS左右了。且听我慢慢说来。
首先是用我的引擎内部剖析分析了代码的瓶颈(Profile这东西真的有用啊,让我很容易就找到了慢的原因,参见GPG3 1.17《实时的层次化性能评测》),发现处理时间主要被Cache算法和渲染两部份占了,于是,我在想,渲染慢是正常的(当时的想法比较弱智,后文有术),所以,我打算从Cache算法着手。首先是优化了ListCtrl的Cache算法,把那些在屏幕外的Item的Visible属性设置成false(我的算法中Visible为false,Cache部分算法就直接跳过),于是速度一下子就上来了,Release版本达到了130FPS。但是,还是慢啊。怎么办?剖析之后,发现大部分的处理时间都集中在渲染部分,我之前的想法是渲染慢是正常的,所以暂时无法解决。。。
下班的时候,出去遛了一圈,路上突然想到了我渲染算法中另外一个跟渲染速度有关的东西,动态修改顶点数据!难道是这里的原因?回来后马上测试,把动态修改的代码屏蔽,直接每帧渲染10000三角形,妈呀,1000+的FPS!完全否定了我之前的想法(渲染慢是正常的),唉,想想也是,每秒千万、上亿个三角形生成速度的显卡,对于区区一万个三角形怎么会慢呢...既然找到原因,就要优化啊,现在找到原因是因为动态修改顶点导致,想到了以前看过一篇文章说顶点数据存储的位置(即CreateVertexBuffer的D3DPool参数),说到做到,把原来的D3DPOOL_MANAGED改成D3DPOOL_SYSMEMORY,哇,速度一下子提升到360FPS左右!想起来原因也是简单的,既然要每帧Lock这么多数据,那么顶点数据需要从显存->CPU处理,然后CPU提交回显存,总线交换也太频繁了,如果改成SYSMEMORY的话,就只需要从CPU->显存就可以了。
然后我又想,有没有更好的优化方法?答案是有的。。最快的修改内存数据的方法是什么?当然是直接读写内存啊!那么我想到了DrawPrimitiveUP!把顶点数据直接new出来,然后DrawPrimitiveUP提交!改成这样后,速度再度提升!达到惊人的500FPS!
最后,我把DrawPrimitiveUP改成DrawIndexedPrimitiveUP,那么顶点数量也减少了。但是奇怪的是速度缺没有更快,反而慢了一点点(慢了5~10FPS左右),但是,我用了DrawIndexedPrimitiveUP,我之后还有更好的优化算法准备实现。通过DrawIndexedPrimitiveUP,但是还没做好。。所以先卖个关子了。明天搞好的话再写Blog。
唉,回头看了下自己写的东西,乱七八糟。都不知道有没有人看得懂啊。不管了。知之为知之,不知为不知吧。呵呵,看不懂的请评论一下。
写代码去了~~