opengl - 我什么时候应该调用glDeleteBuffers()?

标签 opengl

我有以下工作代码,但是我不相信我正在以安全的方式调用 glDeleteBuffers。在实践中它是有效的(至少现在是这样),但从我读过的内容来看,我认为它不应该有效。

GLuint vao_id;
glGenVertexArrays(1, &vao_id);
glBindVertexArray(vao_id);

GLuint VBO;
glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, size, data, GL_STATIC_DRAW);

glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
glEnableVertexAttribArray(0);

    //Alternate position <<----

//Unbind the VAO
glBindVertexArray(0);

//Current position <<----
glDeleteBuffers(1, &VBO);

我目前在解除 VAO 绑定(bind)后立即调用 glDeleteBuffers。我尝试在设置属性指针后立即在标记为 - 的替代位置调用它。然而,这导致了崩溃 - 我猜测这是因为当我进行绘制调用时没有可绘制的数据,因为我删除了它。

令我困惑的是它的工作原理与我目前的情况相同。我担心 a) 我不太明白删除缓冲区时会发生什么,b) 它只是偶然工作并且可能会意外中断。

据我了解,调用 glDeleteBuffers 会删除数据,因此不应该有任何数据可供绘制 - 但确实有。所以我的另一个想法是,当我重新绑定(bind) VAO 时,数据会被恢复,尽管这对我来说没有多大意义,因为我无法推断数据将从哪里恢复。

有人可以告诉我我是否正确使用了 glDeleteBuffer 吗?如果不是应该在哪里调用它(我猜一旦不需要再绘制数据,可能在程序结束时)。

最佳答案

您所看到的是明确定义的行为。以下是与此相关的规范的关键部分(已添加重点)。

摘自 OpenGL 4.5 规范中的“5.1.2 自动解除已删除对象的绑定(bind)”部分:

When a buffer, texture, or renderbuffer object is deleted, it is unbound from any bind points it is bound to in the current context, and detached from any attachments of container objects that are bound to the current context, as described for DeleteBuffers, DeleteTextures, and DeleteRenderbuffers.

和“5.1.3 已删除对象和对象名称生命周期”:

When a buffer, texture, sampler, renderbuffer, query, or sync object is deleted, its name immediately becomes invalid (e.g. is marked unused), but the underlying object will not be deleted until it is no longer in use.

A buffer, texture, sampler, or renderbuffer object is in use if any of the following conditions are satisfied:

the object is attached to any container object

...

在这种情况下,VAO 被视为 VBO 的“容器对象”。因此,只要 VBO 在 VAO 中被引用,并且 VAO 本身没有被删除,VBO 就会保持事件状态。这就是为什么您的代码版本在末尾带有 glDeleteBuffers() 有效。

但是,如果当前已绑定(bind) VAO,并且您删除了 VBO,则它会自动与 VAO 解除绑定(bind)。因此,它不再被VAO引用,并立即删除。这适用于在 glVertexAttribPointer() 之后立即调用 glDeleteBuffers() 的情况。

在任何情况下,ID(又名名称)都会立即失效。所以你将无法再次绑定(bind)它,例如修改数据。

如果您更深入地研究规范,会有一些警告。例如,如果您删除一个缓冲区,并且它由于仍被 VAO 引用而保持事件状态,则该缓冲区的名称可用于新缓冲区。这意味着您基本上有两个同名的缓冲区,这可能会导致一些令人困惑的行为。

部分出于这个原因,我个人不会为您想要继续使用的对象调用 glDelete*()。但其他人喜欢尽快调用 glDelete*()

关于opengl - 我什么时候应该调用glDeleteBuffers()?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27937285/

相关文章:

c++ - GLSL编译失败,没有错误日志

c++ - 游戏引擎与物理引擎与几何建模内核之间的区别

java - GLSL 结构统一位置返回 -1

opengl - 变换表面法向量和切向量

c++ - OpenGL 可以处理哪些纹理尺寸

c++ - 如何在 glRotatef 中使用 glm::mat4

c++ - glBlendFunc() 的负色?

c - 当我更改 Z 坐标 (OpenGL) 时,对象不显示?

c++ - 将 QT5 与 glLoadGen 结合使用

java - OpenGL画一颗星星