2 回答
不是嗡嗡声,而是容器对象,例如顶点数组对象,使这个讨论变得非常复杂。
通常,当您删除缓冲区对象时,会发生两件让内存被回收的关键事情:
- 它的名称 (
GLuint
ID) 立即释放以供重用 - 对象未绑定当前活动的上下文
有一个隐藏的警告需要注意:
- 直到在任何上下文中都没有对对象的剩余引用,才真正释放数据存储。
当您删除绑定到顶点数组对象的顶点缓冲区对象并且该顶点数组对象当前未绑定时,项目符号点 2 中讨论的行为不会发生。发生的情况是名称被释放,但 VAO 继续引用名称(现在无效)和数据存储(继续存在)。在删除此顶点数组对象或更改绑定以使其不再引用原始缓冲区对象之前,不会回收缓冲区对象的内存。
对于以上更权威的解释,我建议你阅读OpenGL 4.4 core spec的Section 5.1.2和Section 5.1.3。我将在下面列出两者最相关的部分。
5.1.2 已删除对象的自动解除绑定
当缓冲区、纹理或渲染缓冲区对象被删除时,它与当前上下文中绑定到的任何绑定点解除绑定,并与绑定到当前上下文的容器对象的任何附件分离,如 DeleteBuffers、DeleteTextures 所述, 和 DeleteRenderbuffers。如果对象绑定是与其他相关状态建立的(例如 BindBufferRange 中的缓冲区范围或 FramebufferTexture 或 BindImageTexture 中选择的级别和层信息),则该状态不受自动取消绑定的影响。其他上下文中的绑定点不受影响。未绑定容器对象的附件,例如删除附加到未绑定到上下文的顶点数组对象的缓冲区,不受影响,并继续充当已删除对象的引用,如下节所述。
5.1.3 已删除对象和对象名称生命周期
[...] GL不会回收支持已删除对象的底层存储,直到从容器对象连接点、上下文绑定点或视图中对该对象的所有引用都被删除。
注意:此行为适用于 OpenGL 中的所有容器对象,在消除对资源的所有引用之前,不会回收内存。从长远来看,熟悉删除引用的必要条件(参见:5.1.2)将对您有好处。
glDeleteBuffers
标记选定的缓冲区以进行删除和解除分配,一旦 OpenGL 的任何部分在内部不再需要缓冲区的数据,这就会完成。对于所有实际glDeleteBuffers
的方法,释放缓冲区。