我正在研究一個多線程應用程序,它可以將幾何體同時渲染到多個FBO。我遇到泄漏(如this question中所述)。如何完全取消綁定GL_ELEMENT_ARRAY_BUFFER?
我已經能夠縮小它 - 如果我做了一個改變,它不會泄漏 - 但我不明白爲什麼。
在每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無法在上下文之間共享。
編輯︰我修改我的應用程序提供零大小的緩衝區數據之前扔緩衝池回池,但它仍然泄漏一樣快。
你可以解釋/顯示'throwElementArrayBufferBackInPool(...)'是如何實現的嗎? VAO是容器對象,如果你刪除一個綁定到一個緩衝對象(實際上是VAO追蹤的唯一緩衝對象綁定是**元素**緩衝區,頂點指針工作方式不同),而VAO本身不活動,那麼直到VAO對它的引用被刪除,緩衝區對象才被完全刪除。如果VAO在刪除元素緩衝區時處於活動狀態,則它會自動解除綁定。這*可能*在這種情況下是相關的,但我需要看到實施。 –
您可以通過調用'glBufferData(...)'來調用大小,並保留一組保留但空的緩衝區名稱以供重用,而不是刪除緩衝區對象,從而可以解決所有這些問題。這將立即釋放數據存儲(相對而言),而不必等待所有上下文和容器對象的所有引用都被刪除。 –
@ AndonM.Coleman:池只是C++ std :: vector的簡單線程封裝。我剛剛在這裏發佈了一個源摘錄:https://gist.github.com/smokris/7711889 – smokris