本文介绍了glDeleteTextures,泄漏了吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我发现glDeleteTexture的行为很令人反感,它只删除了部分可取的内存(GPU端,并且为了在RAM中提高速度而将纹理保存回去),在我看来,这是一个严重的错误,程序被吞噬了占用所有内存.

I found a rather disguting behaviour of glDeleteTexture, deleteing only parts of the aqcuired memory (GPU side and as Textures get saved back for the sake of speed in RAM), which in my case, is a showstopper bug, my program eating up all memory.

我不希望/要求您阅读所有代码,这只是一个演示,我想知道如何实际使用glDeleteTextures,这样它不会泄漏而不泄漏. >任何内存.

I don't want/require you to read all of the code, it's just a demo, I'd rather know how to actually use glDeleteTextures so it does not leak any memory.

示例代码要求Qt 4.5或更高版本进行编译:

The example code requires Qt 4.5 or later to compile:

glleak.pro

QT += opengl

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

main.cpp

#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

#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

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.pngA Image to load and render

注意:编译演示:只需将它们全部放在一个文件夹中,将图像重命名为 ballmer_peak.png ,调用qmake,make,./glleak注意: 演示用法:使用鼠标滚轮一次生成或删除50个纹理

Note: Compile demo: Just put it all in a folder, rename your image to ballmer_peak.png, call qmake, make, ./glleakNote: Demo usage: Use mousewheel to generate or delete 50 Textures at once

如果我完全错误地使用glDeleteTextures,请告诉我如何使用它.由于我的用法符合官方OpenGL glDeleteTextures 使用情况.

If I use glDeleteTextures completly wrong, please tell me how to use it.I am way out of ideas as my usage complies to the official OpenGL glDeleteTextures usage.

推荐答案

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

I did not run your example code, but I get a similar thing on Windows7-64bits. Using per-texture glGenTextures() and glDeleteTextures(), it might leak memory, but I'm seeing my thread's handle count increase (in TaskManager for example, but I can also check it from the source).It seems glDeleteTextures() does not release a handle. Perhaps it'd do it later on, but 24-hour tests indicate it never releases the handle. Seems like a leak inside the driver (nVidia GTX285, driver 270.61).Eventually indeed the program runs out of memory. I'm beginning to think it's a driver issue...

这篇关于glDeleteTextures,泄漏了吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-24 20:44