Merge pull request #621 from steve-lunarg/recursive-flattening
HLSL: Recursive composite flattening
This commit is contained in:
		
						commit
						e795cc915c
					
				
							
								
								
									
										197
									
								
								Test/baseResults/hlsl.structarray.flatten.frag.out
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										197
									
								
								Test/baseResults/hlsl.structarray.flatten.frag.out
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,197 @@
 | 
				
			|||||||
 | 
					hlsl.structarray.flatten.frag
 | 
				
			||||||
 | 
					Shader version: 450
 | 
				
			||||||
 | 
					gl_FragCoord origin is upper left
 | 
				
			||||||
 | 
					0:? Sequence
 | 
				
			||||||
 | 
					0:23  Function Definition: main(struct-PS_OUTPUT-vf41; (temp void)
 | 
				
			||||||
 | 
					0:23    Function Parameters: 
 | 
				
			||||||
 | 
					0:23      'ps_output' (out structure{temp 4-component vector of float color})
 | 
				
			||||||
 | 
					0:?     Sequence
 | 
				
			||||||
 | 
					0:24      move second child to first child (temp 4-component vector of float)
 | 
				
			||||||
 | 
					0:?         'color' (layout(location=0 ) out 4-component vector of float)
 | 
				
			||||||
 | 
					0:26        add (temp 4-component vector of float)
 | 
				
			||||||
 | 
					0:25          add (temp 4-component vector of float)
 | 
				
			||||||
 | 
					0:25            texture (temp 4-component vector of float)
 | 
				
			||||||
 | 
					0:25              Construct combined texture-sampler (temp sampler1D)
 | 
				
			||||||
 | 
					0:?                 'tex' (uniform texture1D)
 | 
				
			||||||
 | 
					0:?                 'samp' (uniform sampler)
 | 
				
			||||||
 | 
					0:25              Constant:
 | 
				
			||||||
 | 
					0:25                0.500000
 | 
				
			||||||
 | 
					0:26            texture (temp 4-component vector of float)
 | 
				
			||||||
 | 
					0:26              Construct combined texture-sampler (temp sampler1D)
 | 
				
			||||||
 | 
					0:?                 'g_texdata_array[1].tex' (uniform texture1D)
 | 
				
			||||||
 | 
					0:?                 'g_texdata_array[1].samp' (uniform sampler)
 | 
				
			||||||
 | 
					0:26              Constant:
 | 
				
			||||||
 | 
					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            Constant:
 | 
				
			||||||
 | 
					0:27              0.300000
 | 
				
			||||||
 | 
					0:?   Linker Objects
 | 
				
			||||||
 | 
					0:?     'color' (layout(location=0 ) out 4-component vector of float)
 | 
				
			||||||
 | 
					0:?     'g_samp' (uniform sampler)
 | 
				
			||||||
 | 
					0:?     'g_tex' (uniform texture1D)
 | 
				
			||||||
 | 
					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[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[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)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Linked fragment stage:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Shader version: 450
 | 
				
			||||||
 | 
					gl_FragCoord origin is upper left
 | 
				
			||||||
 | 
					0:? Sequence
 | 
				
			||||||
 | 
					0:23  Function Definition: main(struct-PS_OUTPUT-vf41; (temp void)
 | 
				
			||||||
 | 
					0:23    Function Parameters: 
 | 
				
			||||||
 | 
					0:23      'ps_output' (out structure{temp 4-component vector of float color})
 | 
				
			||||||
 | 
					0:?     Sequence
 | 
				
			||||||
 | 
					0:24      move second child to first child (temp 4-component vector of float)
 | 
				
			||||||
 | 
					0:?         'color' (layout(location=0 ) out 4-component vector of float)
 | 
				
			||||||
 | 
					0:26        add (temp 4-component vector of float)
 | 
				
			||||||
 | 
					0:25          add (temp 4-component vector of float)
 | 
				
			||||||
 | 
					0:25            texture (temp 4-component vector of float)
 | 
				
			||||||
 | 
					0:25              Construct combined texture-sampler (temp sampler1D)
 | 
				
			||||||
 | 
					0:?                 'tex' (uniform texture1D)
 | 
				
			||||||
 | 
					0:?                 'samp' (uniform sampler)
 | 
				
			||||||
 | 
					0:25              Constant:
 | 
				
			||||||
 | 
					0:25                0.500000
 | 
				
			||||||
 | 
					0:26            texture (temp 4-component vector of float)
 | 
				
			||||||
 | 
					0:26              Construct combined texture-sampler (temp sampler1D)
 | 
				
			||||||
 | 
					0:?                 'g_texdata_array[1].tex' (uniform texture1D)
 | 
				
			||||||
 | 
					0:?                 'g_texdata_array[1].samp' (uniform sampler)
 | 
				
			||||||
 | 
					0:26              Constant:
 | 
				
			||||||
 | 
					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            Constant:
 | 
				
			||||||
 | 
					0:27              0.300000
 | 
				
			||||||
 | 
					0:?   Linker Objects
 | 
				
			||||||
 | 
					0:?     'color' (layout(location=0 ) out 4-component vector of float)
 | 
				
			||||||
 | 
					0:?     'g_samp' (uniform sampler)
 | 
				
			||||||
 | 
					0:?     'g_tex' (uniform texture1D)
 | 
				
			||||||
 | 
					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[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[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)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Module Version 10000
 | 
				
			||||||
 | 
					// Generated by (magic number): 80001
 | 
				
			||||||
 | 
					// Id's are bound by 50
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                              Capability Shader
 | 
				
			||||||
 | 
					                              Capability Sampled1D
 | 
				
			||||||
 | 
					               1:             ExtInstImport  "GLSL.std.450"
 | 
				
			||||||
 | 
					                              MemoryModel Logical GLSL450
 | 
				
			||||||
 | 
					                              EntryPoint Fragment 4  "main" 9
 | 
				
			||||||
 | 
					                              ExecutionMode 4 OriginUpperLeft
 | 
				
			||||||
 | 
					                              Name 4  "main"
 | 
				
			||||||
 | 
					                              Name 9  "color"
 | 
				
			||||||
 | 
					                              Name 12  "tex"
 | 
				
			||||||
 | 
					                              Name 16  "samp"
 | 
				
			||||||
 | 
					                              Name 22  "g_texdata_array[1].tex"
 | 
				
			||||||
 | 
					                              Name 24  "g_texdata_array[1].samp"
 | 
				
			||||||
 | 
					                              Name 30  "g_texdata_array2[1].tex[0]"
 | 
				
			||||||
 | 
					                              Name 32  "g_texdata_array2[1].samp[0]"
 | 
				
			||||||
 | 
					                              Name 38  "g_samp"
 | 
				
			||||||
 | 
					                              Name 39  "g_tex"
 | 
				
			||||||
 | 
					                              Name 40  "g_texdata_array2[0].samp[0]"
 | 
				
			||||||
 | 
					                              Name 41  "g_texdata_array2[0].samp[1]"
 | 
				
			||||||
 | 
					                              Name 42  "g_texdata_array2[0].tex[0]"
 | 
				
			||||||
 | 
					                              Name 43  "g_texdata_array2[0].tex[1]"
 | 
				
			||||||
 | 
					                              Name 44  "g_texdata_array2[1].samp[1]"
 | 
				
			||||||
 | 
					                              Name 45  "g_texdata_array2[1].tex[1]"
 | 
				
			||||||
 | 
					                              Name 46  "g_texdata_array2[2].samp[0]"
 | 
				
			||||||
 | 
					                              Name 47  "g_texdata_array2[2].samp[1]"
 | 
				
			||||||
 | 
					                              Name 48  "g_texdata_array2[2].tex[0]"
 | 
				
			||||||
 | 
					                              Name 49  "g_texdata_array2[2].tex[1]"
 | 
				
			||||||
 | 
					                              Decorate 9(color) Location 0
 | 
				
			||||||
 | 
					                              Decorate 12(tex) DescriptorSet 0
 | 
				
			||||||
 | 
					                              Decorate 16(samp) DescriptorSet 0
 | 
				
			||||||
 | 
					                              Decorate 22(g_texdata_array[1].tex) DescriptorSet 0
 | 
				
			||||||
 | 
					                              Decorate 24(g_texdata_array[1].samp) DescriptorSet 0
 | 
				
			||||||
 | 
					                              Decorate 30(g_texdata_array2[1].tex[0]) DescriptorSet 0
 | 
				
			||||||
 | 
					                              Decorate 32(g_texdata_array2[1].samp[0]) DescriptorSet 0
 | 
				
			||||||
 | 
					                              Decorate 38(g_samp) DescriptorSet 0
 | 
				
			||||||
 | 
					                              Decorate 39(g_tex) DescriptorSet 0
 | 
				
			||||||
 | 
					                              Decorate 40(g_texdata_array2[0].samp[0]) DescriptorSet 0
 | 
				
			||||||
 | 
					                              Decorate 41(g_texdata_array2[0].samp[1]) DescriptorSet 0
 | 
				
			||||||
 | 
					                              Decorate 42(g_texdata_array2[0].tex[0]) DescriptorSet 0
 | 
				
			||||||
 | 
					                              Decorate 43(g_texdata_array2[0].tex[1]) DescriptorSet 0
 | 
				
			||||||
 | 
					                              Decorate 44(g_texdata_array2[1].samp[1]) DescriptorSet 0
 | 
				
			||||||
 | 
					                              Decorate 45(g_texdata_array2[1].tex[1]) DescriptorSet 0
 | 
				
			||||||
 | 
					                              Decorate 46(g_texdata_array2[2].samp[0]) DescriptorSet 0
 | 
				
			||||||
 | 
					                              Decorate 47(g_texdata_array2[2].samp[1]) DescriptorSet 0
 | 
				
			||||||
 | 
					                              Decorate 48(g_texdata_array2[2].tex[0]) DescriptorSet 0
 | 
				
			||||||
 | 
					                              Decorate 49(g_texdata_array2[2].tex[1]) DescriptorSet 0
 | 
				
			||||||
 | 
					               2:             TypeVoid
 | 
				
			||||||
 | 
					               3:             TypeFunction 2
 | 
				
			||||||
 | 
					               6:             TypeFloat 32
 | 
				
			||||||
 | 
					               7:             TypeVector 6(float) 4
 | 
				
			||||||
 | 
					               8:             TypePointer Output 7(fvec4)
 | 
				
			||||||
 | 
					        9(color):      8(ptr) Variable Output
 | 
				
			||||||
 | 
					              10:             TypeImage 6(float) 1D sampled format:Unknown
 | 
				
			||||||
 | 
					              11:             TypePointer UniformConstant 10
 | 
				
			||||||
 | 
					         12(tex):     11(ptr) Variable UniformConstant
 | 
				
			||||||
 | 
					              14:             TypeSampler
 | 
				
			||||||
 | 
					              15:             TypePointer UniformConstant 14
 | 
				
			||||||
 | 
					        16(samp):     15(ptr) Variable UniformConstant
 | 
				
			||||||
 | 
					              18:             TypeSampledImage 10
 | 
				
			||||||
 | 
					              20:    6(float) Constant 1056964608
 | 
				
			||||||
 | 
					22(g_texdata_array[1].tex):     11(ptr) Variable UniformConstant
 | 
				
			||||||
 | 
					24(g_texdata_array[1].samp):     15(ptr) Variable UniformConstant
 | 
				
			||||||
 | 
					              27:    6(float) Constant 1053609165
 | 
				
			||||||
 | 
					30(g_texdata_array2[1].tex[0]):     11(ptr) Variable UniformConstant
 | 
				
			||||||
 | 
					32(g_texdata_array2[1].samp[0]):     15(ptr) Variable UniformConstant
 | 
				
			||||||
 | 
					              35:    6(float) Constant 1050253722
 | 
				
			||||||
 | 
					      38(g_samp):     15(ptr) Variable UniformConstant
 | 
				
			||||||
 | 
					       39(g_tex):     11(ptr) Variable UniformConstant
 | 
				
			||||||
 | 
					40(g_texdata_array2[0].samp[0]):     15(ptr) Variable UniformConstant
 | 
				
			||||||
 | 
					41(g_texdata_array2[0].samp[1]):     15(ptr) Variable UniformConstant
 | 
				
			||||||
 | 
					42(g_texdata_array2[0].tex[0]):     11(ptr) Variable UniformConstant
 | 
				
			||||||
 | 
					43(g_texdata_array2[0].tex[1]):     11(ptr) Variable UniformConstant
 | 
				
			||||||
 | 
					44(g_texdata_array2[1].samp[1]):     15(ptr) Variable UniformConstant
 | 
				
			||||||
 | 
					45(g_texdata_array2[1].tex[1]):     11(ptr) Variable UniformConstant
 | 
				
			||||||
 | 
					46(g_texdata_array2[2].samp[0]):     15(ptr) Variable UniformConstant
 | 
				
			||||||
 | 
					47(g_texdata_array2[2].samp[1]):     15(ptr) Variable UniformConstant
 | 
				
			||||||
 | 
					48(g_texdata_array2[2].tex[0]):     11(ptr) Variable UniformConstant
 | 
				
			||||||
 | 
					49(g_texdata_array2[2].tex[1]):     11(ptr) Variable UniformConstant
 | 
				
			||||||
 | 
					         4(main):           2 Function None 3
 | 
				
			||||||
 | 
					               5:             Label
 | 
				
			||||||
 | 
					              13:          10 Load 12(tex)
 | 
				
			||||||
 | 
					              17:          14 Load 16(samp)
 | 
				
			||||||
 | 
					              19:          18 SampledImage 13 17
 | 
				
			||||||
 | 
					              21:    7(fvec4) ImageSampleImplicitLod 19 20
 | 
				
			||||||
 | 
					              23:          10 Load 22(g_texdata_array[1].tex)
 | 
				
			||||||
 | 
					              25:          14 Load 24(g_texdata_array[1].samp)
 | 
				
			||||||
 | 
					              26:          18 SampledImage 23 25
 | 
				
			||||||
 | 
					              28:    7(fvec4) ImageSampleImplicitLod 26 27
 | 
				
			||||||
 | 
					              29:    7(fvec4) FAdd 21 28
 | 
				
			||||||
 | 
					              31:          10 Load 30(g_texdata_array2[1].tex[0])
 | 
				
			||||||
 | 
					              33:          14 Load 32(g_texdata_array2[1].samp[0])
 | 
				
			||||||
 | 
					              34:          18 SampledImage 31 33
 | 
				
			||||||
 | 
					              36:    7(fvec4) ImageSampleImplicitLod 34 35
 | 
				
			||||||
 | 
					              37:    7(fvec4) FAdd 29 36
 | 
				
			||||||
 | 
					                              Store 9(color) 37
 | 
				
			||||||
 | 
					                              Return
 | 
				
			||||||
 | 
					                              FunctionEnd
 | 
				
			||||||
							
								
								
									
										100
									
								
								Test/baseResults/hlsl.structarray.flatten.geom.out
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										100
									
								
								Test/baseResults/hlsl.structarray.flatten.geom.out
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,100 @@
 | 
				
			|||||||
 | 
					hlsl.structarray.flatten.geom
 | 
				
			||||||
 | 
					ERROR: 0:10: 'vin' : recursive type not yet supported in GS input 
 | 
				
			||||||
 | 
					ERROR: 1 compilation errors.  No code generated.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Shader version: 450
 | 
				
			||||||
 | 
					invocations = -1
 | 
				
			||||||
 | 
					max_vertices = 4
 | 
				
			||||||
 | 
					input primitive = lines
 | 
				
			||||||
 | 
					output primitive = triangle_strip
 | 
				
			||||||
 | 
					ERROR: node is still EOpNull!
 | 
				
			||||||
 | 
					0:10  Function Definition: main(struct-VertexData-vf4-vf4-vf21[2];struct-VertexData-vf4-vf4-vf21; (temp void)
 | 
				
			||||||
 | 
					0:10    Function Parameters: 
 | 
				
			||||||
 | 
					0:10      'vin' (in 2-element array of structure{temp 4-component vector of float position, temp 4-component vector of float color, temp 2-component vector of float uv})
 | 
				
			||||||
 | 
					0:10      'outStream' (out structure{temp 4-component vector of float position, temp 4-component vector of float color, temp 2-component vector of float uv})
 | 
				
			||||||
 | 
					0:?     Sequence
 | 
				
			||||||
 | 
					0:13      move second child to first child (temp 4-component vector of float)
 | 
				
			||||||
 | 
					0:13        color: direct index for structure (temp 4-component vector of float)
 | 
				
			||||||
 | 
					0:13          'vout' (temp structure{temp 4-component vector of float position, temp 4-component vector of float color, temp 2-component vector of float uv})
 | 
				
			||||||
 | 
					0:13          Constant:
 | 
				
			||||||
 | 
					0:13            1 (const int)
 | 
				
			||||||
 | 
					0:?         'vin[0].color' (layout(location=1 ) in 4-component vector of float)
 | 
				
			||||||
 | 
					0:14      move second child to first child (temp 2-component vector of float)
 | 
				
			||||||
 | 
					0:14        uv: direct index for structure (temp 2-component vector of float)
 | 
				
			||||||
 | 
					0:14          'vout' (temp structure{temp 4-component vector of float position, temp 4-component vector of float color, temp 2-component vector of float uv})
 | 
				
			||||||
 | 
					0:14          Constant:
 | 
				
			||||||
 | 
					0:14            2 (const int)
 | 
				
			||||||
 | 
					0:?         'vin[0].uv' (layout(location=2 ) in 2-component vector of float)
 | 
				
			||||||
 | 
					0:15      move second child to first child (temp 4-component vector of float)
 | 
				
			||||||
 | 
					0:15        position: direct index for structure (temp 4-component vector of float)
 | 
				
			||||||
 | 
					0:15          'vout' (temp structure{temp 4-component vector of float position, temp 4-component vector of float color, temp 2-component vector of float uv})
 | 
				
			||||||
 | 
					0:15          Constant:
 | 
				
			||||||
 | 
					0:15            0 (const int)
 | 
				
			||||||
 | 
					0:?         'vin[0].position' (layout(location=0 ) in 4-component vector of float)
 | 
				
			||||||
 | 
					0:16      Sequence
 | 
				
			||||||
 | 
					0:16        move second child to first child (temp structure{temp 4-component vector of float position, temp 4-component vector of float color, temp 2-component vector of float uv})
 | 
				
			||||||
 | 
					0:16          'outStream' (out structure{temp 4-component vector of float position, temp 4-component vector of float color, temp 2-component vector of float uv})
 | 
				
			||||||
 | 
					0:16          'vout' (temp structure{temp 4-component vector of float position, temp 4-component vector of float color, temp 2-component vector of float uv})
 | 
				
			||||||
 | 
					0:16        EmitVertex (temp void)
 | 
				
			||||||
 | 
					0:?   Linker Objects
 | 
				
			||||||
 | 
					0:?     'vin[0].position' (layout(location=0 ) in 4-component vector of float)
 | 
				
			||||||
 | 
					0:?     'vin[0].color' (layout(location=1 ) in 4-component vector of float)
 | 
				
			||||||
 | 
					0:?     'vin[0].uv' (layout(location=2 ) in 2-component vector of float)
 | 
				
			||||||
 | 
					0:?     'vin[1].position' (layout(location=3 ) in 4-component vector of float)
 | 
				
			||||||
 | 
					0:?     'vin[1].color' (layout(location=4 ) in 4-component vector of float)
 | 
				
			||||||
 | 
					0:?     'vin[1].uv' (layout(location=5 ) in 2-component vector of float)
 | 
				
			||||||
 | 
					0:?     'position' (layout(location=0 ) out 4-component vector of float)
 | 
				
			||||||
 | 
					0:?     'color' (layout(location=1 ) out 4-component vector of float)
 | 
				
			||||||
 | 
					0:?     'uv' (layout(location=2 ) out 2-component vector of float)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Linked geometry stage:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Shader version: 450
 | 
				
			||||||
 | 
					invocations = 1
 | 
				
			||||||
 | 
					max_vertices = 4
 | 
				
			||||||
 | 
					input primitive = lines
 | 
				
			||||||
 | 
					output primitive = triangle_strip
 | 
				
			||||||
 | 
					ERROR: node is still EOpNull!
 | 
				
			||||||
 | 
					0:10  Function Definition: main(struct-VertexData-vf4-vf4-vf21[2];struct-VertexData-vf4-vf4-vf21; (temp void)
 | 
				
			||||||
 | 
					0:10    Function Parameters: 
 | 
				
			||||||
 | 
					0:10      'vin' (in 2-element array of structure{temp 4-component vector of float position, temp 4-component vector of float color, temp 2-component vector of float uv})
 | 
				
			||||||
 | 
					0:10      'outStream' (out structure{temp 4-component vector of float position, temp 4-component vector of float color, temp 2-component vector of float uv})
 | 
				
			||||||
 | 
					0:?     Sequence
 | 
				
			||||||
 | 
					0:13      move second child to first child (temp 4-component vector of float)
 | 
				
			||||||
 | 
					0:13        color: direct index for structure (temp 4-component vector of float)
 | 
				
			||||||
 | 
					0:13          'vout' (temp structure{temp 4-component vector of float position, temp 4-component vector of float color, temp 2-component vector of float uv})
 | 
				
			||||||
 | 
					0:13          Constant:
 | 
				
			||||||
 | 
					0:13            1 (const int)
 | 
				
			||||||
 | 
					0:?         'vin[0].color' (layout(location=1 ) in 4-component vector of float)
 | 
				
			||||||
 | 
					0:14      move second child to first child (temp 2-component vector of float)
 | 
				
			||||||
 | 
					0:14        uv: direct index for structure (temp 2-component vector of float)
 | 
				
			||||||
 | 
					0:14          'vout' (temp structure{temp 4-component vector of float position, temp 4-component vector of float color, temp 2-component vector of float uv})
 | 
				
			||||||
 | 
					0:14          Constant:
 | 
				
			||||||
 | 
					0:14            2 (const int)
 | 
				
			||||||
 | 
					0:?         'vin[0].uv' (layout(location=2 ) in 2-component vector of float)
 | 
				
			||||||
 | 
					0:15      move second child to first child (temp 4-component vector of float)
 | 
				
			||||||
 | 
					0:15        position: direct index for structure (temp 4-component vector of float)
 | 
				
			||||||
 | 
					0:15          'vout' (temp structure{temp 4-component vector of float position, temp 4-component vector of float color, temp 2-component vector of float uv})
 | 
				
			||||||
 | 
					0:15          Constant:
 | 
				
			||||||
 | 
					0:15            0 (const int)
 | 
				
			||||||
 | 
					0:?         'vin[0].position' (layout(location=0 ) in 4-component vector of float)
 | 
				
			||||||
 | 
					0:16      Sequence
 | 
				
			||||||
 | 
					0:16        move second child to first child (temp structure{temp 4-component vector of float position, temp 4-component vector of float color, temp 2-component vector of float uv})
 | 
				
			||||||
 | 
					0:16          'outStream' (out structure{temp 4-component vector of float position, temp 4-component vector of float color, temp 2-component vector of float uv})
 | 
				
			||||||
 | 
					0:16          'vout' (temp structure{temp 4-component vector of float position, temp 4-component vector of float color, temp 2-component vector of float uv})
 | 
				
			||||||
 | 
					0:16        EmitVertex (temp void)
 | 
				
			||||||
 | 
					0:?   Linker Objects
 | 
				
			||||||
 | 
					0:?     'vin[0].position' (layout(location=0 ) in 4-component vector of float)
 | 
				
			||||||
 | 
					0:?     'vin[0].color' (layout(location=1 ) in 4-component vector of float)
 | 
				
			||||||
 | 
					0:?     'vin[0].uv' (layout(location=2 ) in 2-component vector of float)
 | 
				
			||||||
 | 
					0:?     'vin[1].position' (layout(location=3 ) in 4-component vector of float)
 | 
				
			||||||
 | 
					0:?     'vin[1].color' (layout(location=4 ) in 4-component vector of float)
 | 
				
			||||||
 | 
					0:?     'vin[1].uv' (layout(location=5 ) in 2-component vector of float)
 | 
				
			||||||
 | 
					0:?     'position' (layout(location=0 ) out 4-component vector of float)
 | 
				
			||||||
 | 
					0:?     'color' (layout(location=1 ) out 4-component vector of float)
 | 
				
			||||||
 | 
					0:?     'uv' (layout(location=2 ) out 2-component vector of float)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					SPIR-V is not generated for failed compile or link
 | 
				
			||||||
@ -16,14 +16,8 @@ Shader version: 450
 | 
				
			|||||||
0:11          add (temp 4-component vector of float)
 | 
					0:11          add (temp 4-component vector of float)
 | 
				
			||||||
0:11            add (temp 4-component vector of float)
 | 
					0:11            add (temp 4-component vector of float)
 | 
				
			||||||
0:11              add (temp 4-component vector of float)
 | 
					0:11              add (temp 4-component vector of float)
 | 
				
			||||||
0:11                direct index (layout(location=1 ) temp 4-component vector of float)
 | 
					0:?                 'm[1]' (layout(location=2 ) in 4-component vector of float)
 | 
				
			||||||
0:?                   'm' (layout(location=1 ) in 2-element array of 4-component vector of float)
 | 
					0:?                 'm[0]' (layout(location=1 ) in 4-component vector of float)
 | 
				
			||||||
0:11                  Constant:
 | 
					 | 
				
			||||||
0:11                    1 (const int)
 | 
					 | 
				
			||||||
0:11                direct index (layout(location=1 ) temp 4-component vector of float)
 | 
					 | 
				
			||||||
0:?                   'm' (layout(location=1 ) in 2-element array of 4-component vector of float)
 | 
					 | 
				
			||||||
0:11                  Constant:
 | 
					 | 
				
			||||||
0:11                    0 (const int)
 | 
					 | 
				
			||||||
0:11              Construct vec4 (temp 4-component vector of float)
 | 
					0:11              Construct vec4 (temp 4-component vector of float)
 | 
				
			||||||
0:11                Convert uint to float (temp float)
 | 
					0:11                Convert uint to float (temp float)
 | 
				
			||||||
0:11                  direct index (temp uint)
 | 
					0:11                  direct index (temp uint)
 | 
				
			||||||
@ -34,12 +28,24 @@ Shader version: 450
 | 
				
			|||||||
0:11          'e' (layout(location=5 ) in 4-component vector of float)
 | 
					0:11          'e' (layout(location=5 ) in 4-component vector of float)
 | 
				
			||||||
0:13      Sequence
 | 
					0:13      Sequence
 | 
				
			||||||
0:13        Sequence
 | 
					0:13        Sequence
 | 
				
			||||||
0:13          move second child to first child (temp 2-element array of 4-component vector of float)
 | 
					0:13          move second child to first child (temp 4-component vector of float)
 | 
				
			||||||
0:?             'm' (layout(location=0 ) out 2-element array of 4-component vector of float)
 | 
					0:?             'm[0]' (layout(location=0 ) out 4-component vector of float)
 | 
				
			||||||
0:13            m: direct index for structure (temp 2-element array of 4-component vector of float)
 | 
					0:13            direct index (temp 4-component vector of float)
 | 
				
			||||||
0:13              'local' (temp structure{temp 2-element array of 4-component vector of float m, temp 2-component vector of uint coord, temp 4-component vector of float b})
 | 
					0:13              m: direct index for structure (temp 2-element array of 4-component vector of float)
 | 
				
			||||||
 | 
					0:13                'local' (temp structure{temp 2-element array of 4-component vector of float m, temp 2-component vector of uint coord, temp 4-component vector of float b})
 | 
				
			||||||
 | 
					0:13                Constant:
 | 
				
			||||||
 | 
					0:13                  0 (const int)
 | 
				
			||||||
0:13              Constant:
 | 
					0:13              Constant:
 | 
				
			||||||
0:13                0 (const int)
 | 
					0:13                0 (const int)
 | 
				
			||||||
 | 
					0:13          move second child to first child (temp 4-component vector of float)
 | 
				
			||||||
 | 
					0:?             'm[1]' (layout(location=1 ) out 4-component vector of float)
 | 
				
			||||||
 | 
					0:13            direct index (temp 4-component vector of float)
 | 
				
			||||||
 | 
					0:13              m: direct index for structure (temp 2-element array of 4-component vector of float)
 | 
				
			||||||
 | 
					0:13                'local' (temp structure{temp 2-element array of 4-component vector of float m, temp 2-component vector of uint coord, temp 4-component vector of float b})
 | 
				
			||||||
 | 
					0:13                Constant:
 | 
				
			||||||
 | 
					0:13                  0 (const int)
 | 
				
			||||||
 | 
					0:13              Constant:
 | 
				
			||||||
 | 
					0:13                1 (const int)
 | 
				
			||||||
0:13          move second child to first child (temp 2-component vector of uint)
 | 
					0:13          move second child to first child (temp 2-component vector of uint)
 | 
				
			||||||
0:?             'coord' (layout(location=2 ) out 2-component vector of uint)
 | 
					0:?             'coord' (layout(location=2 ) out 2-component vector of uint)
 | 
				
			||||||
0:13            coord: direct index for structure (temp 2-component vector of uint)
 | 
					0:13            coord: direct index for structure (temp 2-component vector of uint)
 | 
				
			||||||
@ -54,14 +60,20 @@ Shader version: 450
 | 
				
			|||||||
0:13                2 (const int)
 | 
					0:13                2 (const int)
 | 
				
			||||||
0:13        Branch: Return
 | 
					0:13        Branch: Return
 | 
				
			||||||
0:?   Linker Objects
 | 
					0:?   Linker Objects
 | 
				
			||||||
0:?     'm' (layout(location=0 ) out 2-element array of 4-component vector of float)
 | 
					0:?     'm[0]' (layout(location=0 ) out 4-component vector of float)
 | 
				
			||||||
 | 
					0:?     'm[1]' (layout(location=1 ) out 4-component vector of float)
 | 
				
			||||||
0:?     'coord' (layout(location=2 ) out 2-component vector of uint)
 | 
					0:?     'coord' (layout(location=2 ) out 2-component vector of uint)
 | 
				
			||||||
0:?     'b' (layout(location=3 ) smooth out 4-component vector of float)
 | 
					0:?     'b' (layout(location=3 ) smooth out 4-component vector of float)
 | 
				
			||||||
0:?     'd' (layout(location=0 ) in 4-component vector of float)
 | 
					0:?     'd' (layout(location=0 ) in 4-component vector of float)
 | 
				
			||||||
0:?     'm' (layout(location=1 ) in 2-element array of 4-component vector of float)
 | 
					0:?     'm[0]' (layout(location=1 ) in 4-component vector of float)
 | 
				
			||||||
 | 
					0:?     'm[1]' (layout(location=2 ) in 4-component vector of float)
 | 
				
			||||||
0:?     'coord' (layout(location=3 ) in 2-component vector of uint)
 | 
					0:?     'coord' (layout(location=3 ) in 2-component vector of uint)
 | 
				
			||||||
0:?     'b' (layout(location=4 ) in 4-component vector of float)
 | 
					0:?     'b' (layout(location=4 ) in 4-component vector of float)
 | 
				
			||||||
0:?     'e' (layout(location=5 ) in 4-component vector of float)
 | 
					0:?     'e' (layout(location=5 ) in 4-component vector of float)
 | 
				
			||||||
 | 
					0:?     'm[0]' (layout(location=0 ) out 4-component vector of float)
 | 
				
			||||||
 | 
					0:?     'm[1]' (layout(location=1 ) out 4-component vector of float)
 | 
				
			||||||
 | 
					0:?     'm[0]' (layout(location=1 ) in 4-component vector of float)
 | 
				
			||||||
 | 
					0:?     'm[1]' (layout(location=2 ) in 4-component vector of float)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Linked vertex stage:
 | 
					Linked vertex stage:
 | 
				
			||||||
@ -84,14 +96,8 @@ Shader version: 450
 | 
				
			|||||||
0:11          add (temp 4-component vector of float)
 | 
					0:11          add (temp 4-component vector of float)
 | 
				
			||||||
0:11            add (temp 4-component vector of float)
 | 
					0:11            add (temp 4-component vector of float)
 | 
				
			||||||
0:11              add (temp 4-component vector of float)
 | 
					0:11              add (temp 4-component vector of float)
 | 
				
			||||||
0:11                direct index (layout(location=1 ) temp 4-component vector of float)
 | 
					0:?                 'm[1]' (layout(location=2 ) in 4-component vector of float)
 | 
				
			||||||
0:?                   'm' (layout(location=1 ) in 2-element array of 4-component vector of float)
 | 
					0:?                 'm[0]' (layout(location=1 ) in 4-component vector of float)
 | 
				
			||||||
0:11                  Constant:
 | 
					 | 
				
			||||||
0:11                    1 (const int)
 | 
					 | 
				
			||||||
0:11                direct index (layout(location=1 ) temp 4-component vector of float)
 | 
					 | 
				
			||||||
0:?                   'm' (layout(location=1 ) in 2-element array of 4-component vector of float)
 | 
					 | 
				
			||||||
0:11                  Constant:
 | 
					 | 
				
			||||||
0:11                    0 (const int)
 | 
					 | 
				
			||||||
0:11              Construct vec4 (temp 4-component vector of float)
 | 
					0:11              Construct vec4 (temp 4-component vector of float)
 | 
				
			||||||
0:11                Convert uint to float (temp float)
 | 
					0:11                Convert uint to float (temp float)
 | 
				
			||||||
0:11                  direct index (temp uint)
 | 
					0:11                  direct index (temp uint)
 | 
				
			||||||
@ -102,12 +108,24 @@ Shader version: 450
 | 
				
			|||||||
0:11          'e' (layout(location=5 ) in 4-component vector of float)
 | 
					0:11          'e' (layout(location=5 ) in 4-component vector of float)
 | 
				
			||||||
0:13      Sequence
 | 
					0:13      Sequence
 | 
				
			||||||
0:13        Sequence
 | 
					0:13        Sequence
 | 
				
			||||||
0:13          move second child to first child (temp 2-element array of 4-component vector of float)
 | 
					0:13          move second child to first child (temp 4-component vector of float)
 | 
				
			||||||
0:?             'm' (layout(location=0 ) out 2-element array of 4-component vector of float)
 | 
					0:?             'm[0]' (layout(location=0 ) out 4-component vector of float)
 | 
				
			||||||
0:13            m: direct index for structure (temp 2-element array of 4-component vector of float)
 | 
					0:13            direct index (temp 4-component vector of float)
 | 
				
			||||||
0:13              'local' (temp structure{temp 2-element array of 4-component vector of float m, temp 2-component vector of uint coord, temp 4-component vector of float b})
 | 
					0:13              m: direct index for structure (temp 2-element array of 4-component vector of float)
 | 
				
			||||||
 | 
					0:13                'local' (temp structure{temp 2-element array of 4-component vector of float m, temp 2-component vector of uint coord, temp 4-component vector of float b})
 | 
				
			||||||
 | 
					0:13                Constant:
 | 
				
			||||||
 | 
					0:13                  0 (const int)
 | 
				
			||||||
0:13              Constant:
 | 
					0:13              Constant:
 | 
				
			||||||
0:13                0 (const int)
 | 
					0:13                0 (const int)
 | 
				
			||||||
 | 
					0:13          move second child to first child (temp 4-component vector of float)
 | 
				
			||||||
 | 
					0:?             'm[1]' (layout(location=1 ) out 4-component vector of float)
 | 
				
			||||||
 | 
					0:13            direct index (temp 4-component vector of float)
 | 
				
			||||||
 | 
					0:13              m: direct index for structure (temp 2-element array of 4-component vector of float)
 | 
				
			||||||
 | 
					0:13                'local' (temp structure{temp 2-element array of 4-component vector of float m, temp 2-component vector of uint coord, temp 4-component vector of float b})
 | 
				
			||||||
 | 
					0:13                Constant:
 | 
				
			||||||
 | 
					0:13                  0 (const int)
 | 
				
			||||||
 | 
					0:13              Constant:
 | 
				
			||||||
 | 
					0:13                1 (const int)
 | 
				
			||||||
0:13          move second child to first child (temp 2-component vector of uint)
 | 
					0:13          move second child to first child (temp 2-component vector of uint)
 | 
				
			||||||
0:?             'coord' (layout(location=2 ) out 2-component vector of uint)
 | 
					0:?             'coord' (layout(location=2 ) out 2-component vector of uint)
 | 
				
			||||||
0:13            coord: direct index for structure (temp 2-component vector of uint)
 | 
					0:13            coord: direct index for structure (temp 2-component vector of uint)
 | 
				
			||||||
@ -122,45 +140,55 @@ Shader version: 450
 | 
				
			|||||||
0:13                2 (const int)
 | 
					0:13                2 (const int)
 | 
				
			||||||
0:13        Branch: Return
 | 
					0:13        Branch: Return
 | 
				
			||||||
0:?   Linker Objects
 | 
					0:?   Linker Objects
 | 
				
			||||||
0:?     'm' (layout(location=0 ) out 2-element array of 4-component vector of float)
 | 
					0:?     'm[0]' (layout(location=0 ) out 4-component vector of float)
 | 
				
			||||||
 | 
					0:?     'm[1]' (layout(location=1 ) out 4-component vector of float)
 | 
				
			||||||
0:?     'coord' (layout(location=2 ) out 2-component vector of uint)
 | 
					0:?     'coord' (layout(location=2 ) out 2-component vector of uint)
 | 
				
			||||||
0:?     'b' (layout(location=3 ) smooth out 4-component vector of float)
 | 
					0:?     'b' (layout(location=3 ) smooth out 4-component vector of float)
 | 
				
			||||||
0:?     'd' (layout(location=0 ) in 4-component vector of float)
 | 
					0:?     'd' (layout(location=0 ) in 4-component vector of float)
 | 
				
			||||||
0:?     'm' (layout(location=1 ) in 2-element array of 4-component vector of float)
 | 
					0:?     'm[0]' (layout(location=1 ) in 4-component vector of float)
 | 
				
			||||||
 | 
					0:?     'm[1]' (layout(location=2 ) in 4-component vector of float)
 | 
				
			||||||
0:?     'coord' (layout(location=3 ) in 2-component vector of uint)
 | 
					0:?     'coord' (layout(location=3 ) in 2-component vector of uint)
 | 
				
			||||||
0:?     'b' (layout(location=4 ) in 4-component vector of float)
 | 
					0:?     'b' (layout(location=4 ) in 4-component vector of float)
 | 
				
			||||||
0:?     'e' (layout(location=5 ) in 4-component vector of float)
 | 
					0:?     'e' (layout(location=5 ) in 4-component vector of float)
 | 
				
			||||||
 | 
					0:?     'm[0]' (layout(location=0 ) out 4-component vector of float)
 | 
				
			||||||
 | 
					0:?     'm[1]' (layout(location=1 ) out 4-component vector of float)
 | 
				
			||||||
 | 
					0:?     'm[0]' (layout(location=1 ) in 4-component vector of float)
 | 
				
			||||||
 | 
					0:?     'm[1]' (layout(location=2 ) in 4-component vector of float)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Module Version 10000
 | 
					// Module Version 10000
 | 
				
			||||||
// Generated by (magic number): 80001
 | 
					// Generated by (magic number): 80001
 | 
				
			||||||
// Id's are bound by 60
 | 
					// Id's are bound by 59
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                              Capability Shader
 | 
					                              Capability Shader
 | 
				
			||||||
               1:             ExtInstImport  "GLSL.std.450"
 | 
					               1:             ExtInstImport  "GLSL.std.450"
 | 
				
			||||||
                              MemoryModel Logical GLSL450
 | 
					                              MemoryModel Logical GLSL450
 | 
				
			||||||
                              EntryPoint Vertex 4  "main" 18 28 36 39 45 50 55 59
 | 
					                              EntryPoint Vertex 4  "main" 18 20 24 32 35 41 45 50 54 58
 | 
				
			||||||
                              Name 4  "main"
 | 
					                              Name 4  "main"
 | 
				
			||||||
                              Name 12  "VI"
 | 
					                              Name 12  "VI"
 | 
				
			||||||
                              MemberName 12(VI) 0  "m"
 | 
					                              MemberName 12(VI) 0  "m"
 | 
				
			||||||
                              MemberName 12(VI) 1  "coord"
 | 
					                              MemberName 12(VI) 1  "coord"
 | 
				
			||||||
                              MemberName 12(VI) 2  "b"
 | 
					                              MemberName 12(VI) 2  "b"
 | 
				
			||||||
                              Name 14  "local"
 | 
					                              Name 14  "local"
 | 
				
			||||||
                              Name 18  "m"
 | 
					                              Name 18  "m[1]"
 | 
				
			||||||
                              Name 28  "coord"
 | 
					                              Name 20  "m[0]"
 | 
				
			||||||
                              Name 36  "d"
 | 
					                              Name 24  "coord"
 | 
				
			||||||
                              Name 39  "e"
 | 
					                              Name 32  "d"
 | 
				
			||||||
                              Name 45  "m"
 | 
					                              Name 35  "e"
 | 
				
			||||||
 | 
					                              Name 41  "m[0]"
 | 
				
			||||||
 | 
					                              Name 45  "m[1]"
 | 
				
			||||||
                              Name 50  "coord"
 | 
					                              Name 50  "coord"
 | 
				
			||||||
                              Name 55  "b"
 | 
					                              Name 54  "b"
 | 
				
			||||||
                              Name 59  "b"
 | 
					                              Name 58  "b"
 | 
				
			||||||
                              Decorate 18(m) Location 1
 | 
					                              Decorate 18(m[1]) Location 2
 | 
				
			||||||
                              Decorate 28(coord) Location 3
 | 
					                              Decorate 20(m[0]) Location 1
 | 
				
			||||||
                              Decorate 36(d) Location 0
 | 
					                              Decorate 24(coord) Location 3
 | 
				
			||||||
                              Decorate 39(e) Location 5
 | 
					                              Decorate 32(d) Location 0
 | 
				
			||||||
                              Decorate 45(m) Location 0
 | 
					                              Decorate 35(e) Location 5
 | 
				
			||||||
 | 
					                              Decorate 41(m[0]) Location 0
 | 
				
			||||||
 | 
					                              Decorate 45(m[1]) Location 1
 | 
				
			||||||
                              Decorate 50(coord) Location 2
 | 
					                              Decorate 50(coord) Location 2
 | 
				
			||||||
                              Decorate 55(b) Location 3
 | 
					                              Decorate 54(b) Location 3
 | 
				
			||||||
                              Decorate 59(b) Location 4
 | 
					                              Decorate 58(b) Location 4
 | 
				
			||||||
               2:             TypeVoid
 | 
					               2:             TypeVoid
 | 
				
			||||||
               3:             TypeFunction 2
 | 
					               3:             TypeFunction 2
 | 
				
			||||||
               6:             TypeFloat 32
 | 
					               6:             TypeFloat 32
 | 
				
			||||||
@ -173,54 +201,54 @@ Shader version: 450
 | 
				
			|||||||
              13:             TypePointer Function 12(VI)
 | 
					              13:             TypePointer Function 12(VI)
 | 
				
			||||||
              15:             TypeInt 32 1
 | 
					              15:             TypeInt 32 1
 | 
				
			||||||
              16:     15(int) Constant 2
 | 
					              16:     15(int) Constant 2
 | 
				
			||||||
              17:             TypePointer Input 10
 | 
					              17:             TypePointer Input 7(fvec4)
 | 
				
			||||||
           18(m):     17(ptr) Variable Input
 | 
					        18(m[1]):     17(ptr) Variable Input
 | 
				
			||||||
              19:     15(int) Constant 1
 | 
					        20(m[0]):     17(ptr) Variable Input
 | 
				
			||||||
              20:             TypePointer Input 7(fvec4)
 | 
					              23:             TypePointer Input 11(ivec2)
 | 
				
			||||||
              23:     15(int) Constant 0
 | 
					       24(coord):     23(ptr) Variable Input
 | 
				
			||||||
              27:             TypePointer Input 11(ivec2)
 | 
					              25:      8(int) Constant 0
 | 
				
			||||||
       28(coord):     27(ptr) Variable Input
 | 
					              26:             TypePointer Input 8(int)
 | 
				
			||||||
              29:      8(int) Constant 0
 | 
					           32(d):     17(ptr) Variable Input
 | 
				
			||||||
              30:             TypePointer Input 8(int)
 | 
					           35(e):     17(ptr) Variable Input
 | 
				
			||||||
           36(d):     20(ptr) Variable Input
 | 
					              38:             TypePointer Function 7(fvec4)
 | 
				
			||||||
           39(e):     20(ptr) Variable Input
 | 
					              40:             TypePointer Output 7(fvec4)
 | 
				
			||||||
              42:             TypePointer Function 7(fvec4)
 | 
					        41(m[0]):     40(ptr) Variable Output
 | 
				
			||||||
              44:             TypePointer Output 10
 | 
					              42:     15(int) Constant 0
 | 
				
			||||||
           45(m):     44(ptr) Variable Output
 | 
					        45(m[1]):     40(ptr) Variable Output
 | 
				
			||||||
              46:             TypePointer Function 10
 | 
					              46:     15(int) Constant 1
 | 
				
			||||||
              49:             TypePointer Output 11(ivec2)
 | 
					              49:             TypePointer Output 11(ivec2)
 | 
				
			||||||
       50(coord):     49(ptr) Variable Output
 | 
					       50(coord):     49(ptr) Variable Output
 | 
				
			||||||
              51:             TypePointer Function 11(ivec2)
 | 
					              51:             TypePointer Function 11(ivec2)
 | 
				
			||||||
              54:             TypePointer Output 7(fvec4)
 | 
					           54(b):     40(ptr) Variable Output
 | 
				
			||||||
           55(b):     54(ptr) Variable Output
 | 
					           58(b):     17(ptr) Variable Input
 | 
				
			||||||
           59(b):     20(ptr) Variable Input
 | 
					 | 
				
			||||||
         4(main):           2 Function None 3
 | 
					         4(main):           2 Function None 3
 | 
				
			||||||
               5:             Label
 | 
					               5:             Label
 | 
				
			||||||
       14(local):     13(ptr) Variable Function
 | 
					       14(local):     13(ptr) Variable Function
 | 
				
			||||||
              21:     20(ptr) AccessChain 18(m) 19
 | 
					              19:    7(fvec4) Load 18(m[1])
 | 
				
			||||||
              22:    7(fvec4) Load 21
 | 
					              21:    7(fvec4) Load 20(m[0])
 | 
				
			||||||
              24:     20(ptr) AccessChain 18(m) 23
 | 
					              22:    7(fvec4) FAdd 19 21
 | 
				
			||||||
              25:    7(fvec4) Load 24
 | 
					              27:     26(ptr) AccessChain 24(coord) 25
 | 
				
			||||||
              26:    7(fvec4) FAdd 22 25
 | 
					              28:      8(int) Load 27
 | 
				
			||||||
              31:     30(ptr) AccessChain 28(coord) 29
 | 
					              29:    6(float) ConvertUToF 28
 | 
				
			||||||
              32:      8(int) Load 31
 | 
					              30:    7(fvec4) CompositeConstruct 29 29 29 29
 | 
				
			||||||
              33:    6(float) ConvertUToF 32
 | 
					              31:    7(fvec4) FAdd 22 30
 | 
				
			||||||
              34:    7(fvec4) CompositeConstruct 33 33 33 33
 | 
					              33:    7(fvec4) Load 32(d)
 | 
				
			||||||
              35:    7(fvec4) FAdd 26 34
 | 
					              34:    7(fvec4) FAdd 31 33
 | 
				
			||||||
              37:    7(fvec4) Load 36(d)
 | 
					              36:    7(fvec4) Load 35(e)
 | 
				
			||||||
              38:    7(fvec4) FAdd 35 37
 | 
					              37:    7(fvec4) FAdd 34 36
 | 
				
			||||||
              40:    7(fvec4) Load 39(e)
 | 
					              39:     38(ptr) AccessChain 14(local) 16
 | 
				
			||||||
              41:    7(fvec4) FAdd 38 40
 | 
					                              Store 39 37
 | 
				
			||||||
              43:     42(ptr) AccessChain 14(local) 16
 | 
					              43:     38(ptr) AccessChain 14(local) 42 42
 | 
				
			||||||
                              Store 43 41
 | 
					              44:    7(fvec4) Load 43
 | 
				
			||||||
              47:     46(ptr) AccessChain 14(local) 23
 | 
					                              Store 41(m[0]) 44
 | 
				
			||||||
              48:          10 Load 47
 | 
					              47:     38(ptr) AccessChain 14(local) 42 46
 | 
				
			||||||
                              Store 45(m) 48
 | 
					              48:    7(fvec4) Load 47
 | 
				
			||||||
              52:     51(ptr) AccessChain 14(local) 19
 | 
					                              Store 45(m[1]) 48
 | 
				
			||||||
 | 
					              52:     51(ptr) AccessChain 14(local) 46
 | 
				
			||||||
              53:   11(ivec2) Load 52
 | 
					              53:   11(ivec2) Load 52
 | 
				
			||||||
                              Store 50(coord) 53
 | 
					                              Store 50(coord) 53
 | 
				
			||||||
              56:     42(ptr) AccessChain 14(local) 16
 | 
					              55:     38(ptr) AccessChain 14(local) 16
 | 
				
			||||||
              57:    7(fvec4) Load 56
 | 
					              56:    7(fvec4) Load 55
 | 
				
			||||||
                              Store 55(b) 57
 | 
					                              Store 54(b) 56
 | 
				
			||||||
                              Return
 | 
					                              Return
 | 
				
			||||||
                              FunctionEnd
 | 
					                              FunctionEnd
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										28
									
								
								Test/hlsl.structarray.flatten.frag
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								Test/hlsl.structarray.flatten.frag
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,28 @@
 | 
				
			|||||||
 | 
					SamplerState g_samp;
 | 
				
			||||||
 | 
					Texture1D    g_tex;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct tex_t {
 | 
				
			||||||
 | 
					    SamplerState samp;
 | 
				
			||||||
 | 
					    Texture1D tex;
 | 
				
			||||||
 | 
					    int nonopaque_thing;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct tex_with_arrays_t {
 | 
				
			||||||
 | 
					    SamplerState samp[2];
 | 
				
			||||||
 | 
					    Texture1D tex[2];
 | 
				
			||||||
 | 
					    int nonopaque_thing;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uniform tex_t g_texdata;
 | 
				
			||||||
 | 
					uniform tex_t g_texdata_array[3];
 | 
				
			||||||
 | 
					uniform tex_with_arrays_t g_texdata_array2[3];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct PS_OUTPUT { float4 color : SV_Target0; };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void main(out PS_OUTPUT ps_output)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    ps_output.color =
 | 
				
			||||||
 | 
					        g_texdata.tex.Sample(g_texdata.samp, 0.5) +
 | 
				
			||||||
 | 
					        g_texdata_array[1].tex.Sample(g_texdata_array[1].samp, 0.4) +
 | 
				
			||||||
 | 
					        g_texdata_array2[1].tex[0].Sample(g_texdata_array2[1].samp[0], 0.3);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										17
									
								
								Test/hlsl.structarray.flatten.geom
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								Test/hlsl.structarray.flatten.geom
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,17 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					struct VertexData {
 | 
				
			||||||
 | 
						float4 position : POSITION;
 | 
				
			||||||
 | 
						float4 color    : COLOR0;
 | 
				
			||||||
 | 
						float2 uv       : TEXCOORD0;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[maxvertexcount(4)]
 | 
				
			||||||
 | 
					void main(line VertexData vin[2], inout TriangleStream<VertexData> outStream)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    VertexData vout;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    vout.color = vin[0].color;
 | 
				
			||||||
 | 
					    vout.uv = vin[0].uv;
 | 
				
			||||||
 | 
					    vout.position = vin[0].position;
 | 
				
			||||||
 | 
					    outStream.Append(vout);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -11,4 +11,4 @@ VI main(float4 d, VI vi, float4 e) : SV_POSITION
 | 
				
			|||||||
    local.b = vi.m[1] + vi.m[0] + float4(vi.coord.x) + d + e;
 | 
					    local.b = vi.m[1] + vi.m[0] + float4(vi.coord.x) + d + e;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return local;
 | 
					    return local;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -204,6 +204,8 @@ INSTANTIATE_TEST_CASE_P(
 | 
				
			|||||||
        {"hlsl.shapeConvRet.frag", "main"},
 | 
					        {"hlsl.shapeConvRet.frag", "main"},
 | 
				
			||||||
        {"hlsl.stringtoken.frag", "main"},
 | 
					        {"hlsl.stringtoken.frag", "main"},
 | 
				
			||||||
        {"hlsl.string.frag", "main"},
 | 
					        {"hlsl.string.frag", "main"},
 | 
				
			||||||
 | 
					        {"hlsl.structarray.flatten.frag", "main"},
 | 
				
			||||||
 | 
					        {"hlsl.structarray.flatten.geom", "main"},
 | 
				
			||||||
        {"hlsl.structin.vert", "main"},
 | 
					        {"hlsl.structin.vert", "main"},
 | 
				
			||||||
        {"hlsl.intrinsics.vert", "VertexShaderFunction"},
 | 
					        {"hlsl.intrinsics.vert", "VertexShaderFunction"},
 | 
				
			||||||
        {"hlsl.matType.frag", "PixelShaderFunction"},
 | 
					        {"hlsl.matType.frag", "PixelShaderFunction"},
 | 
				
			||||||
 | 
				
			|||||||
@ -389,7 +389,7 @@ bool HlslGrammar::acceptDeclaration(TIntermNode*& node)
 | 
				
			|||||||
                else if (variableType.getBasicType() == EbtBlock)
 | 
					                else if (variableType.getBasicType() == EbtBlock)
 | 
				
			||||||
                    parseContext.declareBlock(idToken.loc, variableType, idToken.string);
 | 
					                    parseContext.declareBlock(idToken.loc, variableType, idToken.string);
 | 
				
			||||||
                else {
 | 
					                else {
 | 
				
			||||||
                    if (variableType.getQualifier().storage == EvqUniform && ! variableType.isOpaque()) {
 | 
					                    if (variableType.getQualifier().storage == EvqUniform && ! variableType.containsOpaque()) {
 | 
				
			||||||
                        // this isn't really an individual variable, but a member of the $Global buffer
 | 
					                        // this isn't really an individual variable, but a member of the $Global buffer
 | 
				
			||||||
                        parseContext.growGlobalUniformBlock(idToken.loc, variableType, *idToken.string);
 | 
					                        parseContext.growGlobalUniformBlock(idToken.loc, variableType, *idToken.string);
 | 
				
			||||||
                    } else {
 | 
					                    } else {
 | 
				
			||||||
@ -2215,6 +2215,20 @@ bool HlslGrammar::acceptPostfixExpression(TIntermTyped*& node)
 | 
				
			|||||||
        return false;
 | 
					        return false;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // This is to guarantee we do this no matter how we get out of the stack frame.
 | 
				
			||||||
 | 
					    // This way there's no bug if an early return forgets to do it.
 | 
				
			||||||
 | 
					    struct tFinalize {
 | 
				
			||||||
 | 
					        tFinalize(HlslParseContext& p) : parseContext(p) { }
 | 
				
			||||||
 | 
					        ~tFinalize() { parseContext.finalizeFlattening(); }
 | 
				
			||||||
 | 
					       HlslParseContext& parseContext;
 | 
				
			||||||
 | 
					    } finalize(parseContext);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Initialize the flattening accumulation data, so we can track data across multiple bracket or
 | 
				
			||||||
 | 
					    // dot operators.  This can also be nested, e.g, for [], so we have to track each nesting
 | 
				
			||||||
 | 
					    // level: hence the init and finalize.  Even though in practice these must be
 | 
				
			||||||
 | 
					    // constants, they are parsed no matter what.
 | 
				
			||||||
 | 
					    parseContext.initFlattening();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Something was found, chain as many postfix operations as exist.
 | 
					    // Something was found, chain as many postfix operations as exist.
 | 
				
			||||||
    do {
 | 
					    do {
 | 
				
			||||||
        TSourceLoc loc = token.loc;
 | 
					        TSourceLoc loc = token.loc;
 | 
				
			||||||
@ -2248,7 +2262,7 @@ bool HlslGrammar::acceptPostfixExpression(TIntermTyped*& node)
 | 
				
			|||||||
            node = parseContext.handleDotDereference(field.loc, node, *field.string);
 | 
					            node = parseContext.handleDotDereference(field.loc, node, *field.string);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // In the event of a method node, we look for an open paren and accept the function call.
 | 
					            // In the event of a method node, we look for an open paren and accept the function call.
 | 
				
			||||||
            if (node->getAsMethodNode() != nullptr && peekTokenClass(EHTokLeftParen)) {
 | 
					            if (node != nullptr && node->getAsMethodNode() != nullptr && peekTokenClass(EHTokLeftParen)) {
 | 
				
			||||||
                if (! acceptFunctionCall(field, node, base)) {
 | 
					                if (! acceptFunctionCall(field, node, base)) {
 | 
				
			||||||
                    expected("function parameters");
 | 
					                    expected("function parameters");
 | 
				
			||||||
                    return false;
 | 
					                    return false;
 | 
				
			||||||
 | 
				
			|||||||
@ -45,6 +45,7 @@
 | 
				
			|||||||
#include "../glslang/OSDependent/osinclude.h"
 | 
					#include "../glslang/OSDependent/osinclude.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <algorithm>
 | 
					#include <algorithm>
 | 
				
			||||||
 | 
					#include <functional>
 | 
				
			||||||
#include <cctype>
 | 
					#include <cctype>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace glslang {
 | 
					namespace glslang {
 | 
				
			||||||
@ -651,11 +652,11 @@ TIntermTyped* HlslParseContext::handleBracketDereference(const TSourceLoc& loc,
 | 
				
			|||||||
    else {
 | 
					    else {
 | 
				
			||||||
        // at least one of base and index is variable...
 | 
					        // at least one of base and index is variable...
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (base->getAsSymbolNode() && shouldFlatten(base->getType())) {
 | 
					        if (base->getAsSymbolNode() && (wasFlattened(base) || shouldFlatten(base->getType()))) {
 | 
				
			||||||
            if (index->getQualifier().storage != EvqConst)
 | 
					            if (index->getQualifier().storage != EvqConst)
 | 
				
			||||||
                error(loc, "Invalid variable index to flattened uniform array", base->getAsSymbolNode()->getName().c_str(), "");
 | 
					                error(loc, "Invalid variable index to flattened uniform array", base->getAsSymbolNode()->getName().c_str(), "");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            result = flattenAccess(base, indexValue);
 | 
					            result = flattenAccess(loc, base, indexValue);
 | 
				
			||||||
            flattened = (result != base);
 | 
					            flattened = (result != base);
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            if (index->getQualifier().storage == EvqConst) {
 | 
					            if (index->getQualifier().storage == EvqConst) {
 | 
				
			||||||
@ -831,8 +832,8 @@ TIntermTyped* HlslParseContext::handleDotDereference(const TSourceLoc& loc, TInt
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        if (fieldFound) {
 | 
					        if (fieldFound) {
 | 
				
			||||||
            if (base->getAsSymbolNode() && shouldFlatten(base->getType()))
 | 
					            if (base->getAsSymbolNode() && (wasFlattened(base) || shouldFlatten(base->getType())))
 | 
				
			||||||
                result = flattenAccess(base, member);
 | 
					                result = flattenAccess(loc, base, member);
 | 
				
			||||||
            else {
 | 
					            else {
 | 
				
			||||||
                if (base->getType().getQualifier().storage == EvqConst)
 | 
					                if (base->getType().getQualifier().storage == EvqConst)
 | 
				
			||||||
                    result = intermediate.foldDereference(base, member, loc);
 | 
					                    result = intermediate.foldDereference(base, member, loc);
 | 
				
			||||||
@ -850,6 +851,12 @@ TIntermTyped* HlslParseContext::handleDotDereference(const TSourceLoc& loc, TInt
 | 
				
			|||||||
    return result;
 | 
					    return result;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Determine whether we should flatten an arbitrary type.
 | 
				
			||||||
 | 
					bool HlslParseContext::shouldFlatten(const TType& type) const
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return shouldFlattenIO(type) || shouldFlattenUniform(type); 
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Is this an IO variable that can't be passed down the stack?
 | 
					// Is this an IO variable that can't be passed down the stack?
 | 
				
			||||||
// E.g., pipeline inputs to the vertex stage and outputs from the fragment stage.
 | 
					// E.g., pipeline inputs to the vertex stage and outputs from the fragment stage.
 | 
				
			||||||
bool HlslParseContext::shouldFlattenIO(const TType& type) const
 | 
					bool HlslParseContext::shouldFlattenIO(const TType& type) const
 | 
				
			||||||
@ -869,27 +876,98 @@ bool HlslParseContext::shouldFlattenUniform(const TType& type) const
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    const TStorageQualifier qualifier = type.getQualifier().storage;
 | 
					    const TStorageQualifier qualifier = type.getQualifier().storage;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return type.isArray() &&
 | 
					    return ((type.isArray() && intermediate.getFlattenUniformArrays()) || type.isStruct()) &&
 | 
				
			||||||
        intermediate.getFlattenUniformArrays() &&
 | 
					 | 
				
			||||||
        qualifier == EvqUniform &&
 | 
					        qualifier == EvqUniform &&
 | 
				
			||||||
        type.isOpaque();
 | 
					        type.containsOpaque();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Top level variable flattening: construct data
 | 
				
			||||||
void HlslParseContext::flatten(const TSourceLoc& loc, const TVariable& variable)
 | 
					void HlslParseContext::flatten(const TSourceLoc& loc, const TVariable& variable)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    const TType& type = variable.getType();
 | 
					    const TType& type = variable.getType();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Presently, flattening of structure arrays is unimplemented.
 | 
					    // emplace gives back a pair whose .first is an iterator to the item...
 | 
				
			||||||
    // We handle one, or the other.
 | 
					    auto entry = flattenMap.emplace(variable.getUniqueId(), 
 | 
				
			||||||
    if (type.isArray() && type.isStruct()) {
 | 
					                                    TFlattenData(type.getQualifier().layoutBinding));
 | 
				
			||||||
        error(loc, "cannot flatten structure array", variable.getName().c_str(), "");
 | 
					        
 | 
				
			||||||
 | 
					    // ... and the item is a map pair, so first->second is the TFlattenData itself.
 | 
				
			||||||
 | 
					    flatten(loc, variable, type, entry.first->second, "");
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					// Recursively flatten the given variable at the provided type, building the flattenData as we go.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// This is mutually recursive with flattenStruct and flattenArray.
 | 
				
			||||||
 | 
					// We are going to flatten an arbitrarily nested composite structure into a linear sequence of
 | 
				
			||||||
 | 
					// members, and later on, we want to turn a path through the tree structure into a final
 | 
				
			||||||
 | 
					// location in this linear sequence.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// If the tree was N-ary, that can be directly calculated.  However, we are dealing with
 | 
				
			||||||
 | 
					// arbitrary numbers - peraps a struct of 7 members containing an array of 3.  Thus, we must
 | 
				
			||||||
 | 
					// build a data structure to allow the sequence of bracket and dot operators on arrays and
 | 
				
			||||||
 | 
					// structs to arrive at the proper member.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// To avoid storing a tree with pointers, we are going to flatten the tree into a vector of integers.
 | 
				
			||||||
 | 
					// The leaves are the indexes into the flattened member array.
 | 
				
			||||||
 | 
					// Each level will have the next location for the Nth item stored sequentially, so for instance:
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// struct { float2 a[2]; int b; float4 c[3] };
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// This will produce the following flattened tree:
 | 
				
			||||||
 | 
					// Pos: 0  1   2    3  4    5  6   7     8   9  10   11  12 13
 | 
				
			||||||
 | 
					//     (3, 7,  8,   5, 6,   0, 1,  2,   11, 12, 13,   3,  4, 5}
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Given a reference to mystruct.c[1], the access chain is (2,1), so we traverse:
 | 
				
			||||||
 | 
					//   (0+2) = 8  -->  (8+1) = 12 -->   12 = 4
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// so the 4th flattened member in traversal order is ours.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					int HlslParseContext::flatten(const TSourceLoc& loc, const TVariable& variable, const TType& type,
 | 
				
			||||||
 | 
					                              TFlattenData& flattenData, TString name)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    // TODO: when struct splitting is in place we can remove this restriction.
 | 
				
			||||||
 | 
					    if (language == EShLangGeometry) {
 | 
				
			||||||
 | 
					        const TType derefType(type, 0);
 | 
				
			||||||
 | 
					        if (!isFinalFlattening(derefType) && type.getQualifier().storage == EvqVaryingIn)
 | 
				
			||||||
 | 
					            error(loc, "recursive type not yet supported in GS input", variable.getName().c_str(), "");
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (type.isStruct())
 | 
					    // If something is an arrayed struct, the array flattener will recursively call flatten()
 | 
				
			||||||
        flattenStruct(variable);
 | 
					    // to then flatten the struct, so this is an "if else": we don't do both.
 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    if (type.isArray())
 | 
					    if (type.isArray())
 | 
				
			||||||
        flattenArray(loc, variable);
 | 
					        return flattenArray(loc, variable, type, flattenData, name);
 | 
				
			||||||
 | 
					    else if (type.isStruct())
 | 
				
			||||||
 | 
					        return flattenStruct(loc, variable, type, flattenData, name);
 | 
				
			||||||
 | 
					    else {
 | 
				
			||||||
 | 
					        assert(0); // should never happen
 | 
				
			||||||
 | 
					        return -1;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Add a single flattened member to the flattened data being tracked for the composite
 | 
				
			||||||
 | 
					// Returns true for the final flattening level.
 | 
				
			||||||
 | 
					int HlslParseContext::addFlattenedMember(const TSourceLoc& loc, 
 | 
				
			||||||
 | 
					                                          const TVariable& variable, const TType& type, TFlattenData& flattenData, 
 | 
				
			||||||
 | 
					                                          const TString& memberName, bool track)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (isFinalFlattening(type)) {
 | 
				
			||||||
 | 
					        // This is as far as we flatten.  Insert the variable.
 | 
				
			||||||
 | 
					        TVariable* memberVariable = makeInternalVariable(memberName.c_str(), type);
 | 
				
			||||||
 | 
					        mergeQualifiers(memberVariable->getWritableType().getQualifier(), variable.getType().getQualifier());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (flattenData.nextBinding != TQualifier::layoutBindingEnd)
 | 
				
			||||||
 | 
					            memberVariable->getWritableType().getQualifier().layoutBinding = flattenData.nextBinding++;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        flattenData.offsets.push_back(flattenData.members.size());
 | 
				
			||||||
 | 
					        flattenData.members.push_back(memberVariable);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (track)
 | 
				
			||||||
 | 
					            trackLinkageDeferred(*memberVariable);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return flattenData.offsets.size()-1; // location of the member reference
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        // Further recursion required
 | 
				
			||||||
 | 
					        return flatten(loc, variable, type, flattenData, memberName);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Figure out the mapping between an aggregate's top members and an
 | 
					// Figure out the mapping between an aggregate's top members and an
 | 
				
			||||||
@ -899,84 +977,103 @@ void HlslParseContext::flatten(const TSourceLoc& loc, const TVariable& variable)
 | 
				
			|||||||
//      effecting a transfer of this information to the flattened variable form.
 | 
					//      effecting a transfer of this information to the flattened variable form.
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
// Assumes shouldFlatten() or equivalent was called first.
 | 
					// Assumes shouldFlatten() or equivalent was called first.
 | 
				
			||||||
//
 | 
					int HlslParseContext::flattenStruct(const TSourceLoc& loc, const TVariable& variable, const TType& type, 
 | 
				
			||||||
// TODO: generalize this to arbitrary nesting?
 | 
					                                     TFlattenData& flattenData, TString name)
 | 
				
			||||||
void HlslParseContext::flattenStruct(const TVariable& variable)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    TVector<TVariable*> memberVariables;
 | 
					    assert(type.isStruct());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    auto members = *type.getStruct();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Reserve space for this tree level.
 | 
				
			||||||
 | 
					    int start = flattenData.offsets.size();
 | 
				
			||||||
 | 
					    int pos   = start;
 | 
				
			||||||
 | 
					    flattenData.offsets.resize(int(pos + members.size()), -1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    auto members = *variable.getType().getStruct();
 | 
					 | 
				
			||||||
    for (int member = 0; member < (int)members.size(); ++member) {
 | 
					    for (int member = 0; member < (int)members.size(); ++member) {
 | 
				
			||||||
        TVariable* memberVariable = makeInternalVariable(members[member].type->getFieldName().c_str(),
 | 
					        TType& dereferencedType = *members[member].type;
 | 
				
			||||||
                                                         *members[member].type);
 | 
					        const TString memberName = name + (name.empty() ? "" : ".") + dereferencedType.getFieldName();
 | 
				
			||||||
        mergeQualifiers(memberVariable->getWritableType().getQualifier(), variable.getType().getQualifier());
 | 
					
 | 
				
			||||||
        memberVariables.push_back(memberVariable);
 | 
					        const int mpos = addFlattenedMember(loc, variable, dereferencedType, flattenData, memberName, false);
 | 
				
			||||||
 | 
					        flattenData.offsets[pos++] = mpos;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // N.B. Erase I/O-related annotations from the source-type member.
 | 
					        // N.B. Erase I/O-related annotations from the source-type member.
 | 
				
			||||||
        members[member].type->getQualifier().makeTemporary();
 | 
					        dereferencedType.getQualifier().makeTemporary();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    flattenMap[variable.getUniqueId()] = memberVariables;
 | 
					    return start;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Figure out mapping between an array's members and an
 | 
					// Figure out mapping between an array's members and an
 | 
				
			||||||
// equivalent set of individual variables.
 | 
					// equivalent set of individual variables.
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
// Assumes shouldFlatten() or equivalent was called first.
 | 
					// Assumes shouldFlatten() or equivalent was called first.
 | 
				
			||||||
void HlslParseContext::flattenArray(const TSourceLoc& loc, const TVariable& variable)
 | 
					int HlslParseContext::flattenArray(const TSourceLoc& loc, const TVariable& variable, const TType& type, 
 | 
				
			||||||
 | 
					                                   TFlattenData& flattenData, TString name)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    const TType& type = variable.getType();
 | 
					 | 
				
			||||||
    assert(type.isArray());
 | 
					    assert(type.isArray());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (type.isImplicitlySizedArray())
 | 
					    if (type.isImplicitlySizedArray())
 | 
				
			||||||
        error(loc, "cannot flatten implicitly sized array", variable.getName().c_str(), "");
 | 
					        error(loc, "cannot flatten implicitly sized array", variable.getName().c_str(), "");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (type.getArraySizes()->getNumDims() != 1)
 | 
					    const int size = type.getOuterArraySize();
 | 
				
			||||||
        error(loc, "cannot flatten multi-dimensional array", variable.getName().c_str(), "");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    const int size = type.getCumulativeArraySize();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    TVector<TVariable*> memberVariables;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    const TType dereferencedType(type, 0);
 | 
					    const TType dereferencedType(type, 0);
 | 
				
			||||||
    int binding = type.getQualifier().layoutBinding;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (dereferencedType.isStruct() || dereferencedType.isArray()) {
 | 
					    if (name.empty())
 | 
				
			||||||
        error(loc, "cannot flatten array of aggregate types", variable.getName().c_str(), "");
 | 
					        name = variable.getName();
 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (int element=0; element < size; ++element) {
 | 
					    // Reserve space for this tree level.
 | 
				
			||||||
 | 
					    int start = flattenData.offsets.size();
 | 
				
			||||||
 | 
					    int pos   = start;
 | 
				
			||||||
 | 
					    flattenData.offsets.resize(int(pos + size), -1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (int element=0; element < size; ++element) {      
 | 
				
			||||||
        char elementNumBuf[20];  // sufficient for MAXINT
 | 
					        char elementNumBuf[20];  // sufficient for MAXINT
 | 
				
			||||||
        snprintf(elementNumBuf, sizeof(elementNumBuf)-1, "[%d]", element);
 | 
					        snprintf(elementNumBuf, sizeof(elementNumBuf)-1, "[%d]", element);
 | 
				
			||||||
        const TString memberName = variable.getName() + elementNumBuf;
 | 
					        const int mpos = addFlattenedMember(loc, variable, dereferencedType, flattenData,
 | 
				
			||||||
 | 
					                                            name + elementNumBuf, true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        TVariable* memberVariable = makeInternalVariable(memberName.c_str(), dereferencedType);
 | 
					        flattenData.offsets[pos++] = mpos;
 | 
				
			||||||
        memberVariable->getWritableType().getQualifier() = variable.getType().getQualifier();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        memberVariable->getWritableType().getQualifier().layoutBinding = binding;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (binding != TQualifier::layoutBindingEnd)
 | 
					 | 
				
			||||||
            ++binding;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        memberVariables.push_back(memberVariable);
 | 
					 | 
				
			||||||
        trackLinkageDeferred(*memberVariable);
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    flattenMap[variable.getUniqueId()] = memberVariables;
 | 
					    return start;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Return true if we have flattened this node.
 | 
				
			||||||
 | 
					bool HlslParseContext::wasFlattened(const TIntermTyped* node) const
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return node != nullptr &&
 | 
				
			||||||
 | 
					        node->getAsSymbolNode() != nullptr &&
 | 
				
			||||||
 | 
					        wasFlattened(node->getAsSymbolNode()->getId());
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Turn an access into an aggregate that was flattened to instead be
 | 
					// Turn an access into an aggregate that was flattened to instead be
 | 
				
			||||||
// an access to the individual variable the member was flattened to.
 | 
					// an access to the individual variable the member was flattened to.
 | 
				
			||||||
// Assumes shouldFlatten() or equivalent was called first.
 | 
					// Assumes shouldFlatten() or equivalent was called first.
 | 
				
			||||||
TIntermTyped* HlslParseContext::flattenAccess(TIntermTyped* base, int member)
 | 
					TIntermTyped* HlslParseContext::flattenAccess(const TSourceLoc&, TIntermTyped* base, int member)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    const TType dereferencedType(base->getType(), member);  // dereferenced type
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const TIntermSymbol& symbolNode = *base->getAsSymbolNode();
 | 
					    const TIntermSymbol& symbolNode = *base->getAsSymbolNode();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (flattenMap.find(symbolNode.getId()) == flattenMap.end())
 | 
					    const auto flattenData = flattenMap.find(symbolNode.getId());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (flattenData == flattenMap.end())
 | 
				
			||||||
        return base;
 | 
					        return base;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const TVariable* memberVariable = flattenMap[symbolNode.getId()][member];
 | 
					    // Calculate new cumulative offset from the packed tree
 | 
				
			||||||
    return intermediate.addSymbol(*memberVariable);
 | 
					    flattenOffset.back() = flattenData->second.offsets[flattenOffset.back() + member];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (isFinalFlattening(dereferencedType)) {
 | 
				
			||||||
 | 
					        // Finished flattening: create symbol for variable
 | 
				
			||||||
 | 
					        member = flattenData->second.offsets[flattenOffset.back()];
 | 
				
			||||||
 | 
					        const TVariable* memberVariable = flattenData->second.members[member];
 | 
				
			||||||
 | 
					        return intermediate.addSymbol(*memberVariable);
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        // If this is not the final flattening, accumulate the position and return
 | 
				
			||||||
 | 
					        // an object of the partially dereferenced type.
 | 
				
			||||||
 | 
					        return new TIntermSymbol(symbolNode.getId(), "flattenShadow", dereferencedType);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Variables that correspond to the user-interface in and out of a stage
 | 
					// Variables that correspond to the user-interface in and out of a stage
 | 
				
			||||||
@ -1002,8 +1099,8 @@ void HlslParseContext::assignLocations(TVariable& variable)
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (shouldFlatten(variable.getType())) {
 | 
					    if (wasFlattened(variable.getUniqueId())) {
 | 
				
			||||||
        auto& memberList = flattenMap[variable.getUniqueId()];
 | 
					        auto& memberList = flattenMap[variable.getUniqueId()].members;
 | 
				
			||||||
        for (auto member = memberList.begin(); member != memberList.end(); ++member)
 | 
					        for (auto member = memberList.begin(); member != memberList.end(); ++member)
 | 
				
			||||||
            assignLocation(**member);
 | 
					            assignLocation(**member);
 | 
				
			||||||
    } else
 | 
					    } else
 | 
				
			||||||
@ -1294,7 +1391,7 @@ TIntermTyped* HlslParseContext::handleAssign(const TSourceLoc& loc, TOperator op
 | 
				
			|||||||
        return nullptr;
 | 
					        return nullptr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const auto mustFlatten = [&](const TIntermTyped& node) {
 | 
					    const auto mustFlatten = [&](const TIntermTyped& node) {
 | 
				
			||||||
        return shouldFlatten(node.getType()) && node.getAsSymbolNode() &&
 | 
					        return wasFlattened(&node) && node.getAsSymbolNode() &&
 | 
				
			||||||
               flattenMap.find(node.getAsSymbolNode()->getId()) != flattenMap.end();
 | 
					               flattenMap.find(node.getAsSymbolNode()->getId()) != flattenMap.end();
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -1327,10 +1424,10 @@ TIntermTyped* HlslParseContext::handleAssign(const TSourceLoc& loc, TOperator op
 | 
				
			|||||||
        memberCount = left->getType().getCumulativeArraySize();
 | 
					        memberCount = left->getType().getCumulativeArraySize();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (flattenLeft)
 | 
					    if (flattenLeft)
 | 
				
			||||||
        leftVariables = &flattenMap.find(left->getAsSymbolNode()->getId())->second;
 | 
					        leftVariables = &flattenMap.find(left->getAsSymbolNode()->getId())->second.members;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (flattenRight) {
 | 
					    if (flattenRight) {
 | 
				
			||||||
        rightVariables = &flattenMap.find(right->getAsSymbolNode()->getId())->second;
 | 
					        rightVariables = &flattenMap.find(right->getAsSymbolNode()->getId())->second.members;
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
        // The RHS is not flattened.  There are several cases:
 | 
					        // The RHS is not flattened.  There are several cases:
 | 
				
			||||||
        // 1. 1 item to copy:  Use the RHS directly.
 | 
					        // 1. 1 item to copy:  Use the RHS directly.
 | 
				
			||||||
@ -1355,13 +1452,15 @@ TIntermTyped* HlslParseContext::handleAssign(const TSourceLoc& loc, TOperator op
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    int memberIdx = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const auto getMember = [&](bool flatten, TIntermTyped* node,
 | 
					    const auto getMember = [&](bool flatten, TIntermTyped* node,
 | 
				
			||||||
                               const TVector<TVariable*>& memberVariables, int member,
 | 
					                               const TVector<TVariable*>& memberVariables, int member,
 | 
				
			||||||
                               TOperator op, const TType& memberType) -> TIntermTyped * {
 | 
					                               TOperator op, const TType& memberType) -> TIntermTyped * {
 | 
				
			||||||
        TIntermTyped* subTree;
 | 
					        TIntermTyped* subTree;
 | 
				
			||||||
        if (flatten)
 | 
					        if (flatten && isFinalFlattening(memberType)) {
 | 
				
			||||||
            subTree = intermediate.addSymbol(*memberVariables[member]);
 | 
					            subTree = intermediate.addSymbol(*memberVariables[memberIdx++]);
 | 
				
			||||||
        else {
 | 
					        } else {
 | 
				
			||||||
            subTree = intermediate.addIndex(op, node, intermediate.addConstantUnion(member, loc), loc);
 | 
					            subTree = intermediate.addIndex(op, node, intermediate.addConstantUnion(member, loc), loc);
 | 
				
			||||||
            subTree->setType(memberType);
 | 
					            subTree->setType(memberType);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@ -1369,46 +1468,59 @@ TIntermTyped* HlslParseContext::handleAssign(const TSourceLoc& loc, TOperator op
 | 
				
			|||||||
        return subTree;
 | 
					        return subTree;
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Return the proper RHS node: a new symbol from a TVariable, copy
 | 
					    // Cannot use auto here, because this is recursive, and auto can't work out the type without seeing the
 | 
				
			||||||
    // of an TIntermSymbol node, or sometimes the right node directly.
 | 
					    // whole thing.  So, we'll resort to an explicit type via std::function.
 | 
				
			||||||
    const auto getRHS = [&]() {
 | 
					    const std::function<void(TIntermTyped* left, TIntermTyped* right)>
 | 
				
			||||||
        return rhsTempVar   ? intermediate.addSymbol(*rhsTempVar, loc) :
 | 
					    traverse = [&](TIntermTyped* left, TIntermTyped* right) -> void {
 | 
				
			||||||
               cloneSymNode ? intermediate.addSymbol(*cloneSymNode) :
 | 
					        // If we get here, we are assigning to or from a whole array or struct that must be
 | 
				
			||||||
                              right;
 | 
					        // flattened, so have to do member-by-member assignment:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (left->getType().isArray()) {
 | 
				
			||||||
 | 
					            // array case
 | 
				
			||||||
 | 
					            const TType dereferencedType(left->getType(), 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            for (int element=0; element < left->getType().getOuterArraySize(); ++element) {
 | 
				
			||||||
 | 
					                    // Add a new AST symbol node if we have a temp variable holding a complex RHS.
 | 
				
			||||||
 | 
					                TIntermTyped* subRight = getMember(flattenRight, right, *rightVariables, element,
 | 
				
			||||||
 | 
					                                                   EOpIndexDirect, dereferencedType);
 | 
				
			||||||
 | 
					                TIntermTyped* subLeft = getMember(flattenLeft, left, *leftVariables, element,
 | 
				
			||||||
 | 
					                                                  EOpIndexDirect, dereferencedType);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if (isFinalFlattening(dereferencedType))
 | 
				
			||||||
 | 
					                    assignList = intermediate.growAggregate(assignList, intermediate.addAssign(op, subLeft, subRight, loc), loc);
 | 
				
			||||||
 | 
					                else
 | 
				
			||||||
 | 
					                    traverse(subLeft, subRight);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        } else if (left->getType().isStruct()) {
 | 
				
			||||||
 | 
					            // struct case
 | 
				
			||||||
 | 
					            const auto& members = *left->getType().getStruct();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            for (int member = 0; member < (int)members.size(); ++member) {
 | 
				
			||||||
 | 
					                TIntermTyped* subRight = getMember(flattenRight, right, *rightVariables, member,
 | 
				
			||||||
 | 
					                                                   EOpIndexDirectStruct, *members[member].type);
 | 
				
			||||||
 | 
					                TIntermTyped* subLeft = getMember(flattenLeft, left, *leftVariables, member,
 | 
				
			||||||
 | 
					                                                  EOpIndexDirectStruct, *members[member].type);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if (isFinalFlattening(*members[member].type))
 | 
				
			||||||
 | 
					                    assignList = intermediate.growAggregate(assignList, intermediate.addAssign(op, subLeft, subRight, loc), loc);
 | 
				
			||||||
 | 
					                else
 | 
				
			||||||
 | 
					                    traverse(subLeft, subRight);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            assert(0);  // we should never be called on a non-flattenable thing, because
 | 
				
			||||||
 | 
					                        // that case bails out above to a simple copy.
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Handle struct assignment
 | 
					    // Use the proper RHS node: a new symbol from a TVariable, copy
 | 
				
			||||||
    if (left->getType().isStruct()) {
 | 
					    // of an TIntermSymbol node, or sometimes the right node directly.
 | 
				
			||||||
        // If we get here, we are assigning to or from a whole struct that must be
 | 
					    right = rhsTempVar   ? intermediate.addSymbol(*rhsTempVar, loc) :
 | 
				
			||||||
        // flattened, so have to do member-by-member assignment:
 | 
					            cloneSymNode ? intermediate.addSymbol(*cloneSymNode) :
 | 
				
			||||||
        const auto& members = *left->getType().getStruct();
 | 
					            right;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        for (int member = 0; member < (int)members.size(); ++member) {
 | 
					    // This makes the whole assignment, recursing through subtypes as needed.
 | 
				
			||||||
            TIntermTyped* subRight = getMember(flattenRight, getRHS(), *rightVariables, member,
 | 
					    traverse(left, right);
 | 
				
			||||||
                                               EOpIndexDirectStruct, *members[member].type);
 | 
					 | 
				
			||||||
            TIntermTyped* subLeft = getMember(flattenLeft, left, *leftVariables, member,
 | 
					 | 
				
			||||||
                                              EOpIndexDirectStruct, *members[member].type);
 | 
					 | 
				
			||||||
            assignList = intermediate.growAggregate(assignList, intermediate.addAssign(op, subLeft, subRight, loc), loc);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // Handle array assignment
 | 
					 | 
				
			||||||
    if (left->getType().isArray()) {
 | 
					 | 
				
			||||||
        // If we get here, we are assigning to or from a whole array that must be
 | 
					 | 
				
			||||||
        // flattened, so have to do member-by-member assignment:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        const TType dereferencedType(left->getType(), 0);
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        for (int element=0; element < memberCount; ++element) {
 | 
					 | 
				
			||||||
            // Add a new AST symbol node if we have a temp variable holding a complex RHS.
 | 
					 | 
				
			||||||
            TIntermTyped* subRight = getMember(flattenRight, getRHS(), *rightVariables, element,
 | 
					 | 
				
			||||||
                                               EOpIndexDirect, dereferencedType);
 | 
					 | 
				
			||||||
            TIntermTyped* subLeft = getMember(flattenLeft, left, *leftVariables, element,
 | 
					 | 
				
			||||||
                                              EOpIndexDirect, dereferencedType);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            assignList = intermediate.growAggregate(assignList, intermediate.addAssign(op, subLeft, subRight, loc), loc);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    assert(assignList != nullptr);
 | 
					    assert(assignList != nullptr);
 | 
				
			||||||
    assignList->setOperator(EOpSequence);
 | 
					    assignList->setOperator(EOpSequence);
 | 
				
			||||||
@ -2701,7 +2813,7 @@ void HlslParseContext::addInputArgumentConversions(const TFunction& function, TI
 | 
				
			|||||||
            arg = intermediate.addShapeConversion(EOpFunctionCall, *function[i].type, arg);
 | 
					            arg = intermediate.addShapeConversion(EOpFunctionCall, *function[i].type, arg);
 | 
				
			||||||
            setArg(i, arg);
 | 
					            setArg(i, arg);
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            if (shouldFlatten(arg->getType())) {
 | 
					            if (wasFlattened(arg)) {
 | 
				
			||||||
                // Will make a two-level subtree.
 | 
					                // Will make a two-level subtree.
 | 
				
			||||||
                // The deepest will copy member-by-member to build the structure to pass.
 | 
					                // The deepest will copy member-by-member to build the structure to pass.
 | 
				
			||||||
                // The level above that will be a two-operand EOpComma sequence that follows the copy by the
 | 
					                // The level above that will be a two-operand EOpComma sequence that follows the copy by the
 | 
				
			||||||
@ -2749,7 +2861,7 @@ TIntermTyped* HlslParseContext::addOutputArgumentConversions(const TFunction& fu
 | 
				
			|||||||
        return function[argNum].type->getQualifier().isParamOutput() &&
 | 
					        return function[argNum].type->getQualifier().isParamOutput() &&
 | 
				
			||||||
               (*function[argNum].type != arguments[argNum]->getAsTyped()->getType() ||
 | 
					               (*function[argNum].type != arguments[argNum]->getAsTyped()->getType() ||
 | 
				
			||||||
                shouldConvertLValue(arguments[argNum]) ||
 | 
					                shouldConvertLValue(arguments[argNum]) ||
 | 
				
			||||||
                shouldFlatten(arguments[argNum]->getAsTyped()->getType()));
 | 
					                wasFlattened(arguments[argNum]->getAsTyped()));
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Will there be any output conversions?
 | 
					    // Will there be any output conversions?
 | 
				
			||||||
@ -4623,23 +4735,23 @@ TIntermNode* HlslParseContext::declareVariable(const TSourceLoc& loc, TString& i
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    inheritGlobalDefaults(type.getQualifier());
 | 
					    inheritGlobalDefaults(type.getQualifier());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    bool flattenVar = false;
 | 
					    const bool flattenVar = shouldFlatten(type);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Declare the variable
 | 
					    // Declare the variable
 | 
				
			||||||
    if (type.isArray()) {
 | 
					    if (type.isArray()) {
 | 
				
			||||||
        // array case
 | 
					        // array case
 | 
				
			||||||
        flattenVar = shouldFlatten(type);
 | 
					 | 
				
			||||||
        declareArray(loc, identifier, type, symbol, !flattenVar);
 | 
					        declareArray(loc, identifier, type, symbol, !flattenVar);
 | 
				
			||||||
        if (flattenVar)
 | 
					 | 
				
			||||||
            flatten(loc, *symbol->getAsVariable());
 | 
					 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
        // non-array case
 | 
					        // non-array case
 | 
				
			||||||
        if (! symbol)
 | 
					        if (! symbol)
 | 
				
			||||||
            symbol = declareNonArray(loc, identifier, type);
 | 
					            symbol = declareNonArray(loc, identifier, type, !flattenVar);
 | 
				
			||||||
        else if (type != symbol->getType())
 | 
					        else if (type != symbol->getType())
 | 
				
			||||||
            error(loc, "cannot change the type of", "redeclaration", symbol->getName().c_str());
 | 
					            error(loc, "cannot change the type of", "redeclaration", symbol->getName().c_str());
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (flattenVar)
 | 
				
			||||||
 | 
					        flatten(loc, *symbol->getAsVariable());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (! symbol)
 | 
					    if (! symbol)
 | 
				
			||||||
        return nullptr;
 | 
					        return nullptr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -4692,14 +4804,14 @@ TVariable* HlslParseContext::makeInternalVariable(const char* name, const TType&
 | 
				
			|||||||
//
 | 
					//
 | 
				
			||||||
// Return the successfully declared variable.
 | 
					// Return the successfully declared variable.
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
TVariable* HlslParseContext::declareNonArray(const TSourceLoc& loc, TString& identifier, TType& type)
 | 
					TVariable* HlslParseContext::declareNonArray(const TSourceLoc& loc, TString& identifier, TType& type, bool track)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    // make a new variable
 | 
					    // make a new variable
 | 
				
			||||||
    TVariable* variable = new TVariable(&identifier, type);
 | 
					    TVariable* variable = new TVariable(&identifier, type);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // add variable to symbol table
 | 
					    // add variable to symbol table
 | 
				
			||||||
    if (symbolTable.insert(*variable)) {
 | 
					    if (symbolTable.insert(*variable)) {
 | 
				
			||||||
        if (symbolTable.atGlobalLevel())
 | 
					        if (track && symbolTable.atGlobalLevel())
 | 
				
			||||||
            trackLinkageDeferred(*variable);
 | 
					            trackLinkageDeferred(*variable);
 | 
				
			||||||
        return variable;
 | 
					        return variable;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
@ -169,10 +169,23 @@ public:
 | 
				
			|||||||
    // Potentially rename shader entry point function
 | 
					    // Potentially rename shader entry point function
 | 
				
			||||||
    void renameShaderFunction(TString*& name) const;
 | 
					    void renameShaderFunction(TString*& name) const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Reset data for incrementally built referencing of flattened composite structures
 | 
				
			||||||
 | 
					    void initFlattening() { flattenLevel.push_back(0); flattenOffset.push_back(0); }
 | 
				
			||||||
 | 
					    void finalizeFlattening() { flattenLevel.pop_back(); flattenOffset.pop_back(); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
protected:
 | 
					protected:
 | 
				
			||||||
 | 
					    struct TFlattenData {
 | 
				
			||||||
 | 
					        TFlattenData() : nextBinding(TQualifier::layoutBindingEnd) { }
 | 
				
			||||||
 | 
					        TFlattenData(int nb) : nextBinding(nb) { }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        TVector<TVariable*> members;     // individual flattened variables
 | 
				
			||||||
 | 
					        TVector<int>        offsets;     // offset to next tree level
 | 
				
			||||||
 | 
					        int                 nextBinding; // next binding to use.
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void inheritGlobalDefaults(TQualifier& dst) const;
 | 
					    void inheritGlobalDefaults(TQualifier& dst) const;
 | 
				
			||||||
    TVariable* makeInternalVariable(const char* name, const TType&) const;
 | 
					    TVariable* makeInternalVariable(const char* name, const TType&) const;
 | 
				
			||||||
    TVariable* declareNonArray(const TSourceLoc&, TString& identifier, TType&);
 | 
					    TVariable* declareNonArray(const TSourceLoc&, TString& identifier, TType&, bool track);
 | 
				
			||||||
    void declareArray(const TSourceLoc&, TString& identifier, const TType&, TSymbol*&, bool track);
 | 
					    void declareArray(const TSourceLoc&, TString& identifier, const TType&, TSymbol*&, bool track);
 | 
				
			||||||
    TIntermNode* executeInitializer(const TSourceLoc&, TIntermTyped* initializer, TVariable* variable);
 | 
					    TIntermNode* executeInitializer(const TSourceLoc&, TIntermTyped* initializer, TVariable* variable);
 | 
				
			||||||
    TIntermTyped* convertInitializerList(const TSourceLoc&, const TType&, TIntermTyped* initializer);
 | 
					    TIntermTyped* convertInitializerList(const TSourceLoc&, const TType&, TIntermTyped* initializer);
 | 
				
			||||||
@ -183,13 +196,19 @@ protected:
 | 
				
			|||||||
    bool shouldConvertLValue(const TIntermNode*) const;
 | 
					    bool shouldConvertLValue(const TIntermNode*) const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Array and struct flattening
 | 
					    // Array and struct flattening
 | 
				
			||||||
    bool shouldFlatten(const TType& type) const { return shouldFlattenIO(type) || shouldFlattenUniform(type); }
 | 
					    bool shouldFlatten(const TType& type) const;
 | 
				
			||||||
    TIntermTyped* flattenAccess(TIntermTyped* base, int member);
 | 
					    TIntermTyped* flattenAccess(const TSourceLoc&, TIntermTyped* base, int member);
 | 
				
			||||||
    bool shouldFlattenIO(const TType&) const;
 | 
					    bool shouldFlattenIO(const TType&) const;
 | 
				
			||||||
    bool shouldFlattenUniform(const TType&) const;
 | 
					    bool shouldFlattenUniform(const TType&) const;
 | 
				
			||||||
 | 
					    bool wasFlattened(const TIntermTyped* node) const;
 | 
				
			||||||
 | 
					    bool wasFlattened(int id) const { return flattenMap.find(id) != flattenMap.end(); }
 | 
				
			||||||
 | 
					    int  addFlattenedMember(const TSourceLoc& loc, const TVariable&, const TType&, TFlattenData&, const TString& name, bool track);
 | 
				
			||||||
 | 
					    bool isFinalFlattening(const TType& type) const { return !(type.isStruct() || type.isArray()); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void flatten(const TSourceLoc& loc, const TVariable& variable);
 | 
					    void flatten(const TSourceLoc& loc, const TVariable& variable);
 | 
				
			||||||
    void flattenStruct(const TVariable& variable);
 | 
					    int flatten(const TSourceLoc& loc, const TVariable& variable, const TType&, TFlattenData&, TString name);
 | 
				
			||||||
    void flattenArray(const TSourceLoc& loc, const TVariable& variable);
 | 
					    int flattenStruct(const TSourceLoc& loc, const TVariable& variable, const TType&, TFlattenData&, TString name);
 | 
				
			||||||
 | 
					    int flattenArray(const TSourceLoc& loc, const TVariable& variable, const TType&, TFlattenData&, TString name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Current state of parsing
 | 
					    // Current state of parsing
 | 
				
			||||||
    struct TPragma contextPragma;
 | 
					    struct TPragma contextPragma;
 | 
				
			||||||
@ -252,7 +271,10 @@ protected:
 | 
				
			|||||||
    //
 | 
					    //
 | 
				
			||||||
    TVector<TSymbol*> ioArraySymbolResizeList;
 | 
					    TVector<TSymbol*> ioArraySymbolResizeList;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    TMap<int, TVector<TVariable*>> flattenMap;
 | 
					    TMap<int, TFlattenData> flattenMap;
 | 
				
			||||||
 | 
					    TVector<int> flattenLevel;  // nested postfix operator level for flattening
 | 
				
			||||||
 | 
					    TVector<int> flattenOffset; // cumulative offset for flattening
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    unsigned int nextInLocation;
 | 
					    unsigned int nextInLocation;
 | 
				
			||||||
    unsigned int nextOutLocation;
 | 
					    unsigned int nextOutLocation;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user