HLSL: Build IO types bottom up, as parsed, and cache the original (IO).

Previously, this was done recursively, per object, and the nonIO version
was cached. This reverses both those approaches.
This commit is contained in:
John Kessenich
2017-02-03 17:57:55 -07:00
parent 88c4464df5
commit 727b374fd3
7 changed files with 295 additions and 324 deletions

View File

@@ -153,12 +153,12 @@ output primitive = triangle_strip
// Module Version 10000 // Module Version 10000
// Generated by (magic number): 80001 // Generated by (magic number): 80001
// Id's are bound by 97 // Id's are bound by 88
Capability Geometry Capability Geometry
1: ExtInstImport "GLSL.std.450" 1: ExtInstImport "GLSL.std.450"
MemoryModel Logical GLSL450 MemoryModel Logical GLSL450
EntryPoint Geometry 4 "main" 90 EntryPoint Geometry 4 "main" 81
ExecutionMode 4 InputPoints ExecutionMode 4 InputPoints
ExecutionMode 4 Invocations 1 ExecutionMode 4 Invocations 1
ExecutionMode 4 OutputTriangleStrip ExecutionMode 4 OutputTriangleStrip
@@ -173,26 +173,20 @@ output primitive = triangle_strip
Name 17 "v" Name 17 "v"
Name 18 "OutputStream" Name 18 "OutputStream"
Name 21 "Out" Name 21 "Out"
Name 22 "PSInput" Name 30 "x"
MemberName 22(PSInput) 0 "Pos" Name 41 "y"
MemberName 22(PSInput) 1 "TexCoord" Name 49 "PSInput"
MemberName 22(PSInput) 2 "TerrainPos" MemberName 49(PSInput) 0 "Pos"
MemberName 22(PSInput) 3 "VertexID" MemberName 49(PSInput) 1 "TexCoord"
Name 47 "x" MemberName 49(PSInput) 2 "TerrainPos"
Name 56 "y" MemberName 49(PSInput) 3 "VertexID"
Name 64 "PSInput" Name 55 "Verts"
MemberName 64(PSInput) 0 "Pos" Name 79 "v"
MemberName 64(PSInput) 1 "TexCoord" Name 81 "v"
MemberName 64(PSInput) 2 "TerrainPos" Name 83 "OutputStream"
MemberName 64(PSInput) 3 "VertexID" Name 84 "param"
Name 70 "Verts" Name 86 "param"
Name 88 "v" Decorate 81(v) Location 0
Name 90 "v"
Name 92 "OutputStream"
Name 93 "param"
Name 95 "param"
MemberDecorate 22(PSInput) 0 BuiltIn Position
Decorate 90(v) Location 0
2: TypeVoid 2: TypeVoid
3: TypeFunction 2 3: TypeFunction 2
6: TypeInt 32 0 6: TypeInt 32 0
@@ -206,44 +200,43 @@ output primitive = triangle_strip
14(PSInput): TypeStruct 11(fvec4) 12(fvec2) 13(fvec3) 6(int) 14(PSInput): TypeStruct 11(fvec4) 12(fvec2) 13(fvec3) 6(int)
15: TypePointer Function 14(PSInput) 15: TypePointer Function 14(PSInput)
16: TypeFunction 2 9(ptr) 15(ptr) 16: TypeFunction 2 9(ptr) 15(ptr)
22(PSInput): TypeStruct 11(fvec4) 12(fvec2) 13(fvec3) 6(int) 22: 10(float) Constant 0
23: 10(float) Constant 0 23: 11(fvec4) ConstantComposite 22 22 22 22
24: 11(fvec4) ConstantComposite 23 23 23 23 24: 12(fvec2) ConstantComposite 22 22
25: 12(fvec2) ConstantComposite 23 23 25: 13(fvec3) ConstantComposite 22 22 22
26: 13(fvec3) ConstantComposite 23 23 23 26: 6(int) Constant 0
27: 6(int) Constant 0 27: 14(PSInput) ConstantComposite 23 24 25 26
28: 22(PSInput) ConstantComposite 24 25 26 27 28: TypeInt 32 1
30: TypeInt 32 1 29: TypePointer Function 28(int)
31: 30(int) Constant 0 31: 28(int) Constant 0
32: TypePointer Function 11(fvec4) 38: 28(int) Constant 2
35: 30(int) Constant 1 39: TypeBool
36: TypePointer Function 12(fvec2) 49(PSInput): TypeStruct 11(fvec4) 12(fvec2) 13(fvec3) 6(int)
39: 30(int) Constant 2 50: 6(int) Constant 3
40: TypePointer Function 13(fvec3) 51: TypeArray 49(PSInput) 50
43: 30(int) Constant 3 52: 6(int) Constant 2
44: TypePointer Function 6(int) 53: TypeArray 51 52
46: TypePointer Function 30(int) 54: TypePointer Function 53
54: TypeBool 59: TypePointer Function 49(PSInput)
64(PSInput): TypeStruct 11(fvec4) 12(fvec2) 13(fvec3) 6(int) 62: TypePointer Function 11(fvec4)
65: 6(int) Constant 3 65: 28(int) Constant 1
66: TypeArray 64(PSInput) 65 66: TypePointer Function 12(fvec2)
67: 6(int) Constant 2 69: TypePointer Function 13(fvec3)
68: TypeArray 66 67 72: 28(int) Constant 3
69: TypePointer Function 68 73: TypePointer Function 6(int)
74: TypePointer Function 64(PSInput) 80: TypePointer Input 8
89: TypePointer Input 8 81(v): 80(ptr) Variable Input
90(v): 89(ptr) Variable Input
4(main): 2 Function None 3 4(main): 2 Function None 3
5: Label 5: Label
88(v): 9(ptr) Variable Function 79(v): 9(ptr) Variable Function
92(OutputStream): 15(ptr) Variable Function 83(OutputStream): 15(ptr) Variable Function
93(param): 9(ptr) Variable Function 84(param): 9(ptr) Variable Function
95(param): 15(ptr) Variable Function 86(param): 15(ptr) Variable Function
91: 8 Load 90(v) 82: 8 Load 81(v)
Store 88(v) 91 Store 79(v) 82
94: 8 Load 88(v) 85: 8 Load 79(v)
Store 93(param) 94 Store 84(param) 85
96: 2 FunctionCall 19(@main(u1[1];struct-PSInput-vf4-vf2-vf3-u11;) 93(param) 95(param) 87: 2 FunctionCall 19(@main(u1[1];struct-PSInput-vf4-vf2-vf3-u11;) 84(param) 86(param)
Return Return
FunctionEnd FunctionEnd
19(@main(u1[1];struct-PSInput-vf4-vf2-vf3-u11;): 2 Function None 16 19(@main(u1[1];struct-PSInput-vf4-vf2-vf3-u11;): 2 Function None 16
@@ -251,70 +244,59 @@ output primitive = triangle_strip
18(OutputStream): 15(ptr) FunctionParameter 18(OutputStream): 15(ptr) FunctionParameter
20: Label 20: Label
21(Out): 15(ptr) Variable Function 21(Out): 15(ptr) Variable Function
47(x): 46(ptr) Variable Function 30(x): 29(ptr) Variable Function
56(y): 46(ptr) Variable Function 41(y): 29(ptr) Variable Function
70(Verts): 69(ptr) Variable Function 55(Verts): 54(ptr) Variable Function
29: 11(fvec4) CompositeExtract 28 0 Store 21(Out) 27
33: 32(ptr) AccessChain 21(Out) 31 Store 30(x) 31
Store 33 29 Branch 32
34: 12(fvec2) CompositeExtract 28 1 32: Label
37: 36(ptr) AccessChain 21(Out) 35 LoopMerge 34 35 None
Store 37 34 Branch 36
38: 13(fvec3) CompositeExtract 28 2 36: Label
41: 40(ptr) AccessChain 21(Out) 39 37: 28(int) Load 30(x)
Store 41 38 40: 39(bool) SLessThan 37 38
42: 6(int) CompositeExtract 28 3 BranchConditional 40 33 34
45: 44(ptr) AccessChain 21(Out) 43 33: Label
Store 45 42 Store 41(y) 31
Store 47(x) 31 Branch 42
Branch 48 42: Label
48: Label LoopMerge 44 45 None
LoopMerge 50 51 None Branch 46
Branch 52 46: Label
52: Label 47: 28(int) Load 41(y)
53: 30(int) Load 47(x) 48: 39(bool) SLessThan 47 38
55: 54(bool) SLessThan 53 39 BranchConditional 48 43 44
BranchConditional 55 49 50 43: Label
49: Label 56: 28(int) Load 30(x)
Store 56(y) 31 57: 28(int) Load 41(y)
Branch 57 58: 14(PSInput) Load 21(Out)
57: Label 60: 59(ptr) AccessChain 55(Verts) 56 57
LoopMerge 59 60 None 61: 11(fvec4) CompositeExtract 58 0
Branch 61 63: 62(ptr) AccessChain 60 31
61: Label Store 63 61
62: 30(int) Load 56(y) 64: 12(fvec2) CompositeExtract 58 1
63: 54(bool) SLessThan 62 39 67: 66(ptr) AccessChain 60 65
BranchConditional 63 58 59 Store 67 64
58: Label 68: 13(fvec3) CompositeExtract 58 2
71: 30(int) Load 47(x) 70: 69(ptr) AccessChain 60 38
72: 30(int) Load 56(y) Store 70 68
73: 14(PSInput) Load 21(Out) 71: 6(int) CompositeExtract 58 3
75: 74(ptr) AccessChain 70(Verts) 71 72 74: 73(ptr) AccessChain 60 72
76: 11(fvec4) CompositeExtract 73 0 Store 74 71
77: 32(ptr) AccessChain 75 31 Branch 45
Store 77 76 45: Label
78: 12(fvec2) CompositeExtract 73 1 75: 28(int) Load 41(y)
79: 36(ptr) AccessChain 75 35 76: 28(int) IAdd 75 65
Store 79 78 Store 41(y) 76
80: 13(fvec3) CompositeExtract 73 2 Branch 42
81: 40(ptr) AccessChain 75 39 44: Label
Store 81 80 Branch 35
82: 6(int) CompositeExtract 73 3 35: Label
83: 44(ptr) AccessChain 75 43 77: 28(int) Load 30(x)
Store 83 82 78: 28(int) IAdd 77 65
Branch 60 Store 30(x) 78
60: Label Branch 32
84: 30(int) Load 56(y) 34: Label
85: 30(int) IAdd 84 35
Store 56(y) 85
Branch 57
59: Label
Branch 51
51: Label
86: 30(int) Load 47(x)
87: 30(int) IAdd 86 35
Store 47(x) 87
Branch 48
50: Label
Return Return
FunctionEnd FunctionEnd

View File

@@ -267,12 +267,12 @@ output primitive = triangle_strip
// Module Version 10000 // Module Version 10000
// Generated by (magic number): 80001 // Generated by (magic number): 80001
// Id's are bound by 76 // Id's are bound by 75
Capability Geometry Capability Geometry
1: ExtInstImport "GLSL.std.450" 1: ExtInstImport "GLSL.std.450"
MemoryModel Logical GLSL450 MemoryModel Logical GLSL450
EntryPoint Geometry 4 "main" 45 53 EntryPoint Geometry 4 "main" 44 52
ExecutionMode 4 Triangles ExecutionMode 4 Triangles
ExecutionMode 4 Invocations 1 ExecutionMode 4 Invocations 1
ExecutionMode 4 OutputTriangleStrip ExecutionMode 4 OutputTriangleStrip
@@ -281,29 +281,26 @@ output primitive = triangle_strip
Name 9 "PS_IN" Name 9 "PS_IN"
MemberName 9(PS_IN) 0 "pos" MemberName 9(PS_IN) 0 "pos"
MemberName 9(PS_IN) 1 "tc" MemberName 9(PS_IN) 1 "tc"
Name 14 "PS_IN" Name 17 "STRUCT_WITH_NO_BUILTIN_INTERSTAGE_IO"
MemberName 14(PS_IN) 0 "pos" MemberName 17(STRUCT_WITH_NO_BUILTIN_INTERSTAGE_IO) 0 "m0_array"
MemberName 14(PS_IN) 1 "tc" MemberName 17(STRUCT_WITH_NO_BUILTIN_INTERSTAGE_IO) 1 "m1"
Name 18 "STRUCT_WITH_NO_BUILTIN_INTERSTAGE_IO" Name 18 "GS_OUT"
MemberName 18(STRUCT_WITH_NO_BUILTIN_INTERSTAGE_IO) 0 "m0_array" MemberName 18(GS_OUT) 0 "psIn"
MemberName 18(STRUCT_WITH_NO_BUILTIN_INTERSTAGE_IO) 1 "m1" MemberName 18(GS_OUT) 1 "contains_no_builtin_io"
Name 19 "GS_OUT" Name 23 "@main(struct-PS_IN-vf4-vf21[3];struct-GS_OUT-struct-PS_IN-vf4-vf21-struct-STRUCT_WITH_NO_BUILTIN_INTERSTAGE_IO-f1[2]-i111;"
MemberName 19(GS_OUT) 0 "psIn" Name 21 "tin"
MemberName 19(GS_OUT) 1 "contains_no_builtin_io" Name 22 "ts"
Name 24 "@main(struct-PS_IN-vf4-vf21[3];struct-GS_OUT-struct-PS_IN-vf4-vf21-struct-STRUCT_WITH_NO_BUILTIN_INTERSTAGE_IO-f1[2]-i111;" Name 25 "o"
Name 22 "tin" Name 41 "tin"
Name 23 "ts" Name 44 "tin_pos"
Name 26 "o" Name 49 "PS_IN"
Name 42 "tin" MemberName 49(PS_IN) 0 "tc"
Name 45 "tin_pos" Name 52 "tin"
Name 50 "PS_IN" Name 70 "ts"
MemberName 50(PS_IN) 0 "tc" Name 71 "param"
Name 53 "tin" Name 73 "param"
Name 71 "ts" Decorate 44(tin_pos) BuiltIn Position
Name 72 "param" Decorate 52(tin) Location 0
Name 74 "param"
Decorate 45(tin_pos) BuiltIn Position
Decorate 53(tin) Location 0
2: TypeVoid 2: TypeVoid
3: TypeFunction 2 3: TypeFunction 2
6: TypeFloat 32 6: TypeFloat 32
@@ -314,82 +311,81 @@ output primitive = triangle_strip
11: 10(int) Constant 3 11: 10(int) Constant 3
12: TypeArray 9(PS_IN) 11 12: TypeArray 9(PS_IN) 11
13: TypePointer Function 12 13: TypePointer Function 12
14(PS_IN): TypeStruct 7(fvec4) 8(fvec2) 14: 10(int) Constant 2
15: 10(int) Constant 2 15: TypeArray 6(float) 14
16: TypeArray 6(float) 15 16: TypeInt 32 1
17: TypeInt 32 1 17(STRUCT_WITH_NO_BUILTIN_INTERSTAGE_IO): TypeStruct 15 16(int)
18(STRUCT_WITH_NO_BUILTIN_INTERSTAGE_IO): TypeStruct 16 17(int) 18(GS_OUT): TypeStruct 9(PS_IN) 17(STRUCT_WITH_NO_BUILTIN_INTERSTAGE_IO)
19(GS_OUT): TypeStruct 14(PS_IN) 18(STRUCT_WITH_NO_BUILTIN_INTERSTAGE_IO) 19: TypePointer Function 18(GS_OUT)
20: TypePointer Function 19(GS_OUT) 20: TypeFunction 2 13(ptr) 19(ptr)
21: TypeFunction 2 13(ptr) 20(ptr) 26: 16(int) Constant 0
27: 17(int) Constant 0 27: 6(float) Constant 1065353216
28: 6(float) Constant 1065353216 28: 6(float) Constant 1073741824
29: 6(float) Constant 1073741824 29: 6(float) Constant 1077936128
30: 6(float) Constant 1077936128 30: 6(float) Constant 1082130432
31: 6(float) Constant 1082130432 31: 7(fvec4) ConstantComposite 27 28 29 30
32: 7(fvec4) ConstantComposite 28 29 30 31 32: TypePointer Function 7(fvec4)
33: TypePointer Function 7(fvec4) 34: 16(int) Constant 1
35: 17(int) Constant 1 35: 6(float) Constant 1084227584
36: 6(float) Constant 1084227584 36: 6(float) Constant 1086324736
37: 6(float) Constant 1086324736 37: 8(fvec2) ConstantComposite 35 36
38: 8(fvec2) ConstantComposite 36 37 38: TypePointer Function 8(fvec2)
39: TypePointer Function 8(fvec2) 42: TypeArray 7(fvec4) 11
43: TypeArray 7(fvec4) 11 43: TypePointer Input 42
44: TypePointer Input 43 44(tin_pos): 43(ptr) Variable Input
45(tin_pos): 44(ptr) Variable Input 45: TypePointer Input 7(fvec4)
46: TypePointer Input 7(fvec4) 49(PS_IN): TypeStruct 8(fvec2)
50(PS_IN): TypeStruct 8(fvec2) 50: TypeArray 49(PS_IN) 11
51: TypeArray 50(PS_IN) 11 51: TypePointer Input 50
52: TypePointer Input 51 52(tin): 51(ptr) Variable Input
53(tin): 52(ptr) Variable Input 53: TypePointer Input 8(fvec2)
54: TypePointer Input 8(fvec2) 63: 16(int) Constant 2
64: 17(int) Constant 2
4(main): 2 Function None 3 4(main): 2 Function None 3
5: Label 5: Label
42(tin): 13(ptr) Variable Function 41(tin): 13(ptr) Variable Function
71(ts): 20(ptr) Variable Function 70(ts): 19(ptr) Variable Function
72(param): 13(ptr) Variable Function 71(param): 13(ptr) Variable Function
74(param): 20(ptr) Variable Function 73(param): 19(ptr) Variable Function
47: 46(ptr) AccessChain 45(tin_pos) 27 46: 45(ptr) AccessChain 44(tin_pos) 26
48: 7(fvec4) Load 47 47: 7(fvec4) Load 46
49: 33(ptr) AccessChain 42(tin) 27 27 48: 32(ptr) AccessChain 41(tin) 26 26
Store 49 48 Store 48 47
55: 54(ptr) AccessChain 53(tin) 27 27 54: 53(ptr) AccessChain 52(tin) 26 26
56: 8(fvec2) Load 55 55: 8(fvec2) Load 54
57: 39(ptr) AccessChain 42(tin) 27 35 56: 38(ptr) AccessChain 41(tin) 26 34
Store 57 56 Store 56 55
58: 46(ptr) AccessChain 45(tin_pos) 35 57: 45(ptr) AccessChain 44(tin_pos) 34
59: 7(fvec4) Load 58 58: 7(fvec4) Load 57
60: 33(ptr) AccessChain 42(tin) 35 27 59: 32(ptr) AccessChain 41(tin) 34 26
Store 60 59 Store 59 58
61: 54(ptr) AccessChain 53(tin) 35 27 60: 53(ptr) AccessChain 52(tin) 34 26
62: 8(fvec2) Load 61 61: 8(fvec2) Load 60
63: 39(ptr) AccessChain 42(tin) 35 35 62: 38(ptr) AccessChain 41(tin) 34 34
Store 63 62 Store 62 61
65: 46(ptr) AccessChain 45(tin_pos) 64 64: 45(ptr) AccessChain 44(tin_pos) 63
66: 7(fvec4) Load 65 65: 7(fvec4) Load 64
67: 33(ptr) AccessChain 42(tin) 64 27 66: 32(ptr) AccessChain 41(tin) 63 26
Store 67 66 Store 66 65
68: 54(ptr) AccessChain 53(tin) 64 27 67: 53(ptr) AccessChain 52(tin) 63 26
69: 8(fvec2) Load 68 68: 8(fvec2) Load 67
70: 39(ptr) AccessChain 42(tin) 64 35 69: 38(ptr) AccessChain 41(tin) 63 34
Store 70 69 Store 69 68
73: 12 Load 42(tin) 72: 12 Load 41(tin)
Store 72(param) 73 Store 71(param) 72
75: 2 FunctionCall 24(@main(struct-PS_IN-vf4-vf21[3];struct-GS_OUT-struct-PS_IN-vf4-vf21-struct-STRUCT_WITH_NO_BUILTIN_INTERSTAGE_IO-f1[2]-i111;) 72(param) 74(param) 74: 2 FunctionCall 23(@main(struct-PS_IN-vf4-vf21[3];struct-GS_OUT-struct-PS_IN-vf4-vf21-struct-STRUCT_WITH_NO_BUILTIN_INTERSTAGE_IO-f1[2]-i111;) 71(param) 73(param)
Return Return
FunctionEnd FunctionEnd
24(@main(struct-PS_IN-vf4-vf21[3];struct-GS_OUT-struct-PS_IN-vf4-vf21-struct-STRUCT_WITH_NO_BUILTIN_INTERSTAGE_IO-f1[2]-i111;): 2 Function None 21 23(@main(struct-PS_IN-vf4-vf21[3];struct-GS_OUT-struct-PS_IN-vf4-vf21-struct-STRUCT_WITH_NO_BUILTIN_INTERSTAGE_IO-f1[2]-i111;): 2 Function None 20
22(tin): 13(ptr) FunctionParameter 21(tin): 13(ptr) FunctionParameter
23(ts): 20(ptr) FunctionParameter 22(ts): 19(ptr) FunctionParameter
25: Label 24: Label
26(o): 20(ptr) Variable Function 25(o): 19(ptr) Variable Function
34: 33(ptr) AccessChain 26(o) 27 27 33: 32(ptr) AccessChain 25(o) 26 26
Store 34 32 Store 33 31
40: 39(ptr) AccessChain 26(o) 27 35 39: 38(ptr) AccessChain 25(o) 26 34
Store 40 38 Store 39 37
41: 19(GS_OUT) Load 26(o) 40: 18(GS_OUT) Load 25(o)
Store 23(ts) 41 Store 22(ts) 40
EmitVertex EmitVertex
Return Return
FunctionEnd FunctionEnd

View File

@@ -412,7 +412,7 @@ public:
} }
// Remove IO related data from qualifier. // Remove IO related data from qualifier.
void makeNonIo() void makeNonIo() //?? remove?
{ {
// This preserves the storage type // This preserves the storage type
builtIn = EbvNone; builtIn = EbvNone;
@@ -429,7 +429,7 @@ public:
} }
// Return true if there is data which would be scrubbed by makeNonIo // Return true if there is data which would be scrubbed by makeNonIo
bool hasIoData() const bool hasIoData() const // ?? remove?
{ {
return builtIn != EbvNone || return builtIn != EbvNone ||
hasLayout() || hasLayout() ||
@@ -626,7 +626,6 @@ public:
{ {
return hasUniformLayout() || return hasUniformLayout() ||
hasAnyLocation() || hasAnyLocation() ||
hasBinding() ||
hasStream() || hasStream() ||
hasXfb() || hasXfb() ||
hasFormat() || hasFormat() ||
@@ -1221,34 +1220,10 @@ public:
// Make complete copy of the whole type graph rooted at 'copyOf'. // Make complete copy of the whole type graph rooted at 'copyOf'.
void deepCopy(const TType& copyOf) void deepCopy(const TType& copyOf)
{ {
TMap<TTypeList*,TTypeList*> copied; // to enable copying a type graph as a graph, not a tree TMap<TTypeList*,TTypeList*> copied; // to enable copying a type graph as a graph, not a tree //?? turn off again?
deepCopy(copyOf, copied); deepCopy(copyOf, copied);
} }
// Return true if type (recursively) contains IO data.
bool hasIoData() const
{
if (getQualifier().hasIoData())
return true;
if (isStruct())
for (unsigned int i = 0; i < structure->size(); ++i)
if ((*structure)[i].type->hasIoData())
return true;
return false;
}
// Remove IO related data from type
void makeNonIo()
{
getQualifier().makeNonIo();
if (isStruct())
for (unsigned int i = 0; i < structure->size(); ++i)
(*structure)[i].type->makeNonIo();
}
// Recursively make temporary // Recursively make temporary
void makeTemporary() void makeTemporary()
{ {

View File

@@ -2,5 +2,5 @@
// For the version, it uses the latest git tag followed by the number of commits. // For the version, it uses the latest git tag followed by the number of commits.
// For the date, it uses the current date (when then script is run). // For the date, it uses the current date (when then script is run).
#define GLSLANG_REVISION "Overload400-PrecQual.1787" #define GLSLANG_REVISION "Overload400-PrecQual.1791"
#define GLSLANG_DATE "03-Feb-2017" #define GLSLANG_DATE "04-Feb-2017"

View File

@@ -1708,14 +1708,7 @@ bool HlslGrammar::acceptStruct(TType& type)
new(&type) TType(typeList, structName, postDeclQualifier); // sets EbtBlock new(&type) TType(typeList, structName, postDeclQualifier); // sets EbtBlock
} }
// If it was named, which means the type can be reused later, add parseContext.declareStruct(token.loc, structName, type);
// it to the symbol table. (Unless it's a block, in which
// case the name is not a type.)
if (type.getBasicType() != EbtBlock && structName.size() > 0) {
TVariable* userTypeDef = new TVariable(&structName, type, true);
if (! parseContext.symbolTable.insert(*userTypeDef))
parseContext.error(token.loc, "redefinition", structName.c_str(), "struct");
}
return true; return true;
} }

View File

@@ -161,7 +161,7 @@ bool HlslParseContext::shouldConvertLValue(const TIntermNode* node) const
void HlslParseContext::growGlobalUniformBlock(TSourceLoc& loc, TType& memberType, TString& memberName) void HlslParseContext::growGlobalUniformBlock(TSourceLoc& loc, TType& memberType, TString& memberName)
{ {
makeTypeNonIo(&memberType); //?? losing offsets is okay? memberType.getQualifier().makeNonIo(); //?? losing offsets is okay?
TParseContextBase::growGlobalUniformBlock(loc, memberType, memberName); TParseContextBase::growGlobalUniformBlock(loc, memberType, memberName);
} }
@@ -1583,8 +1583,6 @@ TIntermNode* HlslParseContext::transformEntryPoint(const TSourceLoc& loc, TFunct
TVector<TVariable*> inputs; TVector<TVariable*> inputs;
TVector<TVariable*> outputs; TVector<TVariable*> outputs;
remapEntryPointIO(userFunction, entryPointOutput, inputs, outputs); remapEntryPointIO(userFunction, entryPointOutput, inputs, outputs);
// Once the parameters are moved to shader I/O, they should be non-I/O
remapNonEntryPointIO(userFunction);
// Further this return/in/out transform by flattening, splitting, and assigning locations // Further this return/in/out transform by flattening, splitting, and assigning locations
const auto makeVariableInOut = [&](TVariable& variable) { const auto makeVariableInOut = [&](TVariable& variable) {
@@ -1689,9 +1687,10 @@ void HlslParseContext::handleFunctionBody(const TSourceLoc& loc, TFunction& func
// AST I/O is done through shader globals declared in the 'in' or 'out' // AST I/O is done through shader globals declared in the 'in' or 'out'
// storage class. An HLSL entry point has a return value, input parameters // storage class. An HLSL entry point has a return value, input parameters
// and output parameters. These need to get remapped to the AST I/O. // and output parameters. These need to get remapped to the AST I/O.
void HlslParseContext::remapEntryPointIO(const TFunction& function, TVariable*& returnValue, void HlslParseContext::remapEntryPointIO(TFunction& function, TVariable*& returnValue,
TVector<TVariable*>& inputs, TVector<TVariable*>& outputs) TVector<TVariable*>& inputs, TVector<TVariable*>& outputs)
{ {
const auto makeIoVariable = [this](const char* name, TType& type) {
const auto remapType = [&](TType& type) { const auto remapType = [&](TType& type) {
const auto remapBuiltInType = [&](TType& type) { const auto remapBuiltInType = [&](TType& type) {
switch (type.getQualifier().builtIn) { switch (type.getQualifier().builtIn) {
@@ -1709,34 +1708,46 @@ void HlslParseContext::remapEntryPointIO(const TFunction& function, TVariable*&
}; };
remapBuiltInType(type); remapBuiltInType(type);
if (type.isStruct()) { if (type.isStruct()) {
auto members = *type.getStruct(); auto& members = *type.getStruct();
for (auto member = members.begin(); member != members.end(); ++member) for (auto member = members.begin(); member != members.end(); ++member)
remapBuiltInType(*member->type); // TODO: lack-of-recursion structure depth problem remapBuiltInType(*member->type); // TODO: lack-of-recursion structure depth problem
} }
}; };
TVariable* ioVariable = makeInternalVariable(name, type);
// We might have already lost the IO-aspect of the deep parts of this type,
// get them back and also make them if that hadn't been done yet.
// (The shallow part of IO is already safely copied into the return value.)
type.getQualifier().makeNonIo();
if (type.getStruct() != nullptr) {
auto newList = ioTypeMap.find(ioVariable->getType().getStruct());
if (newList != ioTypeMap.end())
ioVariable->getWritableType().setStruct(newList->second);
}
remapType(ioVariable->getWritableType());
return ioVariable;
};
// return value is actually a shader-scoped output (out) // return value is actually a shader-scoped output (out)
if (function.getType().getBasicType() == EbtVoid) if (function.getType().getBasicType() == EbtVoid)
returnValue = nullptr; returnValue = nullptr;
else { else {
returnValue = makeInternalVariable("@entryPointOutput", function.getType()); returnValue = makeIoVariable("@entryPointOutput", function.getWritableType());
returnValue->getWritableType().getQualifier().storage = EvqVaryingOut; returnValue->getWritableType().getQualifier().storage = EvqVaryingOut;
remapType(returnValue->getWritableType());
} }
// parameters are actually shader-scoped inputs and outputs (in or out) // parameters are actually shader-scoped inputs and outputs (in or out)
for (int i = 0; i < function.getParamCount(); i++) { for (int i = 0; i < function.getParamCount(); i++) {
TType& paramType = *function[i].type; TType& paramType = *function[i].type;
if (paramType.getQualifier().isParamInput()) { if (paramType.getQualifier().isParamInput()) {
TVariable* argAsGlobal = makeInternalVariable(*function[i].name, paramType); TVariable* argAsGlobal = makeIoVariable(function[i].name->c_str(), paramType);
argAsGlobal->getWritableType().getQualifier().storage = EvqVaryingIn; argAsGlobal->getWritableType().getQualifier().storage = EvqVaryingIn;
inputs.push_back(argAsGlobal); inputs.push_back(argAsGlobal);
} }
if (paramType.getQualifier().isParamOutput()) { if (paramType.getQualifier().isParamOutput()) {
TVariable* argAsGlobal = makeInternalVariable(*function[i].name, paramType); TVariable* argAsGlobal = makeIoVariable(function[i].name->c_str(), paramType);
argAsGlobal->getWritableType().getQualifier().storage = EvqVaryingOut; argAsGlobal->getWritableType().getQualifier().storage = EvqVaryingOut;
outputs.push_back(argAsGlobal); outputs.push_back(argAsGlobal);
remapType(argAsGlobal->getWritableType());
} }
} }
} }
@@ -1747,11 +1758,11 @@ void HlslParseContext::remapNonEntryPointIO(TFunction& function)
{ {
// return value // return value
if (function.getType().getBasicType() != EbtVoid) if (function.getType().getBasicType() != EbtVoid)
makeTypeNonIo(&function.getWritableType()); function.getWritableType().getQualifier().makeNonIo();
// parameters // parameters
for (int i = 0; i < function.getParamCount(); i++) for (int i = 0; i < function.getParamCount(); i++)
makeTypeNonIo(function[i].type); function[i].type->getQualifier().makeNonIo();
} }
// Handle function returns, including type conversions to the function return type // Handle function returns, including type conversions to the function return type
@@ -5349,41 +5360,59 @@ void HlslParseContext::declareTypedef(const TSourceLoc& loc, TString& identifier
error(loc, "name already defined", "typedef", identifier.c_str()); error(loc, "name already defined", "typedef", identifier.c_str());
} }
// Create a non-IO type from an IO type. If there is no IO data, // Do everything necessary to handle a struct declaration, including
// the input type is unmodified. Otherwise, it modifies the type // making IO aliases because HLSL allows mixed IO in a struct that specializes
// in place. // based on the usage (input, output, uniform, none).
void HlslParseContext::makeTypeNonIo(TType* type) void HlslParseContext::declareStruct(const TSourceLoc& loc, TString& structName, TType& type)
{ {
// early out if there's nothing to do: prevents introduction of unneeded types. // If it was named, which means the type can be reused later, add
if (!type->hasIoData()) // it to the symbol table. (Unless it's a block, in which
// case the name is not a type.)
if (type.getBasicType() == EbtBlock || structName.size() == 0)
return; return;
type->getQualifier().makeNonIo(); // Sanitize the qualifier. TVariable* userTypeDef = new TVariable(&structName, type, true);
if (! symbolTable.insert(*userTypeDef)) {
// Nothing more to do if there is no deep structure. error(loc, "redefinition", structName.c_str(), "struct");
if (!type->isStruct())
return; return;
const auto typeIter = nonIoTypeMap.find(type->getStruct());
if (typeIter != nonIoTypeMap.end()) {
// reuse deep structure if we have sanitized it before, but we must preserve
// our unique shallow structure, which may not be shared with other users of
// the deep copy. Create a new type with the sanitized qualifier, and the
// shared deep structure
type->setStruct(typeIter->second); // share already sanitized deep structure.
} else {
// The type contains interstage IO, but we've never encountered it before.
// Copy it, scrub data we don't want for an non-IO type, and remember it in the nonIoTypeMap
TType nonIoType;
nonIoType.deepCopy(*type);
nonIoType.makeNonIo();
// remember the new deep structure in a map, so we can share it in the future.
nonIoTypeMap[type->getStruct()] = nonIoType.getWritableStruct();
type->shallowCopy(nonIoType); // we modify the input type in place
} }
// See if we need IO aliases for the structure typeList
bool hasIo = false;
for (auto member = type.getStruct()->begin(); member != type.getStruct()->end(); ++member) {
if (member->type->getQualifier().hasIoData()) {
hasIo = true;
break;
}
if (member->type->isStruct()) {
if (ioTypeMap.find(member->type->getStruct()) != ioTypeMap.end()) {
hasIo = true;
break;
}
}
}
if (!hasIo)
return;
// We have IO involved.
// Make a pure typeList for the symbol table, and cache side copies of IO versions.
TTypeList* newList = new TTypeList;
for (auto member = type.getStruct()->begin(); member != type.getStruct()->end(); ++member) {
TType* memberType = new TType;
memberType->shallowCopy(*member->type);
TTypeLoc newMember = { memberType, member->loc };
if (member->type->isStruct()) {
// swap in an IO child if there is one
auto it = ioTypeMap.find(member->type->getStruct());
if (it != ioTypeMap.end())
newMember.type->setStruct(it->second);
}
newList->push_back(newMember);
member->type->getQualifier().makeNonIo();
}
ioTypeMap[type.getStruct()] = newList;
} }
// //
@@ -5416,7 +5445,7 @@ TIntermNode* HlslParseContext::declareVariable(const TSourceLoc& loc, TString& i
switch (type.getQualifier().storage) { switch (type.getQualifier().storage) {
case EvqGlobal: case EvqGlobal:
case EvqTemporary: case EvqTemporary:
makeTypeNonIo(&type); type.getQualifier().makeNonIo();
default: default:
break; break;
} }

View File

@@ -75,7 +75,7 @@ public:
TIntermAggregate* handleFunctionDefinition(const TSourceLoc&, TFunction&, const TAttributeMap&, TIntermNode*& entryPointTree); TIntermAggregate* handleFunctionDefinition(const TSourceLoc&, TFunction&, const TAttributeMap&, TIntermNode*& entryPointTree);
TIntermNode* transformEntryPoint(const TSourceLoc&, TFunction&, const TAttributeMap&); TIntermNode* transformEntryPoint(const TSourceLoc&, TFunction&, const TAttributeMap&);
void handleFunctionBody(const TSourceLoc&, TFunction&, TIntermNode* functionBody, TIntermNode*& node); void handleFunctionBody(const TSourceLoc&, TFunction&, TIntermNode* functionBody, TIntermNode*& node);
void remapEntryPointIO(const TFunction& function, TVariable*& returnValue, TVector<TVariable*>& inputs, TVector<TVariable*>& outputs); void remapEntryPointIO(TFunction& function, TVariable*& returnValue, TVector<TVariable*>& inputs, TVector<TVariable*>& outputs);
void remapNonEntryPointIO(TFunction& function); void remapNonEntryPointIO(TFunction& function);
TIntermNode* handleReturnValue(const TSourceLoc&, TIntermTyped*); TIntermNode* handleReturnValue(const TSourceLoc&, TIntermTyped*);
void handleFunctionArgument(TFunction*, TIntermTyped*& arguments, TIntermTyped* newArg); void handleFunctionArgument(TFunction*, TIntermTyped*& arguments, TIntermTyped* newArg);
@@ -131,6 +131,7 @@ public:
const TFunction* findFunction(const TSourceLoc& loc, TFunction& call, bool& builtIn, TIntermTyped*& args); const TFunction* findFunction(const TSourceLoc& loc, TFunction& call, bool& builtIn, TIntermTyped*& args);
void declareTypedef(const TSourceLoc&, TString& identifier, const TType&, TArraySizes* typeArray = 0); void declareTypedef(const TSourceLoc&, TString& identifier, const TType&, TArraySizes* typeArray = 0);
void declareStruct(const TSourceLoc&, TString& structName, TType&);
TIntermNode* declareVariable(const TSourceLoc&, TString& identifier, TType&, TIntermTyped* initializer = 0); TIntermNode* declareVariable(const TSourceLoc&, TString& identifier, TType&, TIntermTyped* initializer = 0);
void lengthenList(const TSourceLoc&, TIntermSequence& list, int size); void lengthenList(const TSourceLoc&, TIntermSequence& list, int size);
TIntermTyped* addConstructor(const TSourceLoc&, TIntermNode*, const TType&); TIntermTyped* addConstructor(const TSourceLoc&, TIntermNode*, const TType&);
@@ -230,10 +231,6 @@ protected:
int flattenStruct(const TSourceLoc& loc, const TVariable& variable, const TType&, TFlattenData&, TString name); 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); int flattenArray(const TSourceLoc& loc, const TVariable& variable, const TType&, TFlattenData&, TString name);
// Create a non-IO type from an IO type. If there is no IO data, this returns the input type unmodified.
// Otherwise, it modifies the type in place, and returns a pointer to it.
void makeTypeNonIo(TType*);
void finish() override; // post-processing void finish() override; // post-processing
// Current state of parsing // Current state of parsing
@@ -299,9 +296,8 @@ protected:
TVector<int> flattenLevel; // nested postfix operator level for flattening TVector<int> flattenLevel; // nested postfix operator level for flattening
TVector<int> flattenOffset; // cumulative offset for flattening TVector<int> flattenOffset; // cumulative offset for flattening
// Sanitized type map. If the same type is sanitized again, we want to reuse it. // IO-type map.
// We cannot index by the TType: the map is typelist to typelist. TMap<const TTypeList*, TTypeList*> ioTypeMap;
TMap<const TTypeList*, TTypeList*> nonIoTypeMap;
// Structure splitting data: // Structure splitting data:
TMap<int, TVariable*> splitIoVars; // variables with the builtin interstage IO removed, indexed by unique ID. TMap<int, TVariable*> splitIoVars; // variables with the builtin interstage IO removed, indexed by unique ID.