直接写入顶点缓冲区

3
我继承的DirectX 9应用程序/游戏使用动态顶点缓冲区。每一帧,它:
  1. 锁定顶点缓冲区
  2. 循环遍历网格,并将顶点数据写入临时缓冲区(在程序启动时动态分配),直到缓冲区已满
  3. 将临时缓冲区的内容复制到顶点缓冲区
  4. 重复步骤2和3,直到所有数据都被复制
  5. 解锁顶点缓冲区
我的问题是,临时缓冲区的部分是否必要?我不能在官方文档中找到此做法的证据,并且我不信任之前的程序员。是否有理由不直接将顶点数据写入顶点缓冲区?

我认为你直接写入顶点缓冲区会很好... - Nathan Monteleone
虽然我认为,如果锁定的顶点缓存直接映射到GPU上(参见leftaroundabout的答案),它的性能可能不如意。 - Nathan Monteleone
3个回答

2

免责声明: 我不知道DirectX顶点缓冲区是如何工作的,我的理解可能有误。

这样做可能会更慢:顶点缓冲区被分配用于优化GPU访问,即最好在GPU自己的存储器中。这意味着直接从CPU访问它比访问普通RAM要慢得多。另一方面,可以相对快速地复制整个数组,所以最好在主存中准备这样一个数组,并一次性将其复制到顶点缓冲区中。


我有点怀疑从LockVertexBuffer返回的指针是否直接寻址到GPU内存。我认为它将在由驱动程序管理的主内存中,一旦您解锁顶点缓冲区,它就可以自由地将其DMA到显卡上。不幸的是,我也不是Direct3D专家 - 这就是OpenGL的工作方式。 - Nathan Monteleone
是的,这很有道理。我只知道CUDA中的GPU编程,可以直接访问设备内存,但在非硬件特定的图形库中可能不是这样工作的。 - leftaroundabout
2
无论如何,如果没有Direct3D专家来拯救这一天,我认为他应该对其进行基准测试并观察结果 :) - Nathan Monteleone

2
临时缓冲区不是必需的,但有一个重要说明。
DirectX动态顶点缓冲区针对GPU的读取和CPU的写入进行了优化。写入访问的优化称为“写组合”,它涉及与普通内存缓存不同的机制。给定你按顺序以4/8/16字节块写入内存,CPU将批量地将写入操作结合在一起。
请注意,由驱动程序决定从动态缓冲区锁定返回何种类型的内存,可能不是写组合,但将其视为写组合是最佳选择。
写组合内存未被缓存,因此从中读取会导致性能问题。
如果游戏既读取又写入临时缓冲区,或者不按顺序写入组件 -例如首先是位置,然后是纹理坐标- 这可能是解释该游戏为什么使用临时缓冲区的原因。

0

临时缓冲区是不必要的。从Lock返回的指针实际上已经是一个临时缓冲区。驱动程序只有在解锁缓冲区后才能开始对其进行任何有意义的操作。

如果使用D3DLOCK_DISCARD,那么驱动程序没有义务使用任何合理的数据来读取。因此,实现可以完全返回malloc(size)

如果您使用D3DLOCK_DISCARD,那么这实际上是一个单独的问题。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接