如何完全解除GL_ELEMENT_ARRAY_BUFFER的绑定



我正在开发一个多线程应用程序,该应用程序可以同时向多个FBO渲染几何图形。我遇到了泄漏(如本问题所述)。

我已经能够把它缩小一点——如果我做一个改变,它就会停止泄漏——但我不明白为什么。

在4个线程中的每一个线程上(每个线程都有自己的共享上下文),我在每个渲染循环中执行以下操作:

// Upload
positionBuffer = getUnusedArrayBufferFromPool();
glBindBuffer(GL_ARRAY_BUFFER, positionBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(float)*4*vertexCount, positions, GL_STREAM_DRAW);
{
    GLuint vertexArray;
    glGenVertexArrays(1, &vertexArray);
    glBindVertexArray(vertexArray);
    elementBuffer = getUnusedElementArrayBufferFromPool();
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementBuffer);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned int)*elementCount, elements, GL_STREAM_DRAW);
    glBindVertexArray(0);
    glDeleteVertexArrays(1, &vertexArray);
}
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);

// Render (possibly on a different context)
GLuint vertexArray;
glGenVertexArrays(1, &vertexArray);
glBindVertexArray(vertexArray);
glUseProgram(programName);
{
    GLint positionAttribute = glGetAttribLocation(programName, "position");
    glBindBuffer(GL_ARRAY_BUFFER, positionBuffer);
    glVertexAttribPointer((GLuint)positionAttribute, 4 /* XYZW */, GL_FLOAT, GL_FALSE, sizeof(float)*4, (void*)0);
    glEnableVertexAttribArray((GLuint)positionAttribute);
    {
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementBuffer);
        glDrawElements(GL_TRIANGLES, (GLsizei)elementCount, GL_UNSIGNED_INT, (void*)0);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
    }
    glDisableVertexAttribArray((GLuint)positionAttribute);
    glBindBuffer(GL_ARRAY_BUFFER, 0);
}
glUseProgram(0);
glBindVertexArray(0);
glDeleteVertexArrays(1, &vertexArray);

// Cleanup (possibly on a different context)
glBindBuffer(GL_ARRAY_BUFFER, positionBuffer);
glBufferData(GL_ARRAY_BUFFER, 0, 0, GL_STREAM_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
throwArrayBufferBackInPool(positionBuffer);
//glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementBuffer);
//glBufferData(GL_ELEMENT_ARRAY_BUFFER, 0, 0, GL_STREAM_DRAW);
//glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
//throwElementArrayBufferBackInPool(elementBuffer); // Why does this leak if we recycle it?
glDeleteBuffers(1, &elementBuffer);

如果我交换最后两行——如果我将元素缓冲区扔回池中,而不是在每个渲染周期将其删除——OpenGL驱动程序监视器会指示一个巨大的泄漏。

但我更愿意将其池化,因为每帧调用glDeleteBuffers()确实很慢。

我错过了什么?我假设我未能将elementBuffer从某个东西中解除绑定,并且某个东西保留了对它的引用,导致了泄漏,但我不知道是什么。


编辑:刚刚在另一个系统(Mac OS 10.6)上进行了测试——在该系统上,如果我回收任何缓冲区,它就会泄漏。

编辑:我修改了我的应用程序,使GL_ARRAY_BUFFERGL_ELEMENT_ARRAY_BUFFER分离,并使elementBuffer始终绑定到GL_ELEMENT_ARRAY_BUFFER。但如果我throwElementArrayBufferBackInPool(elementBuffer);

编辑:阐明了我为什么在上传和渲染期间创建和删除VAO——因为它们可能发生在不同的共享GL上下文中,并且VAO不能在上下文之间共享。

编辑:在将缓冲区重新放入池中之前,我修改了应用程序以提供零大小的缓冲区数据,但它仍然很快泄漏。

缓冲池用于绑定GL_ARRAY_BUFFER以及GL_ELEMENT_ARRAY_buffer对象。更糟糕的是,首先使用elementBuffer绑定GL_ARRAY_BUFFER,然后继续使用它绑定GL_ELEMENT_ARRAY_BUFFER。我还没有完全理解它,但在混合名称空间和不一致使用绑定之间,我会把钱花在这上面。

我的建议是:创建一个单独的缓冲区名称池供GL_ELEMENT_ARRAY_BUFFER使用,并确保您仅为此使用它。

相关内容

  • 没有找到相关文章

最新更新