3

有可能有一个专门化常量的数组,这样 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”只能应用于标量。目前我正在使用统一缓冲区来提供数据,但我想消除后备缓冲区以及在绘制之前绑定缓冲区的需要,并允许系统在可能的情况下在管道创建期间优化代码。

4

1 回答 1

3

虽然 Vulkan 风格的 GLSL要求专业化常量是标量,但SPIR-V 本身并没有那么严格。你可以声明一个特化常量数组,就像你可以声明一个非特化常量数组一样。后者在提供专业化常数后有效地变为前者。Vulkan 中用于特化常量的接口承认被特化的不同常量具有不同大小的可能性,因此从 API 的角度来看,它们的数组是有效的。

但只要你坚持使用 GLSL,你就必须生活在它的局限内。至少,就 SPIR-V 生成而言。

但是,如果您愿意在生成 SPIR-V 后对其进行一些手术,您可以构建您需要的东西。给定相关数组的名称,您可以追踪OpName与该数组名称匹配的数组。一旦找到它,您就可以找到OpName操作码指定的 ResultID(每个 SPIR-V 操作码都有一个)。该操作码应该是一个OpConstantComposite.

您需要做的就是将此OpConstantComposite操作码转换为OpSpecConstantComposite. 这两个代码使用相同的参数等等,因此您只需将操作码换成另一个。

于 2021-03-02T05:21:20.910 回答