Merge pull request #1446 from KhronosGroup/spv-link
Link/SPV: Correct symbol IDs on merging ASTs to a single coherent space
This commit is contained in:
commit
8103cb9580
@ -198,7 +198,7 @@ gl_FragCoord origin is upper left
|
|||||||
|
|
||||||
// Module Version 10000
|
// Module Version 10000
|
||||||
// Generated by (magic number): 80007
|
// Generated by (magic number): 80007
|
||||||
// Id's are bound by 71
|
// Id's are bound by 70
|
||||||
|
|
||||||
Capability Shader
|
Capability Shader
|
||||||
1: ExtInstImport "GLSL.std.450"
|
1: ExtInstImport "GLSL.std.450"
|
||||||
@ -214,24 +214,24 @@ gl_FragCoord origin is upper left
|
|||||||
Name 32 "b"
|
Name 32 "b"
|
||||||
Name 33 "i"
|
Name 33 "i"
|
||||||
Name 39 "c"
|
Name 39 "c"
|
||||||
Name 54 "s2D"
|
Name 53 "s2D"
|
||||||
Name 63 "bnameRuntime"
|
Name 62 "bnameRuntime"
|
||||||
MemberName 63(bnameRuntime) 0 "r"
|
MemberName 62(bnameRuntime) 0 "r"
|
||||||
Name 65 ""
|
Name 64 ""
|
||||||
Name 68 "bnameImplicit"
|
Name 67 "bnameImplicit"
|
||||||
MemberName 68(bnameImplicit) 0 "m"
|
MemberName 67(bnameImplicit) 0 "m"
|
||||||
Name 70 ""
|
Name 69 ""
|
||||||
Decorate 12(color) Location 0
|
Decorate 12(color) Location 0
|
||||||
Decorate 54(s2D) DescriptorSet 0
|
Decorate 53(s2D) DescriptorSet 0
|
||||||
Decorate 54(s2D) Binding 1
|
Decorate 53(s2D) Binding 1
|
||||||
Decorate 62 ArrayStride 4
|
Decorate 61 ArrayStride 4
|
||||||
MemberDecorate 63(bnameRuntime) 0 Offset 0
|
MemberDecorate 62(bnameRuntime) 0 Offset 0
|
||||||
Decorate 63(bnameRuntime) BufferBlock
|
Decorate 62(bnameRuntime) BufferBlock
|
||||||
Decorate 65 DescriptorSet 0
|
Decorate 64 DescriptorSet 0
|
||||||
Decorate 67 ArrayStride 4
|
Decorate 66 ArrayStride 4
|
||||||
MemberDecorate 68(bnameImplicit) 0 Offset 0
|
MemberDecorate 67(bnameImplicit) 0 Offset 0
|
||||||
Decorate 68(bnameImplicit) BufferBlock
|
Decorate 67(bnameImplicit) BufferBlock
|
||||||
Decorate 70 DescriptorSet 0
|
Decorate 69 DescriptorSet 0
|
||||||
2: TypeVoid
|
2: TypeVoid
|
||||||
3: TypeFunction 2
|
3: TypeFunction 2
|
||||||
6: TypeFloat 32
|
6: TypeFloat 32
|
||||||
@ -263,24 +263,23 @@ gl_FragCoord origin is upper left
|
|||||||
39(c): 38(ptr) Variable Private
|
39(c): 38(ptr) Variable Private
|
||||||
40: 14(int) Constant 3
|
40: 14(int) Constant 3
|
||||||
42: 14(int) Constant 2
|
42: 14(int) Constant 2
|
||||||
43: TypePointer Output 6(float)
|
44: 14(int) Constant 9
|
||||||
45: 14(int) Constant 9
|
50: TypeImage 6(float) 2D sampled format:Unknown
|
||||||
51: TypeImage 6(float) 2D sampled format:Unknown
|
51: TypeSampledImage 50
|
||||||
52: TypeSampledImage 51
|
52: TypePointer UniformConstant 51
|
||||||
53: TypePointer UniformConstant 52
|
53(s2D): 52(ptr) Variable UniformConstant
|
||||||
54(s2D): 53(ptr) Variable UniformConstant
|
55: TypeVector 6(float) 2
|
||||||
56: TypeVector 6(float) 2
|
56: 6(float) Constant 1056964608
|
||||||
57: 6(float) Constant 1056964608
|
57: 55(fvec2) ConstantComposite 56 56
|
||||||
58: 56(fvec2) ConstantComposite 57 57
|
61: TypeRuntimeArray 6(float)
|
||||||
62: TypeRuntimeArray 6(float)
|
62(bnameRuntime): TypeStruct 61
|
||||||
63(bnameRuntime): TypeStruct 62
|
63: TypePointer Uniform 62(bnameRuntime)
|
||||||
64: TypePointer Uniform 63(bnameRuntime)
|
64: 63(ptr) Variable Uniform
|
||||||
65: 64(ptr) Variable Uniform
|
65: 15(int) Constant 4
|
||||||
66: 15(int) Constant 4
|
66: TypeArray 6(float) 65
|
||||||
67: TypeArray 6(float) 66
|
67(bnameImplicit): TypeStruct 66
|
||||||
68(bnameImplicit): TypeStruct 67
|
68: TypePointer Uniform 67(bnameImplicit)
|
||||||
69: TypePointer Uniform 68(bnameImplicit)
|
69: 68(ptr) Variable Uniform
|
||||||
70: 69(ptr) Variable Uniform
|
|
||||||
4(main): 2 Function None 3
|
4(main): 2 Function None 3
|
||||||
5: Label
|
5: Label
|
||||||
13: 7(fvec4) FunctionCall 9(getColor()
|
13: 7(fvec4) FunctionCall 9(getColor()
|
||||||
@ -298,18 +297,18 @@ gl_FragCoord origin is upper left
|
|||||||
FunctionEnd
|
FunctionEnd
|
||||||
9(getColor(): 7(fvec4) Function None 8
|
9(getColor(): 7(fvec4) Function None 8
|
||||||
10: Label
|
10: Label
|
||||||
44: 43(ptr) AccessChain 12(color) 42
|
43: 22(ptr) AccessChain 19(a1) 42
|
||||||
Store 44 21
|
Store 43 21
|
||||||
46: 22(ptr) AccessChain 19(a1) 45
|
45: 22(ptr) AccessChain 27(a2) 44
|
||||||
|
Store 45 21
|
||||||
|
46: 22(ptr) AccessChain 32(b) 42
|
||||||
Store 46 21
|
Store 46 21
|
||||||
47: 22(ptr) AccessChain 27(a2) 42
|
47: 22(ptr) AccessChain 39(c) 40
|
||||||
Store 47 21
|
Store 47 21
|
||||||
48: 22(ptr) AccessChain 32(b) 40
|
48: 14(int) Load 33(i)
|
||||||
Store 48 21
|
49: 22(ptr) AccessChain 39(c) 48
|
||||||
49: 37 Load 39(c)
|
Store 49 21
|
||||||
50: 22(ptr) AccessChain 32(b) 49
|
54: 51 Load 53(s2D)
|
||||||
Store 50 21
|
58: 7(fvec4) ImageSampleImplicitLod 54 57
|
||||||
55: 52 Load 54(s2D)
|
ReturnValue 58
|
||||||
59: 7(fvec4) ImageSampleImplicitLod 55 58
|
|
||||||
ReturnValue 59
|
|
||||||
FunctionEnd
|
FunctionEnd
|
||||||
|
|||||||
272
Test/baseResults/spv.unit1.frag.out
Executable file
272
Test/baseResults/spv.unit1.frag.out
Executable file
@ -0,0 +1,272 @@
|
|||||||
|
spv.unit1.frag
|
||||||
|
Shader version: 460
|
||||||
|
gl_FragCoord origin is upper left
|
||||||
|
0:? Sequence
|
||||||
|
0:8 Function Definition: main( ( global void)
|
||||||
|
0:8 Function Parameters:
|
||||||
|
0:10 Sequence
|
||||||
|
0:10 move second child to first child ( temp highp float)
|
||||||
|
0:10 'f' ( global highp float)
|
||||||
|
0:10 Constant:
|
||||||
|
0:10 10.000000
|
||||||
|
0:11 Sequence
|
||||||
|
0:11 move second child to first child ( temp highp float)
|
||||||
|
0:11 'g' ( temp highp float)
|
||||||
|
0:11 Function Call: foo( ( global highp float)
|
||||||
|
0:12 add second child into first child ( temp highp float)
|
||||||
|
0:12 'f' ( global highp float)
|
||||||
|
0:12 'g' ( temp highp float)
|
||||||
|
0:13 add second child into first child ( temp highp float)
|
||||||
|
0:13 'f' ( global highp float)
|
||||||
|
0:13 direct index ( temp highp float)
|
||||||
|
0:13 'gl_FragCoord' ( gl_FragCoord highp 4-component vector of float FragCoord)
|
||||||
|
0:13 Constant:
|
||||||
|
0:13 1 (const int)
|
||||||
|
0:? Linker Objects
|
||||||
|
0:? 'f' ( global highp float)
|
||||||
|
0:? 'a1' ( global highp float)
|
||||||
|
|
||||||
|
spv.unit2.frag
|
||||||
|
Shader version: 410
|
||||||
|
gl_FragCoord origin is upper left
|
||||||
|
0:? Sequence
|
||||||
|
0:9 Function Definition: foo( ( global highp float)
|
||||||
|
0:9 Function Parameters:
|
||||||
|
0:11 Sequence
|
||||||
|
0:11 Sequence
|
||||||
|
0:11 move second child to first child ( temp highp float)
|
||||||
|
0:11 'h2' ( temp highp float)
|
||||||
|
0:11 component-wise multiply ( temp highp float)
|
||||||
|
0:11 Constant:
|
||||||
|
0:11 2.000000
|
||||||
|
0:11 'f' ( global highp float)
|
||||||
|
0:12 Sequence
|
||||||
|
0:12 move second child to first child ( temp highp float)
|
||||||
|
0:12 'g2' ( temp highp float)
|
||||||
|
0:12 Function Call: bar( ( global highp float)
|
||||||
|
0:13 Branch: Return with expression
|
||||||
|
0:13 add ( temp highp float)
|
||||||
|
0:13 add ( temp highp float)
|
||||||
|
0:13 'h2' ( temp highp float)
|
||||||
|
0:13 'g2' ( temp highp float)
|
||||||
|
0:13 direct index ( temp highp float)
|
||||||
|
0:13 'gl_FragCoord' ( gl_FragCoord highp 4-component vector of float FragCoord)
|
||||||
|
0:13 Constant:
|
||||||
|
0:13 1 (const int)
|
||||||
|
0:? Linker Objects
|
||||||
|
0:? 'a2' ( global highp float)
|
||||||
|
0:? 'f' ( global highp float)
|
||||||
|
|
||||||
|
spv.unit3.frag
|
||||||
|
Shader version: 460
|
||||||
|
gl_FragCoord origin is upper left
|
||||||
|
0:? Sequence
|
||||||
|
0:4 Sequence
|
||||||
|
0:4 move second child to first child ( temp highp float)
|
||||||
|
0:4 'h3' ( global highp float)
|
||||||
|
0:4 Constant:
|
||||||
|
0:4 3.000000
|
||||||
|
0:6 Function Definition: bar( ( global highp float)
|
||||||
|
0:6 Function Parameters:
|
||||||
|
0:8 Sequence
|
||||||
|
0:8 multiply second child into first child ( temp highp float)
|
||||||
|
0:8 'h3' ( global highp float)
|
||||||
|
0:8 'f' ( global highp float)
|
||||||
|
0:9 Sequence
|
||||||
|
0:9 move second child to first child ( temp highp float)
|
||||||
|
0:9 'g3' ( temp highp float)
|
||||||
|
0:9 component-wise multiply ( temp highp float)
|
||||||
|
0:9 Constant:
|
||||||
|
0:9 2.000000
|
||||||
|
0:9 'h3' ( global highp float)
|
||||||
|
0:10 Branch: Return with expression
|
||||||
|
0:10 add ( temp highp float)
|
||||||
|
0:10 add ( temp highp float)
|
||||||
|
0:10 'h3' ( global highp float)
|
||||||
|
0:10 'g3' ( temp highp float)
|
||||||
|
0:10 direct index ( temp highp float)
|
||||||
|
0:10 'gl_FragCoord' ( gl_FragCoord highp 4-component vector of float FragCoord)
|
||||||
|
0:10 Constant:
|
||||||
|
0:10 1 (const int)
|
||||||
|
0:? Linker Objects
|
||||||
|
0:? 'f' ( global highp float)
|
||||||
|
0:? 'h3' ( global highp float)
|
||||||
|
|
||||||
|
|
||||||
|
Linked fragment stage:
|
||||||
|
|
||||||
|
|
||||||
|
Shader version: 460
|
||||||
|
gl_FragCoord origin is upper left
|
||||||
|
0:? Sequence
|
||||||
|
0:8 Function Definition: main( ( global void)
|
||||||
|
0:8 Function Parameters:
|
||||||
|
0:10 Sequence
|
||||||
|
0:10 move second child to first child ( temp highp float)
|
||||||
|
0:10 'f' ( global highp float)
|
||||||
|
0:10 Constant:
|
||||||
|
0:10 10.000000
|
||||||
|
0:11 Sequence
|
||||||
|
0:11 move second child to first child ( temp highp float)
|
||||||
|
0:11 'g' ( temp highp float)
|
||||||
|
0:11 Function Call: foo( ( global highp float)
|
||||||
|
0:12 add second child into first child ( temp highp float)
|
||||||
|
0:12 'f' ( global highp float)
|
||||||
|
0:12 'g' ( temp highp float)
|
||||||
|
0:13 add second child into first child ( temp highp float)
|
||||||
|
0:13 'f' ( global highp float)
|
||||||
|
0:13 direct index ( temp highp float)
|
||||||
|
0:13 'gl_FragCoord' ( gl_FragCoord highp 4-component vector of float FragCoord)
|
||||||
|
0:13 Constant:
|
||||||
|
0:13 1 (const int)
|
||||||
|
0:9 Function Definition: foo( ( global highp float)
|
||||||
|
0:9 Function Parameters:
|
||||||
|
0:11 Sequence
|
||||||
|
0:11 Sequence
|
||||||
|
0:11 move second child to first child ( temp highp float)
|
||||||
|
0:11 'h2' ( temp highp float)
|
||||||
|
0:11 component-wise multiply ( temp highp float)
|
||||||
|
0:11 Constant:
|
||||||
|
0:11 2.000000
|
||||||
|
0:11 'f' ( global highp float)
|
||||||
|
0:12 Sequence
|
||||||
|
0:12 move second child to first child ( temp highp float)
|
||||||
|
0:12 'g2' ( temp highp float)
|
||||||
|
0:12 Function Call: bar( ( global highp float)
|
||||||
|
0:13 Branch: Return with expression
|
||||||
|
0:13 add ( temp highp float)
|
||||||
|
0:13 add ( temp highp float)
|
||||||
|
0:13 'h2' ( temp highp float)
|
||||||
|
0:13 'g2' ( temp highp float)
|
||||||
|
0:13 direct index ( temp highp float)
|
||||||
|
0:13 'gl_FragCoord' ( gl_FragCoord highp 4-component vector of float FragCoord)
|
||||||
|
0:13 Constant:
|
||||||
|
0:13 1 (const int)
|
||||||
|
0:4 Sequence
|
||||||
|
0:4 move second child to first child ( temp highp float)
|
||||||
|
0:4 'h3' ( global highp float)
|
||||||
|
0:4 Constant:
|
||||||
|
0:4 3.000000
|
||||||
|
0:6 Function Definition: bar( ( global highp float)
|
||||||
|
0:6 Function Parameters:
|
||||||
|
0:8 Sequence
|
||||||
|
0:8 multiply second child into first child ( temp highp float)
|
||||||
|
0:8 'h3' ( global highp float)
|
||||||
|
0:8 'f' ( global highp float)
|
||||||
|
0:9 Sequence
|
||||||
|
0:9 move second child to first child ( temp highp float)
|
||||||
|
0:9 'g3' ( temp highp float)
|
||||||
|
0:9 component-wise multiply ( temp highp float)
|
||||||
|
0:9 Constant:
|
||||||
|
0:9 2.000000
|
||||||
|
0:9 'h3' ( global highp float)
|
||||||
|
0:10 Branch: Return with expression
|
||||||
|
0:10 add ( temp highp float)
|
||||||
|
0:10 add ( temp highp float)
|
||||||
|
0:10 'h3' ( global highp float)
|
||||||
|
0:10 'g3' ( temp highp float)
|
||||||
|
0:10 direct index ( temp highp float)
|
||||||
|
0:10 'gl_FragCoord' ( gl_FragCoord highp 4-component vector of float FragCoord)
|
||||||
|
0:10 Constant:
|
||||||
|
0:10 1 (const int)
|
||||||
|
0:? Linker Objects
|
||||||
|
0:? 'f' ( global highp float)
|
||||||
|
0:? 'a1' ( global highp float)
|
||||||
|
0:? 'a2' ( global highp float)
|
||||||
|
0:? 'h3' ( global highp float)
|
||||||
|
|
||||||
|
// Module Version 10000
|
||||||
|
// Generated by (magic number): 80007
|
||||||
|
// Id's are bound by 63
|
||||||
|
|
||||||
|
Capability Shader
|
||||||
|
1: ExtInstImport "GLSL.std.450"
|
||||||
|
MemoryModel Logical GLSL450
|
||||||
|
EntryPoint Fragment 4 "main" 25
|
||||||
|
ExecutionMode 4 OriginUpperLeft
|
||||||
|
Source GLSL 460
|
||||||
|
Name 4 "main"
|
||||||
|
Name 8 "foo("
|
||||||
|
Name 10 "bar("
|
||||||
|
Name 13 "h3"
|
||||||
|
Name 15 "f"
|
||||||
|
Name 18 "g"
|
||||||
|
Name 25 "gl_FragCoord"
|
||||||
|
Name 33 "h2"
|
||||||
|
Name 37 "g2"
|
||||||
|
Name 50 "g3"
|
||||||
|
Name 61 "a1"
|
||||||
|
Name 62 "a2"
|
||||||
|
Decorate 25(gl_FragCoord) BuiltIn FragCoord
|
||||||
|
2: TypeVoid
|
||||||
|
3: TypeFunction 2
|
||||||
|
6: TypeFloat 32
|
||||||
|
7: TypeFunction 6(float)
|
||||||
|
12: TypePointer Private 6(float)
|
||||||
|
13(h3): 12(ptr) Variable Private
|
||||||
|
14: 6(float) Constant 1077936128
|
||||||
|
15(f): 12(ptr) Variable Private
|
||||||
|
16: 6(float) Constant 1092616192
|
||||||
|
17: TypePointer Function 6(float)
|
||||||
|
23: TypeVector 6(float) 4
|
||||||
|
24: TypePointer Input 23(fvec4)
|
||||||
|
25(gl_FragCoord): 24(ptr) Variable Input
|
||||||
|
26: TypeInt 32 0
|
||||||
|
27: 26(int) Constant 1
|
||||||
|
28: TypePointer Input 6(float)
|
||||||
|
34: 6(float) Constant 1073741824
|
||||||
|
61(a1): 12(ptr) Variable Private
|
||||||
|
62(a2): 12(ptr) Variable Private
|
||||||
|
4(main): 2 Function None 3
|
||||||
|
5: Label
|
||||||
|
18(g): 17(ptr) Variable Function
|
||||||
|
Store 13(h3) 14
|
||||||
|
Store 15(f) 16
|
||||||
|
19: 6(float) FunctionCall 8(foo()
|
||||||
|
Store 18(g) 19
|
||||||
|
20: 6(float) Load 18(g)
|
||||||
|
21: 6(float) Load 15(f)
|
||||||
|
22: 6(float) FAdd 21 20
|
||||||
|
Store 15(f) 22
|
||||||
|
29: 28(ptr) AccessChain 25(gl_FragCoord) 27
|
||||||
|
30: 6(float) Load 29
|
||||||
|
31: 6(float) Load 15(f)
|
||||||
|
32: 6(float) FAdd 31 30
|
||||||
|
Store 15(f) 32
|
||||||
|
Return
|
||||||
|
FunctionEnd
|
||||||
|
8(foo(): 6(float) Function None 7
|
||||||
|
9: Label
|
||||||
|
33(h2): 17(ptr) Variable Function
|
||||||
|
37(g2): 17(ptr) Variable Function
|
||||||
|
35: 6(float) Load 15(f)
|
||||||
|
36: 6(float) FMul 34 35
|
||||||
|
Store 33(h2) 36
|
||||||
|
38: 6(float) FunctionCall 10(bar()
|
||||||
|
Store 37(g2) 38
|
||||||
|
39: 6(float) Load 33(h2)
|
||||||
|
40: 6(float) Load 37(g2)
|
||||||
|
41: 6(float) FAdd 39 40
|
||||||
|
42: 28(ptr) AccessChain 25(gl_FragCoord) 27
|
||||||
|
43: 6(float) Load 42
|
||||||
|
44: 6(float) FAdd 41 43
|
||||||
|
ReturnValue 44
|
||||||
|
FunctionEnd
|
||||||
|
10(bar(): 6(float) Function None 7
|
||||||
|
11: Label
|
||||||
|
50(g3): 17(ptr) Variable Function
|
||||||
|
47: 6(float) Load 15(f)
|
||||||
|
48: 6(float) Load 13(h3)
|
||||||
|
49: 6(float) FMul 48 47
|
||||||
|
Store 13(h3) 49
|
||||||
|
51: 6(float) Load 13(h3)
|
||||||
|
52: 6(float) FMul 34 51
|
||||||
|
Store 50(g3) 52
|
||||||
|
53: 6(float) Load 13(h3)
|
||||||
|
54: 6(float) Load 50(g3)
|
||||||
|
55: 6(float) FAdd 53 54
|
||||||
|
56: 28(ptr) AccessChain 25(gl_FragCoord) 27
|
||||||
|
57: 6(float) Load 56
|
||||||
|
58: 6(float) FAdd 55 57
|
||||||
|
ReturnValue 58
|
||||||
|
FunctionEnd
|
||||||
14
Test/spv.unit1.frag
Executable file
14
Test/spv.unit1.frag
Executable file
@ -0,0 +1,14 @@
|
|||||||
|
#version 460
|
||||||
|
|
||||||
|
float f;
|
||||||
|
float a1;
|
||||||
|
|
||||||
|
float foo();
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
f = 10;
|
||||||
|
float g = foo();
|
||||||
|
f += g;
|
||||||
|
f += gl_FragCoord.y;
|
||||||
|
}
|
||||||
14
Test/spv.unit2.frag
Executable file
14
Test/spv.unit2.frag
Executable file
@ -0,0 +1,14 @@
|
|||||||
|
#version 410
|
||||||
|
// a different version number makes different id's for the same shared symbol
|
||||||
|
|
||||||
|
float a2;
|
||||||
|
float f;
|
||||||
|
|
||||||
|
float bar();
|
||||||
|
|
||||||
|
float foo()
|
||||||
|
{
|
||||||
|
float h2 = 2 * f;
|
||||||
|
float g2 = bar();
|
||||||
|
return h2 + g2 + gl_FragCoord.y;
|
||||||
|
}
|
||||||
11
Test/spv.unit3.frag
Executable file
11
Test/spv.unit3.frag
Executable file
@ -0,0 +1,11 @@
|
|||||||
|
#version 460
|
||||||
|
|
||||||
|
float f;
|
||||||
|
float h3 = 3.0;
|
||||||
|
|
||||||
|
float bar()
|
||||||
|
{
|
||||||
|
h3 *= f;
|
||||||
|
float g3 = 2 * h3;
|
||||||
|
return h3 + g3 + gl_FragCoord.y;
|
||||||
|
}
|
||||||
@ -1164,6 +1164,7 @@ public:
|
|||||||
constSubtree(nullptr)
|
constSubtree(nullptr)
|
||||||
{ name = n; }
|
{ name = n; }
|
||||||
virtual int getId() const { return id; }
|
virtual int getId() const { return id; }
|
||||||
|
virtual void changeId(int i) { id = i; }
|
||||||
virtual const TString& getName() const { return name; }
|
virtual const TString& getName() const { return name; }
|
||||||
virtual void traverse(TIntermTraverser*);
|
virtual void traverse(TIntermTraverser*);
|
||||||
virtual TIntermSymbol* getAsSymbolNode() { return this; }
|
virtual TIntermSymbol* getAsSymbolNode() { return this; }
|
||||||
|
|||||||
124
glslang/MachineIndependent/linkValidate.cpp
Normal file → Executable file
124
glslang/MachineIndependent/linkValidate.cpp
Normal file → Executable file
@ -182,22 +182,132 @@ void TIntermediate::merge(TInfoSink& infoSink, TIntermediate& unit)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Getting this far means we have two existing trees to merge...
|
// Getting this far means we have two existing trees to merge...
|
||||||
|
mergeTree(infoSink, unit);
|
||||||
|
|
||||||
version = std::max(version, unit.version);
|
version = std::max(version, unit.version);
|
||||||
requestedExtensions.insert(unit.requestedExtensions.begin(), unit.requestedExtensions.end());
|
requestedExtensions.insert(unit.requestedExtensions.begin(), unit.requestedExtensions.end());
|
||||||
|
ioAccessed.insert(unit.ioAccessed.begin(), unit.ioAccessed.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Merge the 'unit' AST into 'this' AST.
|
||||||
|
// That includes rationalizing the unique IDs, which were set up independently,
|
||||||
|
// and might have overlaps that are not the same symbol, or might have different
|
||||||
|
// IDs for what should be the same shared symbol.
|
||||||
|
//
|
||||||
|
void TIntermediate::mergeTree(TInfoSink& infoSink, TIntermediate& unit)
|
||||||
|
{
|
||||||
// Get the top-level globals of each unit
|
// Get the top-level globals of each unit
|
||||||
TIntermSequence& globals = treeRoot->getAsAggregate()->getSequence();
|
TIntermSequence& globals = treeRoot->getAsAggregate()->getSequence();
|
||||||
TIntermSequence& unitGlobals = unit.treeRoot->getAsAggregate()->getSequence();
|
TIntermSequence& unitGlobals = unit.treeRoot->getAsAggregate()->getSequence();
|
||||||
|
|
||||||
// Get the linker-object lists
|
// Get the linker-object lists
|
||||||
TIntermSequence& linkerObjects = findLinkerObjects();
|
TIntermSequence& linkerObjects = findLinkerObjects()->getSequence();
|
||||||
TIntermSequence& unitLinkerObjects = unit.findLinkerObjects();
|
const TIntermSequence& unitLinkerObjects = unit.findLinkerObjects()->getSequence();
|
||||||
|
|
||||||
|
// Map by global name to unique ID to rationalize the same object having
|
||||||
|
// differing IDs in different trees.
|
||||||
|
TMap<TString, int> idMap;
|
||||||
|
int maxId;
|
||||||
|
seedIdMap(idMap, maxId);
|
||||||
|
remapIds(idMap, maxId + 1, unit);
|
||||||
|
|
||||||
mergeBodies(infoSink, globals, unitGlobals);
|
mergeBodies(infoSink, globals, unitGlobals);
|
||||||
mergeLinkerObjects(infoSink, linkerObjects, unitLinkerObjects);
|
mergeLinkerObjects(infoSink, linkerObjects, unitLinkerObjects);
|
||||||
|
}
|
||||||
|
|
||||||
ioAccessed.insert(unit.ioAccessed.begin(), unit.ioAccessed.end());
|
// Traverser that seeds an ID map with all built-ins, and tracks the
|
||||||
|
// maximum ID used.
|
||||||
|
// (It would be nice to put this in a function, but that causes warnings
|
||||||
|
// on having no bodies for the copy-constructor/operator=.)
|
||||||
|
class TBuiltInIdTraverser : public TIntermTraverser {
|
||||||
|
public:
|
||||||
|
TBuiltInIdTraverser(TMap<TString, int>& idMap) : idMap(idMap), maxId(0) { }
|
||||||
|
// If it's a built in, add it to the map.
|
||||||
|
// Track the max ID.
|
||||||
|
virtual void visitSymbol(TIntermSymbol* symbol)
|
||||||
|
{
|
||||||
|
const TQualifier& qualifier = symbol->getType().getQualifier();
|
||||||
|
if (qualifier.builtIn != EbvNone)
|
||||||
|
idMap[symbol->getName()] = symbol->getId();
|
||||||
|
maxId = std::max(maxId, symbol->getId());
|
||||||
|
}
|
||||||
|
int getMaxId() const { return maxId; }
|
||||||
|
protected:
|
||||||
|
TBuiltInIdTraverser(TBuiltInIdTraverser&);
|
||||||
|
TBuiltInIdTraverser& operator=(TBuiltInIdTraverser&);
|
||||||
|
TMap<TString, int>& idMap;
|
||||||
|
int maxId;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Traverser that seeds an ID map with non-builtin globals.
|
||||||
|
// (It would be nice to put this in a function, but that causes warnings
|
||||||
|
// on having no bodies for the copy-constructor/operator=.)
|
||||||
|
class TUserIdTraverser : public TIntermTraverser {
|
||||||
|
public:
|
||||||
|
TUserIdTraverser(TMap<TString, int>& idMap) : idMap(idMap) { }
|
||||||
|
// If its a non-built-in global, add it to the map.
|
||||||
|
virtual void visitSymbol(TIntermSymbol* symbol)
|
||||||
|
{
|
||||||
|
const TQualifier& qualifier = symbol->getType().getQualifier();
|
||||||
|
if (qualifier.storage == EvqGlobal && qualifier.builtIn == EbvNone)
|
||||||
|
idMap[symbol->getName()] = symbol->getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
TUserIdTraverser(TUserIdTraverser&);
|
||||||
|
TUserIdTraverser& operator=(TUserIdTraverser&);
|
||||||
|
TMap<TString, int>& idMap; // over biggest id
|
||||||
|
};
|
||||||
|
|
||||||
|
// Initialize the the ID map with what we know of 'this' AST.
|
||||||
|
void TIntermediate::seedIdMap(TMap<TString, int>& idMap, int& maxId)
|
||||||
|
{
|
||||||
|
// all built-ins everywhere need to align on IDs and contribute to the max ID
|
||||||
|
TBuiltInIdTraverser builtInIdTraverser(idMap);
|
||||||
|
treeRoot->traverse(&builtInIdTraverser);
|
||||||
|
maxId = builtInIdTraverser.getMaxId();
|
||||||
|
|
||||||
|
// user variables in the linker object list need to align on ids
|
||||||
|
TUserIdTraverser userIdTraverser(idMap);
|
||||||
|
findLinkerObjects()->traverse(&userIdTraverser);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Traverser to map an AST ID to what was known from the seeding AST.
|
||||||
|
// (It would be nice to put this in a function, but that causes warnings
|
||||||
|
// on having no bodies for the copy-constructor/operator=.)
|
||||||
|
class TRemapIdTraverser : public TIntermTraverser {
|
||||||
|
public:
|
||||||
|
TRemapIdTraverser(const TMap<TString, int>& idMap, int idShift) : idMap(idMap), idShift(idShift) { }
|
||||||
|
// Do the mapping:
|
||||||
|
// - if the same symbol, adopt the 'this' ID
|
||||||
|
// - otherwise, ensure a unique ID by shifting to a new space
|
||||||
|
virtual void visitSymbol(TIntermSymbol* symbol)
|
||||||
|
{
|
||||||
|
const TQualifier& qualifier = symbol->getType().getQualifier();
|
||||||
|
bool remapped = false;
|
||||||
|
if (qualifier.storage == EvqGlobal || qualifier.builtIn != EbvNone) {
|
||||||
|
auto it = idMap.find(symbol->getName());
|
||||||
|
if (it != idMap.end()) {
|
||||||
|
symbol->changeId(it->second);
|
||||||
|
remapped = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!remapped)
|
||||||
|
symbol->changeId(symbol->getId() + idShift);
|
||||||
|
}
|
||||||
|
protected:
|
||||||
|
TRemapIdTraverser(TRemapIdTraverser&);
|
||||||
|
TRemapIdTraverser& operator=(TRemapIdTraverser&);
|
||||||
|
const TMap<TString, int>& idMap;
|
||||||
|
int idShift;
|
||||||
|
};
|
||||||
|
|
||||||
|
void TIntermediate::remapIds(const TMap<TString, int>& idMap, int idShift, TIntermediate& unit)
|
||||||
|
{
|
||||||
|
// Remap all IDs to either share or be unique, as dictated by the idMap and idShift.
|
||||||
|
TRemapIdTraverser idTraverser(idMap, idShift);
|
||||||
|
unit.getTreeRoot()->traverse(&idTraverser);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -699,7 +809,7 @@ void TIntermediate::inOutLocationCheck(TInfoSink& infoSink)
|
|||||||
|
|
||||||
// TODO: linker functionality: location collision checking
|
// TODO: linker functionality: location collision checking
|
||||||
|
|
||||||
TIntermSequence& linkObjects = findLinkerObjects();
|
TIntermSequence& linkObjects = findLinkerObjects()->getSequence();
|
||||||
for (size_t i = 0; i < linkObjects.size(); ++i) {
|
for (size_t i = 0; i < linkObjects.size(); ++i) {
|
||||||
const TType& type = linkObjects[i]->getAsTyped()->getType();
|
const TType& type = linkObjects[i]->getAsTyped()->getType();
|
||||||
const TQualifier& qualifier = type.getQualifier();
|
const TQualifier& qualifier = type.getQualifier();
|
||||||
@ -718,7 +828,7 @@ void TIntermediate::inOutLocationCheck(TInfoSink& infoSink)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TIntermSequence& TIntermediate::findLinkerObjects() const
|
TIntermAggregate* TIntermediate::findLinkerObjects() const
|
||||||
{
|
{
|
||||||
// Get the top-level globals
|
// Get the top-level globals
|
||||||
TIntermSequence& globals = treeRoot->getAsAggregate()->getSequence();
|
TIntermSequence& globals = treeRoot->getAsAggregate()->getSequence();
|
||||||
@ -726,7 +836,7 @@ TIntermSequence& TIntermediate::findLinkerObjects() const
|
|||||||
// Get the last member of the sequences, expected to be the linker-object lists
|
// Get the last member of the sequences, expected to be the linker-object lists
|
||||||
assert(globals.back()->getAsAggregate()->getOp() == EOpLinkerObjects);
|
assert(globals.back()->getAsAggregate()->getOp() == EOpLinkerObjects);
|
||||||
|
|
||||||
return globals.back()->getAsAggregate()->getSequence();
|
return globals.back()->getAsAggregate();
|
||||||
}
|
}
|
||||||
|
|
||||||
// See if a variable was both a user-declared output and used.
|
// See if a variable was both a user-declared output and used.
|
||||||
@ -734,7 +844,7 @@ TIntermSequence& TIntermediate::findLinkerObjects() const
|
|||||||
// is more useful, and perhaps the spec should be changed to reflect that.
|
// is more useful, and perhaps the spec should be changed to reflect that.
|
||||||
bool TIntermediate::userOutputUsed() const
|
bool TIntermediate::userOutputUsed() const
|
||||||
{
|
{
|
||||||
const TIntermSequence& linkerObjects = findLinkerObjects();
|
const TIntermSequence& linkerObjects = findLinkerObjects()->getSequence();
|
||||||
|
|
||||||
bool found = false;
|
bool found = false;
|
||||||
for (size_t i = 0; i < linkerObjects.size(); ++i) {
|
for (size_t i = 0; i < linkerObjects.size(); ++i) {
|
||||||
|
|||||||
@ -645,6 +645,9 @@ protected:
|
|||||||
TIntermSymbol* addSymbol(int Id, const TString&, const TType&, const TConstUnionArray&, TIntermTyped* subtree, const TSourceLoc&);
|
TIntermSymbol* addSymbol(int Id, const TString&, const TType&, const TConstUnionArray&, TIntermTyped* subtree, const TSourceLoc&);
|
||||||
void error(TInfoSink& infoSink, const char*);
|
void error(TInfoSink& infoSink, const char*);
|
||||||
void warn(TInfoSink& infoSink, const char*);
|
void warn(TInfoSink& infoSink, const char*);
|
||||||
|
void mergeTree(TInfoSink&, TIntermediate&);
|
||||||
|
void seedIdMap(TMap<TString, int>& idMap, int& maxId);
|
||||||
|
void remapIds(const TMap<TString, int>& idMap, int idShift, TIntermediate&);
|
||||||
void mergeBodies(TInfoSink&, TIntermSequence& globals, const TIntermSequence& unitGlobals);
|
void mergeBodies(TInfoSink&, TIntermSequence& globals, const TIntermSequence& unitGlobals);
|
||||||
void mergeLinkerObjects(TInfoSink&, TIntermSequence& linkerObjects, const TIntermSequence& unitLinkerObjects);
|
void mergeLinkerObjects(TInfoSink&, TIntermSequence& linkerObjects, const TIntermSequence& unitLinkerObjects);
|
||||||
void mergeImplicitArraySizes(TType&, const TType&);
|
void mergeImplicitArraySizes(TType&, const TType&);
|
||||||
@ -652,7 +655,7 @@ protected:
|
|||||||
void checkCallGraphCycles(TInfoSink&);
|
void checkCallGraphCycles(TInfoSink&);
|
||||||
void checkCallGraphBodies(TInfoSink&, bool keepUncalled);
|
void checkCallGraphBodies(TInfoSink&, bool keepUncalled);
|
||||||
void inOutLocationCheck(TInfoSink&);
|
void inOutLocationCheck(TInfoSink&);
|
||||||
TIntermSequence& findLinkerObjects() const;
|
TIntermAggregate* findLinkerObjects() const;
|
||||||
bool userOutputUsed() const;
|
bool userOutputUsed() const;
|
||||||
bool isSpecializationOperation(const TIntermOperator&) const;
|
bool isSpecializationOperation(const TIntermOperator&) const;
|
||||||
bool isNonuniformPropagating(TOperator) const;
|
bool isNonuniformPropagating(TOperator) const;
|
||||||
|
|||||||
1
gtests/Link.FromFile.Vk.cpp
Normal file → Executable file
1
gtests/Link.FromFile.Vk.cpp
Normal file → Executable file
@ -106,6 +106,7 @@ INSTANTIATE_TEST_CASE_P(
|
|||||||
Glsl, LinkTestVulkan,
|
Glsl, LinkTestVulkan,
|
||||||
::testing::ValuesIn(std::vector<std::vector<std::string>>({
|
::testing::ValuesIn(std::vector<std::vector<std::string>>({
|
||||||
{"link1.vk.frag", "link2.vk.frag"},
|
{"link1.vk.frag", "link2.vk.frag"},
|
||||||
|
{"spv.unit1.frag", "spv.unit2.frag", "spv.unit3.frag"},
|
||||||
})),
|
})),
|
||||||
);
|
);
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user