From 41aa19953f881a93d2a8537a3c8d5f910c708b8e Mon Sep 17 00:00:00 2001 From: John Kessenich Date: Wed, 11 Oct 2017 14:03:45 -0600 Subject: [PATCH] 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. --- .../hlsl.partialFlattenLocal.vert.out | 366 ++++++++++++++++++ .../hlsl.partialFlattenMixed.vert.out | 150 +++++++ .../hlsl.structarray.flatten.frag.out | 234 ++++++----- Test/hlsl.partialFlattenLocal.vert | 27 ++ Test/hlsl.partialFlattenMixed.vert | 16 + gtests/Hlsl.FromFile.cpp | 2 + hlsl/hlslParseHelper.cpp | 104 +++-- hlsl/hlslParseHelper.h | 5 +- 8 files changed, 741 insertions(+), 163 deletions(-) create mode 100755 Test/baseResults/hlsl.partialFlattenLocal.vert.out create mode 100755 Test/baseResults/hlsl.partialFlattenMixed.vert.out create mode 100644 Test/hlsl.partialFlattenLocal.vert create mode 100644 Test/hlsl.partialFlattenMixed.vert diff --git a/Test/baseResults/hlsl.partialFlattenLocal.vert.out b/Test/baseResults/hlsl.partialFlattenLocal.vert.out new file mode 100755 index 000000000..7847c088c --- /dev/null +++ b/Test/baseResults/hlsl.partialFlattenLocal.vert.out @@ -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 diff --git a/Test/baseResults/hlsl.partialFlattenMixed.vert.out b/Test/baseResults/hlsl.partialFlattenMixed.vert.out new file mode 100755 index 000000000..50c8cb9bd --- /dev/null +++ b/Test/baseResults/hlsl.partialFlattenMixed.vert.out @@ -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 diff --git a/Test/baseResults/hlsl.structarray.flatten.frag.out b/Test/baseResults/hlsl.structarray.flatten.frag.out index 20a021111..534ea7ce2 100644 --- a/Test/baseResults/hlsl.structarray.flatten.frag.out +++ b/Test/baseResults/hlsl.structarray.flatten.frag.out @@ -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 diff --git a/Test/hlsl.partialFlattenLocal.vert b/Test/hlsl.partialFlattenLocal.vert new file mode 100644 index 000000000..9d6cdc900 --- /dev/null +++ b/Test/hlsl.partialFlattenLocal.vert @@ -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); +} \ No newline at end of file diff --git a/Test/hlsl.partialFlattenMixed.vert b/Test/hlsl.partialFlattenMixed.vert new file mode 100644 index 000000000..3fc9d68e2 --- /dev/null +++ b/Test/hlsl.partialFlattenMixed.vert @@ -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; +} \ No newline at end of file diff --git a/gtests/Hlsl.FromFile.cpp b/gtests/Hlsl.FromFile.cpp index 8a64991e5..ca5fb3b0f 100644 --- a/gtests/Hlsl.FromFile.cpp +++ b/gtests/Hlsl.FromFile.cpp @@ -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{ {"hlsl.array.flatten.frag", "main"}, + {"hlsl.partialFlattenMixed.vert", "main"}, }), FileNameAsCustomTestSuffix ); diff --git a/hlsl/hlslParseHelper.cpp b/hlsl/hlslParseHelper.cpp index b2b80d05d..71f43c550 100755 --- a/hlsl/hlslParseHelper.cpp +++ b/hlsl/hlslParseHelper.cpp @@ -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,7 +1689,8 @@ TIntermAggregate* HlslParseContext::handleFunctionDefinition(const TSourceLoc& l for (int mem = 0; mem < (int)structure->size(); ++mem) { paramNodes = intermediate.growAggregate(paramNodes, flattenAccess(variable->getUniqueId(), mem, - *(*structure)[mem].type), + variable->getType().getQualifier().storage, + *(*structure)[mem].type), loc); } } else { @@ -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 - traverse = [&](TIntermTyped* left, TIntermTyped* right, TIntermTyped* splitLeft, TIntermTyped* splitRight) -> void { + const std::function + 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 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) { diff --git a/hlsl/hlslParseHelper.h b/hlsl/hlslParseHelper.h index e4c15a1af..669c1ec0d 100755 --- a/hlsl/hlslParseHelper.h +++ b/hlsl/hlslParseHelper.h @@ -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& 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&);