我有以下工作代码,但是我不相信我是以安全的方式调用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*().