英文:
OpenGL best practice regarding VBO updating when VAO are required
问题
我之前在团队中制作了一个引擎,其中一位工程师建议我使用两个顶点缓冲区并交换它们。这是链接:https://www.khronos.org/opengl/wiki/GLAPI/glBufferSubData
其中提到:
在替换整个数据存储时,考虑使用glBufferSubData而不是使用glBufferData完全重新创建数据存储。这避免了重新分配数据存储的成本。
考虑使用多个缓冲对象以避免在数据存储更新期间阻塞渲染流水线。如果流水线中的任何渲染引用由glBufferSubData更新的缓冲对象中的数据,特别是来自正在更新的特定区域的数据,那么在可以更新数据存储之前,必须从流水线中排出该渲染。
因此,当时我们创建了两个VBO(顶点缓冲对象),用glBufferData为它们设置了大小,然后每帧我们会“交换”使用哪个VBO(以避免使用glBufferSubData时的同步减速),通过绑定另一个VBO,使用glBufferSubData更新数据,然后绘制。
关于在OpenGL中是否最佳实践,我找不到任何信息,也不确定是使用一个VBO并在每帧使用glBufferData还是使用两个VBO。
我还在想,在GL 3.3核心要求声明VAO的情况下,对于这两个缓冲区,是更好声明两个VAO并在它们之间切换,还是只声明一个VAO并在其中切换VBO。
英文:
I made an engine in a team a while back and one of the engineer told me to use 2 vertex buffers and swap them, giving me this link :
https://www.khronos.org/opengl/wiki/GLAPI/glBufferSubData
Where it says :
>When replacing the entire data store, consider using glBufferSubData rather than completely recreating the data store with glBufferData. This avoids the cost of reallocating the data store.
>Consider using multiple buffer objects to avoid stalling the rendering pipeline during data store updates. If any rendering in the pipeline makes reference to data in the buffer object being updated by glBufferSubData, especially from the specific region being updated, that rendering must drain from the pipeline before the data store can be updated.
So back then we instanced 2 VBOs, gave them a size with glBufferData and then every frame we would "swap" which of the two VBOs was used (to avoid getting the synchronization slow down that comes with glBufferSubData) by binding the other one, using glBufferSubData on it to update the data and then drawing.
I can't find information anywhere as if this is a best practice using OpenGL or if it would be better to just use 1 VBO and use glBufferData every frame instead.
I was also wondering, with GL 3.3 core requiring to declare a VAO, in the case of the 2 buffers would it be better to declare 2 VAOs as well and just swap between them or would it be better to only make 1 VAO and swap between the VBOs in this single VAO?
答案1
得分: 1
我建议学习OpenGL维基关于这个主题的内容:
流式传输
<sub>主要文章: 缓冲对象流式传输</sub>
流式传输是频繁将数据上传到缓冲对象,然后在某个OpenGL过程中使用该缓冲对象的过程。
...
流式传输的关键在于并行性。OpenGL规范允许实现延迟执行绘图命令。这使您可以绘制大量内容,然后让OpenGL在自己的时间内处理事务。因此,很有可能在您使用缓冲对象调用渲染函数之后,您可能会尝试将顶点数据流式传输到该缓冲对象。如果发生这种情况,OpenGL规范要求线程等待,直到与您的缓冲对象更新可能受影响的所有绘图命令完成。这显然忽略了流式传输的全部意义。
有效流式传输的关键在于同步。
有关VBO和VAO的更多信息可以在这里找到:顶点规范,特别是顶点缓冲对象和顶点数组对象。
您可能还会发现这些信息有用:顶点规范最佳实践(动态VBO - 这可能是您问题的实际答案)。
英文:
I would recommend to study the OpenGL wiki on that topic:
Streaming<br>
<sub>Main article: Buffer Object Streaming</sub>
> Streaming is the process of frequently uploading data to a buffer object and then using that buffer object in some OpenGL process.
>
> ...
>
> The key to streaming is parallelism. The OpenGL specification permits an implementation to delay the execution of drawing commands. This allows you to draw a lot of stuff, and then let OpenGL handle things on its own time. Because of this, it is entirely possible that well after you called the rendering function with a buffer object, you might start trying to stream vertex data into that buffer. If this happens, the OpenGL specification requires that the thread halt until all drawing commands that could be affected by your update of the buffer object complete. This obviously misses the whole point of streaming.
>
> The key to effective streaming is synchronization.
More info related to VBO's and VAO's can be found here: Vertex Specification, especially Vertex Buffer Object and Vertex Array Object.
You may also find this info useful: Vertex Specification Best Practices (Dynamic VBO - which could be the actual answer to your question).
> Another thing you can do is double buffered VBO. This means you make 2 VBOs. On frame N, you update VBO 2 and you render with VBO 1. On frame N+1, you update VBO 1 and you render from VBO 2.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论