如何完全取消绑定GL_ELEMENT_ARRAY_BUFFER? [英] How to fully unbind a GL_ELEMENT_ARRAY_BUFFER?

查看:177
本文介绍了如何完全取消绑定GL_ELEMENT_ARRAY_BUFFER?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在研究一个多线程应用程序,它可以同时将几何图形渲染到多个FBO。我遇到了泄漏(如此问题所述)。



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



开每一个线程(每个线程都有自己的共享上下文),我在做每个渲染周期的下列代码:

  //上传

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);



//渲染(可能位于不同的上下文中)

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);



//清理(可能位于不同的上下文中)

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); //为什么如果我们回收它会泄漏?
glDeleteBuffers(1,& elementBuffer);

如果我交换最后2行 - 如果我将元素缓冲区放回池中而不是删除它每个渲染周期 - OpenGL驱动监视器表明一个巨大的泄漏。

但我更喜欢将它集中,因为调用 glDeleteBuffers() code>每一帧都很慢。



我错过了什么?我假设我无法从某些东西中解除 elementBuffer 的作用,并且某些东西持续引用它,导致泄漏 - 但我无法弄清楚是什么。




编辑:刚刚在另一个系统上测试过(Mac OS 10.6)如果我回收任何缓冲区,它就会泄漏。
$ b 编辑:我修改了我的应用程序,使 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 使用创建一个独立的缓冲区名称池,并确保您始终如一地使用它。


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.

解决方案

Your buffer pool is used for binding GL_ARRAY_BUFFER as well as GL_ELEMENT_ARRAY_BUFFER objects. Worse, you're first using elementBuffer for binding a GL_ARRAY_BUFFER, but then carry on using it for an GL_ELEMENT_ARRAY_BUFFER. I haven't fully wrapped my head around it, but somewhere between mixing the namespaces and the inconsistent use of bindings I'd put my money on that.

My suggestion: Create a separate pool of buffer names for GL_ELEMENT_ARRAY_BUFFER use and make sure you're using it consistently for only that.

这篇关于如何完全取消绑定GL_ELEMENT_ARRAY_BUFFER?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆