我们使用缓冲区对象来减少来自CPU-GPU的复制操作,对于纹理缓冲区对象,我们可以将目标从顶点更改为缓冲区对象中的纹理.这里有纹理缓冲对象的其他优点吗?另外,它不允许过滤,这有什么不利之处吗?
缓冲区纹理类似于1D纹理,但有一个后备缓冲区存储,它不是纹理对象的一部分(与任何其他纹理对象相比),但是实现了绑定到的实际缓冲区对象TEXTURE_BUFFER
.使用缓冲区纹理有几个含义,AFAIK是一个无法映射到任何其他类型纹理的用例.
请注意,缓冲区纹理不是缓冲区对象 - 缓冲区纹理仅与使用glTexBuffer的缓冲区对象相关联.
相比之下,缓冲区纹理可能很大.表23.53及其核心OpenGL 4.4规范定义了最小最大值(即实现必须提供的最小值)纹素 数量MAX_TEXTURE_BUFFER_SIZE
.存储在缓冲区对象中的潜在纹素数量计算如下(如GL_ARB_texture_buffer_object中所示):
floor(<buffer_size> / (<components> * sizeof(<base_type>))
限制的结果值MAX_TEXTURE_BUFFER_SIZE
是可寻址纹素的数量.
例:
您有一个存储4MiB数据的缓冲区对象.您想要的是用于寻址RGBA纹素的缓冲区纹理,因此您可以选择内部格式RGBA8
.然后是可寻址的纹素数
floor(4MiB / (4 * sizeof(UNSIGNED_BYTE)) == 1024^2 texels == 2^20 texels
如果您的实现支持此数字,则可以处理缓冲区对象中的所有值.上面的内容并不太令人印象深刻,只需在当前实现中使用任何其他纹理即可实现.但是,我写这个答案的机器支持2^28 == 268435456
纹素.
使用OpenGL 4.4(以及4.3和可能的早期4.x版本),MAX_TEXTURE_SIZE
每个1D纹理是2 ^ 16个纹素,因此缓冲纹理仍然可以是4倍大.在我的本地机器上,我可以分配2GiB缓冲区纹理(实际上甚至更大),但在使用RGBAF32
纹素时只能分配1GiB 1D 纹理.
缓冲区纹理的用例是随机(和原子,如果需要)读/写访问(后者通过图像加载/存储)到着色器内的大型数据存储.是的,您可以在一个或多个块内对制服阵列进行随机读取 -访问,但如果您必须处理大量数据并且必须使用多个块,即使这样,查看最大组合大小,也会非常繁琐.单个阶段的所有统一块中的所有统一组件(其中单个浮点组件的大小为4个字节),
MAX_(stage)_UNIFORM_BLOCKS *
MAX_UNIFORM_BLOCK_SIZE +
MAX_(stage)_UNIFORM_COMPONENTS * 4
在着色器阶段实际上并没有很多空间(取决于您的实现允许以上数字的大小).
纹理和缓冲区纹理之间的一个重要区别是,作为常规缓冲区对象的数据存储可以用于纹理根本不起作用的操作中.扩展提到:
使用缓冲对象提供存储允许以许多不同的方式来指定纹理数据:经由缓冲器对象负载(BufferData),直接CPU写(MapBuffer),帧缓冲回读(EXT_pixel_buffer_object扩展名).缓冲对象也可以通过变换反馈(NV_transform_feedback扩展)加载,其反映由GL处理的顶点的所选变换属性.其中一些机制不需要额外的数据复制,这在使用传统的类似TexImage的入口点时是必需的.
使用缓冲区纹理的一个含义是着色器内部的查找只能通过texelFetch
.缓冲区纹理也不是mip-mapping,正如您已经提到的,在提取过程中没有过滤.
附录:
从OpenGL 4.3开始,我们就拥有了所谓的
着色器存储缓冲区.这些也提供对大型数据存储的随机(原子)读/写访问,但不需要texelFetch()
像缓冲区纹理那样使用图像加载/存储函数.使用缓冲区纹理也意味着必须gvec4
使用texelFetch()
和imageLoad()
/ 来处理返回值imageStore()
.一旦你想要使用结构(或其数组)并且你不想考虑使用多个实例vec4
或使用多个缓冲区纹理来实现类似的一些愚蠢的打包方案,这就变得非常繁琐.使用作为着色器存储访问的缓冲区,您可以简单地索引到数据存储,并struct {}
直接从缓冲区中提取一些或多个实例.
此外,由于它们与统一块非常相似,因此使用它们应该相当直接 - 如果您知道如何使用统一缓冲区,那么学习如何使用着色器存储缓冲区还有很长的路要走.
同样值得浏览相应ARB扩展的问题部分也是绝对值得的.
性能影响
几年前Daniel Rakos做了一些性能分析,既可以作为统一缓冲区和缓冲区纹理的比较,也可以根据AMD OpenCL编程指南中的信息进行更一般的说明.现在有一个非常新的版本,专门针对AMD平台的OpenCL优化.
影响绩效的因素有很多:
访问模式和生成的缓存行为
缓存行大小和内存布局
访问什么样的内存(寄存器,本地,全局,L1/L2等)及其各自的内存带宽
在此期间通过做其他事情来隐藏内存提取延迟的程度
您使用的是哪种硬件,即具有专用内存或某种统一内存架构的专用显卡
等等
一如既往地担心性能:实施有效的方法,看看解决方案是否足够快,满足您的需求.否则,实现两个或更多的方法来解决这个问题,轮廓他们和比较.
此外,供应商特定指南可提供大量见解.上面提到的OpenCL用户和优化指南提供了一个高级架构视角和关于如何优化CL内核的特定提示 - 在开发着色器时也是相关的东西.