为什么要为动态对象使用顶点缓冲区对象?

Why use Vertex Buffer Objects for dynamic objects?

不确定 DX 对这些的说法是什么,但我确定他们有类似的概念。

据我所知,VBO 的优势在于它们分配的内存可由 GPU 直接使用。然后我们可以将数据上传到这个缓冲区,并在其中保存更多的帧,从而避免每帧上传数据的所有开销。此外,如果我们愿意,我们可以在每个数据的基础上更改此数据。

因此,我可以看到将 VBO 用于静态地理的优势,但我看不到对动态对象有任何好处 - 因为您几乎每帧都必须更新所有数据?

在 OpenGL 中有几种更新缓冲区的方法。如果您有动态数据,您可以简单地使用新数据(例如 glBufferData)每帧重新初始化缓冲区存储。您还可以在兼容性上下文中使用客户端顶点缓冲区指针。但是,这些方法会导致 'churn' 在内存分配中出现 driver。新的数据存储本质上必须位于系统内存中,直到 GPU driver 处理它,并且不可能获得有关此过程的反馈。

在后来的 OpenGL 版本(4.4,以及通过早期版本的扩展)中,引入了一些功能来尝试减少更新动态缓冲区的开销,从而允许在不直接写入 GPU 分配的内存的情况下 driver同步。这基本上要求您具有可用的 glBufferStorage and glMapBufferRange 功能。您使用 GL_DYNAMIC_STORAGE_BIT 创建缓冲区存储,然后使用 GL_MAP_PERSISTENT_BIT 映射它(您可能需要其他标志,具体取决于您是否正在读取 and/or 写入数据)。但是,此技术还要求您使用 GPU 防护以确保您不会在 GPU 读取数据时覆盖数据。使用此方法使更新 VBO 比重新初始化数据存储或使用客户端缓冲区更有效。

GDC Vault 上有关于此技术的很好的介绍(跳至 DynamicStreaming 标题)。

AFAIK,通过创建动态顶点缓冲区,您给图形适配器驱动程序一个提示,将顶点缓冲区放置在内存中,这对于 CPU 来说写入速度很快,但对于 GPU 读取它也相当快。驱动程序通常会通过提供非重叠内存区域来管理它以最大限度地减少 GPU 停顿,以便 CPU 可以在 GPU 读取其他内存区域时写入。

如果您不给出提示,则假定为静态资源,因此它将被放置在内存中,GPU read/write 速度很快,但 CPU 写入速度非常慢。