不确定DX的说法是什么,但我相信他们有类似的概念。
据我所知,VBO 的优势在于它们分配了 GPU 直接可用的内存。然后,我们可以将数据上传到此缓冲区,并将其保留更长的帧数,从而避免每帧上传数据的所有开销。此外,如果我们愿意,我们可以按基准面更改此数据。
因此,我可以看到将 VBO 用于静态地理的优势,但我看不到动态对象的任何好处 - 因为无论如何您几乎都必须每帧更新所有数据?
有几种方法可以在OpenGL中更新缓冲区。如果您有动态数据,则可以简单地使用新数据(例如,使用glBufferData)在每一帧重新初始化缓冲区存储。还可以在兼容性上下文中使用客户端顶点缓冲区指针。但是,这些方法可能会导致驱动程序的内存分配"改动"。新的数据存储基本上必须位于系统内存中,直到 GPU 驱动程序处理它,并且无法获得有关此过程的反馈。
在更高版本的 OpenGL 版本(4.4 和早期版本中的 via 扩展)中,引入了一些功能来尝试减少更新动态缓冲区的开销,允许在不直接驱动程序同步的情况下写入 GPU 分配的内存。这实质上要求您具有可用的 glBufferStorage 和 glMapBufferRange 功能。使用 GL_DYNAMIC_STORAGE_BIT
创建缓冲区存储,然后用 GL_MAP_PERSISTENT_BIT
映射它(您可能需要其他标志,具体取决于您是在读取和/或写入数据)。但是,此技术还要求您使用 GPU 屏蔽来确保在 GPU 读取数据时不会覆盖数据。使用此方法使更新 VBO 比重新初始化数据存储或使用客户端缓冲区更有效。
GDC Vault 上有一个关于此技术的良好演示(跳到 DynamicStreaming 标题)。
> AFAIK,通过创建动态顶点缓冲区,您为图形适配器驱动程序提供了一个提示,以将顶点缓冲区放置在内存中,这对于 CPU 写入速度很快,但对于 GPU 读取它的速度也相当快。驱动程序通常会通过提供不重叠的内存区域来管理它以最大限度地减少 GPU 停滞,以便 CPU 可以在 GPU 读取其他内存区域时写入。
如果你不给出提示,它假设是一个静态资源,所以它将被放置在内存中,这对于 GPU 读/写来说速度很快,但对于 CPU 来说写入速度非常慢。