summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/glslang/glslang/MachineIndependent/LiveTraverser.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/3rdparty/glslang/glslang/MachineIndependent/LiveTraverser.h')
-rw-r--r--src/3rdparty/glslang/glslang/MachineIndependent/LiveTraverser.h138
1 files changed, 138 insertions, 0 deletions
diff --git a/src/3rdparty/glslang/glslang/MachineIndependent/LiveTraverser.h b/src/3rdparty/glslang/glslang/MachineIndependent/LiveTraverser.h
new file mode 100644
index 0000000..7333bc9
--- /dev/null
+++ b/src/3rdparty/glslang/glslang/MachineIndependent/LiveTraverser.h
@@ -0,0 +1,138 @@
+//
+// Copyright (C) 2016 LunarG, Inc.
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+
+#pragma once
+
+#include "../Include/Common.h"
+#include "reflection.h"
+#include "localintermediate.h"
+
+#include "gl_types.h"
+
+#include <list>
+#include <unordered_set>
+
+namespace glslang {
+
+//
+// The traverser: mostly pass through, except
+// - processing function-call nodes to push live functions onto the stack of functions to process
+// - processing selection nodes to trim semantically dead code
+//
+// This is in the glslang namespace directly so it can be a friend of TReflection.
+// This can be derived from to implement reflection database traversers or
+// binding mappers: anything that wants to traverse the live subset of the tree.
+//
+
+class TLiveTraverser : public TIntermTraverser {
+public:
+ TLiveTraverser(const TIntermediate& i, bool traverseAll = false,
+ bool preVisit = true, bool inVisit = false, bool postVisit = false) :
+ TIntermTraverser(preVisit, inVisit, postVisit),
+ intermediate(i), traverseAll(traverseAll)
+ { }
+
+ //
+ // Given a function name, find its subroot in the tree, and push it onto the stack of
+ // functions left to process.
+ //
+ void pushFunction(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() == EOpFunction && candidate->getName() == name) {
+ functions.push_back(candidate);
+ break;
+ }
+ }
+ }
+
+ typedef std::list<TIntermAggregate*> TFunctionStack;
+ TFunctionStack functions;
+
+protected:
+ // To catch which function calls are not dead, and hence which functions must be visited.
+ virtual bool visitAggregate(TVisit, TIntermAggregate* node)
+ {
+ if (!traverseAll)
+ if (node->getOp() == EOpFunctionCall)
+ addFunctionCall(node);
+
+ return true; // traverse this subtree
+ }
+
+ // To prune semantically dead paths.
+ virtual bool visitSelection(TVisit /* visit */, TIntermSelection* node)
+ {
+ if (traverseAll)
+ return true; // traverse all code
+
+ TIntermConstantUnion* constant = node->getCondition()->getAsConstantUnion();
+ if (constant) {
+ // cull the path that is dead
+ if (constant->getConstArray()[0].getBConst() == true && node->getTrueBlock())
+ node->getTrueBlock()->traverse(this);
+ if (constant->getConstArray()[0].getBConst() == false && node->getFalseBlock())
+ node->getFalseBlock()->traverse(this);
+
+ return false; // don't traverse any more, we did it all above
+ } else
+ return true; // traverse the whole subtree
+ }
+
+ // Track live functions as well as uniforms, so that we don't visit dead functions
+ // and only visit each function once.
+ void addFunctionCall(TIntermAggregate* call)
+ {
+ // // 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());
+ }
+ }
+
+ const TIntermediate& intermediate;
+ typedef std::unordered_set<TString> TLiveFunctions;
+ TLiveFunctions liveFunctions;
+ bool traverseAll;
+
+private:
+ // prevent copy & copy construct
+ TLiveTraverser(TLiveTraverser&);
+ TLiveTraverser& operator=(TLiveTraverser&);
+};
+
+} // namespace glslang