예제 #1
0
bool TOutputGLSLBase::visitBranch(Visit visit, TIntermBranch* node)
{
    switch (node->getFlowOp())
    {
        case EOpKill: writeTriplet(visit, "discard", NULL, NULL); break;
        case EOpBreak: writeTriplet(visit, "break", NULL, NULL); break;
        case EOpContinue: writeTriplet(visit, "continue", NULL, NULL); break;
        case EOpReturn: writeTriplet(visit, "return ", NULL, NULL); break;
        default: UNREACHABLE(); break;
    }

    return true;
}
예제 #2
0
bool TOutputGLSLBase::visitSwitch(Visit visit, TIntermSwitch *node)
{
    if (node->getStatementList())
    {
        writeTriplet(visit, "switch (", ") ", nullptr);
        // The curly braces get written when visiting the statementList aggregate
    }
    else
    {
        // No statementList, so it won't output curly braces
        writeTriplet(visit, "switch (", ") {", "}\n");
    }
    return true;
}
예제 #3
0
void TOutputGLSLBase::writeBuiltInFunctionTriplet(
    Visit visit, const char *preStr, bool useEmulatedFunction)
{
    TString preString = useEmulatedFunction ?
        BuiltInFunctionEmulator::GetEmulatedFunctionName(preStr) : preStr;
    writeTriplet(visit, preString.c_str(), ", ", ")");
}
예제 #4
0
bool TOutputGLSLBase::visitCase(Visit visit, TIntermCase *node)
{
    if (node->hasCondition())
    {
        writeTriplet(visit, "case (", nullptr, "):\n");
        return true;
    }
    else
    {
        TInfoSinkBase &out = objSink();
        out << "default:\n";
        return false;
    }
}
예제 #5
0
void TOutputGLSLBase::writeConstructorTriplet(Visit visit, const TType &type, const char *constructorBaseType)
{
    TInfoSinkBase &out = objSink();
    if (visit == PreVisit)
    {
        if (type.isArray())
        {
            out << constructorBaseType;
            out << arrayBrackets(type);
            out << "(";
        }
        else
        {
            out << constructorBaseType << "(";
        }
    }
    else
    {
        writeTriplet(visit, nullptr, ", ", ")");
    }
}
예제 #6
0
bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate* node)
{
    bool visitChildren = true;
    TInfoSinkBase& out = objSink();
    TString preString;
    bool delayedWrite = false;
    switch (node->getOp())
    {
        case EOpSequence: {
            // Scope the sequences except when at the global scope.
            if (depth > 0) out << "{\n";

            incrementDepth();
            const TIntermSequence& sequence = node->getSequence();
            for (TIntermSequence::const_iterator iter = sequence.begin();
                 iter != sequence.end(); ++iter)
            {
                TIntermNode* node = *iter;
                ASSERT(node != NULL);
                node->traverse(this);

                if (isSingleStatement(node))
                    out << ";\n";
            }
            decrementDepth();

            // Scope the sequences except when at the global scope.
            if (depth > 0) out << "}\n";
            visitChildren = false;
            break;
        }
        case EOpPrototype: {
            // Function declaration.
            ASSERT(visit == PreVisit);
            writeVariableType(node->getType());
            out << " " << node->getName();

            out << "(";
            writeFunctionParameters(node->getSequence());
            out << ")";

            visitChildren = false;
            break;
        }
        case EOpFunction: {
            // Function definition.
            ASSERT(visit == PreVisit);
            writeVariableType(node->getType());
            out << " " << TFunction::unmangleName(node->getName());

            incrementDepth();
            // Function definition node contains one or two children nodes
            // representing function parameters and function body. The latter
            // is not present in case of empty function bodies.
            const TIntermSequence& sequence = node->getSequence();
            ASSERT((sequence.size() == 1) || (sequence.size() == 2));
            TIntermSequence::const_iterator seqIter = sequence.begin();

            // Traverse function parameters.
            TIntermAggregate* params = (*seqIter)->getAsAggregate();
            ASSERT(params != NULL);
            ASSERT(params->getOp() == EOpParameters);
            params->traverse(this);

            // Traverse function body.
            TIntermAggregate* body = ++seqIter != sequence.end() ?
                (*seqIter)->getAsAggregate() : NULL;
            visitCodeBlock(body);
            decrementDepth();
 
            // Fully processed; no need to visit children.
            visitChildren = false;
            break;
        }
        case EOpFunctionCall:
            // Function call.
            if (visit == PreVisit)
            {
                TString functionName = TFunction::unmangleName(node->getName());
                out << functionName << "(";
            }
            else if (visit == InVisit)
            {
                out << ", ";
            }
            else
            {
                out << ")";
            }
            break;
        case EOpParameters: {
            // Function parameters.
            ASSERT(visit == PreVisit);
            out << "(";
            writeFunctionParameters(node->getSequence());
            out << ")";
            visitChildren = false;
            break;
        }
        case EOpDeclaration: {
            // Variable declaration.
            if (visit == PreVisit)
            {
                const TIntermSequence& sequence = node->getSequence();
                const TIntermTyped* variable = sequence.front()->getAsTyped();
                writeVariableType(variable->getType());
                out << " ";
                mDeclaringVariables = true;
            }
            else if (visit == InVisit)
            {
                out << ", ";
                mDeclaringVariables = true;
            }
            else
            {
                mDeclaringVariables = false;
            }
            break;
        }
        case EOpConstructFloat: writeTriplet(visit, "float(", NULL, ")"); break;
        case EOpConstructVec2: writeTriplet(visit, "vec2(", ", ", ")"); break;
        case EOpConstructVec3: writeTriplet(visit, "vec3(", ", ", ")"); break;
        case EOpConstructVec4: writeTriplet(visit, "vec4(", ", ", ")"); break;
        case EOpConstructBool: writeTriplet(visit, "bool(", NULL, ")"); break;
        case EOpConstructBVec2: writeTriplet(visit, "bvec2(", ", ", ")"); break;
        case EOpConstructBVec3: writeTriplet(visit, "bvec3(", ", ", ")"); break;
        case EOpConstructBVec4: writeTriplet(visit, "bvec4(", ", ", ")"); break;
        case EOpConstructInt: writeTriplet(visit, "int(", NULL, ")"); break;
        case EOpConstructIVec2: writeTriplet(visit, "ivec2(", ", ", ")"); break;
        case EOpConstructIVec3: writeTriplet(visit, "ivec3(", ", ", ")"); break;
        case EOpConstructIVec4: writeTriplet(visit, "ivec4(", ", ", ")"); break;
        case EOpConstructMat2: writeTriplet(visit, "mat2(", ", ", ")"); break;
        case EOpConstructMat3: writeTriplet(visit, "mat3(", ", ", ")"); break;
        case EOpConstructMat4: writeTriplet(visit, "mat4(", ", ", ")"); break;
        case EOpConstructStruct:
            if (visit == PreVisit)
            {
                const TType& type = node->getType();
                ASSERT(type.getBasicType() == EbtStruct);
                out << type.getTypeName() << "(";
            }
            else if (visit == InVisit)
            {
                out << ", ";
            }
            else
            {
                out << ")";
            }
            break;

        case EOpLessThan: preString = "lessThan("; delayedWrite = true; break;
        case EOpGreaterThan: preString = "greaterThan("; delayedWrite = true; break;
        case EOpLessThanEqual: preString = "lessThanEqual("; delayedWrite = true; break;
        case EOpGreaterThanEqual: preString = "greaterThanEqual("; delayedWrite = true; break;
        case EOpVectorEqual: preString = "equal("; delayedWrite = true; break;
        case EOpVectorNotEqual: preString = "notEqual("; delayedWrite = true; break;
        case EOpComma: writeTriplet(visit, NULL, ", ", NULL); break;

        case EOpMod: preString = "mod("; delayedWrite = true; break;
        case EOpPow: preString = "pow("; delayedWrite = true; break;
        case EOpAtan: preString = "atan("; delayedWrite = true; break;
        case EOpMin: preString = "min("; delayedWrite = true; break;
        case EOpMax: preString = "max("; delayedWrite = true; break;
        case EOpClamp: preString = "clamp("; delayedWrite = true; break;
        case EOpMix: preString = "mix("; delayedWrite = true; break;
        case EOpStep: preString = "step("; delayedWrite = true; break;
        case EOpSmoothStep: preString = "smoothstep("; delayedWrite = true; break;

        case EOpDistance: preString = "distance("; delayedWrite = true; break;
        case EOpDot: preString = "dot("; delayedWrite = true; break;
        case EOpCross: preString = "cross("; delayedWrite = true; break;
        case EOpFaceForward: preString = "faceforward("; delayedWrite = true; break;
        case EOpReflect: preString = "reflect("; delayedWrite = true; break;
        case EOpRefract: preString = "refract("; delayedWrite = true; break;
        case EOpMul: preString = "matrixCompMult("; delayedWrite = true; break;

        default: UNREACHABLE(); break;
    }
    if (delayedWrite && visit == PreVisit && node->getUseEmulatedFunction())
        preString = BuiltInFunctionEmulator::GetEmulatedFunctionName(preString);
    if (delayedWrite)
        writeTriplet(visit, preString.c_str(), ", ", ")");
    return visitChildren;
}
예제 #7
0
bool TOutputGLSLBase::visitUnary(Visit visit, TIntermUnary* node)
{
    TString preString;
    TString postString = ")";

    switch (node->getOp())
    {
        case EOpNegative: preString = "(-"; break;
        case EOpVectorLogicalNot: preString = "not("; break;
        case EOpLogicalNot: preString = "(!"; break;

        case EOpPostIncrement: preString = "("; postString = "++)"; break;
        case EOpPostDecrement: preString = "("; postString = "--)"; break;
        case EOpPreIncrement: preString = "(++"; break;
        case EOpPreDecrement: preString = "(--"; break;

        case EOpConvIntToBool:
        case EOpConvFloatToBool:
            switch (node->getOperand()->getType().getNominalSize())
            {
                case 1: preString =  "bool(";  break;
                case 2: preString = "bvec2("; break;
                case 3: preString = "bvec3("; break;
                case 4: preString = "bvec4("; break;
                default: UNREACHABLE();
            }
            break;
        case EOpConvBoolToFloat:
        case EOpConvIntToFloat:
            switch (node->getOperand()->getType().getNominalSize())
            {
                case 1: preString = "float(";  break;
                case 2: preString = "vec2("; break;
                case 3: preString = "vec3("; break;
                case 4: preString = "vec4("; break;
                default: UNREACHABLE();
            }
            break;
        case EOpConvFloatToInt:
        case EOpConvBoolToInt:
            switch (node->getOperand()->getType().getNominalSize())
            {
                case 1: preString = "int(";  break;
                case 2: preString = "ivec2("; break;
                case 3: preString = "ivec3("; break;
                case 4: preString = "ivec4("; break;
                default: UNREACHABLE();
            }
            break;

        case EOpRadians: preString = "radians("; break;
        case EOpDegrees: preString = "degrees("; break;
        case EOpSin: preString = "sin("; break;
        case EOpCos: preString = "cos("; break;
        case EOpTan: preString = "tan("; break;
        case EOpAsin: preString = "asin("; break;
        case EOpAcos: preString = "acos("; break;
        case EOpAtan: preString = "atan("; break;

        case EOpExp: preString = "exp("; break;
        case EOpLog: preString = "log("; break;
        case EOpExp2: preString = "exp2("; break;
        case EOpLog2: preString = "log2("; break;
        case EOpSqrt: preString = "sqrt("; break;
        case EOpInverseSqrt: preString = "inversesqrt("; break;

        case EOpAbs: preString = "abs("; break;
        case EOpSign: preString = "sign("; break;
        case EOpFloor: preString = "floor("; break;
        case EOpCeil: preString = "ceil("; break;
        case EOpFract: preString = "fract("; break;

        case EOpLength: preString = "length("; break;
        case EOpNormalize: preString = "normalize("; break;

        case EOpDFdx: preString = "dFdx("; break;
        case EOpDFdy: preString = "dFdy("; break;
        case EOpFwidth: preString = "fwidth("; break;

        case EOpAny: preString = "any("; break;
        case EOpAll: preString = "all("; break;

        default: UNREACHABLE(); break;
    }

    if (visit == PreVisit && node->getUseEmulatedFunction())
        preString = BuiltInFunctionEmulator::GetEmulatedFunctionName(preString);
    writeTriplet(visit, preString.c_str(), NULL, postString.c_str());

    return true;
}
예제 #8
0
bool TOutputGLSLBase::visitBinary(Visit visit, TIntermBinary* node)
{
    bool visitChildren = true;
    TInfoSinkBase& out = objSink();
    switch (node->getOp())
    {
        case EOpInitialize:
            if (visit == InVisit)
            {
                out << " = ";
                // RHS of initialize is not being declared.
                mDeclaringVariables = false;
            }
            break;
        case EOpAssign: writeTriplet(visit, "(", " = ", ")"); break;
        case EOpAddAssign: writeTriplet(visit, "(", " += ", ")"); break;
        case EOpSubAssign: writeTriplet(visit, "(", " -= ", ")"); break;
        case EOpDivAssign: writeTriplet(visit, "(", " /= ", ")"); break;
        // Notice the fall-through.
        case EOpMulAssign: 
        case EOpVectorTimesMatrixAssign:
        case EOpVectorTimesScalarAssign:
        case EOpMatrixTimesScalarAssign:
        case EOpMatrixTimesMatrixAssign:
            writeTriplet(visit, "(", " *= ", ")");
            break;

        case EOpIndexDirect:
        case EOpIndexIndirect:
            writeTriplet(visit, NULL, "[", "]");
            break;
        case EOpIndexDirectStruct:
            if (visit == InVisit)
            {
                out << ".";
                // TODO(alokp): ASSERT
                out << node->getType().getFieldName();
                visitChildren = false;
            }
            break;
        case EOpVectorSwizzle:
            if (visit == InVisit)
            {
                out << ".";
                TIntermAggregate* rightChild = node->getRight()->getAsAggregate();
                TIntermSequence& sequence = rightChild->getSequence();
                for (TIntermSequence::iterator sit = sequence.begin(); sit != sequence.end(); ++sit)
                {
                    TIntermConstantUnion* element = (*sit)->getAsConstantUnion();
                    ASSERT(element->getBasicType() == EbtInt);
                    ASSERT(element->getNominalSize() == 1);
                    const ConstantUnion& data = element->getUnionArrayPointer()[0];
                    ASSERT(data.getType() == EbtInt);
                    switch (data.getIConst())
                    {
                        case 0: out << "x"; break;
                        case 1: out << "y"; break;
                        case 2: out << "z"; break;
                        case 3: out << "w"; break;
                        default: UNREACHABLE(); break;
                    }
                }
                visitChildren = false;
            }
            break;

        case EOpAdd: writeTriplet(visit, "(", " + ", ")"); break;
        case EOpSub: writeTriplet(visit, "(", " - ", ")"); break;
        case EOpMul: writeTriplet(visit, "(", " * ", ")"); break;
        case EOpDiv: writeTriplet(visit, "(", " / ", ")"); break;
        case EOpMod: UNIMPLEMENTED(); break;
        case EOpEqual: writeTriplet(visit, "(", " == ", ")"); break;
        case EOpNotEqual: writeTriplet(visit, "(", " != ", ")"); break;
        case EOpLessThan: writeTriplet(visit, "(", " < ", ")"); break;
        case EOpGreaterThan: writeTriplet(visit, "(", " > ", ")"); break;
        case EOpLessThanEqual: writeTriplet(visit, "(", " <= ", ")"); break;
        case EOpGreaterThanEqual: writeTriplet(visit, "(", " >= ", ")"); break;

        // Notice the fall-through.
        case EOpVectorTimesScalar:
        case EOpVectorTimesMatrix:
        case EOpMatrixTimesVector:
        case EOpMatrixTimesScalar:
        case EOpMatrixTimesMatrix:
            writeTriplet(visit, "(", " * ", ")");
            break;

        case EOpLogicalOr: writeTriplet(visit, "(", " || ", ")"); break;
        case EOpLogicalXor: writeTriplet(visit, "(", " ^^ ", ")"); break;
        case EOpLogicalAnd: writeTriplet(visit, "(", " && ", ")"); break;
        default: UNREACHABLE(); break;
    }

    return visitChildren;
}
예제 #9
0
bool TOutputGLSLBase::visitBinary(Visit visit, TIntermBinary* node)
{
    bool visitChildren = true;
    TInfoSinkBase& out = objSink();
    switch (node->getOp())
    {
        case EOpInitialize:
            if (visit == InVisit)
            {
                out << " = ";
                // RHS of initialize is not being declared.
                mDeclaringVariables = false;
            }
            break;
        case EOpAssign: writeTriplet(visit, "(", " = ", ")"); break;
        case EOpAddAssign: writeTriplet(visit, "(", " += ", ")"); break;
        case EOpSubAssign: writeTriplet(visit, "(", " -= ", ")"); break;
        case EOpDivAssign: writeTriplet(visit, "(", " /= ", ")"); break;
        // Notice the fall-through.
        case EOpMulAssign: 
        case EOpVectorTimesMatrixAssign:
        case EOpVectorTimesScalarAssign:
        case EOpMatrixTimesScalarAssign:
        case EOpMatrixTimesMatrixAssign:
            writeTriplet(visit, "(", " *= ", ")");
            break;

        case EOpIndexDirect:
            writeTriplet(visit, NULL, "[", "]");
            break;
        case EOpIndexIndirect:
            if (node->getAddIndexClamp())
            {
                if (visit == InVisit)
                {
                    if (mClampingStrategy == SH_CLAMP_WITH_CLAMP_INTRINSIC) {
                        out << "[int(clamp(float(";
                    } else {
                        out << "[webgl_int_clamp(";
                    }
                }
                else if (visit == PostVisit)
                {
                    int maxSize;
                    TIntermTyped *left = node->getLeft();
                    TType leftType = left->getType();

                    if (left->isArray())
                    {
                        // The shader will fail validation if the array length is not > 0.
                        maxSize = leftType.getArraySize() - 1;
                    }
                    else
                    {
                        maxSize = leftType.getNominalSize() - 1;
                    }

                    if (mClampingStrategy == SH_CLAMP_WITH_CLAMP_INTRINSIC) {
                        out << "), 0.0, float(" << maxSize << ")))]";
                    } else {
                        out << ", 0, " << maxSize << ")]";
                    }
                }
            }
            else
            {
                writeTriplet(visit, NULL, "[", "]");
            }
            break;
        case EOpIndexDirectStruct:
            if (visit == InVisit)
            {
                out << ".";
                // TODO(alokp): ASSERT
                TString fieldName = node->getType().getFieldName();

                const TType& structType = node->getLeft()->getType();
                if (!mSymbolTable.findBuiltIn(structType.getTypeName()))
                    fieldName = hashName(fieldName);

                out << fieldName;
                visitChildren = false;
            }
            break;
        case EOpVectorSwizzle:
            if (visit == InVisit)
            {
                out << ".";
                TIntermAggregate* rightChild = node->getRight()->getAsAggregate();
                TIntermSequence& sequence = rightChild->getSequence();
                for (TIntermSequence::iterator sit = sequence.begin(); sit != sequence.end(); ++sit)
                {
                    TIntermConstantUnion* element = (*sit)->getAsConstantUnion();
                    ASSERT(element->getBasicType() == EbtInt);
                    ASSERT(element->getNominalSize() == 1);
                    const ConstantUnion& data = element->getUnionArrayPointer()[0];
                    ASSERT(data.getType() == EbtInt);
                    switch (data.getIConst())
                    {
                        case 0: out << "x"; break;
                        case 1: out << "y"; break;
                        case 2: out << "z"; break;
                        case 3: out << "w"; break;
                        default: UNREACHABLE(); break;
                    }
                }
                visitChildren = false;
            }
            break;

        case EOpAdd: writeTriplet(visit, "(", " + ", ")"); break;
        case EOpSub: writeTriplet(visit, "(", " - ", ")"); break;
        case EOpMul: writeTriplet(visit, "(", " * ", ")"); break;
        case EOpDiv: writeTriplet(visit, "(", " / ", ")"); break;
        case EOpMod: UNIMPLEMENTED(); break;
        case EOpEqual: writeTriplet(visit, "(", " == ", ")"); break;
        case EOpNotEqual: writeTriplet(visit, "(", " != ", ")"); break;
        case EOpLessThan: writeTriplet(visit, "(", " < ", ")"); break;
        case EOpGreaterThan: writeTriplet(visit, "(", " > ", ")"); break;
        case EOpLessThanEqual: writeTriplet(visit, "(", " <= ", ")"); break;
        case EOpGreaterThanEqual: writeTriplet(visit, "(", " >= ", ")"); break;

        // Notice the fall-through.
        case EOpVectorTimesScalar:
        case EOpVectorTimesMatrix:
        case EOpMatrixTimesVector:
        case EOpMatrixTimesScalar:
        case EOpMatrixTimesMatrix:
            writeTriplet(visit, "(", " * ", ")");
            break;

        case EOpLogicalOr: writeTriplet(visit, "(", " || ", ")"); break;
        case EOpLogicalXor: writeTriplet(visit, "(", " ^^ ", ")"); break;
        case EOpLogicalAnd: writeTriplet(visit, "(", " && ", ")"); break;
        default: UNREACHABLE(); break;
    }

    return visitChildren;
}
예제 #10
0
bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate *node)
{
    bool visitChildren = true;
    TInfoSinkBase &out = objSink();
    bool useEmulatedFunction = (visit == PreVisit && node->getUseEmulatedFunction());
    switch (node->getOp())
    {
      case EOpSequence:
        // Scope the sequences except when at the global scope.
        if (mDepth > 0)
        {
            out << "{\n";
        }

        incrementDepth(node);
        for (TIntermSequence::const_iterator iter = node->getSequence()->begin();
             iter != node->getSequence()->end(); ++iter)
        {
            TIntermNode *curNode = *iter;
            ASSERT(curNode != NULL);
            curNode->traverse(this);

            if (isSingleStatement(curNode))
                out << ";\n";
        }
        decrementDepth();

        // Scope the sequences except when at the global scope.
        if (mDepth > 0)
        {
            out << "}\n";
        }
        visitChildren = false;
        break;
      case EOpPrototype:
        // Function declaration.
        ASSERT(visit == PreVisit);
        {
            const TType &type = node->getType();
            writeVariableType(type);
            if (type.isArray())
                out << arrayBrackets(type);
        }

        out << " " << hashFunctionNameIfNeeded(node->getNameObj());

        out << "(";
        writeFunctionParameters(*(node->getSequence()));
        out << ")";

        visitChildren = false;
        break;
      case EOpFunction: {
        // Function definition.
        ASSERT(visit == PreVisit);
        {
            const TType &type = node->getType();
            writeVariableType(type);
            if (type.isArray())
                out << arrayBrackets(type);
        }

        out << " " << hashFunctionNameIfNeeded(node->getNameObj());

        incrementDepth(node);
        // Function definition node contains one or two children nodes
        // representing function parameters and function body. The latter
        // is not present in case of empty function bodies.
        const TIntermSequence &sequence = *(node->getSequence());
        ASSERT((sequence.size() == 1) || (sequence.size() == 2));
        TIntermSequence::const_iterator seqIter = sequence.begin();

        // Traverse function parameters.
        TIntermAggregate *params = (*seqIter)->getAsAggregate();
        ASSERT(params != NULL);
        ASSERT(params->getOp() == EOpParameters);
        params->traverse(this);

        // Traverse function body.
        TIntermAggregate *body = ++seqIter != sequence.end() ?
            (*seqIter)->getAsAggregate() : NULL;
        visitCodeBlock(body);
        decrementDepth();

        // Fully processed; no need to visit children.
        visitChildren = false;
        break;
      }
      case EOpFunctionCall:
        // Function call.
        if (visit == PreVisit)
            out << hashFunctionNameIfNeeded(node->getNameObj()) << "(";
        else if (visit == InVisit)
            out << ", ";
        else
            out << ")";
        break;
      case EOpParameters:
        // Function parameters.
        ASSERT(visit == PreVisit);
        out << "(";
        writeFunctionParameters(*(node->getSequence()));
        out << ")";
        visitChildren = false;
        break;
      case EOpDeclaration:
        // Variable declaration.
        if (visit == PreVisit)
        {
            const TIntermSequence &sequence = *(node->getSequence());
            const TIntermTyped *variable = sequence.front()->getAsTyped();
            writeVariableType(variable->getType());
            out << " ";
            mDeclaringVariables = true;
        }
        else if (visit == InVisit)
        {
            out << ", ";
            mDeclaringVariables = true;
        }
        else
        {
            mDeclaringVariables = false;
        }
        break;
      case EOpInvariantDeclaration:
        // Invariant declaration.
        ASSERT(visit == PreVisit);
        {
            const TIntermSequence *sequence = node->getSequence();
            ASSERT(sequence && sequence->size() == 1);
            const TIntermSymbol *symbol = sequence->front()->getAsSymbolNode();
            ASSERT(symbol);
            out << "invariant " << hashVariableName(symbol->getSymbol());
        }
        visitChildren = false;
        break;
      case EOpConstructFloat:
        writeConstructorTriplet(visit, node->getType(), "float");
        break;
      case EOpConstructVec2:
        writeConstructorTriplet(visit, node->getType(), "vec2");
        break;
      case EOpConstructVec3:
        writeConstructorTriplet(visit, node->getType(), "vec3");
        break;
      case EOpConstructVec4:
        writeConstructorTriplet(visit, node->getType(), "vec4");
        break;
      case EOpConstructBool:
        writeConstructorTriplet(visit, node->getType(), "bool");
        break;
      case EOpConstructBVec2:
        writeConstructorTriplet(visit, node->getType(), "bvec2");
        break;
      case EOpConstructBVec3:
        writeConstructorTriplet(visit, node->getType(), "bvec3");
        break;
      case EOpConstructBVec4:
        writeConstructorTriplet(visit, node->getType(), "bvec4");
        break;
      case EOpConstructInt:
        writeConstructorTriplet(visit, node->getType(), "int");
        break;
      case EOpConstructIVec2:
        writeConstructorTriplet(visit, node->getType(), "ivec2");
        break;
      case EOpConstructIVec3:
        writeConstructorTriplet(visit, node->getType(), "ivec3");
        break;
      case EOpConstructIVec4:
        writeConstructorTriplet(visit, node->getType(), "ivec4");
        break;
      case EOpConstructUInt:
        writeConstructorTriplet(visit, node->getType(), "uint");
        break;
      case EOpConstructUVec2:
        writeConstructorTriplet(visit, node->getType(), "uvec2");
        break;
      case EOpConstructUVec3:
        writeConstructorTriplet(visit, node->getType(), "uvec3");
        break;
      case EOpConstructUVec4:
        writeConstructorTriplet(visit, node->getType(), "uvec4");
        break;
      case EOpConstructMat2:
        writeConstructorTriplet(visit, node->getType(), "mat2");
        break;
      case EOpConstructMat2x3:
        writeConstructorTriplet(visit, node->getType(), "mat2x3");
        break;
      case EOpConstructMat2x4:
        writeConstructorTriplet(visit, node->getType(), "mat2x4");
        break;
      case EOpConstructMat3x2:
        writeConstructorTriplet(visit, node->getType(), "mat3x2");
        break;
      case EOpConstructMat3:
        writeConstructorTriplet(visit, node->getType(), "mat3");
        break;
      case EOpConstructMat3x4:
        writeConstructorTriplet(visit, node->getType(), "mat3x4");
        break;
      case EOpConstructMat4x2:
        writeConstructorTriplet(visit, node->getType(), "mat4x2");
        break;
      case EOpConstructMat4x3:
        writeConstructorTriplet(visit, node->getType(), "mat4x3");
        break;
      case EOpConstructMat4:
        writeConstructorTriplet(visit, node->getType(), "mat4");
        break;
      case EOpConstructStruct:
        {
            const TType &type = node->getType();
            ASSERT(type.getBasicType() == EbtStruct);
            TString constructorName = hashName(type.getStruct()->name());
            writeConstructorTriplet(visit, node->getType(), constructorName.c_str());
            break;
        }

      case EOpOuterProduct:
        writeBuiltInFunctionTriplet(visit, "outerProduct(", useEmulatedFunction);
        break;

      case EOpLessThan:
        writeBuiltInFunctionTriplet(visit, "lessThan(", useEmulatedFunction);
        break;
      case EOpGreaterThan:
        writeBuiltInFunctionTriplet(visit, "greaterThan(", useEmulatedFunction);
        break;
      case EOpLessThanEqual:
        writeBuiltInFunctionTriplet(visit, "lessThanEqual(", useEmulatedFunction);
        break;
      case EOpGreaterThanEqual:
        writeBuiltInFunctionTriplet(visit, "greaterThanEqual(", useEmulatedFunction);
        break;
      case EOpVectorEqual:
        writeBuiltInFunctionTriplet(visit, "equal(", useEmulatedFunction);
        break;
      case EOpVectorNotEqual:
        writeBuiltInFunctionTriplet(visit, "notEqual(", useEmulatedFunction);
        break;
      case EOpComma:
        writeTriplet(visit, "(", ", ", ")");
        break;

      case EOpMod:
        writeBuiltInFunctionTriplet(visit, "mod(", useEmulatedFunction);
        break;
      case EOpModf:
        writeBuiltInFunctionTriplet(visit, "modf(", useEmulatedFunction);
        break;
      case EOpPow:
        writeBuiltInFunctionTriplet(visit, "pow(", useEmulatedFunction);
        break;
      case EOpAtan:
        writeBuiltInFunctionTriplet(visit, "atan(", useEmulatedFunction);
        break;
      case EOpMin:
        writeBuiltInFunctionTriplet(visit, "min(", useEmulatedFunction);
        break;
      case EOpMax:
        writeBuiltInFunctionTriplet(visit, "max(", useEmulatedFunction);
        break;
      case EOpClamp:
        writeBuiltInFunctionTriplet(visit, "clamp(", useEmulatedFunction);
        break;
      case EOpMix:
        writeBuiltInFunctionTriplet(visit, "mix(", useEmulatedFunction);
        break;
      case EOpStep:
        writeBuiltInFunctionTriplet(visit, "step(", useEmulatedFunction);
        break;
      case EOpSmoothStep:
        writeBuiltInFunctionTriplet(visit, "smoothstep(", useEmulatedFunction);
        break;
      case EOpDistance:
        writeBuiltInFunctionTriplet(visit, "distance(", useEmulatedFunction);
        break;
      case EOpDot:
        writeBuiltInFunctionTriplet(visit, "dot(", useEmulatedFunction);
        break;
      case EOpCross:
        writeBuiltInFunctionTriplet(visit, "cross(", useEmulatedFunction);
        break;
      case EOpFaceForward:
        writeBuiltInFunctionTriplet(visit, "faceforward(", useEmulatedFunction);
        break;
      case EOpReflect:
        writeBuiltInFunctionTriplet(visit, "reflect(", useEmulatedFunction);
        break;
      case EOpRefract:
        writeBuiltInFunctionTriplet(visit, "refract(", useEmulatedFunction);
        break;
      case EOpMul:
        writeBuiltInFunctionTriplet(visit, "matrixCompMult(", useEmulatedFunction);
        break;

      default:
        UNREACHABLE();
    }
    return visitChildren;
}
예제 #11
0
bool TOutputGLSLBase::visitUnary(Visit visit, TIntermUnary *node)
{
    TString preString;
    TString postString = ")";

    switch (node->getOp())
    {
      case EOpNegative: preString = "(-"; break;
      case EOpPositive: preString = "(+"; break;
      case EOpVectorLogicalNot: preString = "not("; break;
      case EOpLogicalNot: preString = "(!"; break;
      case EOpBitwiseNot: preString = "(~"; break;

      case EOpPostIncrement: preString = "("; postString = "++)"; break;
      case EOpPostDecrement: preString = "("; postString = "--)"; break;
      case EOpPreIncrement: preString = "(++"; break;
      case EOpPreDecrement: preString = "(--"; break;

      case EOpRadians:
        preString = "radians(";
        break;
      case EOpDegrees:
        preString = "degrees(";
        break;
      case EOpSin:
        preString = "sin(";
        break;
      case EOpCos:
        preString = "cos(";
        break;
      case EOpTan:
        preString = "tan(";
        break;
      case EOpAsin:
        preString = "asin(";
        break;
      case EOpAcos:
        preString = "acos(";
        break;
      case EOpAtan:
        preString = "atan(";
        break;

      case EOpSinh:
        preString = "sinh(";
        break;
      case EOpCosh:
        preString = "cosh(";
        break;
      case EOpTanh:
        preString = "tanh(";
        break;
      case EOpAsinh:
        preString = "asinh(";
        break;
      case EOpAcosh:
        preString = "acosh(";
        break;
      case EOpAtanh:
        preString = "atanh(";
        break;

      case EOpExp:
        preString = "exp(";
        break;
      case EOpLog:
        preString = "log(";
        break;
      case EOpExp2:
        preString = "exp2(";
        break;
      case EOpLog2:
        preString = "log2(";
        break;
      case EOpSqrt:
        preString = "sqrt(";
        break;
      case EOpInverseSqrt:
        preString = "inversesqrt(";
        break;

      case EOpAbs:
        preString = "abs(";
        break;
      case EOpSign:
        preString = "sign(";
        break;
      case EOpFloor:
        preString = "floor(";
        break;
      case EOpTrunc:
        preString = "trunc(";
        break;
      case EOpRound:
        preString = "round(";
        break;
      case EOpRoundEven:
        preString = "roundEven(";
        break;
      case EOpCeil:
        preString = "ceil(";
        break;
      case EOpFract:
        preString = "fract(";
        break;
      case EOpIsNan:
        preString = "isnan(";
        break;
      case EOpIsInf:
        preString = "isinf(";
        break;

      case EOpFloatBitsToInt:
        preString = "floatBitsToInt(";
        break;
      case EOpFloatBitsToUint:
        preString = "floatBitsToUint(";
        break;
      case EOpIntBitsToFloat:
        preString = "intBitsToFloat(";
        break;
      case EOpUintBitsToFloat:
        preString = "uintBitsToFloat(";
        break;

      case EOpPackSnorm2x16:
        preString = "packSnorm2x16(";
        break;
      case EOpPackUnorm2x16:
        preString = "packUnorm2x16(";
        break;
      case EOpPackHalf2x16:
        preString = "packHalf2x16(";
        break;
      case EOpUnpackSnorm2x16:
        preString = "unpackSnorm2x16(";
        break;
      case EOpUnpackUnorm2x16:
        preString = "unpackUnorm2x16(";
        break;
      case EOpUnpackHalf2x16:
        preString = "unpackHalf2x16(";
        break;

      case EOpLength:
        preString = "length(";
        break;
      case EOpNormalize:
        preString = "normalize(";
        break;

      case EOpDFdx:
        preString = "dFdx(";
        break;
      case EOpDFdy:
        preString = "dFdy(";
        break;
      case EOpFwidth:
        preString = "fwidth(";
        break;

      case EOpTranspose:
        preString = "transpose(";
        break;
      case EOpDeterminant:
        preString = "determinant(";
        break;
      case EOpInverse:
        preString = "inverse(";
        break;

      case EOpAny:
        preString = "any(";
        break;
      case EOpAll:
        preString = "all(";
        break;

      default:
        UNREACHABLE();
    }

    if (visit == PreVisit && node->getUseEmulatedFunction())
        preString = BuiltInFunctionEmulator::GetEmulatedFunctionName(preString);
    writeTriplet(visit, preString.c_str(), NULL, postString.c_str());

    return true;
}
예제 #12
0
bool TOutputGLSLBase::visitBinary(Visit visit, TIntermBinary *node)
{
    bool visitChildren = true;
    TInfoSinkBase &out = objSink();
    switch (node->getOp())
    {
      case EOpInitialize:
        if (visit == InVisit)
        {
            out << " = ";
            // RHS of initialize is not being declared.
            mDeclaringVariables = false;
        }
        break;
      case EOpAssign:
        writeTriplet(visit, "(", " = ", ")");
        break;
      case EOpAddAssign:
        writeTriplet(visit, "(", " += ", ")");
        break;
      case EOpSubAssign:
        writeTriplet(visit, "(", " -= ", ")");
        break;
      case EOpDivAssign:
        writeTriplet(visit, "(", " /= ", ")");
        break;
      case EOpIModAssign:
        writeTriplet(visit, "(", " %= ", ")");
        break;
      // Notice the fall-through.
      case EOpMulAssign:
      case EOpVectorTimesMatrixAssign:
      case EOpVectorTimesScalarAssign:
      case EOpMatrixTimesScalarAssign:
      case EOpMatrixTimesMatrixAssign:
        writeTriplet(visit, "(", " *= ", ")");
        break;
      case EOpBitShiftLeftAssign:
        writeTriplet(visit, "(", " <<= ", ")");
        break;
      case EOpBitShiftRightAssign:
        writeTriplet(visit, "(", " >>= ", ")");
        break;
      case EOpBitwiseAndAssign:
        writeTriplet(visit, "(", " &= ", ")");
        break;
      case EOpBitwiseXorAssign:
        writeTriplet(visit, "(", " ^= ", ")");
        break;
      case EOpBitwiseOrAssign:
        writeTriplet(visit, "(", " |= ", ")");
        break;

      case EOpIndexDirect:
        writeTriplet(visit, NULL, "[", "]");
        break;
      case EOpIndexIndirect:
        if (node->getAddIndexClamp())
        {
            if (visit == InVisit)
            {
                if (mClampingStrategy == SH_CLAMP_WITH_CLAMP_INTRINSIC)
                    out << "[int(clamp(float(";
                else
                    out << "[webgl_int_clamp(";
            }
            else if (visit == PostVisit)
            {
                int maxSize;
                TIntermTyped *left = node->getLeft();
                TType leftType = left->getType();

                if (left->isArray())
                {
                    // The shader will fail validation if the array length is not > 0.
                    maxSize = leftType.getArraySize() - 1;
                }
                else
                {
                    maxSize = leftType.getNominalSize() - 1;
                }

                if (mClampingStrategy == SH_CLAMP_WITH_CLAMP_INTRINSIC)
                    out << "), 0.0, float(" << maxSize << ")))]";
                else
                    out << ", 0, " << maxSize << ")]";
            }
        }
        else
        {
            writeTriplet(visit, NULL, "[", "]");
        }
        break;
      case EOpIndexDirectStruct:
        if (visit == InVisit)
        {
            // Here we are writing out "foo.bar", where "foo" is struct
            // and "bar" is field. In AST, it is represented as a binary
            // node, where left child represents "foo" and right child "bar".
            // The node itself represents ".". The struct field "bar" is
            // actually stored as an index into TStructure::fields.
            out << ".";
            const TStructure *structure = node->getLeft()->getType().getStruct();
            const TIntermConstantUnion *index = node->getRight()->getAsConstantUnion();
            const TField *field = structure->fields()[index->getIConst(0)];

            TString fieldName = field->name();
            if (!mSymbolTable.findBuiltIn(structure->name(), mShaderVersion))
                fieldName = hashName(fieldName);

            out << fieldName;
            visitChildren = false;
        }
        break;
      case EOpIndexDirectInterfaceBlock:
          if (visit == InVisit)
          {
              out << ".";
              const TInterfaceBlock *interfaceBlock = node->getLeft()->getType().getInterfaceBlock();
              const TIntermConstantUnion *index = node->getRight()->getAsConstantUnion();
              const TField *field = interfaceBlock->fields()[index->getIConst(0)];

              TString fieldName = field->name();
              ASSERT(!mSymbolTable.findBuiltIn(interfaceBlock->name(), mShaderVersion));
              fieldName = hashName(fieldName);

              out << fieldName;
              visitChildren = false;
          }
          break;
      case EOpVectorSwizzle:
        if (visit == InVisit)
        {
            out << ".";
            TIntermAggregate *rightChild = node->getRight()->getAsAggregate();
            TIntermSequence *sequence = rightChild->getSequence();
            for (TIntermSequence::iterator sit = sequence->begin(); sit != sequence->end(); ++sit)
            {
                TIntermConstantUnion *element = (*sit)->getAsConstantUnion();
                ASSERT(element->getBasicType() == EbtInt);
                ASSERT(element->getNominalSize() == 1);
                const TConstantUnion& data = element->getUnionArrayPointer()[0];
                ASSERT(data.getType() == EbtInt);
                switch (data.getIConst())
                {
                  case 0:
                    out << "x";
                    break;
                  case 1:
                    out << "y";
                    break;
                  case 2:
                    out << "z";
                    break;
                  case 3:
                    out << "w";
                    break;
                  default:
                    UNREACHABLE();
                }
            }
            visitChildren = false;
        }
        break;

      case EOpAdd:
        writeTriplet(visit, "(", " + ", ")");
        break;
      case EOpSub:
        writeTriplet(visit, "(", " - ", ")");
        break;
      case EOpMul:
        writeTriplet(visit, "(", " * ", ")");
        break;
      case EOpDiv:
        writeTriplet(visit, "(", " / ", ")");
        break;
      case EOpIMod:
        writeTriplet(visit, "(", " % ", ")");
        break;
      case EOpBitShiftLeft:
        writeTriplet(visit, "(", " << ", ")");
        break;
      case EOpBitShiftRight:
        writeTriplet(visit, "(", " >> ", ")");
        break;
      case EOpBitwiseAnd:
        writeTriplet(visit, "(", " & ", ")");
        break;
      case EOpBitwiseXor:
        writeTriplet(visit, "(", " ^ ", ")");
        break;
      case EOpBitwiseOr:
        writeTriplet(visit, "(", " | ", ")");
        break;

      case EOpEqual:
        writeTriplet(visit, "(", " == ", ")");
        break;
      case EOpNotEqual:
        writeTriplet(visit, "(", " != ", ")");
        break;
      case EOpLessThan:
        writeTriplet(visit, "(", " < ", ")");
        break;
      case EOpGreaterThan:
        writeTriplet(visit, "(", " > ", ")");
        break;
      case EOpLessThanEqual:
        writeTriplet(visit, "(", " <= ", ")");
        break;
      case EOpGreaterThanEqual:
        writeTriplet(visit, "(", " >= ", ")");
        break;

      // Notice the fall-through.
      case EOpVectorTimesScalar:
      case EOpVectorTimesMatrix:
      case EOpMatrixTimesVector:
      case EOpMatrixTimesScalar:
      case EOpMatrixTimesMatrix:
        writeTriplet(visit, "(", " * ", ")");
        break;

      case EOpLogicalOr:
        writeTriplet(visit, "(", " || ", ")");
        break;
      case EOpLogicalXor:
        writeTriplet(visit, "(", " ^^ ", ")");
        break;
      case EOpLogicalAnd:
        writeTriplet(visit, "(", " && ", ")");
        break;
      default:
        UNREACHABLE();
    }

    return visitChildren;
}
예제 #13
0
bool TOutputGLSLBase::visitUnary(Visit visit, TIntermUnary* node)
{
    switch (node->getOp())
    {
        case EOpNegative: writeTriplet(visit, "(-", NULL, ")"); break;
        case EOpVectorLogicalNot: writeTriplet(visit, "not(", NULL, ")"); break;
        case EOpLogicalNot: writeTriplet(visit, "(!", NULL, ")"); break;

        case EOpPostIncrement: writeTriplet(visit, "(", NULL, "++)"); break;
        case EOpPostDecrement: writeTriplet(visit, "(", NULL, "--)"); break;
        case EOpPreIncrement: writeTriplet(visit, "(++", NULL, ")"); break;
        case EOpPreDecrement: writeTriplet(visit, "(--", NULL, ")"); break;

        case EOpConvIntToBool:
        case EOpConvFloatToBool:
            switch (node->getOperand()->getType().getNominalSize())
            {
                case 1: writeTriplet(visit, "bool(", NULL, ")");  break;
                case 2: writeTriplet(visit, "bvec2(", NULL, ")"); break;
                case 3: writeTriplet(visit, "bvec3(", NULL, ")"); break;
                case 4: writeTriplet(visit, "bvec4(", NULL, ")"); break;
                default: UNREACHABLE();
            }
            break;
        case EOpConvBoolToFloat:
        case EOpConvIntToFloat:
            switch (node->getOperand()->getType().getNominalSize())
            {
                case 1: writeTriplet(visit, "float(", NULL, ")");  break;
                case 2: writeTriplet(visit, "vec2(", NULL, ")"); break;
                case 3: writeTriplet(visit, "vec3(", NULL, ")"); break;
                case 4: writeTriplet(visit, "vec4(", NULL, ")"); break;
                default: UNREACHABLE();
            }
            break;
        case EOpConvFloatToInt:
        case EOpConvBoolToInt:
            switch (node->getOperand()->getType().getNominalSize())
            {
                case 1: writeTriplet(visit, "int(", NULL, ")");  break;
                case 2: writeTriplet(visit, "ivec2(", NULL, ")"); break;
                case 3: writeTriplet(visit, "ivec3(", NULL, ")"); break;
                case 4: writeTriplet(visit, "ivec4(", NULL, ")"); break;
                default: UNREACHABLE();
            }
            break;

        case EOpRadians: writeTriplet(visit, "radians(", NULL, ")"); break;
        case EOpDegrees: writeTriplet(visit, "degrees(", NULL, ")"); break;
        case EOpSin: writeTriplet(visit, "sin(", NULL, ")"); break;
        case EOpCos: writeTriplet(visit, "cos(", NULL, ")"); break;
        case EOpTan: writeTriplet(visit, "tan(", NULL, ")"); break;
        case EOpAsin: writeTriplet(visit, "asin(", NULL, ")"); break;
        case EOpAcos: writeTriplet(visit, "acos(", NULL, ")"); break;
        case EOpAtan: writeTriplet(visit, "atan(", NULL, ")"); break;

        case EOpExp: writeTriplet(visit, "exp(", NULL, ")"); break;
        case EOpLog: writeTriplet(visit, "log(", NULL, ")"); break;
        case EOpExp2: writeTriplet(visit, "exp2(", NULL, ")"); break;
        case EOpLog2: writeTriplet(visit, "log2(", NULL, ")"); break;
        case EOpSqrt: writeTriplet(visit, "sqrt(", NULL, ")"); break;
        case EOpInverseSqrt: writeTriplet(visit, "inversesqrt(", NULL, ")"); break;

        case EOpAbs: writeTriplet(visit, "abs(", NULL, ")"); break;
        case EOpSign: writeTriplet(visit, "sign(", NULL, ")"); break;
        case EOpFloor: writeTriplet(visit, "floor(", NULL, ")"); break;
        case EOpCeil: writeTriplet(visit, "ceil(", NULL, ")"); break;
        case EOpFract: writeTriplet(visit, "fract(", NULL, ")"); break;

        case EOpLength: writeTriplet(visit, "length(", NULL, ")"); break;
        case EOpNormalize: writeTriplet(visit, "normalize(", NULL, ")"); break;

        case EOpDFdx: writeTriplet(visit, "dFdx(", NULL, ")"); break;
        case EOpDFdy: writeTriplet(visit, "dFdy(", NULL, ")"); break;
        case EOpFwidth: writeTriplet(visit, "fwidth(", NULL, ")"); break;

        case EOpAny: writeTriplet(visit, "any(", NULL, ")"); break;
        case EOpAll: writeTriplet(visit, "all(", NULL, ")"); break;

        default: UNREACHABLE(); break;
    }

    return true;
}