【问题标题】:OpenGL (ES 2.0 but not specific to ES): is GL_STATIC_DRAW meant for use with glBufferData?OpenGL(ES 2.0,但不特定于 ES):GL_STATIC_DRAW 是否意味着与 glBufferData 一起使用?
【发布时间】:2013-09-05 13:33:48
【问题描述】:

我现在关心的应用程序是一个 3d 模型查看器。用户偶尔会加载一个大的新网格进行渲染,并且应该(必须)丢弃旧的网格。

因此,GL_STATIC_DRAW 显然是 VBO 的正确提示。

此时我有点不确定是 glDeleteBuffers() 我的 VBO 和 IBO,还有 glDeleteVertexArrays[OES]() 我的 VAO,或者什么都不做,只是 glBufferData() 我新加载的 VBO 和 IBO网格无需删除和重新生成任何内容重新定义glVertexAttribPointer VAO 状态。 (子问题:如果我只删除我的 VBO 然后重新生成它,但我的 VAO 保持不变,我还能跳过glVertexAttribPointer()吗?)

如果我调用glBufferData() 时OpenGL 确实会丢弃VBO 中的先前数据,那么这是完美的。据我所知,glBufferData() 应该重新分配 VBO。

但实际上,我正在寻找的是一个具体的解释,说明我重新加载到这个洋葱的不同层之间会有什么不同,以及如果我只想改变我需要走多远我在应用程序中的顶点和索引缓冲区内容(原始几何图形),或者是否存在可能需要重新生成或删除 VBO 的情况。我确实看到相同的 VBO 可能在不同的 VAO 集之间有用地共享,我可以想象这样一种情况,你有一些你永远不会再使用的 VAO,所以你会释放它们,但看起来像 VBO如果存在供您重新分配其中包含的数据的 API,则可以继续回收。

我发现那里的所有教程和解释都只涉及帮助您进行设置,但现在我已经了解了那个阶段,不太清楚如何正确处理其余这些细节。

【问题讨论】:

  • VAO 没有显着的开销,将它们视为轻量级状态块。它们不负责实际的数据存储(VBO 会这样做),它们会持续保存绘制一个或多个 VBO 所需的状态。现在,如果您将 VAO 保留在不再存在的参考 VBO 周围,它们可能会成为一个问题,但防止这种情况发生的重担实际上落在您的肩上,而不是 OpenGL 的肩上。我很少删除 VAO,如果不再需要它,它会进入一个未使用的 VAO 池以供重复使用,这将 OpenGL 名称的动态分配保持在最低限度;也适用于其他类型的对象。
  • 啊哈。因此,您对待 VAO 的方式与我打算对待我的 VBO 的方式相同。作为将不断重复使用的资源池中的句柄。

标签: opengl opengl-es


【解决方案1】:

我不确定您为什么认为删除顶点 array 对象会对 buffer 对象的内容产生任何影响。删除 FBO 不会影响附加到它的纹理或渲染缓冲区的存储,删除 VAO 也不会影响附加到它的任何缓冲区对象的存储。

就标准而言,你可以为所欲为。提示是提示;你不需要关注他们。

就 AMD 而言,您仍然可以为所欲为。原因在于,由于人们不了解提示的工作原理,人们已经做了任何他们喜欢的事情,以至于 AMD 几乎完全忽略提示。它会观察你对缓冲区对象的使用模式并移动它,直到你弄清楚你打算如何实际使用它。

NVIDIA 实际上很在意这些提示,并让您坚持下去。在某种程度上,提示定义明确,足以让你坚持下去。如果您使用错误的提示,您将永远降低性能。而 AMD 最终会弄清楚你真正是什么意思。

在任何情况下,如果您想真正做到这一点,GL_STATIC_DRAW 的意思是“您将只上传一次到此缓冲区对象”。现在,这应该如何与缓冲区对象的重新分配相协调,这取决于您。

但是,如果您想猜测 ARB 的意见,请考虑the recent ARB_buffer_storage 4.4 feature。在那里,他们明确地不允许完全重新分配缓冲区对象的存储空间(不管提示如何)。您可以将其视为“提示”,即重新分配存储(在using glBufferData to invalidate an existing buffer 之外)是一个坏主意,无论您使用何种使用提示。

此外,从 buffer_storage 中,GL_STATIC_DRAW 的“等效”禁止您从客户端存储上传到它。一旦它在那里,您可以从其他缓冲区复制到它,或将其用作 in-GL 进程的其他目的地。但是你不能改变它的内容。你只能删除它。

我认为GL_STATIC_DRAW 的意思是“删除,不要重新分配或重新上传到”。

现在这对 OpenGL ES 意味着什么,我无法理解。这取决于不同的实现如何实现其缓冲区的存储(这就是为什么询问桌面 GL 和 GL ES 实现的行为是错误的)。然而,考虑到移动 GPU 通常没有两个独立的内存池,我想他们真的不在乎。当然,实现可以将内存分配为未缓存或其他方式以更快地访问它或其他方式。但除此之外,它可能并不重要。

【讨论】:

  • 太好了,感谢您引用了只有您的才能知道的事情。 ;) 我想如果我只使用 GL_DYNAMIC_DRAW 就可以了,看看我是否不能让glBufferData 工作。
  • 我想说的是,如果“the”缓冲区的内容很少更改,GL_DYNAMIC_DRAW 可能不是您真正想要的(这意味着您最终会对内容进行更改) .删除缓冲区并分配一个新缓冲区并以 GL_STATIC_DRAW 方式加载数据对于模型查看器来说听起来更合理,因为缓冲区中包含的数据只有在加载新模型时才会更改。
  • @StevenLu:我同意 Datenwolf 的观点。删除缓冲区更符合此处的使用场景。特别是因为您将分配一个任意大小的新缓冲区。
猜你喜欢
  • 2012-05-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-14
  • 2012-02-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多