我正在开发一个多线程应用程序,该应用程序可以同时向多个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_BUFFER
与GL_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
使用,并确保您仅为此使用它。