// // 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" 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) { if (mUnrollCondition == kIntegerIndex) { // Check if loop index type is integer. // This is called after ValidateLimitations pass, so all the calls // should be valid. See ValidateLimitations::validateForLoopInit(). TIntermSequence *declSeq = node->getInit()->getAsAggregate()->getSequence(); TIntermSymbol *symbol = (*declSeq)[0]->getAsBinaryNode()->getLeft()->getAsSymbolNode(); if (symbol->getBasicType() == EbtInt) node->setUnrollFlag(true); } TIntermNode *body = node->getBody(); if (body != NULL) { mLoopStack.push(node); body->traverse(this); mLoopStack.pop(); } // 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(); } } }