| // |
| // 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(); |
| } |
| } |
| } |