KhronosGroup / KhronosGroup/glslang

Conflicting interface variables emitted when multiple variables have same set/binding

Open
#3,472 0 comments 0 reactions 0 assignees View on GitHub
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

Open the contributing 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.