Я работаю над многопоточным приложением, которое одновременно отображает геометрию для нескольких 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);
Если я поменяю местами последние 2 строки — если я верну буфер элемента обратно в пул вместо того, чтобы удалять его в каждом цикле рендеринга — OpenGL Driver Monitor укажет на огромную утечку.
Но я бы предпочел объединить его, так как вызов 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_ELEMENT_ARRAY_BUFFER
. Но все равно протекает, если яthrowElementArrayBufferBackInPool(elementBuffer);
. 28.11.2013