flgrx driver eats a large amount of memory when the same texture is mapped many times

Discussion created by dephlector on Nov 9, 2011


I have an another problem with the fglrx driver. When doing simple things like showing a single texture, the driver eats a large amount of memory - somewhere between 300MB and 900MB. I think the memory is allocated from the kernel module, because the process shows small amount of memory used, but the free memory of the system decreases. I can see in /proc/meminfo that the "HighFree:" field decreases when I run the sample program. The decrease is relatively slow, at around 10MB/sec.

I am attaching the sample program so that it is seen exactly what I am doing. The program requires a parameter that tells it how many lines from the image to transfer at once. I noticed, that when the texture is loaded in smaller chunks (800kB or so) the problem dissapears. Only when I load the texture with chunks of 1MB or more the problem is seen.

In other words if the program is run with parameter 200 - no problem. If the parameter is 300 or more the problem appears.

Can someone point me if I am doing something wrong or if there is a bug in the driver? And is there a workaround in this situation?



My hardware:

AMD Athlon Neo dual core 1.5GHz

Video card: ATI RADEON E4690

Memory: 3GB of RAM


Software configuration:

Debian Squeeze with linux 2.6.32 (32bit)

Ati catalyst driver 11.8

X.Org X Server 1.7.7

KDE 4.4.5



Regards, Kalin



//compile with g++ -o mvplayer -lGL `sdl-config --libs` `sdl-config --cflags` -lSDL_image mvplayer.cpp #include <GL/glu.h> #include <string> #include <iostream> #include "SDL.h" #include <signal.h> #include "SDL_image.h" #include <cstdlib> #include <cmath> using namespace std; static unsigned int MainLoopSleepTime = 15000; void quitplayer(){ SDL_Quit(); exit(0); } void sighandler(int sig) { quitplayer(); } int main(int argc, char *argv[]) { if (argc < 2) { printf("mmoooo!\n"); exit(-1); } const int dy0 = atoi(argv[1]); signal(SIGABRT, sighandler); signal(SIGTERM, sighandler); signal(SIGINT, sighandler); unsigned int nScreenWidth = 1280; unsigned int nScreenHeight = 1024; SDL_Init( SDL_INIT_EVERYTHING ); // glClear(GL_COLOR_BUFFER_BIT); // SDL_GL_SwapBuffers(); // glClear(GL_COLOR_BUFFER_BIT); if (!( SDL_WasInit(SDL_INIT_VIDEO) & SDL_INIT_VIDEO)){ return 1; } SDL_GL_SetAttribute( SDL_GL_RED_SIZE, 8 ); SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, 8 ); SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, 8 ); SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, 24 ); SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 ); SDL_Surface* screen = SDL_SetVideoMode(nScreenWidth, nScreenHeight, 24, SDL_OPENGL); if ( screen == NULL ){ fprintf(stderr, "Couldn't set GL mode: %s", SDL_GetError()); SDL_Quit(); return 1; } glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0, nScreenWidth, nScreenHeight, 0, 0, -10000); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glEnable(GL_TEXTURE_2D); glClearDepth(1.0f); glDepthFunc(GL_LEQUAL); glAlphaFunc(GL_GREATER,0.1f); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_DEPTH_TEST); glClearColor(0, 0, 0, 1); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); SDL_Surface* image[4]; image[0] = IMG_Load_RW(SDL_RWFromFile("Untitled-1_02.png", "rb"), 1); // image[1] = IMG_Load_RW(SDL_RWFromFile("Untitled-1_02.png", "rb"), 1); // image[2] = IMG_Load_RW(SDL_RWFromFile("Untitled-1_02.png", "rb"), 1); // image[3] = IMG_Load_RW(SDL_RWFromFile("Untitled-1_02.png", "rb"), 1); GLuint arrGlTexIds[100]; srand(time(NULL)); glGenTextures( 1, arrGlTexIds ); glBindTexture(GL_TEXTURE_2D, arrGlTexIds[0]); glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, image[0]->w, image[0]->h, 0, GL_RGB, GL_UNSIGNED_BYTE, image[0]->pixels); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER, GL_NEAREST); int sz = 3 * image[0]->w * dy0; printf("--> max transfer: %d %.3f MiB\n", sz, sz / pow(2.0,20)); while(1) { // SDL_PumpEvents(); glBindTexture(GL_TEXTURE_2D, arrGlTexIds[0]); for (int i=0; ; i++) { int dy = dy0; int y = dy0 * i; if ((y + dy) > image[0]->h) dy = image[0]->h - y; glTexSubImage2D(GL_TEXTURE_2D, 0, 0, y, image[0]->w, dy, GL_RGB, GL_UNSIGNED_BYTE, image[0]->pixels + 3*(image[0]->w * y)); if ( y + dy >= image[0]->h ) break; } glBegin(GL_QUADS); glTexCoord2d(0.0,0.0); glVertex2i(0, 0); glTexCoord2d(1.0,0.0); glVertex2i(0 + image[0]->w, 0); glTexCoord2d(1.0,1.0); glVertex2i(0 + image[0]->w, 0 + image[0]->h); glTexCoord2d(0.0,1.0); glVertex2i(0, 0 + image[0]->h); glEnd(); SDL_GL_SwapBuffers(); usleep(10000); } }