渲染优化 lock unlock

转载自:http://www.cnblogs.com/lancidie/archive/2011/05/22/2053342.html

昨天参加了公司组织的nvdia的培训,讲了一些关于D3D的优化和可能的瓶颈所在,具体的条目就不说了,这里说一些关于资源的Lock和Unlock,以及我在GL下的测试。

老师讲到向Draw*这类函数是将其指令放入指令队列,带填满后或者强制刷新时交给显卡去画,也就是说它并不是即时的,而像对资源的Lock和Unlock确是即时的操作,而且cpu和gpu是并行计算的,当lock的资源正是当前gpu正在使用的资源会导致lock堵塞直到gpu使用完后才返回,也就是说不当的使用lock会造成cpu等待gpu的情形。当然D3D的lock函数有一个标记用来告诉lock是否立即返回,使用这个标记后lock会立即返回,并且拿到资源地址,此时cpu如果向该地址写入新的数据,但gpu也正在使用之,则将出现不可预知的效果。比如lock下一个文理并填入新的数据,此时gpu正使用该纹理进行渲染,则使用该纹理渲染出来东西的纹理将是乱的(D3DLOCK_DISCARD 用了VB IB换名(renaming)技术,应该也不会有该问题,应该是拷贝了一份同时使用也不会有问题的

我用OpenGL并且一直使用这么一种方式来管理顶点Buffer和索引Buffer(见下面的描述),但从没考虑过上面的提到的lock造成的堵塞,当然我用的是OpenGL,但我想Lock这个机制应该是驱动或者显卡那一级的事情,D3D和GL都应该存Lock的问题。

我这里所谓的管理顶点Buffer和索引Buffer的方式是这样的。考虑这么一种情况,当场景中那些粒子也好,动画也好,比较多的时候,我们要每个都给他们在显卡上单独分配顶点缓冲和索引缓冲,毕竟他们的数据是不同的,而且每贞都有变化,即便是使用同一个动画的角色,在同一时刻也不一定在播放同一贞,这带来一个问题,当场景中此类对象很多时将占用很多的显村,且很难控制量,毕竟在引擎这个层面无法知道游戏中到底需要摆放多少个角色,显卡到底有多少空间可供分配等等。我采用的方式是在引擎启动之初就再显卡上分配一个65535个顶点缓冲和65535个索引缓冲,所有需要动态更新顶点Buffer和索引Buffer都填入该缓冲内,并在填充完毕后调用渲染方法。伪代码如下

for (int indexMesh = 0; indexMesh < 100; indexMesh++)

{

            vertex *pv = lock(); // 从共享Buffer中获得

            {

                   for (int indexVertex = 0; indexVertex < 1024; indexVertex++)

                  {

                             pv[indexVertex] = position;

                            // ...

                  }

            }

            unlock(pv);

            Render();

}

如果按照之前提到的Lock会被阻塞和数据交叉的问题,那么这么做将会出现效率下降,更严重的是会出现数据混乱的问题,或者画的是最后一次填充的数据。

但是在实际使用和测试中发现这并没有任何问题,首先说一下效率,lock和unlock只消耗0.025毫秒(当然这个和我提交的数据量关系),渲染几乎没有消耗(一共渲染10万左右个面,显卡是nv8600gt)。而数据也没有出现任何混乱。我没有A卡,没办法进行相关测试。

莫非Lock,unLock这个真的是D3D9才有的问题?

你可能感兴趣的:(渲染优化 lock unlock)