Opengl 使用块索引作为UniformBufferObject、ShaderStorage BufferObject等的绑定点安全吗?

Opengl 使用块索引作为UniformBufferObject、ShaderStorage BufferObject等的绑定点安全吗?,opengl,glsl,Opengl,Glsl,我对几个OpenGLs缓冲区对象相关函数中使用的*BlockBinding参数感到好奇 例如,glUniformBlockBinding,storageBlockBinding中的uniformBlockBinding参数​,以及glBindBufferRange和glBindBufferBase中相应的index参数 我知道,如果使用布局限定符在着色器中设置绑定点,则不需要调用glUniformBlockBinding和glShaderStorageBlockBinding layout (b

我对几个OpenGLs缓冲区对象相关函数中使用的
*BlockBinding
参数感到好奇

例如,
glUniformBlockBinding
storageBlockBinding中的
uniformBlockBinding
参数​glShaderStorageBlockBinding
中的code>,以及
glBindBufferRange
glBindBufferBase
中相应的
index
参数

我知道,如果使用布局限定符在着色器中设置绑定点,则不需要调用
glUniformBlockBinding
glShaderStorageBlockBinding

layout (binding = 0) blockName {...}
通过在我的机器上进行测试,我注意到三件事:

1) 使用
glUniformBlockBinding
glShaderStorageBlockBinding设置绑定点
使用布局限定符覆盖着色器中设置的绑定点

2) 对于相同类型的每个块,从
glGetUniformBlockIndex
glGetProgramResourceIndex
返回的块索引的顺序为0到n。例如,如果着色器包含3个均匀块和2个缓冲块,则返回的索引将分别为[0,1,2]和[0,1]

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


考虑到这些假设(如果有任何假设不一定正确且只是巧合,请纠正我),有什么理由不让我的代码自动将
*BlockBinding
参数设置为相应的块索引,省去了通过
gl*BlockBinding
或布局限定符手动指定它们的麻烦。

我曾经有过同样的问题。经过一些探索,特别是阅读了德国劳埃德船级社的权威信息来源: 我很确定这就是为什么块索引和绑定点之间存在分离

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

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

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

  • 块索引和绑定点从0开始连续计数(如您在(2)中观察到的)
  • 每种类型的缓冲区(因为它们位于上下文中)都有一组绑定点,这些绑定点与其他类型(因此您的观察结果为3)是分开的
  • 至于您的观察1,是的,在应用程序端设置关联会抢占着色器中的硬编码绑定
考虑到这些假设(如果有任何假设不一定正确且只是巧合,请纠正我),有什么理由不让我的代码自动将
*BlockBinding
参数设置为相应的块索引,省去了通过
gl*BlockBinding
或布局限定符手动指定它们的麻烦

因为那完全没用

块索引可任意分配给特定块。一个平台上,一个特定块的索引可以是0,而另一个平台对名称进行排序,使其为索引2。因此,您的代码必须查询计划使用的每个块的块索引

然而,如果您为特定块指定要使用的绑定索引,则不必查询任何内容。代码知道绑定索引0是矩阵所在的位置,绑定索引1是照明数据所在的位置,等等

更糟糕的是,可能有多个着色器使用同一块。但它们不太可能有相同的块索引。然而,如果您为它们指定了绑定索引,则可以为它们指定相同的绑定索引。因此,您不必在这些程序的更改之间重新绑定缓冲区