I'm working on a multithreaded app that simultaneously renders geometry to multiple FBOs. I'm experiencing a leak (as described on this question).
I've been able to narrow it down a little — if I make one change, it stops leaking — but I can't figure out why.
On each of 4 threads (each with its own shared context), I'm doing the following each render cycle:
// 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);
If I swap the last 2 lines — if I throw the element buffer back into the pool instead of deleting it each render cycle — OpenGL Driver Monitor indicates a huge leak.
But I'd prefer to pool it, since calling glDeleteBuffers()
each frame is really slow.
What am I missing? I assume I'm failing to unbind elementBuffer
from something — and that something is holding on to a reference to it, causing the leak — but I can't figure out what.
Edit: Just tested on a different system (Mac OS 10.6) — on that system, it leaks if I recycle any buffers.
Edit: I modified my application so that GL_ARRAY_BUFFER
is pooled separately from GL_ELEMENT_ARRAY_BUFFER
, and so that elementBuffer
is consistently bound to GL_ELEMENT_ARRAY_BUFFER
. But it still leaks if I throwElementArrayBufferBackInPool(elementBuffer);
.
Edit: Clarified why I'm creating and deleting a VAO during Upload and during Rendering — because they might happen on different shared GL contexts, and VAOs can't be shared between contexts.
Edit: I modified my application to provide zero-size buffer data before throwing the buffers back into the pool, but it still leaks just as quickly.