爲何要在GLSL中使用UBO

轉載:http://blog.csdn.net/lsldd/article/details/8475908

關於UBO的介紹和使用詳情,請看http://www.zwqxin.com/archives/shaderglsl/communication-between-opengl-glsl-2.html

除了OpenGL手冊,應該沒有比這個更詳細的了。


最近在一個GLSL項目中,需要循環繪製多塊buffer,而每次循環都要給buffer傳入大量的uniform,導致shader的渲染效率極低。

比如之前的代碼是類似這個樣子:

  1. m_pProgramBlock->sendUniform3fv(A);  
  2. m_pProgramBlock->sendUniform3fv(B);  
  3. m_pProgramBlock->sendUniform3fv(C);  
  4. m_pProgramBlock->sendUniform3fv(D);  
  5. glDrawElements(…);  
m_pProgramBlock->sendUniform3fv(A);
m_pProgramBlock->sendUniform3fv(B);
m_pProgramBlock->sendUniform3fv(C);
m_pProgramBlock->sendUniform3fv(D);
glDrawElements(...);

相應的,在shader中uniform有如下定義:

  1. #version 330  
  2. uniform vec3 A;  
  3. uniform vec3 B;  
  4. uniform vec3 C;  
  5. uniform vec3 D;  
#version 330
uniform vec3 A;
uniform vec3 B;
uniform vec3 C;
uniform vec3 D;

結果在性能測試中發現,每執行一次sendUniform的操作耗費的時間居然大於執行一次glDrawElements的時間!

GLSL提供了UBO技術能很好的解決這個問題。通過把uniform綁定到顯卡的緩衝區,可以極大提升修改Uniform數據的速度。此外他的最大優勢在於能在Shader之間共享Uniform。UBO的詳細說明請參閱http://www.opengl.org/wiki/Uniform_Buffer_Object

修改後的opengl代碼是類似這個樣子:

  1. glBindBuffer(GL_UNIFORM_BUFFER, m_uboHandle);  
  2. glBufferSubData(GL_UNIFORM_BUFFER, 0,  16, (char*)(&A);  
  3. glBufferSubData(GL_UNIFORM_BUFFER, 16,  16, (char*)(&B);  
  4. glBufferSubData(GL_UNIFORM_BUFFER, 32,  16, (char*)(&B);  
  5. glBufferSubData(GL_UNIFORM_BUFFER, 48,  16, (char*)(&B);  
  6. glDrawElements(…);  
glBindBuffer(GL_UNIFORM_BUFFER, m_uboHandle);
glBufferSubData(GL_UNIFORM_BUFFER, 0,  16, (char*)(&A);
glBufferSubData(GL_UNIFORM_BUFFER, 16,  16, (char*)(&B);
glBufferSubData(GL_UNIFORM_BUFFER, 32,  16, (char*)(&B);
glBufferSubData(GL_UNIFORM_BUFFER, 48,  16, (char*)(&B);
glDrawElements(...);

相應的,在shader中uniform有如下定義:

  1. #version 330  
  2. layout(std140) uniform BlobSettings{    
  3.         vec3  A;   
  4.     vec3  B;   
  5.     vec3  C;   
  6.     vec3  D;   
  7. }Blob;    
#version 330
layout(std140) uniform BlobSettings{  
        vec3  A; 
    vec3  B; 
    vec3  C; 
    vec3  D; 
}Blob;  

那麼到底性能差異有多大呢?使用VS2012的性能測試,可以得到如下數據:


sendUniform佔用了9.4%的渲染時間,而一條glBufferSubData只佔用了0.1%!

使用glBufferSubData的效率比使用sendUniform高將近2個數量級!

然而使用UBO也要付出代價。因爲每個顯卡不同,UBO裏每個uniform所佔用字節數都未必相同,即使你指定了layout(std140)。


發佈了23 篇原創文章 · 獲贊 10 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章