3

我正在尝试使用 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() {}

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

array size must be a positive integer

使用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

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

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

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

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

4

1 回答 1

4

这是 ARB_spir_v 的一个奇怪的怪癖。从扩展规范

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

由于默认大小为 0,因此块中的结构将被布置为就好像数组的大小为零一样。

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

所以真的,在块数组长度中使用特化常量只是一种简写方式,用默认值作为它的长度声明数组,然后用name.length()特化常量/表达式替换你将使用的地方。它纯粹是语法糖。

于 2018-09-05T18:50:48.367 回答