Jump to content

  • Log In with Google      Sign In   
  • Create Account


mshafey

Member Since 14 Feb 2012
Offline Last Active Private

#4913017 Posssible memory leak in OpenGL Intel Win7 drivers

Posted by mshafey on 14 February 2012 - 10:53 AM

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.viionsyst...k_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);
}



PARTNERS