OpenGL 帧缓冲区附件泄漏 GPU 内存

OpenGL framebuffer attachments leak GPU memory

考虑以下 test code

for (int i = 0; i < 100; ++i) {
    GLuint fboid = 0;
    GLuint colortex = 0;
    GLuint depthtex = 0;

    // create framebuffer & textures
    glGenFramebuffers(1, &fboid);
    glGenTextures(1, &colortex);
    glGenTextures(1, &depthtex);

    glBindTexture(GL_TEXTURE_2D, colortex);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 4000, 4000, 0, GL_BGRA, GL_UNSIGNED_BYTE, 0);

    glBindTexture(GL_TEXTURE_2D, depthtex);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, 4000, 4000, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, 0);

    glBindFramebuffer(GL_FRAMEBUFFER, fboid);
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colortex, 0);
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, depthtex, 0);

    assert(GL_FRAMEBUFFER_COMPLETE == glCheckFramebufferStatus(GL_FRAMEBUFFER));

    // clear it
    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);

    // delete everything
    glBindFramebuffer(GL_FRAMEBUFFER, 0);
    glBindTexture(GL_TEXTURE_2D, 0);

    glDeleteFramebuffers(1, &fboid);
    glDeleteTextures(1, &colortex);
    glDeleteTextures(1, &depthtex);
}

// put breakpoint here

您会在 activity 监视器中看到底部的 "Memory used" 变得很高 (14 GB)。就好像 GPU 还在引用已经发布的纹理。

我尝试了以下方法:

None 其中有任何效果。 但是 (!) 如果我删除 glClear() 调用,问题就会消失。

这可能是什么原因造成的?它在 Windows 上也是可谴责的 ,并且 与另一个实现(不幸的是我无法分享并且无论如何要复杂得多)。

你们见过这样的内存泄漏问题吗?

更新:现在很明显,depth/stencil 缓冲区正在泄漏。如果我创建一个仅深度附件,那么问题又消失了!

更新:使用英特尔卡更容易重现。在我 2011 年底的 mbpro 上,代码在独立卡 (Radeon 6750M) 上运行正常,但在集成卡 (HD 3000) 上会产生所描述的泄漏。

更新:已在 High Sierra (10.13.x)

上修复

虽然我没有找到任何合适的解决方案,但我想出了一个解决方法 (不幸的是,这给 Radeon Pro 580 (?) 卡带来了不同的泄漏问题)

解决方法如下:

  • 首先,我启用 GL 上下文共享
  • 然后每当我想删除 D24S8 纹理时,我都会将它放入缓存中
  • 如果实现请求创建 D24S8 缓冲区,我首先查看缓存(不要忘记,MSAA 样本计数必须匹配!)
  • 如果缓存中有合适的项目(>=比请求的大小),然后我把它拿出来,return它
  • 如果没有,我会根据要求的大小创建一个

通过这个解决方案,我设法最大限度地减少了上述配置的泄漏...aaaaaaa 并在 AMD 卡上搞砸了(我想这是另一种驱动程序错误,但现在我可以'不要用小程序重现)。