问题描述
是否可以有一个专门化常量的数组,这样 glsl 代码看起来类似于以下内容:
layout(constant_id = 0) const vec2 arr[2] = vec2[] (
vec2(2.0f,2.0f),vec2(4.0f,4.0f)
);
或者:
layout(constant_id = 0) const float arr[4] = float[] (
2.0f,2.0f,4.0f,4.0f
);
据我所知,可以使用的专业化常量的数量没有限制,所以感觉很奇怪这是不可能的,但是当我尝试上述操作时,SPIR-V 编译器通知我'constant_id ' 只能应用于标量。目前我正在使用统一缓冲区来提供数据,但我想消除后备缓冲区和在绘制之前绑定缓冲区的需要,并允许系统在可能的情况下在管道创建期间优化代码。
解决方法
Vulkan 风味的 GLSL requires that specialization constants are scalars、SPIR-V itself is not so restrictive。你可以声明一个特化常量数组,就像你可以声明一个非特化常量数组一样。后者在提供专业化常数后有效地变为前者。 Vulkan 中专门用于常量的接口承认被专门化的不同常量具有不同大小的可能性,因此从 API 的角度来看,它们的数组是有效的。
但只要你坚持使用 GLSL,你就必须生活在它的限制之内。至少,就 SPIR-V 生成而言。
但是,如果您愿意在生成 SPIR-V 后对其进行一些手术,则可以构建您需要的内容。给定相关数组的名称,您可以找到与该数组名称匹配的 OpName
。一旦找到它,就可以找到 OpName
操作码指定的 ResultID(每个 SPIR-V 操作码都有一个)。该操作码应该是 OpConstantComposite
。
您需要做的就是将此 OpConstantComposite
操作码转换为 OpSpecConstantComposite
。这两个代码使用相同的参数等等,因此您只需将操作码替换为另一个。