From 5727fb313e5d618374f43de8dc9b59d0b7669340 Mon Sep 17 00:00:00 2001 From: Malcolm Bechard Date: Tue, 14 Jul 2020 12:59:57 -0400 Subject: [PATCH] also search global variables assignment for live variables when traversing the AST to find live UBOs etc, also traverse references to global module-level variables, incase they are being filled in from UBOs etc. --- glslang/MachineIndependent/LiveTraverser.h | 38 +++++++++++++++++++--- glslang/MachineIndependent/iomapper.cpp | 23 ++++++++----- 2 files changed, 49 insertions(+), 12 deletions(-) diff --git a/glslang/MachineIndependent/LiveTraverser.h b/glslang/MachineIndependent/LiveTraverser.h index 7333bc96..9b39b598 100644 --- a/glslang/MachineIndependent/LiveTraverser.h +++ b/glslang/MachineIndependent/LiveTraverser.h @@ -74,14 +74,33 @@ public: for (unsigned int f = 0; f < globals.size(); ++f) { TIntermAggregate* candidate = globals[f]->getAsAggregate(); if (candidate && candidate->getOp() == EOpFunction && candidate->getName() == name) { - functions.push_back(candidate); + destinations.push_back(candidate); break; } } } - typedef std::list TFunctionStack; - TFunctionStack functions; + void pushGlobalReference(const TString& name) + { + TIntermSequence& globals = intermediate.getTreeRoot()->getAsAggregate()->getSequence(); + for (unsigned int f = 0; f < globals.size(); ++f) { + TIntermAggregate* candidate = globals[f]->getAsAggregate(); + if (candidate && candidate->getOp() == EOpSequence && + candidate->getSequence().size() == 1 && + candidate->getSequence()[0]->getAsBinaryNode()) { + TIntermBinary* binary = candidate->getSequence()[0]->getAsBinaryNode(); + TIntermSymbol* symbol = binary->getLeft()->getAsSymbolNode(); + if (symbol && symbol->getQualifier().storage == EvqGlobal && + symbol->getName() == name) { + destinations.push_back(candidate); + break; + } + } + } + } + + typedef std::list TDestinationStack; + TDestinationStack destinations; protected: // To catch which function calls are not dead, and hence which functions must be visited. @@ -117,16 +136,27 @@ protected: // and only visit each function once. void addFunctionCall(TIntermAggregate* call) { - // // just use the map to ensure we process each function at most once + // just use the map to ensure we process each function at most once if (liveFunctions.find(call->getName()) == liveFunctions.end()) { liveFunctions.insert(call->getName()); pushFunction(call->getName()); } } + void addGlobalReference(const TString& name) + { + // just use the map to ensure we process each global at most once + if (liveGlobals.find(name) == liveGlobals.end()) { + liveGlobals.insert(name); + pushGlobalReference(name); + } + } + const TIntermediate& intermediate; typedef std::unordered_set TLiveFunctions; TLiveFunctions liveFunctions; + typedef std::unordered_set TLiveGlobals; + TLiveGlobals liveGlobals; bool traverseAll; private: diff --git a/glslang/MachineIndependent/iomapper.cpp b/glslang/MachineIndependent/iomapper.cpp index fadcb1bf..9859f083 100644 --- a/glslang/MachineIndependent/iomapper.cpp +++ b/glslang/MachineIndependent/iomapper.cpp @@ -79,6 +79,11 @@ public: target = &outputList; else if (base->getQualifier().isUniformOrBuffer() && !base->getQualifier().isPushConstant()) target = &uniformList; + // If a global is being visited, then we should also traverse it incase it's evaluation + // ends up visiting inputs we want to tag as live + else if (base->getQualifier().storage == EvqGlobal) + addGlobalReference(base->getName()); + if (target) { TVarEntryInfo ent = {base->getId(), base, ! traverseAll}; ent.stage = intermediate.getStage(); @@ -1105,11 +1110,12 @@ bool TIoMapper::addStage(EShLanguage stage, TIntermediate& intermediate, TInfoSi TVarGatherTraverser iter_binding_live(intermediate, false, inVarMap, outVarMap, uniformVarMap); root->traverse(&iter_binding_all); iter_binding_live.pushFunction(intermediate.getEntryPointMangledName().c_str()); - while (! iter_binding_live.functions.empty()) { - TIntermNode* function = iter_binding_live.functions.back(); - iter_binding_live.functions.pop_back(); - function->traverse(&iter_binding_live); + while (! iter_binding_live.destinations.empty()) { + TIntermNode* destination = iter_binding_live.destinations.back(); + iter_binding_live.destinations.pop_back(); + destination->traverse(&iter_binding_live); } + // sort entries by priority. see TVarEntryInfo::TOrderByPriority for info. std::for_each(inVarMap.begin(), inVarMap.end(), [&inVector](TVarLivePair p) { inVector.push_back(p); }); @@ -1200,11 +1206,12 @@ bool TGlslIoMapper::addStage(EShLanguage stage, TIntermediate& intermediate, TIn *uniformVarMap[stage]); root->traverse(&iter_binding_all); iter_binding_live.pushFunction(intermediate.getEntryPointMangledName().c_str()); - while (! iter_binding_live.functions.empty()) { - TIntermNode* function = iter_binding_live.functions.back(); - iter_binding_live.functions.pop_back(); - function->traverse(&iter_binding_live); + while (! iter_binding_live.destinations.empty()) { + TIntermNode* destination = iter_binding_live.destinations.back(); + iter_binding_live.destinations.pop_back(); + destination->traverse(&iter_binding_live); } + TNotifyInOutAdaptor inOutNotify(stage, *resolver); TNotifyUniformAdaptor uniformNotify(stage, *resolver); // Resolve current stage input symbol location with previous stage output here,