KhronosGroup / KhronosGroup/SPIRV-Registry
Clarify SPIR-V Specialization Constant Semantics: Allow Multiple OpSpecConstant Instructions with the Same SpecId?
- Dominant language
- HTML
- Stars
- 149
- Forks
- 99
- Avg merge
- 4d 21h
- Merged PRs (30d)
- 2
Description
I recently encountered an edge case regarding the semantics of Specialization Constant IDs (SpecId) in SPIR-V, and I'm seeking clarification to ensure consistent behavior, particularly for reflection library authoring and validation tools.
The GLSL compiler (e.g., `glslc`) rejects explicit duplicate `constant_id` decorations with the error "'constant_id' : specialization-constant id already used" for a payload like this:
```glsl
layout(constant_id = 1) const int X = 1;
layout(constant_id = 1) const int Y = 1;
```
This led me to assume a strict one-to-one correspondence between each scalar specialization constant instruction and its `SpecId` decoration. However, consider the following GLSL compute shader payload (compiled with `glslc` without dead code elimination):
```glsl
#version 450
layout(local_size_x_id = 1, local_size_y = 4, local_size_z = 4) in;
void main() {}
```
The resulting SPIR-V includes:
```spirv
OpDecorate %7 SpecId 1
OpDecorate %9 SpecId 1
%void = OpTypeVoid
%3 = OpTypeFunction %void
%uint = OpTypeInt 32 0
%7 = OpSpecConstant %uint 1
%uint_4 = OpConstant %uint 4
%9 = OpSpecConstant %uint 1
%v3uint = OpTypeVector %uint 3
%11 = OpSpecConstantComposite %v3uint %9 %uint_4 %uint_4
```
Here, `%7` and `%9` are distinct `OpSpecConstant` instructions but share the same `SpecId` (1). `%7` is referenced in the `OpExecutionModeId` for `LocalSizeId`, while `%9` is used as a component in the `OpSpecConstantComposite` for the built-in `gl_WorkGroupSize` (a `vec3` representing the local sizes). Upon re-reading the SPIR-V specification (Section 2.12 "Specialization"), it does not explicitly forbid multiple specialization constant instructions sharing the same `SpecId`. This raises two key questions:
1. Is this usage truly valid in SPIR-V?
2. If valid, must all specialization constant instructions (e.g., `OpSpecConstant`, `OpSpecConstantTrue`, or `OpSpecConstantFalse`) sharing the same `SpecId` have identical types and default values? Allowing different types could imply unintended type punning or lead to ambiguities during specialization. This seems indirectly implied by `VUID-VkSpecializationMapEntry-constantID-00776` in the Vulkan specification, which requires matching sizes for the provided data, suggesting that mismatched types (with different sizes) across aliased instructions would invalidate the module.
Contributor guide
No contributing guide indexed for this repository
Research direction
Start with SPIR-V specification Section 2.12, then compare its specialization rules with the glslc output and Vulkan VUID-VkSpecializationMapEntry-constantID-00776. The clarification should establish whether duplicate SpecId values are valid and, if so, whether their types and default values must match.
Written by the indexing model from the issue text.
Assessment
- Domain
- compilers, documentation
- Issue type
- Documentation
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100