绑定到“顶点数组对象”后,我应该删除“顶点缓冲区对象”吗?

Posted

技术标签:

【中文标题】绑定到“顶点数组对象”后,我应该删除“顶点缓冲区对象”吗?【英文标题】:Should I delete `Vertex Buffer Object` after binding it to `Vertex Array Objects`? 【发布时间】:2017-01-07 11:08:17 【问题描述】:

我创建了一个 VBO(顶点缓冲区对象)和 VAO(顶点数组对象)并这样做了:

glBindVertexArray(vao);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(...);
glVertexAttribPointer(...);
glEnableVertexAttribArray(0);
glBindVertexArray(0);

我可以在我这样做之后删除vbo,然后假设一切正常,然后使用vao 进行绘制吗?

我知道缓冲区绑定到vao,所以我假设我可以。

问题是,如果我删除计算机(Intel 显卡)上的缓冲区,效果会很好(一切都正确显示),但在我的朋友计算机 (AMD) 上没有任何显示。

这可能是什么问题?

(顺便说一句,如果我不删除缓冲区,该程序在我的计算机和我朋友的计算机上都可以运行)

【问题讨论】:

【参考方案1】:

是的,根据 OpenGL 4.5,在解除绑定 VAO 后删除它是合法的

2.6.1.2 名称删除和对象删除

如果一个对象在 GL 上下文当前正在使用时被删除,它的名称 立即标记为未使用,某些类型的对象会自动 从当前上下文中的绑定点未绑定,如第 5.1.2 节所述。 但是,实际的底层对象在不再使用之前不会被删除。 这种情况在 5.1.3 节中有更详细的讨论。

5.1.2 已删除对象的自动解除绑定

当缓冲区、纹理或渲染缓冲区对象被删除时,它与任何 它在当前上下文中绑定的绑定点,并与任何附件分离 绑定到当前上下文的容器对象的数量,如 DeleteBuffers、DeleteTextures 和 DeleteRenderbuffers 所述。 [...] 未绑定容器的附件 对象,例如删除附加到顶点数组对象的缓冲区,该对象不是 绑定到上下文,不受影响并继续作为参考 删除的对象,如下节所述。

5.1.3 已删除对象和对象名称生存期

当缓冲区、纹理、采样器、渲染缓冲区、查询或同步对象被删除时,其 名称立即变为无效(例如标记为未使用),但基础 对象在不再使用之前不会被删除

如果满足以下任一条件,则缓冲区、纹理、采样器或渲染缓冲区对象正在使用中:

对象附加到任何容器对象 [...]

所以要么是 AMD 驱动程序错误,要么情况与您描述的不一样。

【讨论】:

@JohnMiz:你是说 AMD 吗?它要么是 AMD 错误,要么是您未显示的代码中的错误。我也根据 OpenGL 4.5 规范回答,因为你没有说你使用哪个版本。可能会发生在旧版本上它应该表现不同或未定义。欢迎您自己检查规格,它们是免费提供的并且非常易于阅读。 @JohnMiz:应该注意的是,仅仅因为某事是“合法的”并不意味着它是一个好主意。不要删除对象,除非您处理完它们 @NicolBolas:我对此提出质疑。保持那些你不再要修改的对象的提升时间的额外认知负担是一个坏主意。 OpenGL 规范已经暗示了引用计数其对象的实现,因此这是我们可以依赖的特性。删除一个对象,明确说明“从现在开始,我将把它交给司机负责”,这是我经常做的事情,并建议其他人去做。当然,我个人有权选择我正在使用的供应商和 OpenGL 版本。 @JohnMiz:这是不同实现之间的代码风格和可移植性问题。它与显存无关。如果您要构建游戏引擎,那么您可能需要解决用户将使用的不同驱动程序中的错误,在这种情况下,您不应在删除 VAO 之前删除缓冲区,正如 Nicol 所说。 @ybungalobill:还有一个事实是,如果您想迁移到 Vulkan,当您执行删除对象之类的操作时,您不能依靠驱动程序来拯救您。在这样的 API 中,删除意味着 gone,就在此时此地。最好训练自己现在承担“认知负担”,而不是在需要时不承担。

以上是关于绑定到“顶点数组对象”后,我应该删除“顶点缓冲区对象”吗?的主要内容,如果未能解决你的问题,请参考以下文章

如何获取当前绑定的顶点数组对象?

顶点数组对象是上下文的一部分吗?

OpenGL 顶点数组对象是存储顶点缓冲区名称和索引,还是只存储索引?

初识OpenGL (-)VAO顶点数组对象

初识OpenGL (-)VAO顶点数组对象

初识OpenGL (-)VAO顶点数组对象