D3D RUTIME MEMORY & DrawPrimitive

D3D RUTIME MEMORY & DrawPrimitive

带着昨晚很多疑问,今天认真的查阅的很多资料,D3D RUTIME MEMORY分为VIDEO MEMORY(VM)、AGP MEMORY(AM)和SYSTEM MEMORY(SM),在创建资源的时指定的POOL将绝对资源存放的地方,D3D提供了常见的几种方式D3DPOOL_DEFAULT、D3DPOOL_MANAGED、D3DPOOL_SYSTEMMEM。

  解释下三种MEMORY,①VIDEO MEMORY,显存,位于显卡,CPU如果想访问该资源,只能通过AGP或者PCI-E总线,结果当然是读写速度都很慢,但因为CACHE会分配写缓冲,填充满后提交给VM,所有写速度要比读稍微快点②SYSTEM MEMORY,系统内存,CPU不管读写都是最快的,但GPU是无法访问该部分资源的③AGP MEMORY,同样也为显存,不过却存在与系统内存中,因为这部份memory不会被CPU CACHE,所以PCU读写AM都会比较慢,但GPU可以直接通过AGP或者PCI-E总线访问到AM。

  下面就是资源的创建了,昨天仔细研究了irrlicht的资源管理和lost device处理,几种POOL标志中D3DPOOL_DEFAULT将根据我们具体的Usage来决定存储类型,一般在VM或者AM,并且不会进行额外备份,当设备丢失后,这些资源全部会被丢失,D3D doc也写的很清楚,When a device is lost, resources created using D3DPOOL_DEFAULT must be released before calling IDirect3DDevice9::Reset,通过D3DPOOL_DEFAULT创建的静态纹理是不能被CPU LOCK的,但是VB,IB,BackBuffer,RenderTarget可以被lock。

  D3DPOOL_MANAGED是依靠D3D托管的,当然会有利有弊,该标志创建的原始资源会放在SM中,当GPU要用到时会拷贝一份到VM中,其中有任何一方被修改,都会发生update,所以修改比较频繁的资源千万不能用该标志,不然会产生非常昂贵的同步负担,不过优点就是设备丢失后, IDirect3DDevice9::Reset时会自动从SM中拷贝资源到VM,当然如果程序设计的不好处理lost device,也可以用MANAGED创建部分资源。

  D3DPOOL_SYSTEMMEM资源只会放在SM中,D3D设备无法访问,但可以作为UpdateSurface或UpdateTexture的src来操作通过D3DPOOL_DEFAULT创建的资源

  三种标志直接影响了D3DLOCK的使用,D3DPOOL_DEFAULT的资源因为在VM或者AM中,如果在VM中,还得在系统中创建一个临时缓冲用来返回数据,而如果Usage不是WRITEONLY的话,系统还会从VM拷贝一份数据到缓冲,这对程序的性能影响很大,之前说过D3DPOOL_DEFAULT创建的普通texture不能被CPU lock,因为资源存在于VM中,而高频率变化的动态纹理,不能用动态属性创建,比如RenderTarget和TextureVideo因为使用动态属性创建的资源位于AM中,GPU访问要通过AGP/PCI-E来访问,而CPU访问也不如SM中快,所以CPU和GPU访问资源会延迟,这里看到别人建议可以用D3DPOOL_DEFAULT和D3DPOOL_SYSTEMMEM各创建一次,有变化后通过自己手动更新,是个好办法,不过效果不知道怎么样,准备去试试。

  一般LOCK会打断CPU和GPU的并行流水线,导致GPU进入Idle状态,直到Unlock才恢复,不过D3D提供了一个lock标志D3DLOCK_DISCARD,使用该标志回后立刻返回一个新的VM地址,不会影响当前正在使用的资源,当unlock后,以前的资源会废弃,从而使用新的资源。

  合理的指定资源内存池和lock标志对于程序性能非常重要。

  

  接下来是DP了,昨天研究irrlicht的vertex和index buffer时,发现irrlicht通过一个HW( hard ware)V/I B来管理通过D3Dcreate的VB和IB,但是搜遍整个解决方案,发现正常通过VB和IB来提供顶点索引数据的绘制相当之少,绝大多数用的DrawIndexedPrimitiveUP,除了ply和Q3 BSP用了VB和IB,其他所有的模型都采用的本地数据,貌似create***buffer把数据放到显存,应该渲染的时候GPU获取资源更快,效率更高的,实在搞不懂为什么全部用DrawIndexedPrimitiveUP,试着把模型都改用DrawIndexedPrimitive,却发现表现不出任何性能上的提升,找了点资料看,DrawIndexedPrimitiveUP其实就是动态缓冲,和自定义的动态缓冲没区别,lock copy unlock后最终还是用DrawIndexedPrimitive,但我没有确定是否每次call都会导致lock copy unlock操作,如果是的话,那么如果数据量大,copy肯定会对游戏性能有影响,找了篇资料,有如下的话

  If you're drawing less than around 100 vertices, Direct3D automatically copies the vertices into it's own private vertex buffer, so the DrawPrimitiveUP call is actually 'translated' into a DrawPrimitive call, plus a memcpy (and if it's less than 100 vertices, that memcpy probably won't be significant).

  看来在顶点数量很少的情况下,应该不会有什么性能损失,不过他这100应该低了,昨天测试的模型应该有好几百面,像sprite和UI这样顶点极少的可以用DrawPrimitiveUP来绘制,不过可以有更多的优化方案,比如UI每个面板的资源做成一张纹理,配一个rendertagert cache到时候一个面板共用一个VB和IB,不过很多人建议不要多用DrawPrimitiveUP,毕竟本地指针存在安全性,也是,毕竟DX文档也建议少用DPUP了

你可能感兴趣的:(D3D RUTIME MEMORY & DrawPrimitive)