Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to manage memory with texture in opengl?

Tags:

In my application I am using extensively glTexImage2D. I copy some image of an image and render it as a texture, I do it frequently at every mouse click. I give it as a byte array for rendering. The memory is being eaten up and the swap memory is also allocated. Is it a memory leak? or is it due to the fact that glTexImage2D holds any references or anything else.

Edit:

    //I allocate the memory once     GLuint texName;     texture_data = new GLubyte[width*height];      // Each time user click I repeat the following code (this code in in callback)     // Before this code the texture_data is modified to reflect the changes     glGenTextures(3, &texname);     glBindTexture(GL_TEXTURE_2D, texname);     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_MAG_FILTER, GL_NEAREST);     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE,texture_data); 

I hope your close requests and down voting would stop now!

like image 220
Shan Avatar asked Jun 26 '12 22:06

Shan


People also ask

How are textures stored in memory?

There are three kinds of storage for textures: mutable storage, immutable storage, and buffer storage. Only Buffer Textures can use buffer storage, where the texture gets its storage from a Buffer Object. And similarly, buffer textures cannot use mutable or immutable storage.

How do textures work in OpenGL?

A texture is an OpenGL Object that contains one or more images that all have the same image format. A texture can be used in two ways: it can be the source of a texture access from a Shader, or it can be used as a render target.

What is texture buffer?

A Buffer Texture is a one-dimensional Texture whose storage comes from a Buffer Object. They are used to allow a shader to access a large table of memory that is managed by a buffer object.

How do you change textures in OpenGL?

To replace texture data, just bind the texture and call glTexImage2D with the new data. bindTexture, at least the opengl one, just binds a texture name to a specific target, GL_TEXTURE_2D here. It does not delete or replace anything, just put a particular texture in use.


1 Answers

Assuming you're generating a new texture with glGenTextures every time you call glTexImage2D, you are wasting memory, and leaking it if you don't keep track of all the textures you generate. glTexImage2D takes the input data and stores it video card memory. The texture name that you bind before calling glTexImage2D - the one you generate with glGenTextures is a handle to that chunk of video card memory.

If your texture is large and you're allocating new memory to store more and more copies of it every time you use it, then you will quickly run out of memory. The solution is to call glTexImage2D once during your application's initialization and only call glBindTexture when you want to use it. If you want to change the texture itself when you click, only call glBindTexture and glTexImage2D. If your new image is the same size as the previous image, you can call glTexSubImage2D to tell OpenGL to overwrite the old image data instead of deleting it and uploading the new one.

UPDATE

In response to your new code, I'm updating my answer with a more specific answer. You're dealing with OpenGL textures in the wrong way entirely The output of glGenTextures is a GLuint[] and not a String or char[]. For every texture you generate with glGenTextures, OpenGL gives you back a handle (as an unsigned integer) to a texture. This handle stores the state you give it with glTexParameteri as well a chunk of memory on the graphics card if you give it data with glTexImage[1/2/3]D. It's up to you to store the handle and send it new data when you want to update it. If you overwrite the handle or forget about it, the data still stays on the graphics card but you can't access it. You're also telling OpenGL to generate 3 textures when you only need 1.

Seeing as texture_data is of a fixed size, you can update the texture with glTexSubImage2D instead of glTexImage2D. Here is your code modified to avoid the memory leak from this issue:

texture_data = new GLubyte[width*height](); GLuint texname; //handle to a texture glGenTextures(1, &texname); //Gen a new texture and store the handle in texname  //These settings stick with the texture that's bound. You only need to set them //once. glBindTexture(GL_TEXTURE_2D, texname); 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_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);  //allocate memory on the graphics card for the texture. It's fine if //texture_data doesn't have any data in it, the texture will just appear black //until you update it. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB,     GL_UNSIGNED_BYTE, texture_data);  ...  //bind the texture again when you want to update it. glBindTexture(GL_TEXTURE_2D, texname); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, 0, GL_RGB,     GL_UNSIGNED_BYTE, texture_data);  ...  //When you're done using the texture, delete it. This will set texname to 0 and //delete all of the graphics card memory associated with the texture. If you //don't call this method, the texture will stay in graphics card memory until you //close the application. glDeleteTextures(1, &texname); 
like image 78
Robert Rouhani Avatar answered Sep 17 '22 13:09

Robert Rouhani