KhronosGroup / KhronosGroup/glslang
HLSL zero-based matrix indexing (_m00, _m32 etc.) replaced with constant 0 (Missing functionality: matrix swizzle)
- 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
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