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

View File

@ -1146,13 +1146,22 @@ const TType& HlslParseContext::split(const TType& type, const TString& name, con
return type;
}
// Is this a uniform array or structure which should be flattened?
bool HlslParseContext::shouldFlatten(const TType& type) const
// Is this an aggregate that should be flattened?
// 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;
return (qualifier == EvqUniform && type.isArray() && intermediate.getFlattenUniformArrays()) ||
(type.isStruct() && type.containsOpaque());
switch (qualifier) {
case EvqVaryingIn:
case EvqVaryingOut:
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
@ -1223,7 +1232,7 @@ int HlslParseContext::addFlattenedMember(const TVariable& variable, const TType&
const TQualifier& outerQualifier,
const TArraySizes* builtInArraySizes)
{
if (isFinalFlattening(type)) {
if (!shouldFlatten(type, outerQualifier.storage, false)) {
// This is as far as we flatten. Insert the variable.
TVariable* memberVariable = makeInternalVariable(memberName, type);
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 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;
}
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);
@ -1362,7 +1373,7 @@ TIntermTyped* HlslParseContext::flattenAccess(int uniqueId, int member, const TT
int newSubset = flattenData->second.offsets[subset >= 0 ? subset + member : member];
TIntermSymbol* subsetSymbol;
if (isFinalFlattening(dereferencedType)) {
if (!shouldFlatten(dereferencedType, outerStorage, false)) {
// Finished flattening: create symbol for variable
member = flattenData->second.offsets[newSubset];
const TVariable* memberVariable = flattenData->second.members[member];
@ -1670,7 +1681,7 @@ TIntermAggregate* HlslParseContext::handleFunctionDefinition(const TSourceLoc& l
error(loc, "redefinition", variable->getName().c_str(), "");
// 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)
// for structures that need to be flattened.
flatten(*variable, false);
@ -1678,6 +1689,7 @@ TIntermAggregate* HlslParseContext::handleFunctionDefinition(const TSourceLoc& l
for (int mem = 0; mem < (int)structure->size(); ++mem) {
paramNodes = intermediate.growAggregate(paramNodes,
flattenAccess(variable->getUniqueId(), mem,
variable->getType().getQualifier().storage,
*(*structure)[mem].type),
loc);
}
@ -1931,7 +1943,7 @@ TIntermNode* HlslParseContext::transformEntryPoint(const TSourceLoc& loc, TFunct
if (variable.getType().getQualifier().isArrayedIo(language)) {
if (variable.getType().containsBuiltIn())
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() */);
}
// TODO: flatten arrays too
@ -2616,9 +2628,9 @@ TIntermTyped* HlslParseContext::handleAssign(const TSourceLoc& loc, TOperator op
int leftOffset = findSubtreeOffset(*left);
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 * {
const bool flattened = isLeft ? isFlattenLeft : isFlattenRight;
const bool split = isLeft ? isSplitLeft : isSplitRight;
TIntermTyped* subTree;
@ -2643,7 +2655,7 @@ TIntermTyped* HlslParseContext::handleAssign(const TSourceLoc& loc, TOperator op
intermediate.addConstantUnion(arrayElement.back(), loc), loc);
subTree->setType(splitDerefType);
}
} else if (flattened && isFinalFlattening(derefType)) {
} else if (flattened && !shouldFlatten(derefType, isLeft ? leftStorage : rightStorage, false)) {
if (isLeft)
subTree = intermediate.addSymbol(*(*leftVariables)[leftOffset++]);
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
// 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)>
traverse = [&](TIntermTyped* left, TIntermTyped* right, TIntermTyped* splitLeft, TIntermTyped* splitRight) -> void {
const std::function<void(TIntermTyped* left, TIntermTyped* right, TIntermTyped* splitLeft, TIntermTyped* splitRight,
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
// 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 elementsR = right->getType().isArray() ? right->getType().getOuterArraySize() : 1;
@ -2692,19 +2711,24 @@ TIntermTyped* HlslParseContext::handleAssign(const TSourceLoc& loc, TOperator op
arrayElement.push_back(element);
// 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* subRight = getMember(false, right->getType(), element, right, element);
TIntermTyped* subLeft = getMember(true, left->getType(), element, left, 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;
TIntermTyped* subSplitRight = isSplitRight ? getMember(false, right->getType(), element, splitRight, element)
TIntermTyped* subSplitRight = isSplitRight ? getMember(false, right->getType(), element, splitRight,
element, shouldFlattenSubsetRight)
: subRight;
traverse(subLeft, subRight, subSplitLeft, subSplitRight);
traverse(subLeft, subRight, subSplitLeft, subSplitRight, false);
arrayElement.pop_back();
}
} else if (left->getType().isStruct()) {
} else if (left->getType().isStruct() && (shouldFlattenSubsetLeft || isSplitLeft ||
shouldFlattenSubsetRight || isSplitRight)) {
// struct case
const auto& membersL = *left->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& typeR = *membersR[member].type;
TIntermTyped* subLeft = getMember(true, left->getType(), member, left, member);
TIntermTyped* subRight = getMember(false, right->getType(), member, right, member);
TIntermTyped* subLeft = getMember(true, left->getType(), member, left, member,
shouldFlattenSubsetLeft);
TIntermTyped* subRight = getMember(false, right->getType(), member, right, member,
shouldFlattenSubsetRight);
// 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;
TIntermTyped* subSplitRight = isSplitRight ? getMember(false, right->getType(), member, splitRight, memberR)
TIntermTyped* subSplitRight = isSplitRight ? getMember(false, right->getType(), member, splitRight,
memberR, shouldFlattenSubsetRight)
: subRight;
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);
} else if (!isFlattenLeft && !isFlattenRight &&
!typeL.containsBuiltIn() &&
!typeR.containsBuiltIn()) {
} else if (!shouldFlattenSubsetLeft && !shouldFlattenSubsetRight &&
!typeL.containsBuiltIn() && !typeR.containsBuiltIn()) {
// If this is the final flattening (no nested types below to flatten)
// we'll copy the member, else recurse into the type hierarchy.
// 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),
loc);
} else {
traverse(subLeft, subRight, subSplitLeft, subSplitRight);
traverse(subLeft, subRight, subSplitLeft, subSplitRight, false);
}
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);
// This makes the whole assignment, recursing through subtypes as needed.
traverse(left, right, splitLeft, splitRight);
traverse(left, right, splitLeft, splitRight, true);
assert(assignList != nullptr);
assignList->setOperator(EOpSequence);
@ -5083,7 +5110,8 @@ TIntermTyped* HlslParseContext::handleFunctionCall(const TSourceLoc& loc, TFunct
// add buffer and counter buffer argument qualifier
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
for (int memb = 0; memb < (int)(*fnCandidate)[i].type->getStruct()->size(); ++memb)
qualifierList.push_back(qual);
@ -5172,7 +5200,7 @@ void HlslParseContext::addInputArgumentConversions(const TFunction& function, TI
if (wasFlattened(arg)) {
// If both formal and calling arg are to be flattened, leave that to argument
// 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.
// 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
@ -5249,7 +5277,7 @@ void HlslParseContext::expandArguments(const TSourceLoc& loc, const TFunction& f
aggregate->getSequence()[param + functionParamNumberOffset]->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.
TVector<TIntermTyped*> memberArgs;
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());
const bool flattenVar = shouldFlatten(type);
const bool flattenVar = shouldFlatten(type, type.getQualifier().storage, true);
// correct IO in the type
switch (type.getQualifier().storage) {

View File

@ -244,15 +244,14 @@ protected:
// Array and struct flattening
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 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(int id) const { return flattenMap.find(id) != flattenMap.end(); }
int addFlattenedMember(const TVariable&, const TType&, TFlattenData&, const TString& name, bool linkage,
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)
void split(const TVariable&);