为何要在GLSL中使用UBO

来源:互联网 发布:js保存cookie到本地 编辑:程序博客网 时间:2024/05/01 21:17
转载: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的渲染效率极低。

比如之前的代码是类似这个样子:

[cpp] view plain copy
print?
  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有如下定义:

[cpp] view plain copy
print?
  1. #version 330  
  2. uniform vec3 A;  
  3. uniform vec3 B;  
  4. uniform vec3 C;  
  5. uniform vec3 D;  
#version 330uniform 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代码是类似这个样子:

[cpp] view plain copy
print?
  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有如下定义:

[cpp] view plain copy
print?
  1. #version 330  
  2. layout(std140) uniform BlobSettings{    
  3.         vec3  A;   
  4.     vec3  B;   
  5.     vec3  C;   
  6.     vec3  D;   
  7. }Blob;    
#version 330layout(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)。


0 0