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 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 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 '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 Constant:
|
||||||
0:13 0 (const int)
|
0:13 0 (const int)
|
||||||
|
0:13 Constant:
|
||||||
|
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 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 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 '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 Constant:
|
||||||
0:13 0 (const int)
|
0:13 0 (const int)
|
||||||
|
0:13 Constant:
|
||||||
|
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);
|
||||||
|
}
|
||||||
@ -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, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type.isStruct())
|
// Recursively flatten the given variable at the provided type, building the flattenData as we go.
|
||||||
flattenStruct(variable);
|
//
|
||||||
|
// 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 something is an arrayed struct, the array flattener will recursively call flatten()
|
||||||
|
// 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();
|
||||||
}
|
|
||||||
|
// 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) {
|
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
|
||||||
|
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);
|
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;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Handle struct assignment
|
|
||||||
if (left->getType().isStruct()) {
|
|
||||||
// If we get here, we are assigning to or from a whole struct that must be
|
|
||||||
// flattened, so have to do member-by-member assignment:
|
// flattened, so have to do member-by-member assignment:
|
||||||
const auto& members = *left->getType().getStruct();
|
|
||||||
|
|
||||||
for (int member = 0; member < (int)members.size(); ++member) {
|
|
||||||
TIntermTyped* subRight = getMember(flattenRight, getRHS(), *rightVariables, member,
|
|
||||||
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 (left->getType().isArray()) {
|
||||||
// If we get here, we are assigning to or from a whole array that must be
|
// array case
|
||||||
// flattened, so have to do member-by-member assignment:
|
|
||||||
|
|
||||||
const TType dereferencedType(left->getType(), 0);
|
const TType dereferencedType(left->getType(), 0);
|
||||||
|
|
||||||
for (int element=0; element < memberCount; ++element) {
|
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.
|
// Add a new AST symbol node if we have a temp variable holding a complex RHS.
|
||||||
TIntermTyped* subRight = getMember(flattenRight, getRHS(), *rightVariables, element,
|
TIntermTyped* subRight = getMember(flattenRight, right, *rightVariables, element,
|
||||||
EOpIndexDirect, dereferencedType);
|
EOpIndexDirect, dereferencedType);
|
||||||
TIntermTyped* subLeft = getMember(flattenLeft, left, *leftVariables, element,
|
TIntermTyped* subLeft = getMember(flattenLeft, left, *leftVariables, element,
|
||||||
EOpIndexDirect, dereferencedType);
|
EOpIndexDirect, dereferencedType);
|
||||||
|
|
||||||
|
if (isFinalFlattening(dereferencedType))
|
||||||
assignList = intermediate.growAggregate(assignList, intermediate.addAssign(op, subLeft, subRight, loc), loc);
|
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.
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
// Use the proper RHS node: a new symbol from a TVariable, copy
|
||||||
|
// of an TIntermSymbol node, or sometimes the right node directly.
|
||||||
|
right = rhsTempVar ? intermediate.addSymbol(*rhsTempVar, loc) :
|
||||||
|
cloneSymNode ? intermediate.addSymbol(*cloneSymNode) :
|
||||||
|
right;
|
||||||
|
|
||||||
|
// This makes the whole assignment, recursing through subtypes as needed.
|
||||||
|
traverse(left, right);
|
||||||
|
|
||||||
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