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

Fra*_*cis 6 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);
Run Code Online (Sandbox Code Playgroud)

在解除VAO绑定后,我正在调用glDeleteBuffers.我已经尝试在标记的替代位置调用它 - 在我设置属性指针后立即调用它.然而这引起了崩溃 - 我的猜测是因为当我进行绘制调用时没有绘制数据因为我删除了它.

令我困惑的是,它的工作方式与我目前的工作方式相同.我担心a)我不太清楚当缓冲区被删除时会发生什么,以及b)它只是偶然发生并且可能意外地中断.

据我所知,调用glDeleteBuffers会删除数据,因此不应该绘制任何数据 - 但是有.所以我的另一个想法是当我重新绑定VAO时数据被恢复,虽然这对我没有多大意义,因为我无法推断数据将从何处恢复.

如果我正确使用glDeleteBuffer,有人可以告诉我吗?如果不是应该调用的地方(我猜测一旦不再需要绘制数据,可能在程序结束时).

Ret*_*adi 14

你所看到的是明确定义的行为.以下是与此相关的规范的关键部分(强调添加).

从OpenGL 4.5规范中的"5.1.2自动解除删除对象的绑定"部分:

当一个缓冲器,纹理或渲染对象被删除,这是从它被绑定到在当前上下文中的任何绑定点未结合的,并从被绑定到当前上下文容器对象的任何附件分离,作为用于DeleteBuffers,DeleteTextures描述和DeleteRenderbuffers.

和"5.1.3删除的对象和对象名称生命周期":

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

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

该对象附加到任何容器对象

...

在这种情况下,VAO被认为是VBO的"容器对象".因此,只要在VAO中引用VBO,并且不删除VAO本身,VBO就会保持活动状态.这就是为什么你的代码版本与glDeleteBuffers()最终的工作原理.

但是,如果VAO当前已绑定,并且您删除了VBO,则它将自动从VAO中解除绑定.因此,它不再被VAO引用,而是立即删除.这适用于您glDeleteBuffers()之后立即致电的情况glVertexAttribPointer().

在任何情况下,id(aka名称)立即变为无效.因此,您将无法再次绑定它,例如修改数据.

如果你更深入地研究规格,有一些警告.例如,如果删除缓冲区,并且它仍处于活动状态,因为它仍然由VAO引用,则缓冲区的名称可用于新缓冲区.这意味着您基本上有两个具有相同名称的缓冲区,这可能会导致一些令人困惑的行为.

部分由于这个原因,我个人不会要求glDelete*()您继续使用的对象.但其他人喜欢尽快打电话glDelete*().

  • 我刚刚调试完与此相关的图形代码问题。Windows 上的各种 AMD 卡上没有绘制任何内容,但在其他所有平台上(Nvidia、Intel gfx、Mac/Linux 上的 AMD 等)都运行良好。我在解除 VAO 绑定后删除了缓冲区,就像这个答案所说应该有效,但我尝试删除删除调用,它解决了问题。不确定我是否做错了什么,或者是否是驱动程序错误,但我想我会在这里记录,以防其他人偶然发现此页面出现类似问题。 (2认同)