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; }
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; }
void TOutputGLSLBase::writeBuiltInFunctionTriplet( Visit visit, const char *preStr, bool useEmulatedFunction) { TString preString = useEmulatedFunction ? BuiltInFunctionEmulator::GetEmulatedFunctionName(preStr) : preStr; writeTriplet(visit, preString.c_str(), ", ", ")"); }
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; } }
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, ", ", ")"); } }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }