2012-06-26 14 views
14

En mi aplicación estoy usando extensivamente glTexImage2D. Copio una imagen de una imagen y la represento como una textura, lo hago con frecuencia con cada clic del mouse. Lo doy como una matriz de bytes para renderizar. La memoria está siendo consumida y la memoria de intercambio también está asignada. ¿Es una pérdida de memoria? o es debido al hecho de que glTexImage2D contiene referencias o cualquier otra cosa.cómo administrar la memoria con textura en OpenGL?

Editar:

//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); 

espero sus peticiones y abajo cerca de votación detendría ahora!

+2

El código real sería útil para rastrear este problema. –

+0

@NicolBolas, he puesto el código, gracias por mencionar +1 – Shan

Respuesta

40

Suponiendo que está generando una nueva textura con glGenTextures cada vez que llama al glTexImage2D, está desperdiciando memoria y filtrándola si no realiza un seguimiento de todas las texturas que genera. glTexImage2D toma los datos de entrada y los almacena en la memoria de la tarjeta de video. El nombre de textura que enlaza antes de llamar al glTexImage2D - el que genera con glGenTextures es un identificador para ese trozo de memoria de la tarjeta de video.

Si su textura es grande y está asignando memoria nueva para almacenar más y más copias de la misma cada vez que la usa, entonces rápidamente se quedará sin memoria. La solución es llamar al glTexImage2D una vez durante la inicialización de su aplicación y solo llame al glBindTexture cuando desee usarlo. Si desea cambiar la textura al hacer clic, solo llame al glBindTexture y glTexImage2D. Si su nueva imagen es del mismo tamaño que la imagen anterior, puede llamar al glTexSubImage2D para decirle a OpenGL que sobrescriba los datos de imágenes anteriores en lugar de eliminarlos y cargarlos.

ACTUALIZACIÓN

En respuesta a su nuevo código, estoy actualizando mi respuesta con una respuesta más concreta. Está tratando con texturas OpenGL por completo. La salida de glGenTextures es GLuint[] y no String o char[]. Para cada textura que genere con glGenTextures, OpenGL le devuelve un identificador (como un entero sin signo) a una textura. Este identificador almacena el estado que usted le da con glTexParameteri y también un trozo de memoria en la tarjeta gráfica si le da datos con glTexImage[1/2/3]D. Depende de usted almacenar el identificador y enviarle nuevos datos cuando desee actualizarlo. Si sobrescribe el controlador o se olvida de él, la información permanece en la tarjeta gráfica, pero no puede acceder a ella. También está diciendo OpenGL para generar texturas 3 cuando sólo se necesita 1.

Viendo como texture_data es de un tamaño fijo, puede actualizar la textura con glTexSubImage2D en lugar de glTexImage2D. Aquí está su código modificado para evitar la pérdida de memoria de este problema:

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); 
+0

Muchas gracias, he publicado el código, para que pueda ver que utilizo la misma memoria simplemente cambie los contenidos y siempre haga lo mismo. Entonces, según su sugerencia en el fragmento de código anterior, solo necesito llamar a "glGenTextures" una vez y luego siempre llamar a glBindTexture y glTexImage2D. Evitará la pérdida de memoria. ¿Estoy en lo correcto? – Shan

+1

@Shan actualicé mi respuesta con código y (con suerte) suficiente explicación para que usted entienda de dónde viene la fuga dentro de su código y cómo solucionarlo. También use el manual de OpenGL en el futuro, es muy útil para explicar exactamente qué métodos OpenGL hace: http://www.opengl.org/sdk/docs/man/xhtml/glGenTextures.xml –

+0

muchas gracias, ¡Excelente respuesta!, de hecho, he actualizado el código, estaba en mal estado, el tipo es GLuint para texname. Solo una consulta, tengo más de una texturas, ¿cómo glTexSubImage2D sabría cuál estoy actualizando? o se debe a la llamada a glBindTexture. – Shan