void writeFuncCall( const TString &name, TIntermAggregate *node, TGlslOutputTraverser* goit, bool bGenMatrix = false ) { TIntermSequence::iterator sit; TIntermSequence &sequence = node->getSequence(); GlslFunction *current = goit->current; std::stringstream& out = current->getActiveOutput(); current->beginStatement(); if ( bGenMatrix ) { if ( node->isMatrix () ) { out << "xll_"; current->addLibFunction ( node->getOp() ); } } out << name << "("; for (sit = sequence.begin(); sit != sequence.end(); ++sit) { if (sit !=sequence.begin()) out << ", "; (*sit)->traverse(goit); } out << ")"; }
void setupUnaryBuiltInFuncCall( const TString &name, TIntermUnary *node, TString &opStr, bool &funcStyle, bool &prefix, TGlslOutputTraverser* goit ) { GlslFunction *current = goit->current; funcStyle = true; prefix = true; if ( node->isMatrix() ) { current->addLibFunction( node->getOp() ); opStr = "xll_" + name; } else { opStr = name; } }
bool TGlslOutputTraverser::traverseUnary( bool preVisit, TIntermUnary *node, TIntermTraverser *it ) { TString op("??"); TGlslOutputTraverser* goit = static_cast<TGlslOutputTraverser*>(it); GlslFunction *current = goit->current; std::stringstream& out = current->getActiveOutput(); bool funcStyle = false; bool prefix = true; char zero[] = "0"; current->beginStatement(); switch (node->getOp()) { case EOpNegative: op = "-"; funcStyle = false; prefix = true; break; case EOpVectorLogicalNot: case EOpLogicalNot: op = "!"; funcStyle = false; prefix = true; break; case EOpBitwiseNot: op = "-"; funcStyle = false; prefix = true; break; case EOpPostIncrement: op = "++"; funcStyle = false; prefix = false; break; case EOpPostDecrement: op = "--"; funcStyle = false; prefix = false; break; case EOpPreIncrement: op = "++"; funcStyle = false; prefix = true; break; case EOpPreDecrement: op = "--"; funcStyle = false; prefix = true; break; case EOpConvIntToBool: case EOpConvFloatToBool: op = "bool"; if ( node->getTypePointer()->getNominalSize() > 1) { zero[0] += node->getTypePointer()->getNominalSize(); op = TString("bvec") + zero; } funcStyle = true; prefix = true; break; case EOpConvBoolToFloat: case EOpConvIntToFloat: op = "float"; if ( node->getTypePointer()->getNominalSize() > 1) { zero[0] += node->getTypePointer()->getNominalSize(); op = TString("vec") + zero; } funcStyle = true; prefix = true; break; case EOpConvFloatToInt: case EOpConvBoolToInt: op = "int"; if ( node->getTypePointer()->getNominalSize() > 1) { zero[0] += node->getTypePointer()->getNominalSize(); op = TString("ivec") + zero; } funcStyle = true; prefix = true; break; case EOpRadians: setupUnaryBuiltInFuncCall ( "radians", node, op, funcStyle, prefix, goit ); break; case EOpDegrees: setupUnaryBuiltInFuncCall ( "degrees", node, op, funcStyle, prefix, goit ); break; case EOpSin: setupUnaryBuiltInFuncCall ( "sin", node, op, funcStyle, prefix, goit ); break; case EOpCos: setupUnaryBuiltInFuncCall ( "cos", node, op, funcStyle, prefix, goit ); break; case EOpTan: setupUnaryBuiltInFuncCall ( "tan", node, op, funcStyle, prefix, goit ); break; case EOpAsin: setupUnaryBuiltInFuncCall ( "asin", node, op, funcStyle, prefix, goit ); break; case EOpAcos: setupUnaryBuiltInFuncCall ( "acos", node, op, funcStyle, prefix, goit ); break; case EOpAtan: setupUnaryBuiltInFuncCall ( "atan", node, op, funcStyle, prefix, goit ); break; case EOpExp: setupUnaryBuiltInFuncCall ( "exp", node, op, funcStyle, prefix, goit ); break; case EOpLog: setupUnaryBuiltInFuncCall ( "log", node, op, funcStyle, prefix, goit ); break; case EOpExp2: setupUnaryBuiltInFuncCall ( "exp2", node, op, funcStyle, prefix, goit ); break; case EOpLog2: setupUnaryBuiltInFuncCall ( "log2", node, op, funcStyle, prefix, goit ); break; case EOpSqrt: setupUnaryBuiltInFuncCall ( "sqrt", node, op, funcStyle, prefix, goit ); break; case EOpInverseSqrt: setupUnaryBuiltInFuncCall ( "inversesqrt", node, op, funcStyle, prefix, goit ); break; case EOpAbs: setupUnaryBuiltInFuncCall ( "abs", node, op, funcStyle, prefix, goit ); break; case EOpSign: setupUnaryBuiltInFuncCall ( "sign", node, op, funcStyle, prefix, goit ); break; case EOpFloor: setupUnaryBuiltInFuncCall ( "floor", node, op, funcStyle, prefix, goit ); break; case EOpCeil: setupUnaryBuiltInFuncCall ( "ceil", node, op, funcStyle, prefix, goit ); break; case EOpFract: setupUnaryBuiltInFuncCall ( "fract", node, op, funcStyle, prefix, goit ); break; case EOpLength: op = "length"; funcStyle = true; prefix = true; break; case EOpNormalize: op = "normalize"; funcStyle = true; prefix = true; break; case EOpDPdx: current->addLibFunction(EOpDPdx); op = "xll_dFdx"; funcStyle = true; prefix = true; break; case EOpDPdy: current->addLibFunction(EOpDPdy); op = "xll_dFdy"; funcStyle = true; prefix = true; break; case EOpFwidth: current->addLibFunction(EOpFwidth); op = "xll_fwidth"; funcStyle = true; prefix = true; break; case EOpFclip: current->addLibFunction(EOpFclip); op = "xll_clip"; funcStyle = true; prefix = true; break; case EOpAny: op = "any"; funcStyle = true; prefix = true; break; case EOpAll: op = "all"; funcStyle = true; prefix = true; break; //these are HLSL specific and they map to the lib functions case EOpSaturate: current->addLibFunction(EOpSaturate); op = "xll_saturate"; funcStyle = true; prefix = true; break; case EOpTranspose: current->addLibFunction(EOpTranspose); op = "xll_transpose"; funcStyle = true; prefix = true; break; case EOpDeterminant: current->addLibFunction(EOpDeterminant); op = "xll_determinant"; funcStyle = true; prefix = true; break; case EOpLog10: current->addLibFunction(EOpLog10); op = "xll_log10"; funcStyle = true; prefix = true; break; case EOpD3DCOLORtoUBYTE4: current->addLibFunction(EOpD3DCOLORtoUBYTE4); op = "xll_D3DCOLORtoUBYTE4"; funcStyle = true; prefix = true; break; default: assert(0); } if (funcStyle) out << op << '('; else { out << '('; if (prefix) out << op; } node->getOperand()->traverse(goit); if (! funcStyle && !prefix) out << op; out << ')'; return false; }
bool TGlslOutputTraverser::traverseBinary( bool preVisit, TIntermBinary *node, TIntermTraverser *it ) { TString op = "??"; TGlslOutputTraverser* goit = static_cast<TGlslOutputTraverser*>(it); GlslFunction *current = goit->current; std::stringstream& out = current->getActiveOutput(); bool infix = true; bool assign = false; bool needsParens = true; switch (node->getOp()) { case EOpAssign: op = "="; infix = true; needsParens = false; break; case EOpAddAssign: op = "+="; infix = true; needsParens = false; break; case EOpSubAssign: op = "-="; infix = true; needsParens = false; break; case EOpMulAssign: op = "*="; infix = true; needsParens = false; break; case EOpVectorTimesMatrixAssign: op = "*="; infix = true; needsParens = false; break; case EOpVectorTimesScalarAssign: op = "*="; infix = true; needsParens = false; break; case EOpMatrixTimesScalarAssign: op = "*="; infix = true; needsParens = false; break; case EOpMatrixTimesMatrixAssign: op = "*="; infix = true; needsParens = false; break; case EOpDivAssign: op = "/="; infix = true; needsParens = false; break; case EOpModAssign: op = "%="; infix = true; needsParens = false; break; case EOpAndAssign: op = "&="; infix = true; needsParens = false; break; case EOpInclusiveOrAssign: op = "|="; infix = true; needsParens = false; break; case EOpExclusiveOrAssign: op = "^="; infix = true; needsParens = false; break; case EOpLeftShiftAssign: op = "<<="; infix = true; needsParens = false; break; case EOpRightShiftAssign: op = "??="; infix = true; needsParens = false; break; case EOpIndexDirect: { TIntermTyped *left = node->getLeft(); TIntermTyped *right = node->getRight(); assert( left && right); current->beginStatement(); if (Check2DMatrixIndex (goit, out, left, right)) return false; if (left->isMatrix() && !left->isArray()) { if (right->getAsConstant()) { current->addLibFunction (EOpMatrixIndex); out << "xll_matrixindex ("; left->traverse(goit); out << ", "; right->traverse(goit); out << ")"; return false; } else { current->addLibFunction (EOpTranspose); current->addLibFunction (EOpMatrixIndex); current->addLibFunction (EOpMatrixIndexDynamic); out << "xll_matrixindexdynamic ("; left->traverse(goit); out << ", "; right->traverse(goit); out << ")"; return false; } } left->traverse(goit); // Special code for handling a vector component select (this improves readability) if (left->isVector() && !left->isArray() && right->getAsConstant()) { char swiz[] = "xyzw"; goit->visitConstantUnion = TGlslOutputTraverser::traverseImmediateConstant; goit->generatingCode = false; right->traverse(goit); assert( goit->indexList.size() == 1); assert( goit->indexList[0] < 4); out << "." << swiz[goit->indexList[0]]; goit->indexList.clear(); goit->visitConstantUnion = TGlslOutputTraverser::traverseConstantUnion; goit->generatingCode = true; } else { out << "["; right->traverse(goit); out << "]"; } return false; } case EOpIndexIndirect: { TIntermTyped *left = node->getLeft(); TIntermTyped *right = node->getRight(); current->beginStatement(); if (Check2DMatrixIndex (goit, out, left, right)) return false; if (left && right && left->isMatrix() && !left->isArray()) { if (right->getAsConstant()) { current->addLibFunction (EOpMatrixIndex); out << "xll_matrixindex ("; left->traverse(goit); out << ", "; right->traverse(goit); out << ")"; return false; } else { current->addLibFunction (EOpTranspose); current->addLibFunction (EOpMatrixIndex); current->addLibFunction (EOpMatrixIndexDynamic); out << "xll_matrixindexdynamic ("; left->traverse(goit); out << ", "; right->traverse(goit); out << ")"; return false; } } if (left) left->traverse(goit); out << "["; if (right) right->traverse(goit); out << "]"; return false; } case EOpIndexDirectStruct: { current->beginStatement(); GlslStruct *s = goit->createStructFromType(node->getLeft()->getTypePointer()); if (node->getLeft()) node->getLeft()->traverse(goit); // The right child is always an offset into the struct, switch to get an // immediate constant, and put it back afterwords goit->visitConstantUnion = TGlslOutputTraverser::traverseImmediateConstant; goit->generatingCode = false; if (node->getRight()) { node->getRight()->traverse(goit); assert( goit->indexList.size() == 1); assert( goit->indexList[0] < s->memberCount()); out << "." << s->getMember(goit->indexList[0]).name; } goit->indexList.clear(); goit->visitConstantUnion = TGlslOutputTraverser::traverseConstantUnion; goit->generatingCode = true; } return false; case EOpVectorSwizzle: current->beginStatement(); if (node->getLeft()) node->getLeft()->traverse(goit); goit->visitConstantUnion = TGlslOutputTraverser::traverseImmediateConstant; goit->generatingCode = false; if (node->getRight()) { node->getRight()->traverse(goit); assert( goit->indexList.size() <= 4); out << '.'; const char fields[] = "xyzw"; for (int ii = 0; ii < (int)goit->indexList.size(); ii++) { int val = goit->indexList[ii]; assert( val >= 0); assert( val < 4); out << fields[val]; } } goit->indexList.clear(); goit->visitConstantUnion = TGlslOutputTraverser::traverseConstantUnion; goit->generatingCode = true; return false; case EOpMatrixSwizzle: // This presently only works for swizzles as rhs operators if (node->getRight()) { goit->visitConstantUnion = TGlslOutputTraverser::traverseImmediateConstant; goit->generatingCode = false; node->getRight()->traverse(goit); goit->visitConstantUnion = TGlslOutputTraverser::traverseConstantUnion; goit->generatingCode = true; std::vector<int> elements = goit->indexList; goit->indexList.clear(); if (elements.size() > 4 || elements.size() < 1) { goit->infoSink.info << "Matrix swizzle operations can must contain at least 1 and at most 4 element selectors."; return true; } unsigned column[4] = {0}, row[4] = {0}; for (unsigned i = 0; i != elements.size(); ++i) { unsigned val = elements[i]; column[i] = val % 4; row[i] = val / 4; } bool sameColumn = true; for (unsigned i = 1; i != elements.size(); ++i) sameColumn &= column[i] == column[i-1]; static const char* fields = "xyzw"; if (sameColumn) { //select column, then swizzle row if (node->getLeft()) node->getLeft()->traverse(goit); out << "[" << column[0] << "]."; for (unsigned i = 0; i < elements.size(); ++i) out << fields[row[i]]; } else { // Insert constructor, and dereference individually // Might need to account for different types here assert( elements.size() != 1); //should have hit same collumn case out << "vec" << elements.size() << "("; if (node->getLeft()) node->getLeft()->traverse(goit); out << "[" << column[0] << "]."; out << fields[row[0]]; for (unsigned i = 1; i < elements.size(); ++i) { out << ", "; if (node->getLeft()) node->getLeft()->traverse(goit); out << "[" << column[i] << "]."; out << fields[row[i]]; } out << ")"; } } return false; case EOpAdd: op = "+"; infix = true; break; case EOpSub: op = "-"; infix = true; break; case EOpMul: op = "*"; infix = true; break; case EOpDiv: op = "/"; infix = true; break; case EOpMod: op = "mod"; infix = false; break; case EOpRightShift: op = "<<"; infix = true; break; case EOpLeftShift: op = ">>"; infix = true; break; case EOpAnd: op = "&"; infix = true; break; case EOpInclusiveOr: op = "|"; infix = true; break; case EOpExclusiveOr: op = "^"; infix = true; break; case EOpEqual: writeComparison ( "==", "equal", node, goit ); return false; case EOpNotEqual: writeComparison ( "!=", "notEqual", node, goit ); return false; case EOpLessThan: writeComparison ( "<", "lessThan", node, goit ); return false; case EOpGreaterThan: writeComparison ( ">", "greaterThan", node, goit ); return false; case EOpLessThanEqual: writeComparison ( "<=", "lessThanEqual", node, goit ); return false; case EOpGreaterThanEqual: writeComparison ( ">=", "greaterThanEqual", node, goit ); return false; case EOpVectorTimesScalar: op = "*"; infix = true; break; case EOpVectorTimesMatrix: op = "*"; infix = true; break; case EOpMatrixTimesVector: op = "*"; infix = true; break; case EOpMatrixTimesScalar: op = "*"; infix = true; break; case EOpMatrixTimesMatrix: op = "*"; infix = true; break; case EOpLogicalOr: op = "||"; infix = true; break; case EOpLogicalXor: op = "^^"; infix = true; break; case EOpLogicalAnd: op = "&&"; infix = true; break; default: assert(0); } current->beginStatement(); if (infix) { // special case for swizzled matrix assignment if (node->getOp() == EOpAssign && node->getLeft() && node->getRight()) { TIntermBinary* lval = node->getLeft()->getAsBinaryNode(); if (lval && lval->getOp() == EOpMatrixSwizzle) { static const char* vec_swizzles = "xyzw"; TIntermTyped* rval = node->getRight(); TIntermTyped* lexp = lval->getLeft(); goit->visitConstantUnion = TGlslOutputTraverser::traverseImmediateConstant; goit->generatingCode = false; lval->getRight()->traverse(goit); goit->visitConstantUnion = TGlslOutputTraverser::traverseConstantUnion; goit->generatingCode = true; std::vector<int> swizzles = goit->indexList; goit->indexList.clear(); char temp_rval[128]; unsigned n_swizzles = swizzles.size(); if (n_swizzles > 1) { snprintf(temp_rval, 128, "xlat_swiztemp%d", goit->swizzleAssignTempCounter++); current->beginStatement(); out << "vec" << n_swizzles << " " << temp_rval << " = "; rval->traverse(goit); current->endStatement(); } for (unsigned i = 0; i != n_swizzles; ++i) { unsigned col = swizzles[i] / 4; unsigned row = swizzles[i] % 4; current->beginStatement(); lexp->traverse(goit); out << "[" << row << "][" << col << "] = "; if (n_swizzles > 1) out << temp_rval << "." << vec_swizzles[i]; else rval->traverse(goit); current->endStatement(); } return false; } } if (needsParens) out << '('; if (node->getLeft()) node->getLeft()->traverse(goit); out << ' ' << op << ' '; if (node->getRight()) node->getRight()->traverse(goit); if (needsParens) out << ')'; } else { if (assign) { // Need to traverse the left child twice to allow for the assign and the op // This is OK, because we know it is an lvalue if (node->getLeft()) node->getLeft()->traverse(goit); out << " = " << op << '('; if (node->getLeft()) node->getLeft()->traverse(goit); out << ", "; if (node->getRight()) node->getRight()->traverse(goit); out << ')'; } else { out << op << '('; if (node->getLeft()) node->getLeft()->traverse(goit); out << ", "; if (node->getRight()) node->getRight()->traverse(goit); out << ')'; } } return false; }
bool TGlslOutputTraverser::traverseAggregate( bool preVisit, TIntermAggregate *node, TIntermTraverser *it ) { TGlslOutputTraverser* goit = static_cast<TGlslOutputTraverser*>(it); GlslFunction *current = goit->current; std::stringstream& out = current->getActiveOutput(); int argCount = (int) node->getSequence().size(); if (node->getOp() == EOpNull) { goit->infoSink.info << "node is still EOpNull!\n"; return true; } switch (node->getOp()) { case EOpSequence: if (goit->generatingCode) { goit->outputLineDirective (node->getLine()); TIntermSequence::iterator sit; TIntermSequence &sequence = node->getSequence(); for (sit = sequence.begin(); sit != sequence.end(); ++sit) { goit->outputLineDirective((*sit)->getLine()); (*sit)->traverse(it); //out << ";\n"; current->endStatement(); } } else { TIntermSequence::iterator sit; TIntermSequence &sequence = node->getSequence(); for (sit = sequence.begin(); sit != sequence.end(); ++sit) { (*sit)->traverse(it); } } return false; case EOpFunction: { GlslFunction *func = new GlslFunction( node->getPlainName().c_str(), node->getName().c_str(), translateType(node->getTypePointer()), goit->m_UsePrecision?node->getPrecision():EbpUndefined, node->getSemantic().c_str(), node->getLine()); if (func->getReturnType() == EgstStruct) { GlslStruct *s = goit->createStructFromType( node->getTypePointer()); func->setStruct(s); } goit->functionList.push_back( func); goit->current = func; goit->current->beginBlock( false); TIntermSequence::iterator sit; TIntermSequence &sequence = node->getSequence(); for (sit = sequence.begin(); sit != sequence.end(); ++sit) { (*sit)->traverse(it); } goit->current->endBlock(); goit->current = goit->global; return false; } case EOpParameters: it->visitSymbol = traverseParameterSymbol; { TIntermSequence::iterator sit; TIntermSequence &sequence = node->getSequence(); for (sit = sequence.begin(); sit != sequence.end(); ++sit) (*sit)->traverse(it); } it->visitSymbol = traverseSymbol; return false; case EOpConstructFloat: writeFuncCall( "float", node, goit); return false; case EOpConstructVec2: writeFuncCall( "vec2", node, goit); return false; case EOpConstructVec3: writeFuncCall( "vec3", node, goit); return false; case EOpConstructVec4: writeFuncCall( "vec4", node, goit); return false; case EOpConstructBool: writeFuncCall( "bool", node, goit); return false; case EOpConstructBVec2: writeFuncCall( "bvec2", node, goit); return false; case EOpConstructBVec3: writeFuncCall( "bvec3", node, goit); return false; case EOpConstructBVec4: writeFuncCall( "bvec4", node, goit); return false; case EOpConstructInt: writeFuncCall( "int", node, goit); return false; case EOpConstructIVec2: writeFuncCall( "ivec2", node, goit); return false; case EOpConstructIVec3: writeFuncCall( "ivec3", node, goit); return false; case EOpConstructIVec4: writeFuncCall( "ivec4", node, goit); return false; case EOpConstructMat2FromMat: case EOpConstructMat2: writeFuncCall( "mat2", node, goit); return false; case EOpConstructMat3FromMat: case EOpConstructMat3: writeFuncCall( "mat3", node, goit); return false; case EOpConstructMat4: writeFuncCall( "mat4", node, goit); return false; case EOpConstructStruct: writeFuncCall( node->getTypePointer()->getTypeName(), node, goit); return false; case EOpConstructArray: writeFuncCall( buildArrayConstructorString(*node->getTypePointer()), node, goit); return false; case EOpComma: { TIntermSequence::iterator sit; TIntermSequence &sequence = node->getSequence(); for (sit = sequence.begin(); sit != sequence.end(); ++sit) { (*sit)->traverse(it); if ( sit+1 != sequence.end()) out << ", "; } } return false; case EOpFunctionCall: current->addCalledFunction(node->getName().c_str()); writeFuncCall( node->getPlainName(), node, goit); return false; case EOpLessThan: writeFuncCall( "lessThan", node, goit); return false; case EOpGreaterThan: writeFuncCall( "greaterThan", node, goit); return false; case EOpLessThanEqual: writeFuncCall( "lessThanEqual", node, goit); return false; case EOpGreaterThanEqual: writeFuncCall( "greaterThanEqual", node, goit); return false; case EOpVectorEqual: writeFuncCall( "equal", node, goit); return false; case EOpVectorNotEqual: writeFuncCall( "notEqual", node, goit); return false; case EOpMod: writeFuncCall( "mod", node, goit, true); return false; case EOpPow: writeFuncCall( "pow", node, goit, true); return false; case EOpAtan2: writeFuncCall( "atan", node, goit, true); return false; case EOpMin: writeFuncCall( "min", node, goit, true); return false; case EOpMax: writeFuncCall( "max", node, goit, true); return false; case EOpClamp: writeFuncCall( "clamp", node, goit, true); return false; case EOpMix: writeFuncCall( "mix", node, goit, true); return false; case EOpStep: writeFuncCall( "step", node, goit, true); return false; case EOpSmoothStep: writeFuncCall( "smoothstep", node, goit, true); return false; case EOpDistance: writeFuncCall( "distance", node, goit); return false; case EOpDot: writeFuncCall( "dot", node, goit); return false; case EOpCross: writeFuncCall( "cross", node, goit); return false; case EOpFaceForward: writeFuncCall( "faceforward", node, goit); return false; case EOpReflect: writeFuncCall( "reflect", node, goit); return false; case EOpRefract: writeFuncCall( "refract", node, goit); return false; case EOpMul: { //This should always have two arguments assert(node->getSequence().size() == 2); current->beginStatement(); out << '('; node->getSequence()[0]->traverse(goit); out << " * "; node->getSequence()[1]->traverse(goit); out << ')'; return false; } //HLSL texture functions case EOpTex1D: if (argCount == 2) writeTex( "texture1D", node, goit); else { current->addLibFunction(EOpTex1DGrad); writeTex( "xll_tex1Dgrad", node, goit); } return false; case EOpTex1DProj: writeTex( "texture1DProj", node, goit); return false; case EOpTex1DLod: current->addLibFunction(EOpTex1DLod); writeTex( "xll_tex1Dlod", node, goit); return false; case EOpTex1DBias: current->addLibFunction(EOpTex1DBias); writeTex( "xll_tex1Dbias", node, goit); return false; case EOpTex1DGrad: current->addLibFunction(EOpTex1DGrad); writeTex( "xll_tex1Dgrad", node, goit); return false; case EOpTex2D: if (argCount == 2) writeTex( "texture2D", node, goit); else { current->addLibFunction(EOpTex2DGrad); writeTex( "xll_tex2Dgrad", node, goit); } return false; case EOpTex2DProj: writeTex( "texture2DProj", node, goit); return false; case EOpTex2DLod: current->addLibFunction(EOpTex2DLod); writeTex( "xll_tex2Dlod", node, goit); return false; case EOpTex2DBias: current->addLibFunction(EOpTex2DBias); writeTex( "xll_tex2Dbias", node, goit); return false; case EOpTex2DGrad: current->addLibFunction(EOpTex2DGrad); writeTex( "xll_tex2Dgrad", node, goit); return false; case EOpTex3D: if (argCount == 2) writeTex( "texture3D", node, goit); else { current->addLibFunction(EOpTex3DGrad); writeTex( "xll_tex3Dgrad", node, goit); } return false; case EOpTex3DProj: writeTex( "texture3DProj", node, goit); return false; case EOpTex3DLod: current->addLibFunction(EOpTex3DLod); writeTex( "xll_tex3Dlod", node, goit); return false; case EOpTex3DBias: current->addLibFunction(EOpTex3DBias); writeTex( "xll_tex3Dbias", node, goit); return false; case EOpTex3DGrad: current->addLibFunction(EOpTex3DGrad); writeTex( "xll_tex3Dgrad", node, goit); return false; case EOpTexCube: if (argCount == 2) writeTex( "textureCube", node, goit); else { current->addLibFunction(EOpTexCubeGrad); writeTex( "xll_texCUBEgrad", node, goit); } return false; case EOpTexCubeProj: writeTex( "textureCubeProj", node, goit); return false; case EOpTexCubeLod: current->addLibFunction(EOpTexCubeLod); writeTex( "xll_texCUBElod", node, goit); return false; case EOpTexCubeBias: current->addLibFunction(EOpTexCubeBias); writeTex( "xll_texCUBEbias", node, goit); return false; case EOpTexCubeGrad: current->addLibFunction(EOpTexCubeGrad); writeTex( "xll_texCUBEgrad", node, goit); return false; case EOpTexRect: writeTex( "texture2DRect", node, goit); return false; case EOpTexRectProj: writeTex( "texture2DRectProj", node, goit); return false; case EOpModf: current->addLibFunction(EOpModf); writeFuncCall( "xll_modf", node, goit); break; case EOpLdexp: current->addLibFunction(EOpLdexp); writeFuncCall( "xll_ldexp", node, goit); break; case EOpSinCos: current->addLibFunction(EOpSinCos); writeFuncCall ( "xll_sincos", node, goit); break; case EOpLit: current->addLibFunction(EOpLit); writeFuncCall( "xll_lit", node, goit); break; default: goit->infoSink.info << "Bad aggregation op\n"; } return false; }
bool TGlslOutputTraverser::traverseSelection( bool preVisit, TIntermSelection *node, TIntermTraverser *it ) { TGlslOutputTraverser* goit = static_cast<TGlslOutputTraverser*>(it); GlslFunction *current = goit->current; std::stringstream& out = current->getActiveOutput(); current->beginStatement(); if (node->getBasicType() == EbtVoid) { // if/else selection out << "if ("; node->getCondition()->traverse(goit); out << ')'; current->beginBlock(); node->getTrueBlock()->traverse(goit); current->endBlock(); if (node->getFalseBlock()) { current->indent(); out << "else"; current->beginBlock(); node->getFalseBlock()->traverse(goit); current->endBlock(); } } else if (node->isVector() && node->getCondition()->getAsTyped()->isVector()) { // ?: selection on vectors, e.g. bvec4 ? vec4 : vec4 // emulate HLSL's component-wise selection here current->addLibFunction(EOpVecTernarySel); out << "xll_vecTSel ("; node->getCondition()->traverse(goit); out << ", "; node->getTrueBlock()->traverse(goit); out << ", "; if (node->getFalseBlock()) { node->getFalseBlock()->traverse(goit); } else assert(0); out << ")"; } else { // simple ?: selection out << "(( "; node->getCondition()->traverse(goit); out << " ) ? ( "; node->getTrueBlock()->traverse(goit); out << " ) : ( "; if (node->getFalseBlock()) { node->getFalseBlock()->traverse(goit); } else assert(0); out << " ))"; } return false; }