统一块中的数组不能用顶点属性索引,对吗?

Arrays in uniform blocks cannot be indexed with vertex attributes, right?

我想知道我是否可以使用包含在我绘制的顶点中的值索引到统一缓冲区数组中,例如:

layout (location = 0) in vec3 position;
layout (location = 1) in flat int idx;

layout(binding = 0, std140) uniform uniformValues
    {
        float values[100];
};

void main() 
{
     values[idx];
}

我的理解是这是不可能的,因为

'in flat int idx'

很可能不是 'dynamically uniform expression',并且根据文档不能用于索引到统一缓冲区数组:

There are places where GLSL requires the expression to be dynamically uniform. All of the following must use a dynamically uniform expression:

-The index to buffer-backed interface block arrays.

但是我从 same source 中了解到有关如何访问为 'bindless textures' 保存纹理句柄的采样器数组的信息,它说(强调我的):

Sampler and image types used in default block uniform variables can be populated from handles rather than the index of a binding point. These types can also now be passed as Shader Stage inputs/outputs (using the flat interpolation qualifier where needed). They can be used as Vertex Attributes, where they are treated as 64-bit integers on the OpenGL side. And they can be used in Interface Blocks of all kinds; buffer-backed interface blocks treat them as 64-bit integers.

它说的是,我相信,而不是这样做:

layout (location = 0) in flat int textureBinding;

layout (binding = 0) uniform sampler2D textures[16];

void main()
{
     textures[textureBinding];
}

你这样做:

layout (location = 0) in flat int bindlessTextureHandle;

layout (binding = 0) uniform textureBuffer 
{
      sampler2D textures[200];
}

void main()
{
     textures[bindlessTextureHandle];
}

'bindlessTextureHandle' 不是 'dynamically uniform expression',它如何用于索引统一缓冲区?

以下所有必须使用动态统一表达式:

-The index to buffer-backed interface block arrays.

那么为什么说您可以使用顶点输入的值索引到 'interface blocks' 中的所有类型?

您还可以索引到:

'uniform sampler2D[16] textures;'

与 'non-dynamically uniform expression'?

My understanding is that this is not possible because

in flat int idx

Is most likely not a 'dynamically uniform expression', and according to the documentation cannot be used to index into a uniform buffer array.

你是对的,你需要一个动态统一的值来索引到一个统一的缓冲区数组。然而,这:

layout(binding = 0, std140) uniform uniformValues
{
        float values[100];
};

不是统一缓冲区数组。这是一个位于单个统一缓冲区对象中的数组,您可以根据需要使用非统一值对该数组进行索引。统一缓冲区数组为:

 layout(binding = 0, std140) uniform myUBO
 {
         float value;
 } myUBOArray[4];

你的问题的其余部分变得更加模糊。您有时会引用“缓冲区支持的接口块数组的索引”,您的代码从不使用它。这是在谈论 SSBO,它使用 layout(...) buffer foo {...}.

形式的接口块

So why is it saying that you can index into 'interface blocks' of all kinds with values from vertex inputs?

因为事情就是这样。您只需要了解索引到接口块数组与索引其他数组不同(可能在接口块内定义也可能不定义,这无关紧要)。

Also are you allowed to index into:

uniform sampler2D[16] textures; with a 'non-dynamically uniform expression'?

不,不在标准 GL 中。

关于无绑定纹理的第一件事是,这不是迄今为止发布的任何 OpenGL 版本(即 4.6在撰写本文时)。它仅被定义为一些现代 GPU 和驱动程序公开的 extension GL_ARB_bindless_textures,但该功能的可用性远非通用.

其次,上面的扩展规范解释说:“传递给纹理内置函数的采样器和图像句柄必须是动态统一的”,所以它仍然无法让您到达那里。但是,扩展 GL_NV_gpu_shader5 删除了该限制。因此,在最近的 NVIDIA GPU 上,您可以在无绑定纹理采样器数组中获得非动态统一索引 - 但如果这样做,性能仍然会受到很大影响。

这里有无数独立、重叠的问题。

索引数组 统一块中从来不限于动态统一表达式(通常,见下文)。即使在 GL 3.x 中,您也可以使用任意索引在缓冲区支持的块中索引数组。

但是,你问的不是一般数组;你问的是纹理数组。或者更一般地说,整个操作序列导致通过无绑定纹理计算采样器类型。

整个序列必须是动态统一的(除非您使用的是 NVIDIA,它允许任意表达式)。无论您是在索引 SSBO 数组、使用输入变量直接传递纹理句柄,还是其他任何东西,都没有关系。导致获取采样器类型的值必须是动态统一的。

So why is it saying that you can index into 'interface blocks' of all kinds with values from vertex inputs?

因为你可以。

对“动态统一”的一个常见误解是它是静态的属性。表达式 本身 要么是动态统一的,要么不是。这接近于真实,但实际上并非如此。

一些表达式本质上是动态统一的。您可以将这些称为“静态动态统一”表达式。例如,常量表达式总是动态统一的。

然而,动态统一是关于表达式的。所有调用(在渲染命令中)必须产生相同的 value。着色器阶段的 in 变量可以是动态统一的,只要它恰好在渲染命令中始终具有相同的值。例如,VS 可以使用 gl_DrawID(动态统一)从 uniform 数组访问值,将其作为 in 传递给 FS,然后 FS 可以使用该值作为采样器。或者访问一组采样器。管他呢。所有 FS 调用将在绘制命令中获得相同的值,因此该值是动态统一的。