1. Shader数据存储结构
1.1 Uniform Buffer Object
Uniform Buffer Object(简称UBO)是OpenGL 3.1引入的数据存储结构,不过在一些早期的GL版本中,通过扩展GL_ARM_uniform_buffer_object也可以使用。这个结构是用于将GLSL的一些uniform常量数据塞入到一个group中以实现对数据流水线式的访问。
UBO通常尺寸很小,因此可以很方便的塞入到local memory中,因为Local Memory(LMEM)具有缓存机制,因此其访问速度通常快于GMEM,同时由于缓存机制对于数据访问的连续性有一定要求,连续性越好,缓存也就越有效,因此在使用的时候,最好将数据放在一块连续的存储空间中,访问也按照顺序进行。
1.2 Texture Buffer Object
Texture Buffer Object(简称TBO)同样是OpenGL 3.1引入的数据存储结构,也可以通过扩展GL_ARM_texture_buffer_object/GL_EXT_texture_buffer_object来降低API版本限制。
TBO是一个texel数据的一维数组,其数据来源于一个attached的buffer object,这个结构能够提供比常规1D贴图大得多的数据访问,不过与常规贴图不同的是,按照这种结构对数据进行访问不会自动进行filter处理(因为这种结构存储的数据通常更倾向于被看成是数组而非贴图)。
TBO是存储在Global Memory中的,因此对TBO的访问需要一个texture unit的参与,同时还需要等待几个时钟周期才能完成一次数据访问,不过由于目前NVIDIA/AMD等厂商的设计精良,这个访问的延迟可以被掩盖住。
相对于UBO,TBO中的数据可以更方便的实现随机存取,因此如果需要读取的数据顺序是不确定的,那么在UBO跟TBO中,最好选择后者,这样可以得到更好的性能表现。
1.3 Frame Buffer Object
简称FBO,这是渲染结果最终的目的地,包括Color Buffer, Depth Buffer与Stencil Buffer等,类似于D3D中的RenderTarget。
FBO默认是由窗口系统创建完成的,这是我们渲染最终输出的目的地,这个FBO称为Window-System-Provided FrameBuffer。
除了默认的FBO之外,我们也可以另外手动创建FBO,并将渲染结果输出到这个新创建的FBO上面,为了与默认的FBO区别开来,这个FBO我们称之为Application-Created FrameBuffer,自建的FBO在属性与功能上与默认的FBO并无两样。
FBO通常包含两种类型的framebuffer-attachable:
- texture images
- RenderBuffer Images
如果将texture image关联到FBO上,渲染的时候执行的就是render to texture逻辑,否则将Renderbuffer image关联到FBO上面,执行的就是offscreen rendering逻辑。
这里与framebuffer-attachable相关的一个概念叫做attachment points,每个FBO包含了多个attachment points,其中color attachment可以有多个,而depth attachment与stencil attachment则只有一个,texture, renderbuffer, FBO与attachment之间的关系如下图所示:
Connectivity between FOB, texture & renderbuffer
注意,FBO中存储的是attachment points,这个其实可以看成是attachment的指针,而并不是直接存储了attachment。
1.4 Render Buffer Object
如果FBO中关联的是texture images的话,那么渲染完成后,可以在后处理中完成对texture image数据的读取;而如果我们不需要获取渲染后的texture image数据,那么我们还可以不关联texture image,而是关联renderbuffer image,这类image主要用于存储depth/s等没有相对应的纹理格式的buffer数据,这里的renderbuffer image指的就是render buffer object,简称RBO。
RBO相对于TBO,实际上是做了牺牲的,那么这样做有什么好处呢,据khronos的wiki描述,这种结构是专为RenderTarget专门优化的,也就是说性能上是有优化的,而且天生兼容MSAA(即不需要任何扩展支持,虽然并不能将结果resolve出来。。。)
在显存统计中,FBO被当成Texture看待,而RBO则是只写不读的。
1.5 Uniform Buffer Object(UBO)
UBO(Uniform Buffer Object)可用于在多个shader program之间共享uniform变量,批量管理。UBO大小限制为KB级别,64KB或128KB,具体与硬件相关。储区为显卡的常量区,速度较快(快于Texture Sampling,快于SSBO)。UBO对于shader来讲是只读常量,只能通过外部程序更新。
1.6 Shader Storage Buffer Object(SSBO)
跟UBO一样,SSBO也可用于多个Shader Program之间的变量共享。相对于UBO,SSBO灵活得多,大小可为显存大小(GB),因而更适合与存储大量的数据。而且SSBO可以在shader运行时再确定大小,而非编译时。此外,SSBO的数据存储在全局的显存,速度慢于UBO。在读写方面,SSBO是shader可以读写的(例如在compute shader中更新定点的位置)。另外,任何其他类型的OpenGL buffer都可绑定到GL_SHADER_STORAGE_BUFFER 目标上,因而很灵活
2. OpenGL & GLSL & OpenGL ES版本关联
OpenGL是Open Graphics Library的缩写,这是最开始由SGI在1991年进行开发的一个跨平台图形API(所谓的图形API指的是通过与显卡驱动之间的交互,高效的实现图形渲染的API),支持2D&3D渲染,目前最高版本为OpenGL 4.6,各个版本的相关特性可以从维基百科中找到。
OpenGL ES是OpenGL Embedded System的缩写,这是OpenGL API的一个子集,主要用于一些嵌入式环境(比如手机平板等)的图形开发,跟OpenGL一样,GLES也是跨平台的,目前最高版本为ES 3.2。
OpenGL Shading Language,简称GLSL,是OpenGL ARB(Architecture Review Board)所开发的用于OpenGL/GLES图形shader编写的高级语言。
在开发图形功能时,经常需要了解当前版本的API所支持的GLSL版本,为了避免反复查找,这里直接将相关数据罗列到一起。
首先给出OpenGL与GLSL之间的版本关联:
OpenGL-GLSL
OpenGL ES与GLSL之间的版本关联:
GLSL ES Version | Shader Preprocessor |
---|---|
2.0 | #version 100 |
3.0 | #version 300 es |
3.1 | #version 310 es |
3.2 | #version 320 es |
此前原本打算给出OpenGL与GLES之间的版本关联,后来经过深入了解后发现,部分OpenGL早期版本的内容在GLES上的版本却较晚,某些GL晚期版本内容在GLES上出现的时间却比较早,从这个结论可以得知,GL版本与GLES版本并不是一一对应的,而是相互混合的,因此就没有一套固定的映射关系,当需要查找某个功能支持的最低版本时,就需要对于GL与GLES分别进行查询。
参考文献
[1].Uniform Buffers VS Texture Buffers
[2].OpenGL学习脚印: 帧缓冲对象(Frame Buffer Object)
作者:离原春草
链接:https://www.jianshu.com/p/cc1ea3a8d7c2
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。