在draw调用中使用glDisable(GL_TEXTURE_2D)时内存泄漏



我注意到我的程序中有一个小内存泄漏,我终于能够找到这个问题。

我正在做的是通过调用以下函数在屏幕上绘制5个矩形:

bool OpenGlEntity::fillRect(SDL_Rect rect, float R, float G, float B, float A){
glPushMatrix();
    glDisable(GL_TEXTURE_2D);
    GLfloat vertices_position[] = {
    (GLfloat)rect.x, (GLfloat)rect.y,
    (GLfloat)(rect.x+rect.w), (GLfloat)rect.y,
    (GLfloat)(rect.x+rect.w), (GLfloat)(rect.y+rect.h),
    (GLfloat)rect.x, (GLfloat)(rect.y+rect.h),
    };
    glTranslatef(0, 0, 0);
    //scale
    glScalef(1,1,1);
    //set color
    glColor4f(R, G, B, A);
    glEnableClientState(GL_VERTEX_ARRAY);
    glVertexPointer(2, GL_FLOAT, 0, vertices_position);
    glLockArraysEXT(0, 4);
    glDrawArrays(GL_QUADS, 0, 4);
    glUnlockArraysEXT();
    glDisableClientState(GL_VERTEX_ARRAY);
    glEnable(GL_TEXTURE_2D);
    //reset color
    glColor4f(1.f, 1.f, 1.f, 1.f);
glPopMatrix();
return true;}

如果我从未运行过"glDisable(GL_TEXTURE_2D);"(或"glEnable(GL_TEXTURE_2D);"),则不会发生泄漏。为什么会这样?

对我来说,这没有任何意义,但话说回来,我在OpenGL渲染方面没有那么丰富的经验。

启用或禁用特定状态会导致内存"泄漏"的原因有很多。例如,如果对纹理启用三线性过滤,而纹理没有mipmap数据,则驱动程序通常会为mipmap链/金字塔分配内存(无论是否生成实际的mipmap级别)。仅仅因为更改了纹理过滤器状态,这将导致约33%的内存消耗增长。

顺便说一句,draw调用并不是内存增加的真正来源。Draw调用通常是驱动程序提交排队命令的一个点。这就是为什么您不能对调用glEnable(…)或glDisable(…)的持续时间进行计时,并获得更改该状态的开销。智能驱动程序将运行最后一次绘图调用和当前调用之间的所有状态更改请求,这是大多数状态设置真正发生的时候。因此,在您的情况下,驱动程序可能会推迟一些纹理设置操作,直到第一次绑定并启用纹理单元和/或对象。因此,当您发出绘制调用时,驱动程序会在其执行的任务清单中为纹理分配内存。

评测一个应用程序是很诱人的,看看glDraw(…)似乎是你的瓶颈,并假设你是顶点绑定的,但在许多情况下,这与事实相去甚远:)这只是你需要更多专门构建的工具和API来有效调试、跟踪内存资源分配和评测使用GPU的应用程序的众多原因之一。

无论如何,你所经历的很可能是正常行为,驱动程序必须在多个位置(CPU、GPU等)分配内存,以处理"设备丢失"等事件。如果"泄漏"是一次性发生的,你可以忽略它,并将其归因于驱动程序内存管理。

最新更新