首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >glDeleteTextures,漏水?

glDeleteTextures,漏水?
EN

Stack Overflow用户
提问于 2010-02-20 10:17:47
回答 7查看 6.5K关注 0票数 0

我发现了glDeleteTexture的一种相当令人厌恶的行为,只删除部分内存(GPU侧,并且为了内存中的速度而将纹理保存回来),在我的例子中,这是一个显示错误,我的程序消耗了所有的内存。

我不想/要求你阅读所有的代码,这只是一个演示,我宁愿知道如何实际使用glDeleteTextures,这样它就可以使而不是泄漏任何内存。< code >E29

示例代码需要QT4.5或更高版本来编译:

glleak.pro

代码语言:javascript
复制
QT += opengl

SOURCES += main.cpp \
    glleak.cpp
HEADERS += glleak.h

main.cpp

代码语言:javascript
复制
#include <QtOpenGL>
#include <QtGui>
#include "glleak.h"

int main(int argc, char** argv){
    QApplication app(argc, argv);
    glleak gll(0);
    gll.show();
    return app.exec();
}

glleak.h

代码语言:javascript
复制
#ifndef GLLEAK_H
#define GLLEAK_H

#include <QGLWidget>
#include <QMouseEvent>
#include <QDebug>
#include <QList>

class glleak : public QGLWidget
{
    Q_OBJECT
public:
    glleak(QWidget* parent = 0);
    virtual ~glleak();
protected:
    void initializeGL();
    void paintGL();
    void resizeGL(int w, int h);
    void drawScene(GLenum mode);

    void wheelEvent(QWheelEvent* event);

    void hardcoreTexturing();
private:
    QList<GLuint> texels;

};

#endif // GLLEAK_H

glleak.cpp

代码语言:javascript
复制
glleak::glleak(QWidget* parent) :
        QGLWidget(parent)
{
}

glleak::~glleak()
{
}


void glleak::initializeGL(){
    glClearColor(0.0f,0.0f,0.0f,0.0f);
    glEnable(GL_TEXTURE_2D);
    glEnable(GL_MULTISAMPLE);
    glLineWidth (1.5f);
    glPointSize(4.5f);
    glEnable (GL_BLEND);
    glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}

void glleak::resizeGL(int w, int h){
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(-w/2.0, w/2.0, h/2.0, -h/2.0, -1.0, 1.0);
    glMatrixMode(GL_MODELVIEW);
    glViewport(0, 0, w, h);
    glLoadIdentity();
}

void glleak::paintGL(){
    glPushMatrix();
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glLoadIdentity();
    glColor3f(1.0f,1.0f,1.0f);
    drawScene(GL_RENDER);
    glPopMatrix();
}




void glleak::drawScene(GLenum mode){
    qDebug() << "drawed #" << texels.count() << " Textures";
    hardcoreTexturing();
}


void glleak::hardcoreTexturing(){
    glEnable(GL_TEXTURE_2D);
    for ( int i(0); i<texels.count(); ++i){
        glPushMatrix();
        glTranslatef(1.1f*i, 2.2f*i, 0.0f);
        glBindTexture(GL_TEXTURE_2D, texels.at(i));
        glBegin(GL_QUADS);
        {
            glTexCoord2i(0,0);
            glVertex2i(-128,-128);

            glTexCoord2i(0,1);
            glVertex2i(-128,128);

            glTexCoord2i(1,1);
            glVertex2i(128,128);

            glTexCoord2i(1,0);
            glVertex2i(128,-128);

        }
        glEnd();
        glPopMatrix();
    }
    glDisable(GL_TEXTURE_2D);
}


void glleak::wheelEvent(QWheelEvent* event){
    glEnable(GL_TEXTURE_2D);
    int n(50);
    if (event->delta()>0){
        qDebug() << "gen textures";
        for (int i(0); i<n; ++i){
            QImage t("./ballmer_peak.png","png");
            GLuint tex(0);
            glGenTextures(1, &tex);
            glBindTexture(GL_TEXTURE_2D, tex);
            glTexImage2D( GL_TEXTURE_2D, 0, 3, t.width(), t.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, t.bits() );
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
            glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
            texels.append(tex);
        }
    }
    else{
        qDebug() << "del textures";
        for (QList<GLuint>::iterator i(texels.begin()); i!=texels.end();){
            glDeleteTextures(1, &(*i));
            i = texels.erase(i);
            if (--n <= 0)
                break;


        }
    }
    glDisable(GL_TEXTURE_2D);
        updateGL();
}

ballmer_peak.png要加载和呈现的图像

注意:编译演示:只需将所有内容都放在一个文件夹中,将图像重命名为ballmer_peak.png,调用qmake,make,./ generate:演示用法:使用鼠标轮一次生成或删除50个纹理

如果我使用glDeleteTextures完全错误,请告诉我如何使用它。由于我的用法符合官方的OpenGL glDeleteTextures用法,所以我的想法已经过时了。

EN

回答 7

Stack Overflow用户

发布于 2011-04-14 03:06:59

这可能是也可能不是您泄漏的原因,但首先您错误地使用了glGenTextures。

1)不应将其放入初始化纹理的for循环中。您需要将其放在循环之前,并调用它一次,第一个参数是所需的纹理数。假设n == 50:

glGenTextures(50,&tex);

2) tex应该是n个GLuints的静态数组,并且应该持久化(而不是像您拥有的那样是一个自动变量!)在glDeleteTextures再次被调用之前,不要在循环中调用:

glDeleteTextures(50,&tex);

可以将tex看作存储纹理ids的存储库。对于绑定纹理,使用它而不是像您所做的那样使用单独的QList是很重要的,因为(如OpenGL引用中所指定的),不能保证纹理ids将是一个连续的整数集。我应该设想,您的泄漏发生在内部,因为OpenGL丢失了指向用于生成每个纹理的本地(自动)变量的原始指针,因此纹理内存成为孤儿。

希望这能有所帮助!

票数 1
EN

Stack Overflow用户

发布于 2011-05-25 12:44:47

我没有运行您的示例代码,但是在Windows7 7-64位上也有类似的情况。使用每个纹理的glGenTextures()和glDeleteTextures(),它可能会泄漏内存,但我看到线程的句柄计数增加了(例如,在TaskManager中,但我也可以从源代码中检查)。glDeleteTextures()似乎没有释放句柄。也许它以后会这么做,但24小时的测试表明它从未释放过句柄。似乎是驱动程序内部的漏洞(nVidia GTX285,驱动程序270.61)。实际上,这个程序最终耗尽了内存。我开始觉得这是司机的问题..。

票数 1
EN

Stack Overflow用户

发布于 2010-02-20 14:55:43

在您的代码中没有什么问题。所以..。你凭什么认为你有记忆泄露?是什么让你认为是纹理--特别是纹理--泄露的?

您使用的OpenGL实现可能(但极不可能)泄漏。这将是具体的执行情况。

不管您使用什么机制来查看内存泄漏,一旦释放了OpenGL上下文,会发生什么?

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2301813

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档