加载着色器后清除内存

Posted

技术标签:

【中文标题】加载着色器后清除内存【英文标题】:Clearing memory after loading shaders 【发布时间】:2014-05-06 13:56:41 【问题描述】:

虽然我执行了建议的步骤,但还是出现了内存泄漏。我加载和删除着色器如下:

glCreateShader
glShaderSource
glCompileShader
glAttachShader
glLinkProgram
glUseProgram
glDetachShader
glDeleteShader
glUseProgram(0);
glDeleteProgram

glLingProgram() 在我循环执行所有这些步骤时似乎会导致泄漏。下面是我的测试代码。你能帮我找出问题吗? (代码基于http://opengl-tutorial.org/上的教程)。

编辑:我认为这只发生在顶点着色器包含attribute 类型时。

for (int i = 0; i < 1000; i++) 
    GLuint VertexShaderID = glCreateShader(GL_VERTEX_SHADER);
    GLuint FragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);

    std::string VertexShaderCode;
    std::ifstream VertexShaderStream("VertexShader.vs", std::ios::in);
    if(VertexShaderStream.is_open()) 
        std::string Line = "";
        while(getline(VertexShaderStream, Line))
            VertexShaderCode += "\n" + Line;
        VertexShaderStream.close();
    
    else 
        printf("Cannot open vertex shader!");
        getchar();
        return 0;
    

    std::string FragmentShaderCode;
    std::ifstream FragmentShaderStream("FragmentShader.fs", std::ios::in);
    if(FragmentShaderStream.is_open()) 
        std::string Line = "";
        while(getline(FragmentShaderStream, Line)) 
            FragmentShaderCode += "\n" + Line;
        
        FragmentShaderStream.close();
    
    else 
        printf("Cannot open fragment shader!");
        getchar();
        return 0;
    

    char const * VertexSourcePointer = VertexShaderCode.c_str();
    glShaderSource(VertexShaderID, 1, &VertexSourcePointer , NULL);
    glCompileShader(VertexShaderID);

    char const * FragmentSourcePointer = FragmentShaderCode.c_str();
    glShaderSource(FragmentShaderID, 1, &FragmentSourcePointer , NULL);
    glCompileShader(FragmentShaderID);

    GLuint ProgramID = glCreateProgram();

    glAttachShader(ProgramID, VertexShaderID);
    glAttachShader(ProgramID, FragmentShaderID);

    glLinkProgram(ProgramID);

    glUseProgram(ProgramID);

    glDetachShader(ProgramID, VertexShaderID);
    glDetachShader(ProgramID, FragmentShaderID);

    glDeleteShader(VertexShaderID);
    glDeleteShader(FragmentShaderID);

    glUseProgram(0);

    glDeleteProgram(ProgramID);

【问题讨论】:

您是如何识别内存泄漏的? @R.MartinhoFernandes 运行此代码(仅添加创建 GLFW 窗口并启动 GLEW)会导致快速泄漏,我从系统监控工具中观察到这一点。只需几秒钟即可达到千兆字节。 @R.MartinhoFernandes 我发现如果顶点着色器包含attribute 类型,则会出现此问题。 这听起来像是驱动程序中的一个错误:(您可以在具有不同图形适配器(最好来自不同制造商)的机器上尝试吗? gist.github.com/anonymous/32d33f0f4ec0ce0eab95 【参考方案1】:

您应该只在开始时加载着色器。只有 glUseProgram 打算在渲染循环中使用。

使用着色器的标准模板是这样的:

glCreateProgram
glCreateShader
glShaderSource
glCompileShader
glAttachShader
glLinkProgram <- after this line opengl got everything it needs, 
                 you can free shader resources
glDetachShader
glDeleteShader

for//render loop
   glUseProgram
   //...drawing operations
   glUseProgram(0);


glDeleteProgram

【讨论】:

以上是关于加载着色器后清除内存的主要内容,如果未能解决你的问题,请参考以下文章

着色器破坏相机

着色器存储缓冲区中的 OpenGL 顶点

OpenGlES:如何加载着色器代码

[2D凹凸映射-Monogame

OpenGL 着色器加载失败

c_cpp 一个加载着色器文件,编译和链接到着色器程序的函数。