3

我最近发现 glDrawArrays 在每一帧上分配和释放大量内存。我怀疑它与 openGL 分析器报告的“在初始化之外编译的着色器”问题有关。这发生在每一帧!它应该只有一次,并且在着色器编译后消失吗?

编辑:我还仔细检查了我的顶点是否正确对齐。所以我真的很困惑内存驱动程序需要在每一帧上分配什么。

编辑#2:我正在使用 VBO 和退化的三角形条来渲染精灵和 . 我在每一帧(GL_STREAM_DRAW)上传递几何图形。

在此处输入图像描述

编辑#3:

我想我已经接近问题但仍然无法解决它。如果我将相同的纹理 id 值传递给着色器,问题就会消失(参见源代码注释)。不知何故,这个问题与我认为的片段着色器有关。

在我的精灵批次中,我有精灵列表,并通过纹理 ID 和 FIFO 队列渲染它们。

这是我的精灵批处理类的源代码:

void spriteBatch::renderInRange(shader& prog, int start, int count){


int curTexture = textures[start];
int startFrom = start;

//Looping through all vertexes and rendering them by texture id's
for(int i=start;i<start+count;++i){
    if(textures[i] != curTexture || i == (start + count) -1){


        //Problem occurs after decommenting this line
       // prog.setUniform("texture", curTexture-1);

         prog.setUniform("texture", 0); // if I pass same texture id everything is OK

        int startVertex = startFrom * vertexesPerSprite;
        int cnt = ((i - startFrom) * vertexesPerSprite);

        //If last one has same texture we just adding it
        //to last render call

        if(i == (start + count) - 1 && textures[i] == curTexture)
            cnt = ((i + 1) - startFrom) * vertexesPerSprite;

        render(vbo, GL_TRIANGLE_STRIP, startVertex+1, cnt-1);

        //if last element has different texture
        //we need to render it separately

        if(i == (start + count) - 1 && textures[i] != curTexture){

         //   prog.setUniform("texture", textures[i]-1);
            render(vbo, GL_TRIANGLE_STRIP, (i * vertexesPerSprite) + 1, 5);
        }


        curTexture = textures[i];
        startFrom = i;
    }
}

}

inline GLint getUniformLocation(GLuint shaderID, const string& name) {
    GLint iLocation = glGetUniformLocation(shaderID, name.data());
    if(iLocation == -1){ // shader variable not found
        stringstream errorText;
        errorText << "Uniform \"" << name << " was not found!";
        throw logic_error(errorText.str());
    }
    return iLocation;
}

void shader::setUniform(const string& name, const matrix& value) {
    GLint location = getUniformLocation(this->programID, name.data());
    glUniformMatrix4fv(location, 1, GL_FALSE, &(value[0]));
}

void shader::setUniform(const string& name, int value) {
    GLint iLocation = getUniformLocation(this->programID, name.data());
            //GLenum error =  glGetError();
    glUniform1i(iLocation, value);
            //    error =  glGetError();
}

编辑#4:我试图在 IOS 6 和 Iphone5 上分析应用程序,并且分配要大得多。但是在这种情况下方法是不同的。我附上了新的截图。

在此处输入图像描述

4

3 回答 3

1

通过为每个纹理创建单独的着色器来解决问题。它看起来像所有 IOS 设备上确实发生的驱动程序实现中的错误(我在 IOS 5/6 上测试过)。然而,在更高的 iPhone 型号上,它并不那么明显。

在 iPhone4 上,从 60 FPS 到 38 FPS 的性能影响非常显着!

于 2013-02-17T18:20:09.343 回答
0

尝试只查询一次纹理统一(在初始化中)并缓存它。在一帧中过多调用“glGetUniformLocation”会影响性能(取决于精灵数量)。

于 2012-10-18T16:08:16.020 回答
0

更多代码会有所帮助,但您是否检查过所涉及的内存量是否与您正在更新的几何体量相当?(尽管这看起来像很多几何图形!)看起来 GL 将您的更新保留到 glDrawArrays,当它可以被拉入内部 GL 状态时释放它。

如果您可以在 MacOS 应用程序中运行代码,则 OpenGL Profiler 工具可能能够进一步隔离条件。(如果您不熟悉此工具,请查看 XCode 文档以获取更多信息)。考虑到所涉及的内存量,我还建议查看纹理使用。

最简单的做法可能是有条件地中断 malloc() 以进行大分配,记下地址,并检查那里加载了什么。

于 2012-10-17T17:07:04.303 回答