将块索引用作UniformBufferObject,ShaderStorageBufferObjects等的绑定点是否安全?

kbi*_*irk 5 opengl glsl

我很好奇*BlockBinding一些与OpenGLs缓冲区对象相关的函数中使用的参数。

例如,该uniformBlockBinding参数中glUniformBlockBindingstorageBlockBinding?glShaderStorageBlockBinding和对应的index参数glBindBufferRangeglBindBufferBase

我知道,如果使用布局限定符在着色器中设置绑定点glUniformBlockBindingglShaderStorageBlockBinding则不必调用和,例如:

layout (binding = 0) blockName {...}
Run Code Online (Sandbox Code Playgroud)

通过在我的机器上进行的测试,我注意到了三件事:

1)使用布局限定符在shader中设置绑定点,glUniformBlockBindingglShaderStorageBlockBinding覆盖它们。

2)对于相同类型的每个块,从中返回块索引,glGetUniformBlockIndex并按glGetProgramResourceIndex0到n的顺序对其进行排序。例如,如果着色器包含3个统一块和2个缓冲区块,则返回的索引分别为[0,1,2]和[0,1]。

3)绑定点,无论哪种方式设置,都不会在类型之间发生冲突。例如,将统一块设置为binding = 0并将缓冲块设置为binding = 0是完全安全的。

牢记这些假设(如果有必要不一定正确并且只是巧合,请纠正我),有什么原因为什么我不应该让我的代码自动将*BlockBinding参数设置为相应的块索引,从而省去了麻烦呢?通过gl*BlockBinding或通过布局限定符手动指定它们。

小智 2

我曾经也有过同样的疑问。经过一番探索,特别是阅读有关 GL 的权威信息来源: https: //www.khronos.org/opengl/wiki/Uniform_Buffer_Object] 我很确定这就是块索引和绑定点之间分离的原因。

将 GL 渲染上下文视为端口,将 glsl 程序对象视为一艘船。绑定点是港口的港湾,区块索引是通往船舶储藏室的门。一艘船需要停靠在港口,其一扇门与特定港口对齐,才能将货物装载到船上(或反之亦然)。类似地,块索引需要与要在着色器块和上下文缓冲区之间传输的数据的绑定点相关联。

由于这种设计,块索引和绑定点是独立的实体。因此,简单地将绑定点等同于块索引是不安全的,因为这可能会无意中覆盖绑定点(可能已被其他船只停靠)。

您的观察结果也可以解释:

  • 块索引和绑定点从 0 开始连续计数(如您在 (2) 中观察到的那样)。
  • 每种类型的缓冲区(因为它们驻留在上下文中)都有一组与其他类型分开的绑定点(因此您的观察结果为 3)。
  • 至于您的观察 1,是的,在应用程序端设置关联会抢占着色器中的硬编码绑定。