summaryrefslogtreecommitdiffstats
path: root/gfx/angle/src/compiler/translator/ForLoopUnroll.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'gfx/angle/src/compiler/translator/ForLoopUnroll.cpp')
-rwxr-xr-xgfx/angle/src/compiler/translator/ForLoopUnroll.cpp102
1 files changed, 102 insertions, 0 deletions
diff --git a/gfx/angle/src/compiler/translator/ForLoopUnroll.cpp b/gfx/angle/src/compiler/translator/ForLoopUnroll.cpp
new file mode 100755
index 000000000..58cce845f
--- /dev/null
+++ b/gfx/angle/src/compiler/translator/ForLoopUnroll.cpp
@@ -0,0 +1,102 @@
+//
+// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/translator/ForLoopUnroll.h"
+
+#include "compiler/translator/ValidateLimitations.h"
+#include "angle_gl.h"
+
+namespace sh
+{
+
+bool ForLoopUnrollMarker::visitBinary(Visit, TIntermBinary *node)
+{
+ if (mUnrollCondition != kSamplerArrayIndex)
+ return true;
+
+ // If a sampler array index is also the loop index,
+ // 1) if the index type is integer, mark the loop for unrolling;
+ // 2) if the index type if float, set a flag to later fail compile.
+ switch (node->getOp())
+ {
+ case EOpIndexIndirect:
+ if (node->getLeft() != NULL && node->getRight() != NULL && node->getLeft()->getAsSymbolNode())
+ {
+ TIntermSymbol *symbol = node->getLeft()->getAsSymbolNode();
+ if (IsSampler(symbol->getBasicType()) && symbol->isArray() && !mLoopStack.empty())
+ {
+ mVisitSamplerArrayIndexNodeInsideLoop = true;
+ node->getRight()->traverse(this);
+ mVisitSamplerArrayIndexNodeInsideLoop = false;
+ // We have already visited all the children.
+ return false;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ return true;
+}
+
+bool ForLoopUnrollMarker::visitLoop(Visit, TIntermLoop *node)
+{
+ bool canBeUnrolled = mHasRunLoopValidation;
+ if (!mHasRunLoopValidation)
+ {
+ canBeUnrolled = ValidateLimitations::IsLimitedForLoop(node);
+ }
+ if (mUnrollCondition == kIntegerIndex && canBeUnrolled)
+ {
+ // Check if loop index type is integer.
+ // This is called after ValidateLimitations pass, so the loop has the limited form specified
+ // in ESSL 1.00 appendix A.
+ TIntermSequence *declSeq = node->getInit()->getAsDeclarationNode()->getSequence();
+ TIntermSymbol *symbol = (*declSeq)[0]->getAsBinaryNode()->getLeft()->getAsSymbolNode();
+ if (symbol->getBasicType() == EbtInt)
+ node->setUnrollFlag(true);
+ }
+
+ TIntermNode *body = node->getBody();
+ if (body != nullptr)
+ {
+ if (canBeUnrolled)
+ {
+ mLoopStack.push(node);
+ body->traverse(this);
+ mLoopStack.pop();
+ }
+ else
+ {
+ body->traverse(this);
+ }
+ }
+ // The loop is fully processed - no need to visit children.
+ return false;
+}
+
+void ForLoopUnrollMarker::visitSymbol(TIntermSymbol* symbol)
+{
+ if (!mVisitSamplerArrayIndexNodeInsideLoop)
+ return;
+ TIntermLoop *loop = mLoopStack.findLoop(symbol);
+ if (loop)
+ {
+ switch (symbol->getBasicType())
+ {
+ case EbtFloat:
+ mSamplerArrayIndexIsFloatLoopIndex = true;
+ break;
+ case EbtInt:
+ loop->setUnrollFlag(true);
+ break;
+ default:
+ UNREACHABLE();
+ }
+ }
+}
+
+} // namespace sh