引擎瓶颈被确定为过多DP/DIP Calls
这个消息真是可喜可悲。可喜的是如果消除了DP/DIP Calls的瓶颈,那么引擎能力会有大幅提高(至少是同屏三角形数目上);可悲的是要消除这个瓶颈带来的重构代价应该不小。
下面说一下为什么DP/DIP Calls会造成瓶颈。
现代PC的体系结构决定了我们在提交三角形时需要通过d3d runtime和driver。我们每一次提交三角形都要通过调用d3d runtime给我们的接口,而d3d runtime又会通知driver去对相关硬件做操作。如果你的场景中有10,000个三角形,但你每次只提交10多个,那么这样下来就会需要提交1,000次左右,也就是说调用1,000次左右的DP/DIP。这样d3d runtime和driver就忙于和硬件(主要应是AGP总线和GPU)打交道,而高度优化的显卡流水线只是每次处理了10多个三角形就被迫全线停止,然后等待下一次启动流水线。
这样大部分时间都被CPU花在了愚蠢的“多次提交三角形”上,而GPU闲在那边没事做。GPU没事做意味着什么?意味着我们可以大幅增加三角形复杂度!反正GPU闲着也是闲着,每次处理10个三角形停下和每次处理100个三角形停下,差不了多少时间。还意味着我们可以用更多的Vertex Shader/Pixel Shader,反正是闲着嘛!
当然这里不是讨论如何在这些idle时间中加些什么给GPU处理。而是:既然知道了DP/DIP Calls太多,怎么去解决这个问题。
首先利用Vertex Buffer/Index Buffer。就以静态的场景来说,当场景从磁盘载入内存时,把所有的顶点都读入Vertex Buffer。该Vertex Buffer可以创建为static(或dynamic亦可)。然后每次裁剪之后,通过裁剪结果,组织生成新的Index Buffer。然后一举DP/DIP将它渲染出来!
当然,这其中还有其他的问题。Texture的处理就很麻烦。如何让一个拥有多张纹理的场景(非常常见)用一个DP/DIP渲染出来?如果不进行texture atlas的工作的话,这样上面的方法几乎是行不通的。nVIDIA提供了一个称为Texture Atlas Tool的工具,其中包括源码。它提供了一种将多个纹理拼合成一张大纹理的方法,然后提供一个外部文件以记录所有uv remapping的信息。然后我们可以通过这些信息改动我们的模型文件中的数据。
这样,再对shader/state进行管理的话(这里就不进行讨论了),将场景通过一个DP/DIP完全渲染就不再是个梦想了。
![](http://c.spaces.msn.com/CollectionWebService/c.gif?space=fengye2001&page=RSS%3a+%e5%bc%95%e6%93%8e%e7%93%b6%e9%a2%88%e8%a2%ab%e7%a1%ae%e5%ae%9a%e4%b8%ba%e8%bf%87%e5%a4%9aDP%2fDIP+Calls&referrer=)
![](http://c.msn.com/c.gif?NC=31263&NA=1149&PI=73329&DI=3919&PS=85545)