From 41436ad2042af1ade8a415dd4f23bb3aefd26aa0 Mon Sep 17 00:00:00 2001 From: John Kessenich Date: Fri, 13 Jul 2018 10:40:40 -0600 Subject: [PATCH] Link/SPV: Correct symbol IDs on merging ASTs to a single coherent space This is one step in providing full linker functionality for creating correct SPIR-V from multiple compilation units for the same stage. (This was the only remaining "hard" part. The rest should be simple.) --- Test/baseResults/link1.vk.frag.out | 95 +++++---- Test/baseResults/spv.unit1.frag.out | 272 +++++++++++++++++++++++++ Test/spv.unit1.frag | 14 ++ Test/spv.unit2.frag | 14 ++ Test/spv.unit3.frag | 11 + glslang/Include/intermediate.h | 1 + glslang/MachineIndependent/linkValidate.cpp | 124 ++++++++++- glslang/MachineIndependent/localintermediate.h | 5 +- gtests/Link.FromFile.Vk.cpp | 1 + 9 files changed, 481 insertions(+), 56 deletions(-) create mode 100755 Test/baseResults/spv.unit1.frag.out create mode 100755 Test/spv.unit1.frag create mode 100755 Test/spv.unit2.frag create mode 100755 Test/spv.unit3.frag mode change 100644 => 100755 glslang/MachineIndependent/linkValidate.cpp mode change 100644 => 100755 gtests/Link.FromFile.Vk.cpp diff --git a/Test/baseResults/link1.vk.frag.out b/Test/baseResults/link1.vk.frag.out index 63660db..333594e 100644 --- a/Test/baseResults/link1.vk.frag.out +++ b/Test/baseResults/link1.vk.frag.out @@ -198,7 +198,7 @@ gl_FragCoord origin is upper left // Module Version 10000 // Generated by (magic number): 80007 -// Id's are bound by 71 +// Id's are bound by 70 Capability Shader 1: ExtInstImport "GLSL.std.450" @@ -214,24 +214,24 @@ gl_FragCoord origin is upper left Name 32 "b" Name 33 "i" Name 39 "c" - Name 54 "s2D" - Name 63 "bnameRuntime" - MemberName 63(bnameRuntime) 0 "r" - Name 65 "" - Name 68 "bnameImplicit" - MemberName 68(bnameImplicit) 0 "m" - Name 70 "" + Name 53 "s2D" + Name 62 "bnameRuntime" + MemberName 62(bnameRuntime) 0 "r" + Name 64 "" + Name 67 "bnameImplicit" + MemberName 67(bnameImplicit) 0 "m" + Name 69 "" Decorate 12(color) Location 0 - Decorate 54(s2D) DescriptorSet 0 - Decorate 54(s2D) Binding 1 - Decorate 62 ArrayStride 4 - MemberDecorate 63(bnameRuntime) 0 Offset 0 - Decorate 63(bnameRuntime) BufferBlock - Decorate 65 DescriptorSet 0 - Decorate 67 ArrayStride 4 - MemberDecorate 68(bnameImplicit) 0 Offset 0 - Decorate 68(bnameImplicit) BufferBlock - Decorate 70 DescriptorSet 0 + Decorate 53(s2D) DescriptorSet 0 + Decorate 53(s2D) Binding 1 + Decorate 61 ArrayStride 4 + MemberDecorate 62(bnameRuntime) 0 Offset 0 + Decorate 62(bnameRuntime) BufferBlock + Decorate 64 DescriptorSet 0 + Decorate 66 ArrayStride 4 + MemberDecorate 67(bnameImplicit) 0 Offset 0 + Decorate 67(bnameImplicit) BufferBlock + Decorate 69 DescriptorSet 0 2: TypeVoid 3: TypeFunction 2 6: TypeFloat 32 @@ -263,24 +263,23 @@ gl_FragCoord origin is upper left 39(c): 38(ptr) Variable Private 40: 14(int) Constant 3 42: 14(int) Constant 2 - 43: TypePointer Output 6(float) - 45: 14(int) Constant 9 - 51: TypeImage 6(float) 2D sampled format:Unknown - 52: TypeSampledImage 51 - 53: TypePointer UniformConstant 52 - 54(s2D): 53(ptr) Variable UniformConstant - 56: TypeVector 6(float) 2 - 57: 6(float) Constant 1056964608 - 58: 56(fvec2) ConstantComposite 57 57 - 62: TypeRuntimeArray 6(float) -63(bnameRuntime): TypeStruct 62 - 64: TypePointer Uniform 63(bnameRuntime) - 65: 64(ptr) Variable Uniform - 66: 15(int) Constant 4 - 67: TypeArray 6(float) 66 -68(bnameImplicit): TypeStruct 67 - 69: TypePointer Uniform 68(bnameImplicit) - 70: 69(ptr) Variable Uniform + 44: 14(int) Constant 9 + 50: TypeImage 6(float) 2D sampled format:Unknown + 51: TypeSampledImage 50 + 52: TypePointer UniformConstant 51 + 53(s2D): 52(ptr) Variable UniformConstant + 55: TypeVector 6(float) 2 + 56: 6(float) Constant 1056964608 + 57: 55(fvec2) ConstantComposite 56 56 + 61: TypeRuntimeArray 6(float) +62(bnameRuntime): TypeStruct 61 + 63: TypePointer Uniform 62(bnameRuntime) + 64: 63(ptr) Variable Uniform + 65: 15(int) Constant 4 + 66: TypeArray 6(float) 65 +67(bnameImplicit): TypeStruct 66 + 68: TypePointer Uniform 67(bnameImplicit) + 69: 68(ptr) Variable Uniform 4(main): 2 Function None 3 5: Label 13: 7(fvec4) FunctionCall 9(getColor() @@ -298,18 +297,18 @@ gl_FragCoord origin is upper left FunctionEnd 9(getColor(): 7(fvec4) Function None 8 10: Label - 44: 43(ptr) AccessChain 12(color) 42 - Store 44 21 - 46: 22(ptr) AccessChain 19(a1) 45 + 43: 22(ptr) AccessChain 19(a1) 42 + Store 43 21 + 45: 22(ptr) AccessChain 27(a2) 44 + Store 45 21 + 46: 22(ptr) AccessChain 32(b) 42 Store 46 21 - 47: 22(ptr) AccessChain 27(a2) 42 + 47: 22(ptr) AccessChain 39(c) 40 Store 47 21 - 48: 22(ptr) AccessChain 32(b) 40 - Store 48 21 - 49: 37 Load 39(c) - 50: 22(ptr) AccessChain 32(b) 49 - Store 50 21 - 55: 52 Load 54(s2D) - 59: 7(fvec4) ImageSampleImplicitLod 55 58 - ReturnValue 59 + 48: 14(int) Load 33(i) + 49: 22(ptr) AccessChain 39(c) 48 + Store 49 21 + 54: 51 Load 53(s2D) + 58: 7(fvec4) ImageSampleImplicitLod 54 57 + ReturnValue 58 FunctionEnd diff --git a/Test/baseResults/spv.unit1.frag.out b/Test/baseResults/spv.unit1.frag.out new file mode 100755 index 0000000..a925724 --- /dev/null +++ b/Test/baseResults/spv.unit1.frag.out @@ -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 diff --git a/Test/spv.unit1.frag b/Test/spv.unit1.frag new file mode 100755 index 0000000..f6c7850 --- /dev/null +++ b/Test/spv.unit1.frag @@ -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; +} \ No newline at end of file diff --git a/Test/spv.unit2.frag b/Test/spv.unit2.frag new file mode 100755 index 0000000..6a6d528 --- /dev/null +++ b/Test/spv.unit2.frag @@ -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; +} \ No newline at end of file diff --git a/Test/spv.unit3.frag b/Test/spv.unit3.frag new file mode 100755 index 0000000..0ab667c --- /dev/null +++ b/Test/spv.unit3.frag @@ -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; +} diff --git a/glslang/Include/intermediate.h b/glslang/Include/intermediate.h index 19eb7aa..96c8749 100755 --- a/glslang/Include/intermediate.h +++ b/glslang/Include/intermediate.h @@ -1164,6 +1164,7 @@ public: constSubtree(nullptr) { name = n; } virtual int getId() const { return id; } + virtual void changeId(int i) { id = i; } virtual const TString& getName() const { return name; } virtual void traverse(TIntermTraverser*); virtual TIntermSymbol* getAsSymbolNode() { return this; } diff --git a/glslang/MachineIndependent/linkValidate.cpp b/glslang/MachineIndependent/linkValidate.cpp old mode 100644 new mode 100755 index c540ae6..f99b5da --- a/glslang/MachineIndependent/linkValidate.cpp +++ b/glslang/MachineIndependent/linkValidate.cpp @@ -182,22 +182,132 @@ void TIntermediate::merge(TInfoSink& infoSink, TIntermediate& unit) } // Getting this far means we have two existing trees to merge... + mergeTree(infoSink, unit); version = std::max(version, unit.version); 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 TIntermSequence& globals = treeRoot->getAsAggregate()->getSequence(); TIntermSequence& unitGlobals = unit.treeRoot->getAsAggregate()->getSequence(); // Get the linker-object lists - TIntermSequence& linkerObjects = findLinkerObjects(); - TIntermSequence& unitLinkerObjects = unit.findLinkerObjects(); + TIntermSequence& linkerObjects = findLinkerObjects()->getSequence(); + 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 idMap; + int maxId; + seedIdMap(idMap, maxId); + remapIds(idMap, maxId + 1, unit); mergeBodies(infoSink, globals, unitGlobals); 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& 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& 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& 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& idMap; // over biggest id +}; + +// Initialize the the ID map with what we know of 'this' AST. +void TIntermediate::seedIdMap(TMap& 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& 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& idMap; + int idShift; +}; + +void TIntermediate::remapIds(const TMap& 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 - TIntermSequence& linkObjects = findLinkerObjects(); + TIntermSequence& linkObjects = findLinkerObjects()->getSequence(); for (size_t i = 0; i < linkObjects.size(); ++i) { const TType& type = linkObjects[i]->getAsTyped()->getType(); 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 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 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. @@ -734,7 +844,7 @@ TIntermSequence& TIntermediate::findLinkerObjects() const // is more useful, and perhaps the spec should be changed to reflect that. bool TIntermediate::userOutputUsed() const { - const TIntermSequence& linkerObjects = findLinkerObjects(); + const TIntermSequence& linkerObjects = findLinkerObjects()->getSequence(); bool found = false; for (size_t i = 0; i < linkerObjects.size(); ++i) { diff --git a/glslang/MachineIndependent/localintermediate.h b/glslang/MachineIndependent/localintermediate.h index f3a0e41..e593fcd 100755 --- a/glslang/MachineIndependent/localintermediate.h +++ b/glslang/MachineIndependent/localintermediate.h @@ -645,6 +645,9 @@ protected: TIntermSymbol* addSymbol(int Id, const TString&, const TType&, const TConstUnionArray&, TIntermTyped* subtree, const TSourceLoc&); void error(TInfoSink& infoSink, const char*); void warn(TInfoSink& infoSink, const char*); + void mergeTree(TInfoSink&, TIntermediate&); + void seedIdMap(TMap& idMap, int& maxId); + void remapIds(const TMap& idMap, int idShift, TIntermediate&); void mergeBodies(TInfoSink&, TIntermSequence& globals, const TIntermSequence& unitGlobals); void mergeLinkerObjects(TInfoSink&, TIntermSequence& linkerObjects, const TIntermSequence& unitLinkerObjects); void mergeImplicitArraySizes(TType&, const TType&); @@ -652,7 +655,7 @@ protected: void checkCallGraphCycles(TInfoSink&); void checkCallGraphBodies(TInfoSink&, bool keepUncalled); void inOutLocationCheck(TInfoSink&); - TIntermSequence& findLinkerObjects() const; + TIntermAggregate* findLinkerObjects() const; bool userOutputUsed() const; bool isSpecializationOperation(const TIntermOperator&) const; bool isNonuniformPropagating(TOperator) const; diff --git a/gtests/Link.FromFile.Vk.cpp b/gtests/Link.FromFile.Vk.cpp old mode 100644 new mode 100755 index 0a616d8..beb79e1 --- a/gtests/Link.FromFile.Vk.cpp +++ b/gtests/Link.FromFile.Vk.cpp @@ -106,6 +106,7 @@ INSTANTIATE_TEST_CASE_P( Glsl, LinkTestVulkan, ::testing::ValuesIn(std::vector>({ {"link1.vk.frag", "link2.vk.frag"}, + {"spv.unit1.frag", "spv.unit2.frag", "spv.unit3.frag"}, })), ); // clang-format on -- 2.7.4