我最近发现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上分析应用程序,分配更大。但在这种情况下方法是不同的。我正在附上新截图。
答案 0 :(得分:1)
通过为每个纹理创建单独的着色器来解决问题。 看起来驱动程序实现中的错误确实发生在所有IOS设备上(我在IOS 5/6上测试过)。然而,在较高的iPhone型号上,它并不明显。
在iPhone4上,性能从60 FPS到38都非常显着!
答案 1 :(得分:0)
更多代码会有所帮助,但您是否检查过所涉及的内存量是否与您要更新的几何体数量相当? (虽然这看起来像是很多几何体!)看起来GL正在保持你的更新,直到glDrawArrays,当它被拉入内部GL状态时释放它。
如果您可以在MacOS应用程序中运行代码,OpenGL Profiler工具可能能够进一步隔离该条件。 (如果您不熟悉此工具,请查看XCode文档以获取更多信息)。考虑到所涉及的内存量,我还建议查看纹理使用。
最简单的方法可能是有条件地在malloc()上进行大量分配,注意地址,并检查那里加载的内容。
答案 2 :(得分:0)
尝试一次查询纹理均匀(在初始化中)并缓存它。在一个帧中调用“glGetUniformLocation”太多会破坏性能(取决于精灵计数)。