2012-10-14 63 views
3

我最近發現glDrawArrays在每一幀都分配和釋放大量內存。 我懷疑它與openGL profiler報告的「初始化之外的着色器編譯問題」有關。這發生在每一幀!是否應該只有一次,並且在着色器編譯之後消失?glDrawArrays在每一幀上分配內存

編輯:我也雙重檢查,我的頂點正確對齊。所以我很困惑內存驅動需要在每一幀上分配哪些內存。編輯#2:我使用VBO的和退化的三角形帶來渲染精靈和。我在每幀上傳遞幾何(GL_STREAM_DRAW)。

enter image description here

編輯#3:

我想我接近發行,但仍然未能解決。 如果我將相同的紋理ID值傳遞給着色器,問題會消失(請參閱源代碼註釋)。不知何故,這個問題與我認爲的片段着色器有關。

在我的sprite批處理中,我有精靈列表,我通過紋理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的分配和配置文件的應用程序都大得多。但是在這種情況下方法是不同的。我附上了新的截圖。

enter image description here

+0

你能展示一些代碼嗎?你有沒有機會......在初始化之外編譯着色器?不要說明顯然,但着色器只需要編譯一次。 VBO還是VAO?我真的不會期待太多的內存分配回事下去,但我懷疑它更可能與在那裏你推到頂點的圖形流水線的每幀VAO。 –

+0

我使用其他信息編輯了我的問題。我在初始化的第一步加載着色器(在任何gl調用之前)。 –

+0

你能發表評論「setUniform」功能的代碼嗎? –

回答

1

通過爲每個紋理創建單獨的着色器來解決問題。 它看起來像在所有IOS設備上發生的驅動程序實現中的錯誤(我在IOS 5/6上測試過)。然而,在更高的iPhone機型上,這並不明顯。

在iPhone4上,從60 FPS到38的性能指標非常顯着!

+0

你有沒有報告的bug蘋果?之前沒有人注意到這個問題? – Cfr

0

更多的代碼會有所幫助,但你檢查,看看是否內存涉案金額相當於你在更新的幾何圖形的數量? (儘管這看起來像很多幾何體!)看起來GL在glDrawArrays之前持有更新,當它被拉入內部GL狀態時釋放它。

如果您可以在MacOS應用程序中運行代碼,則OpenGL Profiler工具可能能夠進一步隔離該情況。 (如果您對此工具不熟悉,請查看XCode文檔獲取更多信息)。考慮到涉及的內存量,我還建議查看紋理使用情況。

最簡單的事情可能是有條件地在malloc()上分配一個大的分配,記下地址,並檢查在那裏加載了什麼。

+0

我不認爲是這樣。我創建了示例應用程序,可以在每個框架上發送數據,並且我沒有看到任何分配。我會提供更多的信息在今天晚些時候 –

0

嘗試僅查詢紋理統一一次(在初始化中)並緩存它。在一幀中調用「glGetUniformLocation」太多會影響性能(取決於精靈數量)。