我继承的 DirectX 9 应用程序/游戏使用动态顶点缓冲区。每一帧,它:
- 锁定顶点缓冲区
- 循环遍历网格并将顶点数据写入临时缓冲区(在程序启动时动态分配),直到它已满
- 将临时缓冲区的内容复制到顶点缓冲区
- 重复步骤 2 和 3,直到复制所有数据
- 解锁顶点缓冲区
我的问题是,需要临时缓冲区的部分吗?我不应该将顶点数据直接写入顶点缓冲区有什么原因吗?
我在官方文档中没有找到任何这种做法的证据,我对之前的程序员也不够信任。
免责声明:我不知道 DirectX 顶点缓冲区是如何工作的,我可能在这里错了。
它可能会更慢:分配一个顶点缓冲区以优化来自 GPU 的访问,即最好在 GPU 自己的内存中的某个地方。这意味着直接从 CPU 访问它比访问普通 RAM 慢得多。另一方面,复制整个数组可以相对较快地完成,因此最好在主内存中准备这样的数组并一次性将其复制到顶点缓冲区。
临时缓冲区不是必需的,但需要注意的是。
DirectX 动态顶点缓冲区针对GPU的读取访问和 CPU 的写入访问进行了优化。写访问优化称为写组合,它涉及与普通内存缓存不同的机制。假设您以 4/8/16 字节块并按顺序写入内存,CPU 将一起批量写入。
请注意,由驱动程序决定从动态缓冲区上的锁定中返回的内存类型,它可能不是写组合的,但这样处理是最好的选择。
写入组合内存没有缓存,因此从它读取是性能灾难。
它可以解释为什么您继承的游戏在读取和写入临时缓冲区时使用临时缓冲区,或者不努力按顺序写入组件 - 例如,首先是位置,然后是纹理坐标。
不需要临时缓冲区。Lock
从本质上讲,您返回的指针实际上已经是一个临时缓冲区。解锁缓冲区后,驱动程序才能真正开始对其进行任何有意义的操作。
如果您使用D3DLOCK_DISCARD
,则驱动程序没有义务使用任何敏感数据来尊重读取。所以执行完全可以返回malloc(size)
。
如果您不使用D3DLOCK_DISCARD
,那么,这确实是一个单独的问题。