HLSL: Partially flatten hierarchies, instead of all or nothing.

Fixes #1092.  Allows arrays of opaques to keep arrayness, unless
needed by uniform array flattening.
Can handle assignments of mixed amounts of flattening.
This commit is contained in:
John Kessenich 2017-10-11 14:03:45 -06:00
parent 60e9161100
commit 41aa19953f
8 changed files with 741 additions and 163 deletions

View File

@ -0,0 +1,366 @@
hlsl.partialFlattenLocal.vert
WARNING: AST will form illegal SPIR-V; need to transform to legalize
Shader version: 500
0:? Sequence
0:12 Function Definition: @main(vf4; ( temp 4-component vector of float)
0:12 Function Parameters:
0:12 'pos' ( in 4-component vector of float)
0:? Sequence
0:14 move second child to first child ( temp texture2D)
0:? 'packed.tex' ( temp texture2D)
0:14 'tex' ( uniform texture2D)
0:15 move second child to first child ( temp 3-component vector of float)
0:15 direct index ( temp 3-component vector of float)
0:? 'packed.pos' ( temp 3-element array of 3-component vector of float)
0:15 Constant:
0:15 0 (const int)
0:? Constant:
0:? 0.000000
0:? 0.000000
0:? 0.000000
0:16 move second child to first child ( temp 2-component vector of float)
0:16 direct index ( temp 2-component vector of float)
0:? 'packed.uv' ( temp 2-element array of 2-component vector of float)
0:16 Constant:
0:16 0 (const int)
0:? Constant:
0:? 0.000000
0:? 1.000000
0:17 move second child to first child ( temp float)
0:? 'packed.x' ( temp float)
0:17 Constant:
0:17 1.000000
0:18 move second child to first child ( temp int)
0:? 'packed.n' ( temp int)
0:18 Constant:
0:18 3 (const int)
0:20 Sequence
0:20 move second child to first child ( temp int)
0:20 'i' ( temp int)
0:20 Constant:
0:20 0 (const int)
0:20 Loop with condition tested first
0:20 Loop Condition
0:20 Compare Less Than ( temp bool)
0:20 'i' ( temp int)
0:20 Constant:
0:20 1 (const int)
0:20 Loop Body
0:? Sequence
0:21 add second child into first child ( temp 2-component vector of float)
0:21 vector swizzle ( temp 2-component vector of float)
0:21 indirect index ( temp 3-component vector of float)
0:? 'packed.pos' ( temp 3-element array of 3-component vector of float)
0:21 'i' ( temp int)
0:21 Sequence
0:21 Constant:
0:21 0 (const int)
0:21 Constant:
0:21 1 (const int)
0:21 indirect index ( temp 2-component vector of float)
0:? 'packed.uv' ( temp 2-element array of 2-component vector of float)
0:21 'i' ( temp int)
0:20 Loop Terminal Expression
0:20 Pre-Increment ( temp int)
0:20 'i' ( temp int)
0:24 Sequence
0:24 Sequence
0:24 move second child to first child ( temp texture2D)
0:? 'packed2.tex' ( temp texture2D)
0:? 'packed.tex' ( temp texture2D)
0:24 move second child to first child ( temp 3-element array of 3-component vector of float)
0:? 'packed2.pos' ( temp 3-element array of 3-component vector of float)
0:? 'packed.pos' ( temp 3-element array of 3-component vector of float)
0:24 move second child to first child ( temp 2-element array of 2-component vector of float)
0:? 'packed2.uv' ( temp 2-element array of 2-component vector of float)
0:? 'packed.uv' ( temp 2-element array of 2-component vector of float)
0:24 move second child to first child ( temp float)
0:? 'packed2.x' ( temp float)
0:? 'packed.x' ( temp float)
0:24 move second child to first child ( temp int)
0:? 'packed2.n' ( temp int)
0:? 'packed.n' ( temp int)
0:26 Branch: Return with expression
0:26 add ( temp 4-component vector of float)
0:26 'pos' ( in 4-component vector of float)
0:? Construct vec4 ( temp 4-component vector of float)
0:26 direct index ( temp 3-component vector of float)
0:? 'packed2.pos' ( temp 3-element array of 3-component vector of float)
0:26 Constant:
0:26 0 (const int)
0:26 Constant:
0:26 0.000000
0:12 Function Definition: main( ( temp void)
0:12 Function Parameters:
0:? Sequence
0:12 move second child to first child ( temp 4-component vector of float)
0:? 'pos' ( temp 4-component vector of float)
0:? 'pos' (layout( location=0) in 4-component vector of float)
0:12 move second child to first child ( temp 4-component vector of float)
0:? '@entryPointOutput' ( out 4-component vector of float Position)
0:12 Function Call: @main(vf4; ( temp 4-component vector of float)
0:? 'pos' ( temp 4-component vector of float)
0:? Linker Objects
0:? 'tex' ( uniform texture2D)
0:? '@entryPointOutput' ( out 4-component vector of float Position)
0:? 'pos' (layout( location=0) in 4-component vector of float)
Linked vertex stage:
Shader version: 500
0:? Sequence
0:12 Function Definition: @main(vf4; ( temp 4-component vector of float)
0:12 Function Parameters:
0:12 'pos' ( in 4-component vector of float)
0:? Sequence
0:14 move second child to first child ( temp texture2D)
0:? 'packed.tex' ( temp texture2D)
0:14 'tex' ( uniform texture2D)
0:15 move second child to first child ( temp 3-component vector of float)
0:15 direct index ( temp 3-component vector of float)
0:? 'packed.pos' ( temp 3-element array of 3-component vector of float)
0:15 Constant:
0:15 0 (const int)
0:? Constant:
0:? 0.000000
0:? 0.000000
0:? 0.000000
0:16 move second child to first child ( temp 2-component vector of float)
0:16 direct index ( temp 2-component vector of float)
0:? 'packed.uv' ( temp 2-element array of 2-component vector of float)
0:16 Constant:
0:16 0 (const int)
0:? Constant:
0:? 0.000000
0:? 1.000000
0:17 move second child to first child ( temp float)
0:? 'packed.x' ( temp float)
0:17 Constant:
0:17 1.000000
0:18 move second child to first child ( temp int)
0:? 'packed.n' ( temp int)
0:18 Constant:
0:18 3 (const int)
0:20 Sequence
0:20 move second child to first child ( temp int)
0:20 'i' ( temp int)
0:20 Constant:
0:20 0 (const int)
0:20 Loop with condition tested first
0:20 Loop Condition
0:20 Compare Less Than ( temp bool)
0:20 'i' ( temp int)
0:20 Constant:
0:20 1 (const int)
0:20 Loop Body
0:? Sequence
0:21 add second child into first child ( temp 2-component vector of float)
0:21 vector swizzle ( temp 2-component vector of float)
0:21 indirect index ( temp 3-component vector of float)
0:? 'packed.pos' ( temp 3-element array of 3-component vector of float)
0:21 'i' ( temp int)
0:21 Sequence
0:21 Constant:
0:21 0 (const int)
0:21 Constant:
0:21 1 (const int)
0:21 indirect index ( temp 2-component vector of float)
0:? 'packed.uv' ( temp 2-element array of 2-component vector of float)
0:21 'i' ( temp int)
0:20 Loop Terminal Expression
0:20 Pre-Increment ( temp int)
0:20 'i' ( temp int)
0:24 Sequence
0:24 Sequence
0:24 move second child to first child ( temp texture2D)
0:? 'packed2.tex' ( temp texture2D)
0:? 'packed.tex' ( temp texture2D)
0:24 move second child to first child ( temp 3-element array of 3-component vector of float)
0:? 'packed2.pos' ( temp 3-element array of 3-component vector of float)
0:? 'packed.pos' ( temp 3-element array of 3-component vector of float)
0:24 move second child to first child ( temp 2-element array of 2-component vector of float)
0:? 'packed2.uv' ( temp 2-element array of 2-component vector of float)
0:? 'packed.uv' ( temp 2-element array of 2-component vector of float)
0:24 move second child to first child ( temp float)
0:? 'packed2.x' ( temp float)
0:? 'packed.x' ( temp float)
0:24 move second child to first child ( temp int)
0:? 'packed2.n' ( temp int)
0:? 'packed.n' ( temp int)
0:26 Branch: Return with expression
0:26 add ( temp 4-component vector of float)
0:26 'pos' ( in 4-component vector of float)
0:? Construct vec4 ( temp 4-component vector of float)
0:26 direct index ( temp 3-component vector of float)
0:? 'packed2.pos' ( temp 3-element array of 3-component vector of float)
0:26 Constant:
0:26 0 (const int)
0:26 Constant:
0:26 0.000000
0:12 Function Definition: main( ( temp void)
0:12 Function Parameters:
0:? Sequence
0:12 move second child to first child ( temp 4-component vector of float)
0:? 'pos' ( temp 4-component vector of float)
0:? 'pos' (layout( location=0) in 4-component vector of float)
0:12 move second child to first child ( temp 4-component vector of float)
0:? '@entryPointOutput' ( out 4-component vector of float Position)
0:12 Function Call: @main(vf4; ( temp 4-component vector of float)
0:? 'pos' ( temp 4-component vector of float)
0:? Linker Objects
0:? 'tex' ( uniform texture2D)
0:? '@entryPointOutput' ( out 4-component vector of float Position)
0:? 'pos' (layout( location=0) in 4-component vector of float)
// Module Version 10000
// Generated by (magic number): 80002
// Id's are bound by 97
Capability Shader
1: ExtInstImport "GLSL.std.450"
MemoryModel Logical GLSL450
EntryPoint Vertex 4 "main" 90 93
Source HLSL 500
Name 4 "main"
Name 11 "@main(vf4;"
Name 10 "pos"
Name 15 "packed.tex"
Name 17 "tex"
Name 24 "packed.pos"
Name 35 "packed.uv"
Name 41 "packed.x"
Name 43 "packed.n"
Name 45 "i"
Name 68 "packed2.tex"
Name 70 "packed2.pos"
Name 72 "packed2.uv"
Name 74 "packed2.x"
Name 76 "packed2.n"
Name 88 "pos"
Name 90 "pos"
Name 93 "@entryPointOutput"
Name 94 "param"
Decorate 17(tex) DescriptorSet 0
Decorate 90(pos) Location 0
Decorate 93(@entryPointOutput) BuiltIn Position
2: TypeVoid
3: TypeFunction 2
6: TypeFloat 32
7: TypeVector 6(float) 4
8: TypePointer Function 7(fvec4)
9: TypeFunction 7(fvec4) 8(ptr)
13: TypeImage 6(float) 2D sampled format:Unknown
14: TypePointer Function 13
16: TypePointer UniformConstant 13
17(tex): 16(ptr) Variable UniformConstant
19: TypeVector 6(float) 3
20: TypeInt 32 0
21: 20(int) Constant 3
22: TypeArray 19(fvec3) 21
23: TypePointer Function 22
25: TypeInt 32 1
26: 25(int) Constant 0
27: 6(float) Constant 0
28: 19(fvec3) ConstantComposite 27 27 27
29: TypePointer Function 19(fvec3)
31: TypeVector 6(float) 2
32: 20(int) Constant 2
33: TypeArray 31(fvec2) 32
34: TypePointer Function 33
36: 6(float) Constant 1065353216
37: 31(fvec2) ConstantComposite 27 36
38: TypePointer Function 31(fvec2)
40: TypePointer Function 6(float)
42: TypePointer Function 25(int)
44: 25(int) Constant 3
52: 25(int) Constant 1
53: TypeBool
89: TypePointer Input 7(fvec4)
90(pos): 89(ptr) Variable Input
92: TypePointer Output 7(fvec4)
93(@entryPointOutput): 92(ptr) Variable Output
4(main): 2 Function None 3
5: Label
88(pos): 8(ptr) Variable Function
94(param): 8(ptr) Variable Function
91: 7(fvec4) Load 90(pos)
Store 88(pos) 91
95: 7(fvec4) Load 88(pos)
Store 94(param) 95
96: 7(fvec4) FunctionCall 11(@main(vf4;) 94(param)
Store 93(@entryPointOutput) 96
Return
FunctionEnd
11(@main(vf4;): 7(fvec4) Function None 9
10(pos): 8(ptr) FunctionParameter
12: Label
15(packed.tex): 14(ptr) Variable Function
24(packed.pos): 23(ptr) Variable Function
35(packed.uv): 34(ptr) Variable Function
41(packed.x): 40(ptr) Variable Function
43(packed.n): 42(ptr) Variable Function
45(i): 42(ptr) Variable Function
68(packed2.tex): 14(ptr) Variable Function
70(packed2.pos): 23(ptr) Variable Function
72(packed2.uv): 34(ptr) Variable Function
74(packed2.x): 40(ptr) Variable Function
76(packed2.n): 42(ptr) Variable Function
18: 13 Load 17(tex)
Store 15(packed.tex) 18
30: 29(ptr) AccessChain 24(packed.pos) 26
Store 30 28
39: 38(ptr) AccessChain 35(packed.uv) 26
Store 39 37
Store 41(packed.x) 36
Store 43(packed.n) 44
Store 45(i) 26
Branch 46
46: Label
LoopMerge 48 49 None
Branch 50
50: Label
51: 25(int) Load 45(i)
54: 53(bool) SLessThan 51 52
BranchConditional 54 47 48
47: Label
55: 25(int) Load 45(i)
56: 25(int) Load 45(i)
57: 38(ptr) AccessChain 35(packed.uv) 56
58: 31(fvec2) Load 57
59: 29(ptr) AccessChain 24(packed.pos) 55
60: 19(fvec3) Load 59
61: 31(fvec2) VectorShuffle 60 60 0 1
62: 31(fvec2) FAdd 61 58
63: 29(ptr) AccessChain 24(packed.pos) 55
64: 19(fvec3) Load 63
65: 19(fvec3) VectorShuffle 64 62 3 4 2
Store 63 65
Branch 49
49: Label
66: 25(int) Load 45(i)
67: 25(int) IAdd 66 52
Store 45(i) 67
Branch 46
48: Label
69: 13 Load 15(packed.tex)
Store 68(packed2.tex) 69
71: 22 Load 24(packed.pos)
Store 70(packed2.pos) 71
73: 33 Load 35(packed.uv)
Store 72(packed2.uv) 73
75: 6(float) Load 41(packed.x)
Store 74(packed2.x) 75
77: 25(int) Load 43(packed.n)
Store 76(packed2.n) 77
78: 7(fvec4) Load 10(pos)
79: 29(ptr) AccessChain 70(packed2.pos) 26
80: 19(fvec3) Load 79
81: 6(float) CompositeExtract 80 0
82: 6(float) CompositeExtract 80 1
83: 6(float) CompositeExtract 80 2
84: 7(fvec4) CompositeConstruct 81 82 83 27
85: 7(fvec4) FAdd 78 84
ReturnValue 85
FunctionEnd

View File

@ -0,0 +1,150 @@
hlsl.partialFlattenMixed.vert
WARNING: AST will form illegal SPIR-V; need to transform to legalize
Shader version: 500
0:? Sequence
0:10 Function Definition: @main(vf4; ( temp 4-component vector of float)
0:10 Function Parameters:
0:10 'pos' ( in 4-component vector of float)
0:? Sequence
0:13 Sequence
0:13 move second child to first child ( temp texture2D)
0:13 direct index ( temp texture2D)
0:? 'packed.membTex' ( temp 2-element array of texture2D)
0:13 Constant:
0:13 0 (const int)
0:? 'tex[0]' ( uniform texture2D)
0:13 move second child to first child ( temp texture2D)
0:13 direct index ( temp texture2D)
0:? 'packed.membTex' ( temp 2-element array of texture2D)
0:13 Constant:
0:13 1 (const int)
0:? 'tex[1]' ( uniform texture2D)
0:15 Branch: Return with expression
0:15 'pos' ( in 4-component vector of float)
0:10 Function Definition: main( ( temp void)
0:10 Function Parameters:
0:? Sequence
0:10 move second child to first child ( temp 4-component vector of float)
0:? 'pos' ( temp 4-component vector of float)
0:? 'pos' (layout( location=0) in 4-component vector of float)
0:10 move second child to first child ( temp 4-component vector of float)
0:? '@entryPointOutput' ( out 4-component vector of float Position)
0:10 Function Call: @main(vf4; ( temp 4-component vector of float)
0:? 'pos' ( temp 4-component vector of float)
0:? Linker Objects
0:? 'tex[0]' ( uniform texture2D)
0:? 'tex[1]' ( uniform texture2D)
0:? '@entryPointOutput' ( out 4-component vector of float Position)
0:? 'pos' (layout( location=0) in 4-component vector of float)
Linked vertex stage:
Shader version: 500
0:? Sequence
0:10 Function Definition: @main(vf4; ( temp 4-component vector of float)
0:10 Function Parameters:
0:10 'pos' ( in 4-component vector of float)
0:? Sequence
0:13 Sequence
0:13 move second child to first child ( temp texture2D)
0:13 direct index ( temp texture2D)
0:? 'packed.membTex' ( temp 2-element array of texture2D)
0:13 Constant:
0:13 0 (const int)
0:? 'tex[0]' ( uniform texture2D)
0:13 move second child to first child ( temp texture2D)
0:13 direct index ( temp texture2D)
0:? 'packed.membTex' ( temp 2-element array of texture2D)
0:13 Constant:
0:13 1 (const int)
0:? 'tex[1]' ( uniform texture2D)
0:15 Branch: Return with expression
0:15 'pos' ( in 4-component vector of float)
0:10 Function Definition: main( ( temp void)
0:10 Function Parameters:
0:? Sequence
0:10 move second child to first child ( temp 4-component vector of float)
0:? 'pos' ( temp 4-component vector of float)
0:? 'pos' (layout( location=0) in 4-component vector of float)
0:10 move second child to first child ( temp 4-component vector of float)
0:? '@entryPointOutput' ( out 4-component vector of float Position)
0:10 Function Call: @main(vf4; ( temp 4-component vector of float)
0:? 'pos' ( temp 4-component vector of float)
0:? Linker Objects
0:? 'tex[0]' ( uniform texture2D)
0:? 'tex[1]' ( uniform texture2D)
0:? '@entryPointOutput' ( out 4-component vector of float Position)
0:? 'pos' (layout( location=0) in 4-component vector of float)
// Module Version 10000
// Generated by (magic number): 80002
// Id's are bound by 42
Capability Shader
1: ExtInstImport "GLSL.std.450"
MemoryModel Logical GLSL450
EntryPoint Vertex 4 "main" 35 38
Source HLSL 500
Name 4 "main"
Name 11 "@main(vf4;"
Name 10 "pos"
Name 18 "packed.membTex"
Name 22 "tex[0]"
Name 27 "tex[1]"
Name 33 "pos"
Name 35 "pos"
Name 38 "@entryPointOutput"
Name 39 "param"
Decorate 22(tex[0]) DescriptorSet 0
Decorate 27(tex[1]) DescriptorSet 0
Decorate 35(pos) Location 0
Decorate 38(@entryPointOutput) BuiltIn Position
2: TypeVoid
3: TypeFunction 2
6: TypeFloat 32
7: TypeVector 6(float) 4
8: TypePointer Function 7(fvec4)
9: TypeFunction 7(fvec4) 8(ptr)
13: TypeImage 6(float) 2D sampled format:Unknown
14: TypeInt 32 0
15: 14(int) Constant 2
16: TypeArray 13 15
17: TypePointer Function 16
19: TypeInt 32 1
20: 19(int) Constant 0
21: TypePointer UniformConstant 13
22(tex[0]): 21(ptr) Variable UniformConstant
24: TypePointer Function 13
26: 19(int) Constant 1
27(tex[1]): 21(ptr) Variable UniformConstant
34: TypePointer Input 7(fvec4)
35(pos): 34(ptr) Variable Input
37: TypePointer Output 7(fvec4)
38(@entryPointOutput): 37(ptr) Variable Output
4(main): 2 Function None 3
5: Label
33(pos): 8(ptr) Variable Function
39(param): 8(ptr) Variable Function
36: 7(fvec4) Load 35(pos)
Store 33(pos) 36
40: 7(fvec4) Load 33(pos)
Store 39(param) 40
41: 7(fvec4) FunctionCall 11(@main(vf4;) 39(param)
Store 38(@entryPointOutput) 41
Return
FunctionEnd
11(@main(vf4;): 7(fvec4) Function None 9
10(pos): 8(ptr) FunctionParameter
12: Label
18(packed.membTex): 17(ptr) Variable Function
23: 13 Load 22(tex[0])
25: 24(ptr) AccessChain 18(packed.membTex) 20
Store 25 23
28: 13 Load 27(tex[1])
29: 24(ptr) AccessChain 18(packed.membTex) 26
Store 29 28
30: 7(fvec4) Load 10(pos)
ReturnValue 30
FunctionEnd

View File

@ -27,8 +27,14 @@ gl_FragCoord origin is upper left
0:26 0.400000 0:26 0.400000
0:27 texture ( temp 4-component vector of float) 0:27 texture ( temp 4-component vector of float)
0:27 Construct combined texture-sampler ( temp sampler1D) 0:27 Construct combined texture-sampler ( temp sampler1D)
0:? 'g_texdata_array2[1].tex[0]' ( uniform texture1D) 0:27 direct index ( temp texture1D)
0:? 'g_texdata_array2[1].samp[0]' ( uniform sampler) 0:? 'g_texdata_array2[1].tex' ( uniform 2-element array of texture1D)
0:27 Constant:
0:27 0 (const int)
0:27 direct index ( temp sampler)
0:? 'g_texdata_array2[1].samp' ( uniform 2-element array of sampler)
0:27 Constant:
0:27 0 (const int)
0:27 Constant: 0:27 Constant:
0:27 0.300000 0:27 0.300000
0:23 Function Definition: main( ( temp void) 0:23 Function Definition: main( ( temp void)
@ -58,20 +64,14 @@ gl_FragCoord origin is upper left
0:? 'g_texdata_array[2].samp' ( uniform sampler) 0:? 'g_texdata_array[2].samp' ( uniform sampler)
0:? 'g_texdata_array[2].tex' ( uniform texture1D) 0:? 'g_texdata_array[2].tex' ( uniform texture1D)
0:? 'g_texdata_array[2].nonopaque_thing' ( uniform int) 0:? 'g_texdata_array[2].nonopaque_thing' ( uniform int)
0:? 'g_texdata_array2[0].samp[0]' ( uniform sampler) 0:? 'g_texdata_array2[0].samp' ( uniform 2-element array of sampler)
0:? 'g_texdata_array2[0].samp[1]' ( uniform sampler) 0:? 'g_texdata_array2[0].tex' ( uniform 2-element array of texture1D)
0:? 'g_texdata_array2[0].tex[0]' ( uniform texture1D)
0:? 'g_texdata_array2[0].tex[1]' ( uniform texture1D)
0:? 'g_texdata_array2[0].nonopaque_thing' ( uniform int) 0:? 'g_texdata_array2[0].nonopaque_thing' ( uniform int)
0:? 'g_texdata_array2[1].samp[0]' ( uniform sampler) 0:? 'g_texdata_array2[1].samp' ( uniform 2-element array of sampler)
0:? 'g_texdata_array2[1].samp[1]' ( uniform sampler) 0:? 'g_texdata_array2[1].tex' ( uniform 2-element array of texture1D)
0:? 'g_texdata_array2[1].tex[0]' ( uniform texture1D)
0:? 'g_texdata_array2[1].tex[1]' ( uniform texture1D)
0:? 'g_texdata_array2[1].nonopaque_thing' ( uniform int) 0:? 'g_texdata_array2[1].nonopaque_thing' ( uniform int)
0:? 'g_texdata_array2[2].samp[0]' ( uniform sampler) 0:? 'g_texdata_array2[2].samp' ( uniform 2-element array of sampler)
0:? 'g_texdata_array2[2].samp[1]' ( uniform sampler) 0:? 'g_texdata_array2[2].tex' ( uniform 2-element array of texture1D)
0:? 'g_texdata_array2[2].tex[0]' ( uniform texture1D)
0:? 'g_texdata_array2[2].tex[1]' ( uniform texture1D)
0:? 'g_texdata_array2[2].nonopaque_thing' ( uniform int) 0:? 'g_texdata_array2[2].nonopaque_thing' ( uniform int)
0:? 'ps_output.color' (layout( location=0) out 4-component vector of float) 0:? 'ps_output.color' (layout( location=0) out 4-component vector of float)
@ -107,8 +107,14 @@ gl_FragCoord origin is upper left
0:26 0.400000 0:26 0.400000
0:27 texture ( temp 4-component vector of float) 0:27 texture ( temp 4-component vector of float)
0:27 Construct combined texture-sampler ( temp sampler1D) 0:27 Construct combined texture-sampler ( temp sampler1D)
0:? 'g_texdata_array2[1].tex[0]' ( uniform texture1D) 0:27 direct index ( temp texture1D)
0:? 'g_texdata_array2[1].samp[0]' ( uniform sampler) 0:? 'g_texdata_array2[1].tex' ( uniform 2-element array of texture1D)
0:27 Constant:
0:27 0 (const int)
0:27 direct index ( temp sampler)
0:? 'g_texdata_array2[1].samp' ( uniform 2-element array of sampler)
0:27 Constant:
0:27 0 (const int)
0:27 Constant: 0:27 Constant:
0:27 0.300000 0:27 0.300000
0:23 Function Definition: main( ( temp void) 0:23 Function Definition: main( ( temp void)
@ -138,32 +144,26 @@ gl_FragCoord origin is upper left
0:? 'g_texdata_array[2].samp' ( uniform sampler) 0:? 'g_texdata_array[2].samp' ( uniform sampler)
0:? 'g_texdata_array[2].tex' ( uniform texture1D) 0:? 'g_texdata_array[2].tex' ( uniform texture1D)
0:? 'g_texdata_array[2].nonopaque_thing' ( uniform int) 0:? 'g_texdata_array[2].nonopaque_thing' ( uniform int)
0:? 'g_texdata_array2[0].samp[0]' ( uniform sampler) 0:? 'g_texdata_array2[0].samp' ( uniform 2-element array of sampler)
0:? 'g_texdata_array2[0].samp[1]' ( uniform sampler) 0:? 'g_texdata_array2[0].tex' ( uniform 2-element array of texture1D)
0:? 'g_texdata_array2[0].tex[0]' ( uniform texture1D)
0:? 'g_texdata_array2[0].tex[1]' ( uniform texture1D)
0:? 'g_texdata_array2[0].nonopaque_thing' ( uniform int) 0:? 'g_texdata_array2[0].nonopaque_thing' ( uniform int)
0:? 'g_texdata_array2[1].samp[0]' ( uniform sampler) 0:? 'g_texdata_array2[1].samp' ( uniform 2-element array of sampler)
0:? 'g_texdata_array2[1].samp[1]' ( uniform sampler) 0:? 'g_texdata_array2[1].tex' ( uniform 2-element array of texture1D)
0:? 'g_texdata_array2[1].tex[0]' ( uniform texture1D)
0:? 'g_texdata_array2[1].tex[1]' ( uniform texture1D)
0:? 'g_texdata_array2[1].nonopaque_thing' ( uniform int) 0:? 'g_texdata_array2[1].nonopaque_thing' ( uniform int)
0:? 'g_texdata_array2[2].samp[0]' ( uniform sampler) 0:? 'g_texdata_array2[2].samp' ( uniform 2-element array of sampler)
0:? 'g_texdata_array2[2].samp[1]' ( uniform sampler) 0:? 'g_texdata_array2[2].tex' ( uniform 2-element array of texture1D)
0:? 'g_texdata_array2[2].tex[0]' ( uniform texture1D)
0:? 'g_texdata_array2[2].tex[1]' ( uniform texture1D)
0:? 'g_texdata_array2[2].nonopaque_thing' ( uniform int) 0:? 'g_texdata_array2[2].nonopaque_thing' ( uniform int)
0:? 'ps_output.color' (layout( location=0) out 4-component vector of float) 0:? 'ps_output.color' (layout( location=0) out 4-component vector of float)
// Module Version 10000 // Module Version 10000
// Generated by (magic number): 80002 // Generated by (magic number): 80002
// Id's are bound by 78 // Id's are bound by 80
Capability Shader Capability Shader
Capability Sampled1D Capability Sampled1D
1: ExtInstImport "GLSL.std.450" 1: ExtInstImport "GLSL.std.450"
MemoryModel Logical GLSL450 MemoryModel Logical GLSL450
EntryPoint Fragment 4 "main" 51 EntryPoint Fragment 4 "main" 59
ExecutionMode 4 OriginUpperLeft ExecutionMode 4 OriginUpperLeft
Source HLSL 500 Source HLSL 500
Name 4 "main" Name 4 "main"
@ -175,57 +175,45 @@ gl_FragCoord origin is upper left
Name 22 "g_texdata.samp" Name 22 "g_texdata.samp"
Name 28 "g_texdata_array[1].tex" Name 28 "g_texdata_array[1].tex"
Name 30 "g_texdata_array[1].samp" Name 30 "g_texdata_array[1].samp"
Name 36 "g_texdata_array2[1].tex[0]" Name 40 "g_texdata_array2[1].tex"
Name 38 "g_texdata_array2[1].samp[0]" Name 45 "g_texdata_array2[1].samp"
Name 46 "ps_output" Name 54 "ps_output"
Name 47 "param" Name 55 "param"
Name 51 "ps_output.color" Name 59 "ps_output.color"
Name 54 "g_samp" Name 62 "g_samp"
Name 55 "g_tex" Name 63 "g_tex"
Name 57 "g_texdata.nonopaque_thing" Name 65 "g_texdata.nonopaque_thing"
Name 58 "g_texdata_array[0].samp" Name 66 "g_texdata_array[0].samp"
Name 59 "g_texdata_array[0].tex" Name 67 "g_texdata_array[0].tex"
Name 60 "g_texdata_array[0].nonopaque_thing" Name 68 "g_texdata_array[0].nonopaque_thing"
Name 61 "g_texdata_array[1].nonopaque_thing" Name 69 "g_texdata_array[1].nonopaque_thing"
Name 62 "g_texdata_array[2].samp" Name 70 "g_texdata_array[2].samp"
Name 63 "g_texdata_array[2].tex" Name 71 "g_texdata_array[2].tex"
Name 64 "g_texdata_array[2].nonopaque_thing" Name 72 "g_texdata_array[2].nonopaque_thing"
Name 65 "g_texdata_array2[0].samp[0]" Name 73 "g_texdata_array2[0].samp"
Name 66 "g_texdata_array2[0].samp[1]" Name 74 "g_texdata_array2[0].tex"
Name 67 "g_texdata_array2[0].tex[0]" Name 75 "g_texdata_array2[0].nonopaque_thing"
Name 68 "g_texdata_array2[0].tex[1]" Name 76 "g_texdata_array2[1].nonopaque_thing"
Name 69 "g_texdata_array2[0].nonopaque_thing" Name 77 "g_texdata_array2[2].samp"
Name 70 "g_texdata_array2[1].samp[1]" Name 78 "g_texdata_array2[2].tex"
Name 71 "g_texdata_array2[1].tex[1]" Name 79 "g_texdata_array2[2].nonopaque_thing"
Name 72 "g_texdata_array2[1].nonopaque_thing"
Name 73 "g_texdata_array2[2].samp[0]"
Name 74 "g_texdata_array2[2].samp[1]"
Name 75 "g_texdata_array2[2].tex[0]"
Name 76 "g_texdata_array2[2].tex[1]"
Name 77 "g_texdata_array2[2].nonopaque_thing"
Decorate 18(g_texdata.tex) DescriptorSet 0 Decorate 18(g_texdata.tex) DescriptorSet 0
Decorate 22(g_texdata.samp) DescriptorSet 0 Decorate 22(g_texdata.samp) DescriptorSet 0
Decorate 28(g_texdata_array[1].tex) DescriptorSet 0 Decorate 28(g_texdata_array[1].tex) DescriptorSet 0
Decorate 30(g_texdata_array[1].samp) DescriptorSet 0 Decorate 30(g_texdata_array[1].samp) DescriptorSet 0
Decorate 36(g_texdata_array2[1].tex[0]) DescriptorSet 0 Decorate 40(g_texdata_array2[1].tex) DescriptorSet 0
Decorate 38(g_texdata_array2[1].samp[0]) DescriptorSet 0 Decorate 45(g_texdata_array2[1].samp) DescriptorSet 0
Decorate 51(ps_output.color) Location 0 Decorate 59(ps_output.color) Location 0
Decorate 54(g_samp) DescriptorSet 0 Decorate 62(g_samp) DescriptorSet 0
Decorate 55(g_tex) DescriptorSet 0 Decorate 63(g_tex) DescriptorSet 0
Decorate 58(g_texdata_array[0].samp) DescriptorSet 0 Decorate 66(g_texdata_array[0].samp) DescriptorSet 0
Decorate 59(g_texdata_array[0].tex) DescriptorSet 0 Decorate 67(g_texdata_array[0].tex) DescriptorSet 0
Decorate 62(g_texdata_array[2].samp) DescriptorSet 0 Decorate 70(g_texdata_array[2].samp) DescriptorSet 0
Decorate 63(g_texdata_array[2].tex) DescriptorSet 0 Decorate 71(g_texdata_array[2].tex) DescriptorSet 0
Decorate 65(g_texdata_array2[0].samp[0]) DescriptorSet 0 Decorate 73(g_texdata_array2[0].samp) DescriptorSet 0
Decorate 66(g_texdata_array2[0].samp[1]) DescriptorSet 0 Decorate 74(g_texdata_array2[0].tex) DescriptorSet 0
Decorate 67(g_texdata_array2[0].tex[0]) DescriptorSet 0 Decorate 77(g_texdata_array2[2].samp) DescriptorSet 0
Decorate 68(g_texdata_array2[0].tex[1]) DescriptorSet 0 Decorate 78(g_texdata_array2[2].tex) DescriptorSet 0
Decorate 70(g_texdata_array2[1].samp[1]) DescriptorSet 0
Decorate 71(g_texdata_array2[1].tex[1]) DescriptorSet 0
Decorate 73(g_texdata_array2[2].samp[0]) DescriptorSet 0
Decorate 74(g_texdata_array2[2].samp[1]) DescriptorSet 0
Decorate 75(g_texdata_array2[2].tex[0]) DescriptorSet 0
Decorate 76(g_texdata_array2[2].tex[1]) DescriptorSet 0
2: TypeVoid 2: TypeVoid
3: TypeFunction 2 3: TypeFunction 2
6: TypeFloat 32 6: TypeFloat 32
@ -246,46 +234,46 @@ gl_FragCoord origin is upper left
28(g_texdata_array[1].tex): 17(ptr) Variable UniformConstant 28(g_texdata_array[1].tex): 17(ptr) Variable UniformConstant
30(g_texdata_array[1].samp): 21(ptr) Variable UniformConstant 30(g_texdata_array[1].samp): 21(ptr) Variable UniformConstant
33: 6(float) Constant 1053609165 33: 6(float) Constant 1053609165
36(g_texdata_array2[1].tex[0]): 17(ptr) Variable UniformConstant 36: TypeInt 32 0
38(g_texdata_array2[1].samp[0]): 21(ptr) Variable UniformConstant 37: 36(int) Constant 2
41: 6(float) Constant 1050253722 38: TypeArray 16 37
44: TypePointer Function 7(fvec4) 39: TypePointer UniformConstant 38
50: TypePointer Output 7(fvec4) 40(g_texdata_array2[1].tex): 39(ptr) Variable UniformConstant
51(ps_output.color): 50(ptr) Variable Output 43: TypeArray 20 37
54(g_samp): 21(ptr) Variable UniformConstant 44: TypePointer UniformConstant 43
55(g_tex): 17(ptr) Variable UniformConstant 45(g_texdata_array2[1].samp): 44(ptr) Variable UniformConstant
56: TypePointer UniformConstant 14(int) 49: 6(float) Constant 1050253722
57(g_texdata.nonopaque_thing): 56(ptr) Variable UniformConstant 52: TypePointer Function 7(fvec4)
58(g_texdata_array[0].samp): 21(ptr) Variable UniformConstant 58: TypePointer Output 7(fvec4)
59(g_texdata_array[0].tex): 17(ptr) Variable UniformConstant 59(ps_output.color): 58(ptr) Variable Output
60(g_texdata_array[0].nonopaque_thing): 56(ptr) Variable UniformConstant 62(g_samp): 21(ptr) Variable UniformConstant
61(g_texdata_array[1].nonopaque_thing): 56(ptr) Variable UniformConstant 63(g_tex): 17(ptr) Variable UniformConstant
62(g_texdata_array[2].samp): 21(ptr) Variable UniformConstant 64: TypePointer UniformConstant 14(int)
63(g_texdata_array[2].tex): 17(ptr) Variable UniformConstant 65(g_texdata.nonopaque_thing): 64(ptr) Variable UniformConstant
64(g_texdata_array[2].nonopaque_thing): 56(ptr) Variable UniformConstant 66(g_texdata_array[0].samp): 21(ptr) Variable UniformConstant
65(g_texdata_array2[0].samp[0]): 21(ptr) Variable UniformConstant 67(g_texdata_array[0].tex): 17(ptr) Variable UniformConstant
66(g_texdata_array2[0].samp[1]): 21(ptr) Variable UniformConstant 68(g_texdata_array[0].nonopaque_thing): 64(ptr) Variable UniformConstant
67(g_texdata_array2[0].tex[0]): 17(ptr) Variable UniformConstant 69(g_texdata_array[1].nonopaque_thing): 64(ptr) Variable UniformConstant
68(g_texdata_array2[0].tex[1]): 17(ptr) Variable UniformConstant 70(g_texdata_array[2].samp): 21(ptr) Variable UniformConstant
69(g_texdata_array2[0].nonopaque_thing): 56(ptr) Variable UniformConstant 71(g_texdata_array[2].tex): 17(ptr) Variable UniformConstant
70(g_texdata_array2[1].samp[1]): 21(ptr) Variable UniformConstant 72(g_texdata_array[2].nonopaque_thing): 64(ptr) Variable UniformConstant
71(g_texdata_array2[1].tex[1]): 17(ptr) Variable UniformConstant 73(g_texdata_array2[0].samp): 44(ptr) Variable UniformConstant
72(g_texdata_array2[1].nonopaque_thing): 56(ptr) Variable UniformConstant 74(g_texdata_array2[0].tex): 39(ptr) Variable UniformConstant
73(g_texdata_array2[2].samp[0]): 21(ptr) Variable UniformConstant 75(g_texdata_array2[0].nonopaque_thing): 64(ptr) Variable UniformConstant
74(g_texdata_array2[2].samp[1]): 21(ptr) Variable UniformConstant 76(g_texdata_array2[1].nonopaque_thing): 64(ptr) Variable UniformConstant
75(g_texdata_array2[2].tex[0]): 17(ptr) Variable UniformConstant 77(g_texdata_array2[2].samp): 44(ptr) Variable UniformConstant
76(g_texdata_array2[2].tex[1]): 17(ptr) Variable UniformConstant 78(g_texdata_array2[2].tex): 39(ptr) Variable UniformConstant
77(g_texdata_array2[2].nonopaque_thing): 56(ptr) Variable UniformConstant 79(g_texdata_array2[2].nonopaque_thing): 64(ptr) Variable UniformConstant
4(main): 2 Function None 3 4(main): 2 Function None 3
5: Label 5: Label
46(ps_output): 9(ptr) Variable Function 54(ps_output): 9(ptr) Variable Function
47(param): 9(ptr) Variable Function 55(param): 9(ptr) Variable Function
48: 2 FunctionCall 12(@main(struct-PS_OUTPUT-vf41;) 47(param) 56: 2 FunctionCall 12(@main(struct-PS_OUTPUT-vf41;) 55(param)
49:8(PS_OUTPUT) Load 47(param) 57:8(PS_OUTPUT) Load 55(param)
Store 46(ps_output) 49 Store 54(ps_output) 57
52: 44(ptr) AccessChain 46(ps_output) 15 60: 52(ptr) AccessChain 54(ps_output) 15
53: 7(fvec4) Load 52 61: 7(fvec4) Load 60
Store 51(ps_output.color) 53 Store 59(ps_output.color) 61
Return Return
FunctionEnd FunctionEnd
12(@main(struct-PS_OUTPUT-vf41;): 2 Function None 10 12(@main(struct-PS_OUTPUT-vf41;): 2 Function None 10
@ -300,12 +288,14 @@ gl_FragCoord origin is upper left
32: 24 SampledImage 29 31 32: 24 SampledImage 29 31
34: 7(fvec4) ImageSampleImplicitLod 32 33 34: 7(fvec4) ImageSampleImplicitLod 32 33
35: 7(fvec4) FAdd 27 34 35: 7(fvec4) FAdd 27 34
37: 16 Load 36(g_texdata_array2[1].tex[0]) 41: 17(ptr) AccessChain 40(g_texdata_array2[1].tex) 15
39: 20 Load 38(g_texdata_array2[1].samp[0]) 42: 16 Load 41
40: 24 SampledImage 37 39 46: 21(ptr) AccessChain 45(g_texdata_array2[1].samp) 15
42: 7(fvec4) ImageSampleImplicitLod 40 41 47: 20 Load 46
43: 7(fvec4) FAdd 35 42 48: 24 SampledImage 42 47
45: 44(ptr) AccessChain 11(ps_output) 15 50: 7(fvec4) ImageSampleImplicitLod 48 49
Store 45 43 51: 7(fvec4) FAdd 35 50
53: 52(ptr) AccessChain 11(ps_output) 15
Store 53 51
Return Return
FunctionEnd FunctionEnd

View File

@ -0,0 +1,27 @@
Texture2D tex;
struct Packed {
Texture2D tex;
float3 pos[3];
float2 uv[2];
float x;
int n;
};
float4 main(float4 pos : POSITION) : SV_POSITION
{
Packed packed;
packed.tex = tex;
packed.pos[0] = float3(0, 0, 0);
packed.uv[0] = float2(0, 1);
packed.x = 1.0;
packed.n = 3;
for (int i = 0; i < 1; ++i) {
packed.pos[i].xy += packed.uv[i];
}
Packed packed2 = packed;
return pos + float4(packed2.pos[0], 0);
}

View File

@ -0,0 +1,16 @@
Texture2D tex[2];
struct Packed {
int a;
Texture2D membTex[2];
int b;
};
float4 main(float4 pos : POSITION) : SV_POSITION
{
Packed packed;
packed.membTex = tex;
return pos;
}

View File

@ -247,6 +247,7 @@ INSTANTIATE_TEST_CASE_P(
{"hlsl.params.default.frag", "main"}, {"hlsl.params.default.frag", "main"},
{"hlsl.params.default.negative.frag", "main"}, {"hlsl.params.default.negative.frag", "main"},
{"hlsl.partialInit.frag", "PixelShaderFunction"}, {"hlsl.partialInit.frag", "PixelShaderFunction"},
{"hlsl.partialFlattenLocal.vert", "main"},
{"hlsl.pp.vert", "main"}, {"hlsl.pp.vert", "main"},
{"hlsl.pp.line.frag", "main"}, {"hlsl.pp.line.frag", "main"},
{"hlsl.precise.frag", "main"}, {"hlsl.precise.frag", "main"},
@ -367,6 +368,7 @@ INSTANTIATE_TEST_CASE_P(
ToSpirv, HlslCompileAndFlattenTest, ToSpirv, HlslCompileAndFlattenTest,
::testing::ValuesIn(std::vector<FileNameEntryPointPair>{ ::testing::ValuesIn(std::vector<FileNameEntryPointPair>{
{"hlsl.array.flatten.frag", "main"}, {"hlsl.array.flatten.frag", "main"},
{"hlsl.partialFlattenMixed.vert", "main"},
}), }),
FileNameAsCustomTestSuffix FileNameAsCustomTestSuffix
); );

View File

@ -1146,13 +1146,22 @@ const TType& HlslParseContext::split(const TType& type, const TString& name, con
return type; return type;
} }
// Is this a uniform array or structure which should be flattened? // Is this an aggregate that should be flattened?
bool HlslParseContext::shouldFlatten(const TType& type) const // Can be applied to intermediate levels of type in a hierarchy.
// Some things like flattening uniform arrays are only about the top level
// of the aggregate, triggered on 'topLevel'.
bool HlslParseContext::shouldFlatten(const TType& type, TStorageQualifier qualifier, bool topLevel) const
{ {
const TStorageQualifier qualifier = type.getQualifier().storage; switch (qualifier) {
case EvqVaryingIn:
return (qualifier == EvqUniform && type.isArray() && intermediate.getFlattenUniformArrays()) || case EvqVaryingOut:
(type.isStruct() && type.containsOpaque()); return type.isStruct() || type.isArray();
case EvqUniform:
return type.isArray() && intermediate.getFlattenUniformArrays() && topLevel ||
type.isStruct() && type.containsOpaque();
default:
return type.isStruct() && type.containsOpaque();
};
} }
// Top level variable flattening: construct data // Top level variable flattening: construct data
@ -1223,7 +1232,7 @@ int HlslParseContext::addFlattenedMember(const TVariable& variable, const TType&
const TQualifier& outerQualifier, const TQualifier& outerQualifier,
const TArraySizes* builtInArraySizes) const TArraySizes* builtInArraySizes)
{ {
if (isFinalFlattening(type)) { if (!shouldFlatten(type, outerQualifier.storage, false)) {
// This is as far as we flatten. Insert the variable. // This is as far as we flatten. Insert the variable.
TVariable* memberVariable = makeInternalVariable(memberName, type); TVariable* memberVariable = makeInternalVariable(memberName, type);
mergeQualifiers(memberVariable->getWritableType().getQualifier(), variable.getType().getQualifier()); mergeQualifiers(memberVariable->getWritableType().getQualifier(), variable.getType().getQualifier());
@ -1347,11 +1356,13 @@ TIntermTyped* HlslParseContext::flattenAccess(TIntermTyped* base, int member)
{ {
const TType dereferencedType(base->getType(), member); // dereferenced type const TType dereferencedType(base->getType(), member); // dereferenced type
const TIntermSymbol& symbolNode = *base->getAsSymbolNode(); const TIntermSymbol& symbolNode = *base->getAsSymbolNode();
TIntermTyped* flattened = flattenAccess(symbolNode.getId(), member, dereferencedType, symbolNode.getFlattenSubset()); TIntermTyped* flattened = flattenAccess(symbolNode.getId(), member, base->getQualifier().storage,
dereferencedType, symbolNode.getFlattenSubset());
return flattened ? flattened : base; return flattened ? flattened : base;
} }
TIntermTyped* HlslParseContext::flattenAccess(int uniqueId, int member, const TType& dereferencedType, int subset) TIntermTyped* HlslParseContext::flattenAccess(int uniqueId, int member, TStorageQualifier outerStorage,
const TType& dereferencedType, int subset)
{ {
const auto flattenData = flattenMap.find(uniqueId); const auto flattenData = flattenMap.find(uniqueId);
@ -1362,7 +1373,7 @@ TIntermTyped* HlslParseContext::flattenAccess(int uniqueId, int member, const TT
int newSubset = flattenData->second.offsets[subset >= 0 ? subset + member : member]; int newSubset = flattenData->second.offsets[subset >= 0 ? subset + member : member];
TIntermSymbol* subsetSymbol; TIntermSymbol* subsetSymbol;
if (isFinalFlattening(dereferencedType)) { if (!shouldFlatten(dereferencedType, outerStorage, false)) {
// Finished flattening: create symbol for variable // Finished flattening: create symbol for variable
member = flattenData->second.offsets[newSubset]; member = flattenData->second.offsets[newSubset];
const TVariable* memberVariable = flattenData->second.members[member]; const TVariable* memberVariable = flattenData->second.members[member];
@ -1670,7 +1681,7 @@ TIntermAggregate* HlslParseContext::handleFunctionDefinition(const TSourceLoc& l
error(loc, "redefinition", variable->getName().c_str(), ""); error(loc, "redefinition", variable->getName().c_str(), "");
// Add parameters to the AST list. // Add parameters to the AST list.
if (shouldFlatten(variable->getType())) { if (shouldFlatten(variable->getType(), variable->getType().getQualifier().storage, true)) {
// Expand the AST parameter nodes (but not the name mangling or symbol table view) // Expand the AST parameter nodes (but not the name mangling or symbol table view)
// for structures that need to be flattened. // for structures that need to be flattened.
flatten(*variable, false); flatten(*variable, false);
@ -1678,7 +1689,8 @@ TIntermAggregate* HlslParseContext::handleFunctionDefinition(const TSourceLoc& l
for (int mem = 0; mem < (int)structure->size(); ++mem) { for (int mem = 0; mem < (int)structure->size(); ++mem) {
paramNodes = intermediate.growAggregate(paramNodes, paramNodes = intermediate.growAggregate(paramNodes,
flattenAccess(variable->getUniqueId(), mem, flattenAccess(variable->getUniqueId(), mem,
*(*structure)[mem].type), variable->getType().getQualifier().storage,
*(*structure)[mem].type),
loc); loc);
} }
} else { } else {
@ -1931,7 +1943,7 @@ TIntermNode* HlslParseContext::transformEntryPoint(const TSourceLoc& loc, TFunct
if (variable.getType().getQualifier().isArrayedIo(language)) { if (variable.getType().getQualifier().isArrayedIo(language)) {
if (variable.getType().containsBuiltIn()) if (variable.getType().containsBuiltIn())
split(variable); split(variable);
} else } else if (shouldFlatten(variable.getType(), EvqVaryingIn /* not assigned yet, but close enough */, true))
flatten(variable, false /* don't track linkage here, it will be tracked in assignToInterface() */); flatten(variable, false /* don't track linkage here, it will be tracked in assignToInterface() */);
} }
// TODO: flatten arrays too // TODO: flatten arrays too
@ -2616,9 +2628,9 @@ TIntermTyped* HlslParseContext::handleAssign(const TSourceLoc& loc, TOperator op
int leftOffset = findSubtreeOffset(*left); int leftOffset = findSubtreeOffset(*left);
int rightOffset = findSubtreeOffset(*right); int rightOffset = findSubtreeOffset(*right);
const auto getMember = [&](bool isLeft, const TType& type, int member, TIntermTyped* splitNode, int splitMember) const auto getMember = [&](bool isLeft, const TType& type, int member, TIntermTyped* splitNode, int splitMember,
bool flattened)
-> TIntermTyped * { -> TIntermTyped * {
const bool flattened = isLeft ? isFlattenLeft : isFlattenRight;
const bool split = isLeft ? isSplitLeft : isSplitRight; const bool split = isLeft ? isSplitLeft : isSplitRight;
TIntermTyped* subTree; TIntermTyped* subTree;
@ -2643,7 +2655,7 @@ TIntermTyped* HlslParseContext::handleAssign(const TSourceLoc& loc, TOperator op
intermediate.addConstantUnion(arrayElement.back(), loc), loc); intermediate.addConstantUnion(arrayElement.back(), loc), loc);
subTree->setType(splitDerefType); subTree->setType(splitDerefType);
} }
} else if (flattened && isFinalFlattening(derefType)) { } else if (flattened && !shouldFlatten(derefType, isLeft ? leftStorage : rightStorage, false)) {
if (isLeft) if (isLeft)
subTree = intermediate.addSymbol(*(*leftVariables)[leftOffset++]); subTree = intermediate.addSymbol(*(*leftVariables)[leftOffset++]);
else else
@ -2674,12 +2686,19 @@ TIntermTyped* HlslParseContext::handleAssign(const TSourceLoc& loc, TOperator op
// Cannot use auto here, because this is recursive, and auto can't work out the type without seeing the // Cannot use auto here, because this is recursive, and auto can't work out the type without seeing the
// whole thing. So, we'll resort to an explicit type via std::function. // whole thing. So, we'll resort to an explicit type via std::function.
const std::function<void(TIntermTyped* left, TIntermTyped* right, TIntermTyped* splitLeft, TIntermTyped* splitRight)> const std::function<void(TIntermTyped* left, TIntermTyped* right, TIntermTyped* splitLeft, TIntermTyped* splitRight,
traverse = [&](TIntermTyped* left, TIntermTyped* right, TIntermTyped* splitLeft, TIntermTyped* splitRight) -> void { bool topLevel)>
traverse = [&](TIntermTyped* left, TIntermTyped* right, TIntermTyped* splitLeft, TIntermTyped* splitRight,
bool topLevel) -> void {
// If we get here, we are assigning to or from a whole array or struct that must be // If we get here, we are assigning to or from a whole array or struct that must be
// flattened, so have to do member-by-member assignment: // flattened, so have to do member-by-member assignment:
if (left->getType().isArray() || right->getType().isArray()) { bool shouldFlattenSubsetLeft = isFlattenLeft && shouldFlatten(left->getType(), leftStorage, topLevel);
bool shouldFlattenSubsetRight = isFlattenRight && shouldFlatten(right->getType(), rightStorage, topLevel);
if ((left->getType().isArray() || right->getType().isArray()) &&
(shouldFlattenSubsetLeft || isSplitLeft ||
shouldFlattenSubsetRight || isSplitRight)) {
const int elementsL = left->getType().isArray() ? left->getType().getOuterArraySize() : 1; const int elementsL = left->getType().isArray() ? left->getType().getOuterArraySize() : 1;
const int elementsR = right->getType().isArray() ? right->getType().getOuterArraySize() : 1; const int elementsR = right->getType().isArray() ? right->getType().getOuterArraySize() : 1;
@ -2692,19 +2711,24 @@ TIntermTyped* HlslParseContext::handleAssign(const TSourceLoc& loc, TOperator op
arrayElement.push_back(element); arrayElement.push_back(element);
// Add a new AST symbol node if we have a temp variable holding a complex RHS. // Add a new AST symbol node if we have a temp variable holding a complex RHS.
TIntermTyped* subLeft = getMember(true, left->getType(), element, left, element); TIntermTyped* subLeft = getMember(true, left->getType(), element, left, element,
TIntermTyped* subRight = getMember(false, right->getType(), element, right, element); shouldFlattenSubsetLeft);
TIntermTyped* subRight = getMember(false, right->getType(), element, right, element,
shouldFlattenSubsetRight);
TIntermTyped* subSplitLeft = isSplitLeft ? getMember(true, left->getType(), element, splitLeft, element) TIntermTyped* subSplitLeft = isSplitLeft ? getMember(true, left->getType(), element, splitLeft,
element, shouldFlattenSubsetLeft)
: subLeft; : subLeft;
TIntermTyped* subSplitRight = isSplitRight ? getMember(false, right->getType(), element, splitRight, element) TIntermTyped* subSplitRight = isSplitRight ? getMember(false, right->getType(), element, splitRight,
element, shouldFlattenSubsetRight)
: subRight; : subRight;
traverse(subLeft, subRight, subSplitLeft, subSplitRight); traverse(subLeft, subRight, subSplitLeft, subSplitRight, false);
arrayElement.pop_back(); arrayElement.pop_back();
} }
} else if (left->getType().isStruct()) { } else if (left->getType().isStruct() && (shouldFlattenSubsetLeft || isSplitLeft ||
shouldFlattenSubsetRight || isSplitRight)) {
// struct case // struct case
const auto& membersL = *left->getType().getStruct(); const auto& membersL = *left->getType().getStruct();
const auto& membersR = *right->getType().getStruct(); const auto& membersR = *right->getType().getStruct();
@ -2722,13 +2746,17 @@ TIntermTyped* HlslParseContext::handleAssign(const TSourceLoc& loc, TOperator op
const TType& typeL = *membersL[member].type; const TType& typeL = *membersL[member].type;
const TType& typeR = *membersR[member].type; const TType& typeR = *membersR[member].type;
TIntermTyped* subLeft = getMember(true, left->getType(), member, left, member); TIntermTyped* subLeft = getMember(true, left->getType(), member, left, member,
TIntermTyped* subRight = getMember(false, right->getType(), member, right, member); shouldFlattenSubsetLeft);
TIntermTyped* subRight = getMember(false, right->getType(), member, right, member,
shouldFlattenSubsetRight);
// If there is no splitting, use the same values to avoid inefficiency. // If there is no splitting, use the same values to avoid inefficiency.
TIntermTyped* subSplitLeft = isSplitLeft ? getMember(true, left->getType(), member, splitLeft, memberL) TIntermTyped* subSplitLeft = isSplitLeft ? getMember(true, left->getType(), member, splitLeft,
memberL, shouldFlattenSubsetLeft)
: subLeft; : subLeft;
TIntermTyped* subSplitRight = isSplitRight ? getMember(false, right->getType(), member, splitRight, memberR) TIntermTyped* subSplitRight = isSplitRight ? getMember(false, right->getType(), member, splitRight,
memberR, shouldFlattenSubsetRight)
: subRight; : subRight;
if (isClipOrCullDistance(subSplitLeft->getType()) || isClipOrCullDistance(subSplitRight->getType())) { if (isClipOrCullDistance(subSplitLeft->getType()) || isClipOrCullDistance(subSplitRight->getType())) {
@ -2747,9 +2775,8 @@ TIntermTyped* HlslParseContext::handleAssign(const TSourceLoc& loc, TOperator op
assignList = intermediate.growAggregate(assignList, clipCullAssign, loc); assignList = intermediate.growAggregate(assignList, clipCullAssign, loc);
} else if (!isFlattenLeft && !isFlattenRight && } else if (!shouldFlattenSubsetLeft && !shouldFlattenSubsetRight &&
!typeL.containsBuiltIn() && !typeL.containsBuiltIn() && !typeR.containsBuiltIn()) {
!typeR.containsBuiltIn()) {
// If this is the final flattening (no nested types below to flatten) // If this is the final flattening (no nested types below to flatten)
// we'll copy the member, else recurse into the type hierarchy. // we'll copy the member, else recurse into the type hierarchy.
// However, if splitting the struct, that means we can copy a whole // However, if splitting the struct, that means we can copy a whole
@ -2762,7 +2789,7 @@ TIntermTyped* HlslParseContext::handleAssign(const TSourceLoc& loc, TOperator op
intermediate.addAssign(op, subSplitLeft, subSplitRight, loc), intermediate.addAssign(op, subSplitLeft, subSplitRight, loc),
loc); loc);
} else { } else {
traverse(subLeft, subRight, subSplitLeft, subSplitRight); traverse(subLeft, subRight, subSplitLeft, subSplitRight, false);
} }
memberL += (typeL.isBuiltIn() ? 0 : 1); memberL += (typeL.isBuiltIn() ? 0 : 1);
@ -2804,7 +2831,7 @@ TIntermTyped* HlslParseContext::handleAssign(const TSourceLoc& loc, TOperator op
splitRight = intermediate.addSymbol(*getSplitNonIoVar(right->getAsSymbolNode()->getId()), loc); splitRight = intermediate.addSymbol(*getSplitNonIoVar(right->getAsSymbolNode()->getId()), loc);
// This makes the whole assignment, recursing through subtypes as needed. // This makes the whole assignment, recursing through subtypes as needed.
traverse(left, right, splitLeft, splitRight); traverse(left, right, splitLeft, splitRight, true);
assert(assignList != nullptr); assert(assignList != nullptr);
assignList->setOperator(EOpSequence); assignList->setOperator(EOpSequence);
@ -5083,7 +5110,8 @@ TIntermTyped* HlslParseContext::handleFunctionCall(const TSourceLoc& loc, TFunct
// add buffer and counter buffer argument qualifier // add buffer and counter buffer argument qualifier
qualifierList.push_back(qual); qualifierList.push_back(qual);
qualifierList.push_back(qual); qualifierList.push_back(qual);
} else if (shouldFlatten(*(*fnCandidate)[i].type)) { } else if (shouldFlatten(*(*fnCandidate)[i].type, (*fnCandidate)[i].type->getQualifier().storage,
true)) {
// add structure member expansion // add structure member expansion
for (int memb = 0; memb < (int)(*fnCandidate)[i].type->getStruct()->size(); ++memb) for (int memb = 0; memb < (int)(*fnCandidate)[i].type->getStruct()->size(); ++memb)
qualifierList.push_back(qual); qualifierList.push_back(qual);
@ -5172,7 +5200,7 @@ void HlslParseContext::addInputArgumentConversions(const TFunction& function, TI
if (wasFlattened(arg)) { if (wasFlattened(arg)) {
// If both formal and calling arg are to be flattened, leave that to argument // If both formal and calling arg are to be flattened, leave that to argument
// expansion, not conversion. // expansion, not conversion.
if (!shouldFlatten(*function[param].type)) { if (!shouldFlatten(*function[param].type, function[param].type->getQualifier().storage, true)) {
// Will make a two-level subtree. // Will make a two-level subtree.
// The deepest will copy member-by-member to build the structure to pass. // The deepest will copy member-by-member to build the structure to pass.
// The level above that will be a two-operand EOpComma sequence that follows the copy by the // The level above that will be a two-operand EOpComma sequence that follows the copy by the
@ -5249,7 +5277,7 @@ void HlslParseContext::expandArguments(const TSourceLoc& loc, const TFunction& f
aggregate->getSequence()[param + functionParamNumberOffset]->getAsTyped() : aggregate->getSequence()[param + functionParamNumberOffset]->getAsTyped() :
arguments->getAsTyped()); arguments->getAsTyped());
if (wasFlattened(arg) && shouldFlatten(*function[param].type)) { if (wasFlattened(arg) && shouldFlatten(*function[param].type, function[param].type->getQualifier().storage, true)) {
// Need to pass the structure members instead of the structure. // Need to pass the structure members instead of the structure.
TVector<TIntermTyped*> memberArgs; TVector<TIntermTyped*> memberArgs;
for (int memb = 0; memb < (int)arg->getType().getStruct()->size(); ++memb) for (int memb = 0; memb < (int)arg->getType().getStruct()->size(); ++memb)
@ -7432,7 +7460,7 @@ TIntermNode* HlslParseContext::declareVariable(const TSourceLoc& loc, const TStr
inheritGlobalDefaults(type.getQualifier()); inheritGlobalDefaults(type.getQualifier());
const bool flattenVar = shouldFlatten(type); const bool flattenVar = shouldFlatten(type, type.getQualifier().storage, true);
// correct IO in the type // correct IO in the type
switch (type.getQualifier().storage) { switch (type.getQualifier().storage) {

View File

@ -244,15 +244,14 @@ protected:
// Array and struct flattening // Array and struct flattening
TIntermTyped* flattenAccess(TIntermTyped* base, int member); TIntermTyped* flattenAccess(TIntermTyped* base, int member);
TIntermTyped* flattenAccess(int uniqueId, int member, const TType&, int subset = -1); TIntermTyped* flattenAccess(int uniqueId, int member, TStorageQualifier outerStorage, const TType&, int subset = -1);
int findSubtreeOffset(const TIntermNode&) const; int findSubtreeOffset(const TIntermNode&) const;
int findSubtreeOffset(const TType&, int subset, const TVector<int>& offsets) const; int findSubtreeOffset(const TType&, int subset, const TVector<int>& offsets) const;
bool shouldFlatten(const TType&) const; bool shouldFlatten(const TType&, TStorageQualifier, bool topLevel) const;
bool wasFlattened(const TIntermTyped* node) const; bool wasFlattened(const TIntermTyped* node) const;
bool wasFlattened(int id) const { return flattenMap.find(id) != flattenMap.end(); } bool wasFlattened(int id) const { return flattenMap.find(id) != flattenMap.end(); }
int addFlattenedMember(const TVariable&, const TType&, TFlattenData&, const TString& name, bool linkage, int addFlattenedMember(const TVariable&, const TType&, TFlattenData&, const TString& name, bool linkage,
const TQualifier& outerQualifier, const TArraySizes* builtInArraySizes); const TQualifier& outerQualifier, const TArraySizes* builtInArraySizes);
bool isFinalFlattening(const TType& type) const { return !(type.isStruct() || type.isArray()); }
// Structure splitting (splits interstage built-in types into its own struct) // Structure splitting (splits interstage built-in types into its own struct)
void split(const TVariable&); void split(const TVariable&);