static TOperator getMatrixConstructOp(const TIntermTyped& intermediate) { switch (intermediate.getColsCount()) { case 2: switch (intermediate.getRowsCount()) { case 2: return EOpConstructMat2x2; case 3: return EOpConstructMat2x3; case 4: return EOpConstructMat2x4; } break; case 3: switch (intermediate.getRowsCount()) { case 2: return EOpConstructMat3x2; case 3: return EOpConstructMat3x3; case 4: return EOpConstructMat3x4; } break; case 4: switch (intermediate.getRowsCount()) { case 2: return EOpConstructMat4x2; case 3: return EOpConstructMat4x3; case 4: return EOpConstructMat4x4; } break; } assert(false); return EOpNull; }
static TOperator getMatrixConstructOp(const TIntermTyped& intermediate, TParseContext& ctx) { // before GLSL 1.20, only square matrices if (ctx.targetVersion < ETargetGLSL_120) { const int c = intermediate.getColsCount(); const int r = intermediate.getRowsCount(); if (c == 2 && r == 2) return EOpConstructMat2x2FromMat; if (c == 3 && r == 3) return EOpConstructMat3x3FromMat; if (c == 4 && r == 4) return EOpConstructMat4x4; ctx.error(intermediate.getLine(), " non-square matrices not supported", "", "(%ix%i)", r, c); return EOpNull; } switch (intermediate.getColsCount()) { case 2: switch (intermediate.getRowsCount()) { case 2: return EOpConstructMat2x2; case 3: return EOpConstructMat2x3; case 4: return EOpConstructMat2x4; } break; case 3: switch (intermediate.getRowsCount()) { case 2: return EOpConstructMat3x2; case 3: return EOpConstructMat3x3; case 4: return EOpConstructMat3x4; } break; case 4: switch (intermediate.getRowsCount()) { case 2: return EOpConstructMat4x2; case 3: return EOpConstructMat4x3; case 4: return EOpConstructMat4x4; } break; } assert(false); return EOpNull; }
bool TIntermSelection::promoteTernary(TInfoSink& infoSink) { if (!condition->isVector()) return true; int size = condition->getRowsCount(); TIntermTyped* trueb = trueBlock->getAsTyped(); TIntermTyped* falseb = falseBlock->getAsTyped(); if (!trueb || !falseb) return false; if (trueb->getRowsCount() == size && falseb->getRowsCount() == size) return true; // Base assumption: just make the type a float vector TPrecision higherPrecision = GetHigherPrecision(trueb->getPrecision(), falseb->getPrecision()); setType(TType(EbtFloat, higherPrecision, EvqTemporary, 1, size, condition->isMatrix())); TOperator convert = EOpNull; { convert = TOperator( EOpConstructVec2 + size - 2); TIntermAggregate *node = new TIntermAggregate(convert); node->setLine(trueb->getLine()); node->setType(TType(condition->getBasicType(), higherPrecision, trueb->getQualifier() == EvqConst ? EvqConst : EvqTemporary, 1, size, condition->isMatrix())); node->getNodes().push_back(trueb); trueBlock = node; } { convert = TOperator( EOpConstructVec2 + size - 2); TIntermAggregate *node = new TIntermAggregate(convert); node->setLine(falseb->getLine()); node->setType(TType(condition->getBasicType(), higherPrecision, falseb->getQualifier() == EvqConst ? EvqConst : EvqTemporary, 1, size, condition->isMatrix())); node->getNodes().push_back(falseb); falseBlock = node; } return true; }
// Add one node as the parent of another that it operates on. TIntermTyped* ir_add_unary_math(TOperator op, TIntermNode* childNode, TSourceLoc line, TParseContext& ctx) { TIntermUnary* node; TIntermTyped* child = childNode->getAsTyped(); if (child == 0) { ctx.infoSink.info.message(EPrefixInternalError, "Bad type in AddUnaryMath", line); return 0; } switch (op) { case EOpLogicalNot: if (!child->isScalar()) return 0; break; case EOpPostIncrement: case EOpPreIncrement: case EOpPostDecrement: case EOpPreDecrement: case EOpNegative: if (child->getType().getBasicType() == EbtStruct || child->getType().isArray()) return 0; default: break; } // // Do we need to promote the operand? // // Note: Implicit promotions were removed from the language. // TBasicType newType = EbtVoid; switch (op) { case EOpConstructInt: newType = EbtInt; break; case EOpConstructBool: newType = EbtBool; break; case EOpConstructFloat: newType = EbtFloat; break; case EOpLogicalNot: newType = EbtBool; break; default: break; } if (newType != EbtVoid) { child = ir_add_conversion(op, TType(newType, child->getPrecision(), EvqTemporary, child->getColsCount(), child->getRowsCount(), child->isMatrix(), child->isArray()), child, ctx.infoSink); if (child == 0) return 0; } // // For constructors, we are now done, it's all in the conversion. // switch (op) { case EOpConstructInt: case EOpConstructBool: case EOpConstructFloat: return child; default: break; } TIntermConstant* childConst = child->getAsConstant(); // // Make a new node for the operator. // node = new TIntermUnary(op); if (line.line == 0) line = child->getLine(); node->setLine(line); node->setOperand(child); if (! node->promote(ctx)) return 0; // // See if we can fold constants if (childConst) { TIntermConstant* FoldUnaryConstantExpression(TOperator op, TIntermConstant* node); TIntermConstant* res = FoldUnaryConstantExpression(node->getOp(), childConst); if (res) { delete node; return res; } } return node; }