KhronosGroup / KhronosGroup/glslang
Conflicting interface variables emitted when multiple variables have same set/binding
- Dominant language
- C++
- Stars
- 3.6k
- Forks
- 989
- Avg merge
- 1d 2h
- Merged PRs (30d)
- 31
Description
The following vertex shader declares two different variables with the same descriptor set and binding number, but only one of them is statically used:
```glsl
#version 450
layout(set = 0, binding = 0) uniform Data {
vec4 pos;
};
layout(set = 0, binding = 0) uniform texture2D dummy;
void main() {
gl_Position = pos;
}
```
Compiling with `glslc -S --target-env=vulkan1.3` gives the following result (showing only relevant parts):
```
OpEntryPoint Vertex %main "main" %_ %__0 %dummy
OpDecorate %__0 DescriptorSet 0
OpDecorate %__0 Binding 0
OpDecorate %dummy DescriptorSet 0
OpDecorate %dummy Binding 0
```
Both variables are included in the interface of the `OpEntryPoint`, which according to the Vulkan spec means that they are considered "statically used":
> 9.24. Static Use
>
> A SPIR-V module declares a global object in memory using the `OpVariable` instruction, which results in a pointer `x` to that object. A specific entry point in a SPIR-V module is said to _statically use_ that object if that entry point’s call tree contains a function containing a instruction with `x` as an `id` operand. A shader entry point also _statically uses_ any variables explicitly declared in its interface.
But the spec section "15.8.3. DescriptorSet and Binding Assignment" contains a note stating that this is disallowed:
> If multiple shader variables with the same set and binding values are declared in a single shader, but with different declared types, where any of those are not supported by the relevant bound descriptor, that shader can only be executed if the variables with the unsupported type are not statically used.
This issue only exists when optimizations are disabled. With the `-O` option, the unused variable is eliminated and no longer appears in the interface. It doesn't happen with SPIR-V versions below 1.4, because descriptor binding variables are not allowed/included in interfaces in older versions.
Contributor guide
Research direction
Start by reproducing the shader with glslc -S --target-env=vulkan1.3 without -O, then compare the OpEntryPoint interface and descriptor decorations with the optimized output. Trace the compiler path that builds the SPIR-V entry-point interface for Vulkan 1.3; done means an unused conflicting variable is not emitted as statically used while the used variable remains, with coverage for the provided shader case.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100