From 727b374fd335bbe413f89fb8587603deb930de8c Mon Sep 17 00:00:00 2001 From: John Kessenich Date: Fri, 3 Feb 2017 17:57:55 -0700 Subject: [PATCH] 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. --- .../hlsl.struct.split.array.geom.out | 228 ++++++++---------- .../hlsl.struct.split.nested.geom.out | 190 +++++++-------- glslang/Include/Types.h | 31 +-- glslang/Include/revision.h | 4 +- hlsl/hlslGrammar.cpp | 9 +- hlsl/hlslParseHelper.cpp | 145 ++++++----- hlsl/hlslParseHelper.h | 12 +- 7 files changed, 295 insertions(+), 324 deletions(-) diff --git a/Test/baseResults/hlsl.struct.split.array.geom.out b/Test/baseResults/hlsl.struct.split.array.geom.out index c136ac95..ca040cce 100644 --- a/Test/baseResults/hlsl.struct.split.array.geom.out +++ b/Test/baseResults/hlsl.struct.split.array.geom.out @@ -153,12 +153,12 @@ output primitive = triangle_strip // Module Version 10000 // Generated by (magic number): 80001 -// Id's are bound by 97 +// Id's are bound by 88 Capability Geometry 1: ExtInstImport "GLSL.std.450" MemoryModel Logical GLSL450 - EntryPoint Geometry 4 "main" 90 + EntryPoint Geometry 4 "main" 81 ExecutionMode 4 InputPoints ExecutionMode 4 Invocations 1 ExecutionMode 4 OutputTriangleStrip @@ -173,26 +173,20 @@ output primitive = triangle_strip Name 17 "v" Name 18 "OutputStream" Name 21 "Out" - Name 22 "PSInput" - MemberName 22(PSInput) 0 "Pos" - MemberName 22(PSInput) 1 "TexCoord" - MemberName 22(PSInput) 2 "TerrainPos" - MemberName 22(PSInput) 3 "VertexID" - Name 47 "x" - Name 56 "y" - Name 64 "PSInput" - MemberName 64(PSInput) 0 "Pos" - MemberName 64(PSInput) 1 "TexCoord" - MemberName 64(PSInput) 2 "TerrainPos" - MemberName 64(PSInput) 3 "VertexID" - Name 70 "Verts" - Name 88 "v" - Name 90 "v" - Name 92 "OutputStream" - Name 93 "param" - Name 95 "param" - MemberDecorate 22(PSInput) 0 BuiltIn Position - Decorate 90(v) Location 0 + Name 30 "x" + Name 41 "y" + Name 49 "PSInput" + MemberName 49(PSInput) 0 "Pos" + MemberName 49(PSInput) 1 "TexCoord" + MemberName 49(PSInput) 2 "TerrainPos" + MemberName 49(PSInput) 3 "VertexID" + Name 55 "Verts" + Name 79 "v" + Name 81 "v" + Name 83 "OutputStream" + Name 84 "param" + Name 86 "param" + Decorate 81(v) Location 0 2: TypeVoid 3: TypeFunction 2 6: TypeInt 32 0 @@ -206,44 +200,43 @@ output primitive = triangle_strip 14(PSInput): TypeStruct 11(fvec4) 12(fvec2) 13(fvec3) 6(int) 15: TypePointer Function 14(PSInput) 16: TypeFunction 2 9(ptr) 15(ptr) - 22(PSInput): TypeStruct 11(fvec4) 12(fvec2) 13(fvec3) 6(int) - 23: 10(float) Constant 0 - 24: 11(fvec4) ConstantComposite 23 23 23 23 - 25: 12(fvec2) ConstantComposite 23 23 - 26: 13(fvec3) ConstantComposite 23 23 23 - 27: 6(int) Constant 0 - 28: 22(PSInput) ConstantComposite 24 25 26 27 - 30: TypeInt 32 1 - 31: 30(int) Constant 0 - 32: TypePointer Function 11(fvec4) - 35: 30(int) Constant 1 - 36: TypePointer Function 12(fvec2) - 39: 30(int) Constant 2 - 40: TypePointer Function 13(fvec3) - 43: 30(int) Constant 3 - 44: TypePointer Function 6(int) - 46: TypePointer Function 30(int) - 54: TypeBool - 64(PSInput): TypeStruct 11(fvec4) 12(fvec2) 13(fvec3) 6(int) - 65: 6(int) Constant 3 - 66: TypeArray 64(PSInput) 65 - 67: 6(int) Constant 2 - 68: TypeArray 66 67 - 69: TypePointer Function 68 - 74: TypePointer Function 64(PSInput) - 89: TypePointer Input 8 - 90(v): 89(ptr) Variable Input + 22: 10(float) Constant 0 + 23: 11(fvec4) ConstantComposite 22 22 22 22 + 24: 12(fvec2) ConstantComposite 22 22 + 25: 13(fvec3) ConstantComposite 22 22 22 + 26: 6(int) Constant 0 + 27: 14(PSInput) ConstantComposite 23 24 25 26 + 28: TypeInt 32 1 + 29: TypePointer Function 28(int) + 31: 28(int) Constant 0 + 38: 28(int) Constant 2 + 39: TypeBool + 49(PSInput): TypeStruct 11(fvec4) 12(fvec2) 13(fvec3) 6(int) + 50: 6(int) Constant 3 + 51: TypeArray 49(PSInput) 50 + 52: 6(int) Constant 2 + 53: TypeArray 51 52 + 54: TypePointer Function 53 + 59: TypePointer Function 49(PSInput) + 62: TypePointer Function 11(fvec4) + 65: 28(int) Constant 1 + 66: TypePointer Function 12(fvec2) + 69: TypePointer Function 13(fvec3) + 72: 28(int) Constant 3 + 73: TypePointer Function 6(int) + 80: TypePointer Input 8 + 81(v): 80(ptr) Variable Input 4(main): 2 Function None 3 5: Label - 88(v): 9(ptr) Variable Function -92(OutputStream): 15(ptr) Variable Function - 93(param): 9(ptr) Variable Function - 95(param): 15(ptr) Variable Function - 91: 8 Load 90(v) - Store 88(v) 91 - 94: 8 Load 88(v) - Store 93(param) 94 - 96: 2 FunctionCall 19(@main(u1[1];struct-PSInput-vf4-vf2-vf3-u11;) 93(param) 95(param) + 79(v): 9(ptr) Variable Function +83(OutputStream): 15(ptr) Variable Function + 84(param): 9(ptr) Variable Function + 86(param): 15(ptr) Variable Function + 82: 8 Load 81(v) + Store 79(v) 82 + 85: 8 Load 79(v) + Store 84(param) 85 + 87: 2 FunctionCall 19(@main(u1[1];struct-PSInput-vf4-vf2-vf3-u11;) 84(param) 86(param) Return FunctionEnd 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 20: Label 21(Out): 15(ptr) Variable Function - 47(x): 46(ptr) Variable Function - 56(y): 46(ptr) Variable Function - 70(Verts): 69(ptr) Variable Function - 29: 11(fvec4) CompositeExtract 28 0 - 33: 32(ptr) AccessChain 21(Out) 31 - Store 33 29 - 34: 12(fvec2) CompositeExtract 28 1 - 37: 36(ptr) AccessChain 21(Out) 35 - Store 37 34 - 38: 13(fvec3) CompositeExtract 28 2 - 41: 40(ptr) AccessChain 21(Out) 39 - Store 41 38 - 42: 6(int) CompositeExtract 28 3 - 45: 44(ptr) AccessChain 21(Out) 43 - Store 45 42 - Store 47(x) 31 - Branch 48 - 48: Label - LoopMerge 50 51 None - Branch 52 - 52: Label - 53: 30(int) Load 47(x) - 55: 54(bool) SLessThan 53 39 - BranchConditional 55 49 50 - 49: Label - Store 56(y) 31 - Branch 57 - 57: Label - LoopMerge 59 60 None - Branch 61 - 61: Label - 62: 30(int) Load 56(y) - 63: 54(bool) SLessThan 62 39 - BranchConditional 63 58 59 - 58: Label - 71: 30(int) Load 47(x) - 72: 30(int) Load 56(y) - 73: 14(PSInput) Load 21(Out) - 75: 74(ptr) AccessChain 70(Verts) 71 72 - 76: 11(fvec4) CompositeExtract 73 0 - 77: 32(ptr) AccessChain 75 31 - Store 77 76 - 78: 12(fvec2) CompositeExtract 73 1 - 79: 36(ptr) AccessChain 75 35 - Store 79 78 - 80: 13(fvec3) CompositeExtract 73 2 - 81: 40(ptr) AccessChain 75 39 - Store 81 80 - 82: 6(int) CompositeExtract 73 3 - 83: 44(ptr) AccessChain 75 43 - Store 83 82 - Branch 60 - 60: Label - 84: 30(int) Load 56(y) - 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 + 30(x): 29(ptr) Variable Function + 41(y): 29(ptr) Variable Function + 55(Verts): 54(ptr) Variable Function + Store 21(Out) 27 + Store 30(x) 31 + Branch 32 + 32: Label + LoopMerge 34 35 None + Branch 36 + 36: Label + 37: 28(int) Load 30(x) + 40: 39(bool) SLessThan 37 38 + BranchConditional 40 33 34 + 33: Label + Store 41(y) 31 + Branch 42 + 42: Label + LoopMerge 44 45 None + Branch 46 + 46: Label + 47: 28(int) Load 41(y) + 48: 39(bool) SLessThan 47 38 + BranchConditional 48 43 44 + 43: Label + 56: 28(int) Load 30(x) + 57: 28(int) Load 41(y) + 58: 14(PSInput) Load 21(Out) + 60: 59(ptr) AccessChain 55(Verts) 56 57 + 61: 11(fvec4) CompositeExtract 58 0 + 63: 62(ptr) AccessChain 60 31 + Store 63 61 + 64: 12(fvec2) CompositeExtract 58 1 + 67: 66(ptr) AccessChain 60 65 + Store 67 64 + 68: 13(fvec3) CompositeExtract 58 2 + 70: 69(ptr) AccessChain 60 38 + Store 70 68 + 71: 6(int) CompositeExtract 58 3 + 74: 73(ptr) AccessChain 60 72 + Store 74 71 + Branch 45 + 45: Label + 75: 28(int) Load 41(y) + 76: 28(int) IAdd 75 65 + Store 41(y) 76 + Branch 42 + 44: Label + Branch 35 + 35: Label + 77: 28(int) Load 30(x) + 78: 28(int) IAdd 77 65 + Store 30(x) 78 + Branch 32 + 34: Label Return FunctionEnd diff --git a/Test/baseResults/hlsl.struct.split.nested.geom.out b/Test/baseResults/hlsl.struct.split.nested.geom.out index 1027aa5a..076fa0d7 100644 --- a/Test/baseResults/hlsl.struct.split.nested.geom.out +++ b/Test/baseResults/hlsl.struct.split.nested.geom.out @@ -267,12 +267,12 @@ output primitive = triangle_strip // Module Version 10000 // Generated by (magic number): 80001 -// Id's are bound by 76 +// Id's are bound by 75 Capability Geometry 1: ExtInstImport "GLSL.std.450" MemoryModel Logical GLSL450 - EntryPoint Geometry 4 "main" 45 53 + EntryPoint Geometry 4 "main" 44 52 ExecutionMode 4 Triangles ExecutionMode 4 Invocations 1 ExecutionMode 4 OutputTriangleStrip @@ -281,29 +281,26 @@ output primitive = triangle_strip Name 9 "PS_IN" MemberName 9(PS_IN) 0 "pos" MemberName 9(PS_IN) 1 "tc" - Name 14 "PS_IN" - MemberName 14(PS_IN) 0 "pos" - MemberName 14(PS_IN) 1 "tc" - Name 18 "STRUCT_WITH_NO_BUILTIN_INTERSTAGE_IO" - MemberName 18(STRUCT_WITH_NO_BUILTIN_INTERSTAGE_IO) 0 "m0_array" - MemberName 18(STRUCT_WITH_NO_BUILTIN_INTERSTAGE_IO) 1 "m1" - Name 19 "GS_OUT" - MemberName 19(GS_OUT) 0 "psIn" - MemberName 19(GS_OUT) 1 "contains_no_builtin_io" - 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 22 "tin" - Name 23 "ts" - Name 26 "o" - Name 42 "tin" - Name 45 "tin_pos" - Name 50 "PS_IN" - MemberName 50(PS_IN) 0 "tc" - Name 53 "tin" - Name 71 "ts" - Name 72 "param" - Name 74 "param" - Decorate 45(tin_pos) BuiltIn Position - Decorate 53(tin) Location 0 + Name 17 "STRUCT_WITH_NO_BUILTIN_INTERSTAGE_IO" + MemberName 17(STRUCT_WITH_NO_BUILTIN_INTERSTAGE_IO) 0 "m0_array" + MemberName 17(STRUCT_WITH_NO_BUILTIN_INTERSTAGE_IO) 1 "m1" + Name 18 "GS_OUT" + MemberName 18(GS_OUT) 0 "psIn" + MemberName 18(GS_OUT) 1 "contains_no_builtin_io" + 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;" + Name 21 "tin" + Name 22 "ts" + Name 25 "o" + Name 41 "tin" + Name 44 "tin_pos" + Name 49 "PS_IN" + MemberName 49(PS_IN) 0 "tc" + Name 52 "tin" + Name 70 "ts" + Name 71 "param" + Name 73 "param" + Decorate 44(tin_pos) BuiltIn Position + Decorate 52(tin) Location 0 2: TypeVoid 3: TypeFunction 2 6: TypeFloat 32 @@ -314,82 +311,81 @@ output primitive = triangle_strip 11: 10(int) Constant 3 12: TypeArray 9(PS_IN) 11 13: TypePointer Function 12 - 14(PS_IN): TypeStruct 7(fvec4) 8(fvec2) - 15: 10(int) Constant 2 - 16: TypeArray 6(float) 15 - 17: TypeInt 32 1 -18(STRUCT_WITH_NO_BUILTIN_INTERSTAGE_IO): TypeStruct 16 17(int) - 19(GS_OUT): TypeStruct 14(PS_IN) 18(STRUCT_WITH_NO_BUILTIN_INTERSTAGE_IO) - 20: TypePointer Function 19(GS_OUT) - 21: TypeFunction 2 13(ptr) 20(ptr) - 27: 17(int) Constant 0 - 28: 6(float) Constant 1065353216 - 29: 6(float) Constant 1073741824 - 30: 6(float) Constant 1077936128 - 31: 6(float) Constant 1082130432 - 32: 7(fvec4) ConstantComposite 28 29 30 31 - 33: TypePointer Function 7(fvec4) - 35: 17(int) Constant 1 - 36: 6(float) Constant 1084227584 - 37: 6(float) Constant 1086324736 - 38: 8(fvec2) ConstantComposite 36 37 - 39: TypePointer Function 8(fvec2) - 43: TypeArray 7(fvec4) 11 - 44: TypePointer Input 43 - 45(tin_pos): 44(ptr) Variable Input - 46: TypePointer Input 7(fvec4) - 50(PS_IN): TypeStruct 8(fvec2) - 51: TypeArray 50(PS_IN) 11 - 52: TypePointer Input 51 - 53(tin): 52(ptr) Variable Input - 54: TypePointer Input 8(fvec2) - 64: 17(int) Constant 2 + 14: 10(int) Constant 2 + 15: TypeArray 6(float) 14 + 16: TypeInt 32 1 +17(STRUCT_WITH_NO_BUILTIN_INTERSTAGE_IO): TypeStruct 15 16(int) + 18(GS_OUT): TypeStruct 9(PS_IN) 17(STRUCT_WITH_NO_BUILTIN_INTERSTAGE_IO) + 19: TypePointer Function 18(GS_OUT) + 20: TypeFunction 2 13(ptr) 19(ptr) + 26: 16(int) Constant 0 + 27: 6(float) Constant 1065353216 + 28: 6(float) Constant 1073741824 + 29: 6(float) Constant 1077936128 + 30: 6(float) Constant 1082130432 + 31: 7(fvec4) ConstantComposite 27 28 29 30 + 32: TypePointer Function 7(fvec4) + 34: 16(int) Constant 1 + 35: 6(float) Constant 1084227584 + 36: 6(float) Constant 1086324736 + 37: 8(fvec2) ConstantComposite 35 36 + 38: TypePointer Function 8(fvec2) + 42: TypeArray 7(fvec4) 11 + 43: TypePointer Input 42 + 44(tin_pos): 43(ptr) Variable Input + 45: TypePointer Input 7(fvec4) + 49(PS_IN): TypeStruct 8(fvec2) + 50: TypeArray 49(PS_IN) 11 + 51: TypePointer Input 50 + 52(tin): 51(ptr) Variable Input + 53: TypePointer Input 8(fvec2) + 63: 16(int) Constant 2 4(main): 2 Function None 3 5: Label - 42(tin): 13(ptr) Variable Function - 71(ts): 20(ptr) Variable Function - 72(param): 13(ptr) Variable Function - 74(param): 20(ptr) Variable Function - 47: 46(ptr) AccessChain 45(tin_pos) 27 - 48: 7(fvec4) Load 47 - 49: 33(ptr) AccessChain 42(tin) 27 27 - Store 49 48 - 55: 54(ptr) AccessChain 53(tin) 27 27 - 56: 8(fvec2) Load 55 - 57: 39(ptr) AccessChain 42(tin) 27 35 - Store 57 56 - 58: 46(ptr) AccessChain 45(tin_pos) 35 - 59: 7(fvec4) Load 58 - 60: 33(ptr) AccessChain 42(tin) 35 27 - Store 60 59 - 61: 54(ptr) AccessChain 53(tin) 35 27 - 62: 8(fvec2) Load 61 - 63: 39(ptr) AccessChain 42(tin) 35 35 - Store 63 62 - 65: 46(ptr) AccessChain 45(tin_pos) 64 - 66: 7(fvec4) Load 65 - 67: 33(ptr) AccessChain 42(tin) 64 27 - Store 67 66 - 68: 54(ptr) AccessChain 53(tin) 64 27 - 69: 8(fvec2) Load 68 - 70: 39(ptr) AccessChain 42(tin) 64 35 - Store 70 69 - 73: 12 Load 42(tin) - Store 72(param) 73 - 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) + 41(tin): 13(ptr) Variable Function + 70(ts): 19(ptr) Variable Function + 71(param): 13(ptr) Variable Function + 73(param): 19(ptr) Variable Function + 46: 45(ptr) AccessChain 44(tin_pos) 26 + 47: 7(fvec4) Load 46 + 48: 32(ptr) AccessChain 41(tin) 26 26 + Store 48 47 + 54: 53(ptr) AccessChain 52(tin) 26 26 + 55: 8(fvec2) Load 54 + 56: 38(ptr) AccessChain 41(tin) 26 34 + Store 56 55 + 57: 45(ptr) AccessChain 44(tin_pos) 34 + 58: 7(fvec4) Load 57 + 59: 32(ptr) AccessChain 41(tin) 34 26 + Store 59 58 + 60: 53(ptr) AccessChain 52(tin) 34 26 + 61: 8(fvec2) Load 60 + 62: 38(ptr) AccessChain 41(tin) 34 34 + Store 62 61 + 64: 45(ptr) AccessChain 44(tin_pos) 63 + 65: 7(fvec4) Load 64 + 66: 32(ptr) AccessChain 41(tin) 63 26 + Store 66 65 + 67: 53(ptr) AccessChain 52(tin) 63 26 + 68: 8(fvec2) Load 67 + 69: 38(ptr) AccessChain 41(tin) 63 34 + Store 69 68 + 72: 12 Load 41(tin) + Store 71(param) 72 + 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 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 - 22(tin): 13(ptr) FunctionParameter - 23(ts): 20(ptr) FunctionParameter - 25: Label - 26(o): 20(ptr) Variable Function - 34: 33(ptr) AccessChain 26(o) 27 27 - Store 34 32 - 40: 39(ptr) AccessChain 26(o) 27 35 - Store 40 38 - 41: 19(GS_OUT) Load 26(o) - Store 23(ts) 41 +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 + 21(tin): 13(ptr) FunctionParameter + 22(ts): 19(ptr) FunctionParameter + 24: Label + 25(o): 19(ptr) Variable Function + 33: 32(ptr) AccessChain 25(o) 26 26 + Store 33 31 + 39: 38(ptr) AccessChain 25(o) 26 34 + Store 39 37 + 40: 18(GS_OUT) Load 25(o) + Store 22(ts) 40 EmitVertex Return FunctionEnd diff --git a/glslang/Include/Types.h b/glslang/Include/Types.h index 883ee3e3..3fbf6112 100644 --- a/glslang/Include/Types.h +++ b/glslang/Include/Types.h @@ -412,7 +412,7 @@ public: } // Remove IO related data from qualifier. - void makeNonIo() + void makeNonIo() //?? remove? { // This preserves the storage type builtIn = EbvNone; @@ -429,7 +429,7 @@ public: } // Return true if there is data which would be scrubbed by makeNonIo - bool hasIoData() const + bool hasIoData() const // ?? remove? { return builtIn != EbvNone || hasLayout() || @@ -626,7 +626,6 @@ public: { return hasUniformLayout() || hasAnyLocation() || - hasBinding() || hasStream() || hasXfb() || hasFormat() || @@ -1221,34 +1220,10 @@ public: // Make complete copy of the whole type graph rooted at 'copyOf'. void deepCopy(const TType& copyOf) { - TMap copied; // to enable copying a type graph as a graph, not a tree + TMap copied; // to enable copying a type graph as a graph, not a tree //?? turn off again? 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 void makeTemporary() { diff --git a/glslang/Include/revision.h b/glslang/Include/revision.h index aa0795d2..866cab11 100644 --- a/glslang/Include/revision.h +++ b/glslang/Include/revision.h @@ -2,5 +2,5 @@ // 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). -#define GLSLANG_REVISION "Overload400-PrecQual.1787" -#define GLSLANG_DATE "03-Feb-2017" +#define GLSLANG_REVISION "Overload400-PrecQual.1791" +#define GLSLANG_DATE "04-Feb-2017" diff --git a/hlsl/hlslGrammar.cpp b/hlsl/hlslGrammar.cpp index 9ef296d3..cd68ee3b 100755 --- a/hlsl/hlslGrammar.cpp +++ b/hlsl/hlslGrammar.cpp @@ -1708,14 +1708,7 @@ bool HlslGrammar::acceptStruct(TType& type) new(&type) TType(typeList, structName, postDeclQualifier); // sets EbtBlock } - // If it was named, which means the type can be reused later, add - // 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"); - } + parseContext.declareStruct(token.loc, structName, type); return true; } diff --git a/hlsl/hlslParseHelper.cpp b/hlsl/hlslParseHelper.cpp index 1c701a33..691ec196 100755 --- a/hlsl/hlslParseHelper.cpp +++ b/hlsl/hlslParseHelper.cpp @@ -161,7 +161,7 @@ bool HlslParseContext::shouldConvertLValue(const TIntermNode* node) const 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); } @@ -1583,8 +1583,6 @@ TIntermNode* HlslParseContext::transformEntryPoint(const TSourceLoc& loc, TFunct TVector inputs; TVector 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 const auto makeVariableInOut = [&](TVariable& variable) { @@ -1689,54 +1687,67 @@ void HlslParseContext::handleFunctionBody(const TSourceLoc& loc, TFunction& func // 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 // 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& inputs, TVector& outputs) { - const auto remapType = [&](TType& type) { - const auto remapBuiltInType = [&](TType& type) { - switch (type.getQualifier().builtIn) { - case EbvFragDepthGreater: - intermediate.setDepth(EldGreater); - type.getQualifier().builtIn = EbvFragDepth; - break; - case EbvFragDepthLesser: - intermediate.setDepth(EldLess); - type.getQualifier().builtIn = EbvFragDepth; - break; - default: - break; + const auto makeIoVariable = [this](const char* name, TType& type) { + const auto remapType = [&](TType& type) { + const auto remapBuiltInType = [&](TType& type) { + switch (type.getQualifier().builtIn) { + case EbvFragDepthGreater: + intermediate.setDepth(EldGreater); + type.getQualifier().builtIn = EbvFragDepth; + break; + case EbvFragDepthLesser: + intermediate.setDepth(EldLess); + type.getQualifier().builtIn = EbvFragDepth; + break; + default: + break; + } + }; + remapBuiltInType(type); + if (type.isStruct()) { + auto& members = *type.getStruct(); + for (auto member = members.begin(); member != members.end(); ++member) + remapBuiltInType(*member->type); // TODO: lack-of-recursion structure depth problem } }; - remapBuiltInType(type); - if (type.isStruct()) { - auto members = *type.getStruct(); - for (auto member = members.begin(); member != members.end(); ++member) - 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) if (function.getType().getBasicType() == EbtVoid) returnValue = nullptr; else { - returnValue = makeInternalVariable("@entryPointOutput", function.getType()); + returnValue = makeIoVariable("@entryPointOutput", function.getWritableType()); returnValue->getWritableType().getQualifier().storage = EvqVaryingOut; - remapType(returnValue->getWritableType()); } // parameters are actually shader-scoped inputs and outputs (in or out) for (int i = 0; i < function.getParamCount(); i++) { TType& paramType = *function[i].type; 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; inputs.push_back(argAsGlobal); } 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; outputs.push_back(argAsGlobal); - remapType(argAsGlobal->getWritableType()); } } } @@ -1747,11 +1758,11 @@ void HlslParseContext::remapNonEntryPointIO(TFunction& function) { // return value if (function.getType().getBasicType() != EbtVoid) - makeTypeNonIo(&function.getWritableType()); + function.getWritableType().getQualifier().makeNonIo(); // parameters 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 @@ -5349,41 +5360,59 @@ void HlslParseContext::declareTypedef(const TSourceLoc& loc, TString& identifier error(loc, "name already defined", "typedef", identifier.c_str()); } -// Create a non-IO type from an IO type. If there is no IO data, -// the input type is unmodified. Otherwise, it modifies the type -// in place. -void HlslParseContext::makeTypeNonIo(TType* type) +// Do everything necessary to handle a struct declaration, including +// making IO aliases because HLSL allows mixed IO in a struct that specializes +// based on the usage (input, output, uniform, none). +void HlslParseContext::declareStruct(const TSourceLoc& loc, TString& structName, TType& type) { - // early out if there's nothing to do: prevents introduction of unneeded types. - if (!type->hasIoData()) + // If it was named, which means the type can be reused later, add + // 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; - type->getQualifier().makeNonIo(); // Sanitize the qualifier. + TVariable* userTypeDef = new TVariable(&structName, type, true); + if (! symbolTable.insert(*userTypeDef)) { + error(loc, "redefinition", structName.c_str(), "struct"); + return; + } - // Nothing more to do if there is no deep structure. - if (!type->isStruct()) + // 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; - const auto typeIter = nonIoTypeMap.find(type->getStruct()); + // We have IO involved. - 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 - } + // 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) { case EvqGlobal: case EvqTemporary: - makeTypeNonIo(&type); + type.getQualifier().makeNonIo(); default: break; } diff --git a/hlsl/hlslParseHelper.h b/hlsl/hlslParseHelper.h index 89ef680d..23f8b95e 100755 --- a/hlsl/hlslParseHelper.h +++ b/hlsl/hlslParseHelper.h @@ -75,7 +75,7 @@ public: TIntermAggregate* handleFunctionDefinition(const TSourceLoc&, TFunction&, const TAttributeMap&, TIntermNode*& entryPointTree); TIntermNode* transformEntryPoint(const TSourceLoc&, TFunction&, const TAttributeMap&); void handleFunctionBody(const TSourceLoc&, TFunction&, TIntermNode* functionBody, TIntermNode*& node); - void remapEntryPointIO(const TFunction& function, TVariable*& returnValue, TVector& inputs, TVector& outputs); + void remapEntryPointIO(TFunction& function, TVariable*& returnValue, TVector& inputs, TVector& outputs); void remapNonEntryPointIO(TFunction& function); TIntermNode* handleReturnValue(const TSourceLoc&, TIntermTyped*); void handleFunctionArgument(TFunction*, TIntermTyped*& arguments, TIntermTyped* newArg); @@ -131,6 +131,7 @@ public: const TFunction* findFunction(const TSourceLoc& loc, TFunction& call, bool& builtIn, TIntermTyped*& args); 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); void lengthenList(const TSourceLoc&, TIntermSequence& list, int size); 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 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 // Current state of parsing @@ -299,9 +296,8 @@ protected: TVector flattenLevel; // nested postfix operator level for flattening TVector flattenOffset; // cumulative offset for flattening - // Sanitized type map. If the same type is sanitized again, we want to reuse it. - // We cannot index by the TType: the map is typelist to typelist. - TMap nonIoTypeMap; + // IO-type map. + TMap ioTypeMap; // Structure splitting data: TMap splitIoVars; // variables with the builtin interstage IO removed, indexed by unique ID.