【问题标题】:Arrays in uniform blocks cannot be indexed with vertex attributes, right?统一块中的数组不能用顶点属性索引,对吗?
【发布时间】:2021-04-12 09:36:39
【问题描述】:

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

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'

很可能不是“动态统一表达式”,并且根据文档不能用于索引统一缓冲区数组:

有些地方 GLSL 要求表达式是动态的 制服。以下所有内容都必须使用动态统一 表达式:

-The index to buffer-backed interface block arrays.

但是,我从same source 中发现了有关如何访问一组持有“无绑定纹理”纹理句柄的采样器的信息,它说(强调我的):

默认块统一变量中使用的采样器和图像类型可以是 从句柄而不是绑定点的索引填充。 这些类型现在也可以作为 Shader Stage 输入/输出传递(在需要时使用平面插值限定符)。 它们可以是 用作顶点属性,,它们被视为 64 位整数 在 OpenGL 方面。而且它们可以用在所有的接口块中 种类;缓冲区支持的接口块将它们视为 64 位整数。

我相信,不是这样做:

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' 不是'动态统一表达式',它如何用于索引统一缓冲区?

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

-The index to buffer-backed interface block arrays.

那么为什么说你可以使用来自顶点输入的值索引到各种“接口块”?

你也可以索引到:

'uniform sampler2D[16] textures;'

使用“非动态统一表达式”?

【问题讨论】:

标签: opengl graphics glsl


【解决方案1】:

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

in flat int idx

很可能不是“动态统一的表达式”,并且根据 到文档不能用于索引到统一缓冲区 数组。

您是对的,您需要一个动态统一的值来索引统一的缓冲区数组。但是,这个:

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

不是统一的缓冲区数组。那是单个统一缓冲区对象内的数组,您可以根据需要将非统一值索引到该数组中。一个统一的缓冲区数组是:

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

您的问题的其余部分变得更加晦涩难懂。您有时会引用您的代码从不使用的“缓冲区支持的接口块数组的索引”。这是关于 SSBO,它使用 layout(...) buffer foo {...} 形式的接口块。

那么为什么说你可以使用来自顶点输入的值索引到各种“接口块”?

因为事情就是这样。您只需要了解对接口块数组的索引与对其他数组的索引不同(可能会或可能不会在接口块内定义,没关系)。

你也可以索引到:

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

不,不在标准 GL 中。

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

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

【讨论】:

  • 所以非动态统一索引可以用于索引统一块{ float[100];] 但不能用于统一块{ sampler2D[100]; } 。两者都是统一的缓冲块,对吧?
  • 部分。 sampler 类型甚至在未扩展 GL 的统一块中允许(只有无绑定纹理才允许这样的事情)。规范明确指出,对于聚合成数组的采样器,您需要一个动态统一的索引,否则结果是不确定的。不知道为什么你如此拼命地试图混合不同的东西。规范要求动态统一表达式的一些东西,索引接口块数组以及索引采样器数组都是这样的两个东西,但除此之外,它们没有任何共同点。
  • 如果这些 64 位纹理整数句柄不能用于索引纹理采样器数组,那么通过顶点属性传入它们有什么用?该页面显示“这些类型现在也可以作为着色器阶段输入/输出传递”-“它们可以用作顶点属性”。作为非动态统一的值,您可以访问数组,而不是它们的预期用途,即纹理,对吗?你怎么能用它们?
  • 引用GL_ARB_bindless_textures 扩展:“此扩展允许 OpenGL 应用程序访问着色器中的纹理对象,而无需先将每个纹理绑定到有限数量的纹理图像单元之一。[...]这些扩展显着减少了管理资源绑定所需的 API 和内部 GL 驱动程序开销。”这就是无绑定纹理的意义所在:不必为每个绘制调用绑定一小部分纹理。这根本不是关于对纹理的非统一访问。正如我所说,只有与GL_NV_gpu_shader5 结合使用才能获得该功能。
  • “编辑:等一下,但你没有用句柄本身索引采样器数组,你用句柄填充采样器数组,然后索引到那个......”不同之处在于,当您进行texture 调用时,单个采样器具有什么值(跨调用组中的多个调用)并不重要。如果该值不是动态统一的,因为它直接来自顶点属性,或者如果该值不是动态统一的,因为您通过将顶点属性索引到统一的值数组中来获得它,不会产生丝毫差异。
【解决方案2】:

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

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

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

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

那么为什么说你可以使用来自顶点输入的值索引到各种“接口块”?

因为你可以。

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

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

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

【讨论】:

  • 要求采样器数组由动态统一索引索引是 OpenGL 或显卡的限制吗?我在 Vulkan 中读到该标志(类似于 samplerNonDynamicallyUniformIndexable)在大多数平台上都是正确的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-16
  • 2023-03-03
相关资源
最近更新 更多