KhronosGroup / KhronosGroup/glslang

HLSL zero-based matrix indexing (_m00, _m32 etc.) replaced with constant 0 (Missing functionality: matrix swizzle)

Open
#1,240 1 comment 0 reactions 0 assignees View on GitHub
bug HLSL
Dominant language
C++
Stars
3.6k
Forks
989
Avg merge
1d 2h
Merged PRs (30d)
31

Description

### Problem
We use matrix swizzeling in our HLSL code, and compile the code to SPIR-V using the C++ glslang API.
After some debugging with RenderDoc, we discovered that the matrices that were indexed were replaced with constants.

Minimal test HLSL vertex shader:
```
uniform float4x4 DISAPEARING_MATRIX;

float4 main(float4 main_input:POSITION):POSITION{
return DISAPEARING_MATRIX._m00_m10_m20_m30;
}
```
when compiled with

`.\glslangValidator.exe -D -H -l -e main test.vert`

produces the following output:
```
test.vert
Missing functionality: matrix swizzle
// Module Version 10000
// Generated by (magic number): 80004
// Id's are bound by 32

Capability Shader
1: ExtInstImport "GLSL.std.450"
MemoryModel Logical GLSL450
EntryPoint Vertex 4 "main" 28 31
Source HLSL 500
Name 4 "main"
Name 28 "main_input"
Name 31 "@entryPointOutput"
Decorate 28(main_input) Location 0
Decorate 31(@entryPointOutput) Location 0
2: TypeVoid
3: TypeFunction 2
6: TypeFloat 32
7: TypeVector 6(float) 4
17: TypeInt 32 1
18: 17(int) Constant 0
27: TypePointer Input 7(fvec4)
28(main_input): 27(ptr) Variable Input
30: TypePointer Output 7(fvec4)
31(@entryPointOutput): 30(ptr) Variable Output
4(main): 2 Function None 3
5: Label
Store 31(@entryPointOutput) 18
Return
FunctionEnd
```
Which stores `%18`, which points to `constant 0`, to the `@entryPointOutput`.
In other words: it replaced the matrix indexing operation with 0.

Note that while in says "Missing functionality: matrix swizzle" at the top, it only says that in the command line utility.
While we found the "illegal SPIR-V may be generated" error messages in the shader and program logs, we did not find "missing functionality: matrix swizzle" error messages.
I only found the error message when producing the minimal example for this issue with the glslang command line utility.

### Workaround
For now, we have changed our shaders to use bracket indexing on matrices.

Same HLSL vertex shader but with workaround:
```
uniform float4x4 DISAPEARING_MATRIX;

float4 main(float4 main_input:POSITION):POSITION{
return float4(DISAPEARING_MATRIX[0][0],
DISAPEARING_MATRIX[1][0],
DISAPEARING_MATRIX[2][0],
DISAPEARING_MATRIX[3][0]);
}
```
`.\glslangValidator.exe -D -H -l -e main workaround.vert`
```
workaround.vert
// Module Version 10000
// Generated by (magic number): 80004
// Id's are bound by 55

Capability Shader
1: ExtInstImport "GLSL.std.450"
MemoryModel Logical GLSL450
EntryPoint Vertex 4 "main" 38 41
Source HLSL 500
Name 4 "main"
Name 14 "$Global"
MemberName 14($Global) 0 "DISAPEARING_MATRIX"
Name 16 ""
Name 38 "main_input"
Name 41 "@entryPointOutput"
MemberDecorate 14($Global) 0 RowMajor
MemberDecorate 14($Global) 0 Offset 0
MemberDecorate 14($Global) 0 MatrixStride 16
Decorate 14($Global) Block
Decorate 16 DescriptorSet 0
Decorate 38(main_input) Location 0
Decorate 41(@entryPointOutput) Location 0
2: TypeVoid
3: TypeFunction 2
6: TypeFloat 32
7: TypeVector 6(float) 4
13: TypeMatrix 7(fvec4) 4
14($Global): TypeStruct 13
15: TypePointer Uniform 14($Global)
16: 15(ptr) Variable Uniform
17: TypeInt 32 1
18: 17(int) Constant 0
19: TypeInt 32 0
20: 19(int) Constant 0
21: TypePointer Uniform 6(float)
24: 17(int) Constant 1
27: 17(int) Constant 2
30: 17(int) Constant 3
37: TypePointer Input 7(fvec4)
38(main_input): 37(ptr) Variable Input
40: TypePointer Output 7(fvec4)
41(@entryPointOutput): 40(ptr) Variable Output
4(main): 2 Function None 3
5: Label
46: 21(ptr) AccessChain 16 18 18 20
47: 6(float) Load 46
48: 21(ptr) AccessChain 16 18 24 20
49: 6(float) Load 48
50: 21(ptr) AccessChain 16 18 27 20
51: 6(float) Load 50
52: 21(ptr) AccessChain 16 18 30 20
53: 6(float) Load 52
54: 7(fvec4) CompositeConstruct 47 49 51 53
Store 41(@entryPointOutput) 54
Return
FunctionEnd
```
Which appears to work as expected.

### Solution
Short term solution: produce a compile error instead of a warning, or at least log the error.

Long term solution: implement matrix swizzeling, as it is a useful HLSL language feature.

Contributor guide

Open the contributing guide

Research direction

Start with the minimal HLSL vertex shader and run it through glslangValidator using the command shown, comparing its SPIR-V output with the bracket-indexing workaround. Trace the HLSL matrix-swizzle handling and diagnostic path; done means matrix swizzling is implemented correctly, or unsupported syntax reliably produces a compile error or visible diagnostic instead of constant output.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp
Domain
compilers
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.