Posssible memory leak in OpenGL Intel Win7 drivers

Hi.

I have been experiencing a memory leak when using pixel buffer objects to update textures. The leak seems to only occur on certain platforms with certain operating systems, and so we began to suspect the leak is occurring inside the Intel HD Series Windows 7 driver. Below is a summary of our testing on different platforms.

Can anyone tell if I’m doing something wrong in the code, or if this is potentially a driver leak?

Series 4 Chipset (Lenovo SL300), Windows XP SP3: No Leak

Series 4 Chipset (Lenovo SL300), Windows 7: Leaks ~500 kB/min

Intel HD Series (Lenovo X1), Windows 7: Leaks ~500 kB/min

Intel HD 3000 (11" MacBook Air) Mac OS 10.7.3: No Leak

Nvidia Quadro NVS, Windows XP: No Leak

Here is a stripped down version of the code to reproduce this issue (VS2008 project at http://www.viionsystems.com/Intel_HD_Series_Win7_Leak_Test_Case.zip). Extensive testing of this code shows no memory leaks detectable by VS2008’s memory leak detector, yet GPU memory seems to grow indefinitely (according to ProcessExplorer).

I would appreciate any thoughts from the community on this issue.


#include <stdio.h>
#include <windows.h>
#include "GL\GLee.h"
#include "GL\freeglut.h"
 
unsigned int w = 640;
unsigned int h = 480;
unsigned int s = 4;
 
char* img = NULL;
char* texData1 = NULL;
char* texData2 = NULL;
char* mappedBuf = NULL;
 
GLuint pixelbufferHandle;
 
void timerCallback(int value);
void initializeTextureBuffer();
void mapAndCopyToBuffer(char* img1);
void paintGL();
void changeSize(int w, int h);

GLuint errorCode;
 
#define checkForGLError() \
    if ((errorCode = glGetError()) != GL_NO_ERROR) \
        printf("OpenGL error at %s line %i: %s", __FILE__, __LINE__-1, gluErrorString(errorCode) );


int main(int argc, char **argv)
{
    texData1 = new char[w * h * s];
    texData2 = new char[w * h * s];
    memset(texData1, 85, w * h * s);
    memset(texData2, 170, w * h * s);
 
    img = texData1;
 
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
 
    glutInitWindowPosition(300, 300);
    glutInitWindowSize(w, h);
    glutCreateWindow("Window");
    glutDisplayFunc(paintGL);
    glutReshapeFunc(changeSize);
 
    initializeTextureBuffer();

    timerCallback(0);

    glutMainLoop();
 
    glDeleteBuffers(1, &pixelbufferHandle);
    delete[] texData1;
    delete[] texData2;

    return 0;
}

void initializeTextureBuffer()
{
    glGenBuffers(1, &pixelbufferHandle);
    checkForGLError();
    glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pixelbufferHandle);
    checkForGLError();
 
    glBufferData(GL_PIXEL_UNPACK_BUFFER, w * h * s, 0, GL_DYNAMIC_DRAW);
 
    checkForGLError();
 
    // initialize and upload the texture
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, 0);
    checkForGLError();
 
    // Specify filtering and edge actions
 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP);
 
    img = (char*) glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY);

    if (img == NULL){
        return;
    }
 
    memset(img, 0, w * h * s);
    glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
}

void mapAndCopyToBuffer(char* img1)
{
    glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, pixelbufferHandle);
    mappedBuf = (char*) glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY);
    memcpy(mappedBuf, img1, w * h * s);
    glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
    mappedBuf = NULL;
 
    glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pixelbufferHandle);
 
    glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, 0);
}

void paintGL()
{
    if (img == texData1) img = texData2;
    else img = texData1; // swap images

    mapAndCopyToBuffer(img);

    glMatrixMode(GL_MODELVIEW);
    glPushMatrix();
 
    glDisable(GL_BLEND);
    glDepthMask(GL_FALSE);
    glDisable(GL_CULL_FACE);
    glDisable(GL_DEPTH_TEST);
    glEnable(GL_TEXTURE_2D);
    glEnable(GL_MULTISAMPLE);
 
    glBegin(GL_QUADS);
    {
        glTexCoord2f(0,0); glVertex3f(-1, 1, 0);
        glTexCoord2f(1,0); glVertex3f(1, 1, 0);
        glTexCoord2f(1,1); glVertex3f(1, -1, 0);
        glTexCoord2f(0,1); glVertex3f(-1, -1, 0);
    }
    glEnd();

    glMatrixMode(GL_MODELVIEW);
    glPopMatrix();
    glutSwapBuffers();
}

void changeSize(int w, int h)
{
    glViewport(0, 0, w, h);
}

void timerCallback(int value) 
{
    glutPostRedisplay();
    glutTimerFunc(5, timerCallback, 0);
}

This topic was automatically closed 183 days after the last reply. New replies are no longer allowed.