Как управлять памятью с текстурой в opengl?

В моем приложении я широко использую glTexImage2D. Я копирую изображение изображения и визуализирую его как текстуру, я делаю это часто при каждом щелчке мыши. Я даю его как массив байтов для рендеринга. Память съедается, и память памяти также выделяется. Это утечка памяти? или это связано с тем, что glTexImage2D содержит любые ссылки или что-то еще.

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

Я надеюсь, что ваши закрытые запросы и голосование по-прежнему прекратятся!

Ответы

Ответ 1

Предполагая, что вы генерируете новую текстуру с glGenTextures каждый раз, когда вы вызываете glTexImage2D, вы теряете память и просачиваете ее, если не отслеживаете все текстуры, которые вы генерируете. glTexImage2D принимает входные данные и сохраняет их в памяти видеокарты. Имя текстуры, которое вы связываете перед вызовом glTexImage2D - тот, который вы создаете с помощью glGenTextures, является дескриптором этого фрагмента памяти видеокарты.

Если ваша текстура большая, и вы выделяете новую память для хранения все большего количества ее копий каждый раз, когда вы ее используете, тогда вы быстро исчерпаете память. Решение состоит в том, чтобы вызвать glTexImage2D один раз во время инициализации вашего приложения и вызвать только glBindTexture, когда вы хотите его использовать. Если вы хотите изменить саму текстуру при нажатии, вызовите только glBindTexture и glTexImage2D. Если ваше новое изображение имеет тот же размер, что и предыдущее изображение, вы можете вызвать glTexSubImage2D, чтобы сообщить OpenGL о замене старых данных изображения вместо его удаления и загрузки нового.

UPDATE

В ответ на ваш новый код я обновляю свой ответ с более конкретным ответом. Вы имеете дело с текстурами OpenGL не так. Результат glGenTextures - это GLuint[], а не String или char[]. Для каждой текстуры, сгенерированной с помощью glGenTextures, OpenGL возвращает вам текстуру в дескриптор (как целое число без знака). Этот дескриптор сохраняет состояние, которое вы передаете ему с помощью glTexParameteri, а также блок памяти на графической карте, если вы передадите данные с помощью glTexImage[1/2/3]D. Вам нужно сохранить дескриптор и отправить его новые данные, когда вы хотите его обновить. Если вы перезапишите дескриптор или забыли об этом, данные все равно остаются на графической карте, но вы не можете получить к нему доступ. Вы также сообщаете OpenGL генерировать 3 текстуры, когда вам нужно только 1.

Увидев, что texture_data имеет фиксированный размер, вы можете обновить текстуру glTexSubImage2D вместо glTexImage2D. Вот ваш код изменен, чтобы избежать утечки памяти из этой проблемы:

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