diff --git a/Test/baseResults/hlsl.partialFlattenLocal.vert.out b/Test/baseResults/hlsl.partialFlattenLocal.vert.out
new file mode 100755
index 0000000000000000000000000000000000000000..7847c088c547ce145ede581554b75c33f9153ac1
--- /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 0000000000000000000000000000000000000000..50c8cb9bd0c4d1f77715f8d417c97852fca3a7ab
--- /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 20a021111cf4c7fe932e0ac85868ede9fe4824f3..534ea7ce23d2a5e6bb54885498ff3ab8a7ab2b5d 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 0000000000000000000000000000000000000000..9d6cdc900c8c342a71f1b510d202aae6b084e9e5
--- /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 0000000000000000000000000000000000000000..3fc9d68e23dc339b887217638d259ef6754ff00e
--- /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 8a64991e5ca662a7a01d61c0d117105681c120bb..ca5fb3b0f9d3e347777d057bf6609440b4e44c41 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<FileNameEntryPointPair>{
         {"hlsl.array.flatten.frag", "main"},
+        {"hlsl.partialFlattenMixed.vert", "main"},
     }),
     FileNameAsCustomTestSuffix
 );
diff --git a/hlsl/hlslParseHelper.cpp b/hlsl/hlslParseHelper.cpp
index b2b80d05dee8bf606d2526242f9629423cb2dd49..71f43c55023e91a484100b5573f8fe751662e99e 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<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) {
diff --git a/hlsl/hlslParseHelper.h b/hlsl/hlslParseHelper.h
index e4c15a1afe4a965e2c0e58366ded3d67205b9b67..669c1ec0d7a8903074496a1d7d3a83e67bbb84fd 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<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&);