用于数组大小的专门化常量

dia*_*pir 5 opengl glsl spir-v

我正在尝试使用 SPIR-V专门化常量来定义统一块中数组的大小。

#version 460 core

layout(constant_id = 0) const uint count = 0;

layout(binding = 0) uniform Uniform
{
    vec4 foo[count];
    uint bar[count];
};

void main() {}
Run Code Online (Sandbox Code Playgroud)

count = 0在着色器中声明 时,编译失败并显示:

array size must be a positive integer
Run Code Online (Sandbox Code Playgroud)

count = 1特化为 5 时,代码可以编译,但在运行时链接失败,并抱怨别名:

error: different uniforms (named Uniform.foo[4] and Uniform.bar[3]) sharing the same offset within a uniform block (named Uniform) between shaders
error: different uniforms (named Uniform.foo[3] and Uniform.bar[2]) sharing the same offset within a uniform block (named Uniform) between shaders
error: different uniforms (named Uniform.foo[2] and Uniform.bar[1]) sharing the same offset within a uniform block (named Uniform) between shaders
error: different uniforms (named Uniform.foo[1] and Uniform.bar[0]) sharing the same offset within a uniform block (named Uniform) between shaders
Run Code Online (Sandbox Code Playgroud)

似乎统一块的布局(每个成员的偏移)在专业化期间不受影响,因此foobar重叠。

显式偏移也不起作用并导致相同的链接错误:

layout(binding = 0, std140) uniform Uniform
{
    layout(offset = 0) vec4 foo[count];
    layout(offset = count) uint bar[count];
};
Run Code Online (Sandbox Code Playgroud)

这是有意的行为吗?俯瞰?可以使用专门化常量来定义数组的大小吗?

Nic*_*las 6

这是 ARB_spir_v 的一个奇怪的现象。从扩展规范来看:

块内的数组可以使用专门化常量来调整大小,但该块将具有静态布局。更改专用尺寸不会重新布局块。在没有显式偏移的情况下,布局将基于数组的默认大小。

由于默认大小为 0,因此块中的结构将按照数组大小为零的方式进行布局。

基本上,您可以使用专门化常量使数组比默认值更短,但不能更长。即使您将它们缩短,它们仍然占用与默认值相同的空间。

所以实际上,在块数组长度中使用专门化常量只是用默认值作为其长度来声明数组的一种简写方式,然后用name.length()专门化常量/表达式替换要使用的位置。它纯粹是语法糖。