Source/ThirdParty/ANGLE/src/compiler/OutputHLSL.cpp
bool OutputHLSL::handleExcessiveLoop(TIntermLoop *node)
{
    TInfoSinkBase &out = mBody;

    // Parse loops of the form:
    // for(int index = initial; index [comparator] limit; index += increment)
    TIntermSymbol *index = NULL;
    TOperator comparator = EOpNull;
    int initial = 0;
    int limit = 0;
    int increment = 0;

    // Parse index name and intial value
    if (node->getInit())
    {
        TIntermAggregate *init = node->getInit()->getAsAggregate();

        if (init)
        {
            TIntermSequence &sequence = init->getSequence();
            TIntermTyped *variable = sequence[0]->getAsTyped();

            if (variable && variable->getQualifier() == EvqTemporary)
            {
                TIntermBinary *assign = variable->getAsBinaryNode();

                if (assign->getOp() == EOpInitialize)
                {
                    TIntermSymbol *symbol = assign->getLeft()->getAsSymbolNode();
                    TIntermConstantUnion *constant = assign->getRight()->getAsConstantUnion();

                    if (symbol && constant)
                    {
                        if (constant->getBasicType() == EbtInt && constant->getNominalSize() == 1)
                        {
                            index = symbol;
                            initial = constant->getUnionArrayPointer()[0].getIConst();
                        }
                    }
                }
            }
        }
    }

    // Parse comparator and limit value
    if (index != NULL && node->getCondition())
    {
        TIntermBinary *test = node->getCondition()->getAsBinaryNode();
        
        if (test && test->getLeft()->getAsSymbolNode()->getId() == index->getId())
        {
            TIntermConstantUnion *constant = test->getRight()->getAsConstantUnion();

            if (constant)
            {
                if (constant->getBasicType() == EbtInt && constant->getNominalSize() == 1)
                {
                    comparator = test->getOp();
                    limit = constant->getUnionArrayPointer()[0].getIConst();
                }
            }
        }
    }

    // Parse increment
    if (index != NULL && comparator != EOpNull && node->getExpression())
    {
        TIntermBinary *binaryTerminal = node->getExpression()->getAsBinaryNode();
        TIntermUnary *unaryTerminal = node->getExpression()->getAsUnaryNode();
        
        if (binaryTerminal)
        {
            TOperator op = binaryTerminal->getOp();
            TIntermConstantUnion *constant = binaryTerminal->getRight()->getAsConstantUnion();

            if (constant)
            {
                if (constant->getBasicType() == EbtInt && constant->getNominalSize() == 1)
                {
                    int value = constant->getUnionArrayPointer()[0].getIConst();

                    switch (op)
                    {
                      case EOpAddAssign: increment = value;  break;
                      case EOpSubAssign: increment = -value; break;
                      default: UNIMPLEMENTED();
                    }
                }
            }
        }
        else if (unaryTerminal)
        {
            TOperator op = unaryTerminal->getOp();

            switch (op)
            {
              case EOpPostIncrement: increment = 1;  break;
              case EOpPostDecrement: increment = -1; break;
              case EOpPreIncrement:  increment = 1;  break;
              case EOpPreDecrement:  increment = -1; break;
              default: UNIMPLEMENTED();
            }
        }
    }

    if (index != NULL && comparator != EOpNull && increment != 0)
    {
        if (comparator == EOpLessThanEqual)
        {
            comparator = EOpLessThan;
            limit += 1;
        }

        if (comparator == EOpLessThan)
        {
            int iterations = (limit - initial + 1) / increment;

            if (iterations <= 255)
            {
                return false;   // Not an excessive loop
            }

            while (iterations > 0)
            {
                int remainder = (limit - initial + 1) % increment;
                int clampedLimit = initial + increment * std::min(255, iterations) - 1 - remainder;

                // for(int index = initial; index < clampedLimit; index += increment)

                out << "for(int ";
                index->traverse(this);
                out << " = ";
                out << initial;

                out << "; ";
                index->traverse(this);
                out << " < ";
                out << clampedLimit;

                out << "; ";
                index->traverse(this);
                out << " += ";
                out << increment;
                out << ")\n"
                       "{\n";

                if (node->getBody())
                {
                    node->getBody()->traverse(this);
                }

                out << "}\n";

                initial += 255 * increment;
                iterations -= 255;
            }

            return true;
        }
        else UNIMPLEMENTED();
    }

    return false;   // Not handled as an excessive loop
}
// Handle loops with more than 255 iterations (unsupported by D3D9) by splitting them
Handle loops with more than 255 iterations (unsupported by D3D9) by splitting them
Handle loops with more than 255 iterations ( unsupported by D3D9 ) by splitting them
bool OutputHLSL::handleExcessiveLoop(TIntermLoop *node)
{
    TInfoSinkBase &out = mBody;
    TIntermSymbol *index = NULL;
    TOperator comparator = EOpNull;
    int initial = 0;
    int limit = 0;
    int increment = 0;
    if (node->getInit())
    {
        TIntermAggregate *init = node->getInit()->getAsAggregate();
        if (init)
        {
            TIntermSequence &sequence = init->getSequence();
            TIntermTyped *variable = sequence[0]->getAsTyped();
            if (variable && variable->getQualifier() == EvqTemporary)
            {
                TIntermBinary *assign = variable->getAsBinaryNode();
                if (assign->getOp() == EOpInitialize)
                {
                    TIntermSymbol *symbol = assign->getLeft()->getAsSymbolNode();
                    TIntermConstantUnion *constant = assign->getRight()->getAsConstantUnion();
                    if (symbol && constant)
                    {
                        if (constant->getBasicType() == EbtInt && constant->getNominalSize() == 1)
                        {
                            index = symbol;
                            initial = constant->getUnionArrayPointer()[0].getIConst();
                        }
                    }
                }
            }
        }
    }
    if (index != NULL && node->getCondition())
    {
        TIntermBinary *test = node->getCondition()->getAsBinaryNode();
        if (test && test->getLeft()->getAsSymbolNode()->getId() == index->getId())
        {
            TIntermConstantUnion *constant = test->getRight()->getAsConstantUnion();
            if (constant)
            {
                if (constant->getBasicType() == EbtInt && constant->getNominalSize() == 1)
                {
                    comparator = test->getOp();
                    limit = constant->getUnionArrayPointer()[0].getIConst();
                }
            }
        }
    }
    if (index != NULL && comparator != EOpNull && node->getExpression())
    {
        TIntermBinary *binaryTerminal = node->getExpression()->getAsBinaryNode();
        TIntermUnary *unaryTerminal = node->getExpression()->getAsUnaryNode();
        if (binaryTerminal)
        {
            TOperator op = binaryTerminal->getOp();
            TIntermConstantUnion *constant = binaryTerminal->getRight()->getAsConstantUnion();
            if (constant)
            {
                if (constant->getBasicType() == EbtInt && constant->getNominalSize() == 1)
                {
                    int value = constant->getUnionArrayPointer()[0].getIConst();
                    switch (op)
                    {
                      case EOpAddAssign: increment = value;  break;
                      case EOpSubAssign: increment = -value; break;
                      default: UNIMPLEMENTED();
                    }
                }
            }
        }
        else if (unaryTerminal)
        {
            TOperator op = unaryTerminal->getOp();
            switch (op)
            {
              case EOpPostIncrement: increment = 1;  break;
              case EOpPostDecrement: increment = -1; break;
              case EOpPreIncrement:  increment = 1;  break;
              case EOpPreDecrement:  increment = -1; break;
              default: UNIMPLEMENTED();
            }
        }
    }
    if (index != NULL && comparator != EOpNull && increment != 0)
    {
        if (comparator == EOpLessThanEqual)
        {
            comparator = EOpLessThan;
            limit += 1;
        }
        if (comparator == EOpLessThan)
        {
            int iterations = (limit - initial + 1) / increment;
            if (iterations <= 255)
            {
                return false;   
            }
            while (iterations > 0)
            {
                int remainder = (limit - initial + 1) % increment;
                int clampedLimit = initial + increment * std::min(255, iterations) - 1 - remainder;
                out << "for(int ";
                index->traverse(this);
                out << " = ";
                out << initial;
                out << "; ";
                index->traverse(this);
                out << " < ";
                out << clampedLimit;
                out << "; ";
                index->traverse(this);
                out << " += ";
                out << increment;
                out << ")\n"
                       "{\n";
                if (node->getBody())
                {
                    node->getBody()->traverse(this);
                }
                out << "}\n";
                initial += 255 * increment;
                iterations -= 255;
            }
            return true;
        }
        else UNIMPLEMENTED();
    }
    return false;   
}
bool OutputHLSL :: handleExcessiveLoop ( TIntermLoop * node ) { TInfoSinkBase & out = mBody ; TIntermSymbol * index = NULL ; TOperator comparator = EOpNull ; int initial = 0 ; int limit = 0 ; int increment = 0 ; if ( node -> getInit ( ) ) { TIntermAggregate * init = node -> getInit ( ) -> getAsAggregate ( ) ; if ( init ) { TIntermSequence & sequence = init -> getSequence ( ) ; TIntermTyped * variable = sequence [ 0 ] -> getAsTyped ( ) ; if ( variable && variable -> getQualifier ( ) == EvqTemporary ) { TIntermBinary * assign = variable -> getAsBinaryNode ( ) ; if ( assign -> getOp ( ) == EOpInitialize ) { TIntermSymbol * symbol = assign -> getLeft ( ) -> getAsSymbolNode ( ) ; TIntermConstantUnion * constant = assign -> getRight ( ) -> getAsConstantUnion ( ) ; if ( symbol && constant ) { if ( constant -> getBasicType ( ) == EbtInt && constant -> getNominalSize ( ) == 1 ) { index = symbol ; initial = constant -> getUnionArrayPointer ( ) [ 0 ] . getIConst ( ) ; } } } } } } if ( index != NULL && node -> getCondition ( ) ) { TIntermBinary * test = node -> getCondition ( ) -> getAsBinaryNode ( ) ; if ( test && test -> getLeft ( ) -> getAsSymbolNode ( ) -> getId ( ) == index -> getId ( ) ) { TIntermConstantUnion * constant = test -> getRight ( ) -> getAsConstantUnion ( ) ; if ( constant ) { if ( constant -> getBasicType ( ) == EbtInt && constant -> getNominalSize ( ) == 1 ) { comparator = test -> getOp ( ) ; limit = constant -> getUnionArrayPointer ( ) [ 0 ] . getIConst ( ) ; } } } } if ( index != NULL && comparator != EOpNull && node -> getExpression ( ) ) { TIntermBinary * binaryTerminal = node -> getExpression ( ) -> getAsBinaryNode ( ) ; TIntermUnary * unaryTerminal = node -> getExpression ( ) -> getAsUnaryNode ( ) ; if ( binaryTerminal ) { TOperator op = binaryTerminal -> getOp ( ) ; TIntermConstantUnion * constant = binaryTerminal -> getRight ( ) -> getAsConstantUnion ( ) ; if ( constant ) { if ( constant -> getBasicType ( ) == EbtInt && constant -> getNominalSize ( ) == 1 ) { int value = constant -> getUnionArrayPointer ( ) [ 0 ] . getIConst ( ) ; switch ( op ) { case EOpAddAssign : increment = value ; break ; case EOpSubAssign : increment = - value ; break ; default : UNIMPLEMENTED ( ) ; } } } } else if ( unaryTerminal ) { TOperator op = unaryTerminal -> getOp ( ) ; switch ( op ) { case EOpPostIncrement : increment = 1 ; break ; case EOpPostDecrement : increment = -1 ; break ; case EOpPreIncrement : increment = 1 ; break ; case EOpPreDecrement : increment = -1 ; break ; default : UNIMPLEMENTED ( ) ; } } } if ( index != NULL && comparator != EOpNull && increment != 0 ) { if ( comparator == EOpLessThanEqual ) { comparator = EOpLessThan ; limit += 1 ; } if ( comparator == EOpLessThan ) { int iterations = ( limit - initial + 1 ) / increment ; if ( iterations <= 255 ) { return false ; } while ( iterations > 0 ) { int remainder = ( limit - initial + 1 ) % increment ; int clampedLimit = initial + increment * std :: min ( 255 , iterations ) - 1 - remainder ; out << " " ; index -> traverse ( this ) ; out << " " ; out << initial ; out << " " ; index -> traverse ( this ) ; out << " " ; out << clampedLimit ; out << " " ; index -> traverse ( this ) ; out << " " ; out << increment ; out << " \n " " \n " ; if ( node -> getBody ( ) ) { node -> getBody ( ) -> traverse ( this ) ; } out << " \n " ; initial += 255 * increment ; iterations -= 255 ; } return true ; } else UNIMPLEMENTED ( ) ; } return false ; }
Handle loops with more than 255 iterations (unsupported by D3D9) by splitting them
Handle loops with more than 255 iterations ( unsupported by D3D9 ) by splitting them
// Parse loops of the form: // for(int index = initial; index [comparator] limit; index += increment) // Parse index name and intial value // Parse comparator and limit value // Parse increment // Not an excessive loop // for(int index = initial; index < clampedLimit; index += increment) // Not handled as an excessive loop