Commit 00106d49 by Alexis Hetu Committed by Alexis Hétu

Fixed NxM matrix construction and minor issues

Fixed NxM matrix construction by properly checking for these types in TIntermOperator::isConstructor. Also fixed a few areas of the code where the secondary size wasn't properly taken into account. Change-Id: I646a41e37460255316f5712f1d744c3a06d8a64d Reviewed-on: https://swiftshader-review.googlesource.com/3195Tested-by: 's avatarAlexis Hétu <sugoi@google.com> Reviewed-by: 's avatarNicolas Capens <capn@google.com>
parent 127fac35
...@@ -21,6 +21,38 @@ static TPrecision GetHigherPrecision( TPrecision left, TPrecision right ){ ...@@ -21,6 +21,38 @@ static TPrecision GetHigherPrecision( TPrecision left, TPrecision right ){
return left > right ? left : right; return left > right ? left : right;
} }
static bool ValidateMultiplication(TOperator op, const TType &left, const TType &right)
{
switch(op)
{
case EOpMul:
case EOpMulAssign:
return left.getNominalSize() == right.getNominalSize() &&
left.getSecondarySize() == right.getSecondarySize();
case EOpVectorTimesScalar:
case EOpVectorTimesScalarAssign:
return true;
case EOpVectorTimesMatrix:
return left.getNominalSize() == right.getSecondarySize();
case EOpVectorTimesMatrixAssign:
return left.getNominalSize() == right.getSecondarySize() &&
left.getNominalSize() == right.getNominalSize();
case EOpMatrixTimesVector:
return left.getNominalSize() == right.getNominalSize();
case EOpMatrixTimesScalar:
case EOpMatrixTimesScalarAssign:
return true;
case EOpMatrixTimesMatrix:
return left.getNominalSize() == right.getSecondarySize();
case EOpMatrixTimesMatrixAssign:
return left.getNominalSize() == right.getNominalSize() &&
left.getSecondarySize() == right.getSecondarySize();
default:
UNREACHABLE();
return false;
}
}
const char* getOperatorString(TOperator op) { const char* getOperatorString(TOperator op) {
switch (op) { switch (op) {
case EOpInitialize: return "="; case EOpInitialize: return "=";
...@@ -645,7 +677,13 @@ bool TIntermOperator::isConstructor() const ...@@ -645,7 +677,13 @@ bool TIntermOperator::isConstructor() const
case EOpConstructVec3: case EOpConstructVec3:
case EOpConstructVec4: case EOpConstructVec4:
case EOpConstructMat2: case EOpConstructMat2:
case EOpConstructMat2x3:
case EOpConstructMat2x4:
case EOpConstructMat3x2:
case EOpConstructMat3: case EOpConstructMat3:
case EOpConstructMat3x4:
case EOpConstructMat4x2:
case EOpConstructMat4x3:
case EOpConstructMat4: case EOpConstructMat4:
case EOpConstructFloat: case EOpConstructFloat:
case EOpConstructIVec2: case EOpConstructIVec2:
...@@ -752,7 +790,6 @@ bool TIntermBinary::promote(TInfoSink& infoSink) ...@@ -752,7 +790,6 @@ bool TIntermBinary::promote(TInfoSink& infoSink)
} }
int primarySize = std::max(left->getNominalSize(), right->getNominalSize()); int primarySize = std::max(left->getNominalSize(), right->getNominalSize());
int secondarySize = std::max(left->getSecondarySize(), right->getSecondarySize());
// //
// All scalars. Code after this test assumes this case is removed! // All scalars. Code after this test assumes this case is removed!
...@@ -791,25 +828,6 @@ bool TIntermBinary::promote(TInfoSink& infoSink) ...@@ -791,25 +828,6 @@ bool TIntermBinary::promote(TInfoSink& infoSink)
// If we reach here, at least one of the operands is vector or matrix. // If we reach here, at least one of the operands is vector or matrix.
// The other operand could be a scalar, vector, or matrix. // The other operand could be a scalar, vector, or matrix.
// Are the sizes compatible?
//
if (left->getNominalSize() != right->getNominalSize()) {
// If the nominal size of operands do not match:
// One of them must be scalar.
if (left->getNominalSize() != 1 && right->getNominalSize() != 1)
return false;
// Operator cannot be of type pure assignment.
if (op == EOpAssign || op == EOpInitialize)
return false;
}
if (left->getSecondarySize() != right->getSecondarySize()) {
// Operator cannot be of type pure assignment.
if (op == EOpAssign || op == EOpInitialize)
return false;
}
//
// Can these two operands be combined? // Can these two operands be combined?
// //
TBasicType basicType = left->getBasicType(); TBasicType basicType = left->getBasicType();
...@@ -817,31 +835,45 @@ bool TIntermBinary::promote(TInfoSink& infoSink) ...@@ -817,31 +835,45 @@ bool TIntermBinary::promote(TInfoSink& infoSink)
case EOpMul: case EOpMul:
if (!left->isMatrix() && right->isMatrix()) { if (!left->isMatrix() && right->isMatrix()) {
if (left->isVector()) if (left->isVector())
{
op = EOpVectorTimesMatrix; op = EOpVectorTimesMatrix;
setType(TType(basicType, higherPrecision, EvqTemporary,
static_cast<unsigned char>(right->getNominalSize()), 1));
}
else { else {
op = EOpMatrixTimesScalar; op = EOpMatrixTimesScalar;
setType(TType(basicType, higherPrecision, EvqTemporary, primarySize, secondarySize)); setType(TType(basicType, higherPrecision, EvqTemporary,
static_cast<unsigned char>(right->getNominalSize()), static_cast<unsigned char>(right->getSecondarySize())));
} }
} else if (left->isMatrix() && !right->isMatrix()) { } else if (left->isMatrix() && !right->isMatrix()) {
if (right->isVector()) { if (right->isVector()) {
op = EOpMatrixTimesVector; op = EOpMatrixTimesVector;
setType(TType(basicType, higherPrecision, EvqTemporary, primarySize, 1)); setType(TType(basicType, higherPrecision, EvqTemporary,
static_cast<unsigned char>(left->getSecondarySize()), 1));
} else { } else {
op = EOpMatrixTimesScalar; op = EOpMatrixTimesScalar;
} }
} else if (left->isMatrix() && right->isMatrix()) { } else if (left->isMatrix() && right->isMatrix()) {
op = EOpMatrixTimesMatrix; op = EOpMatrixTimesMatrix;
setType(TType(basicType, higherPrecision, EvqTemporary,
static_cast<unsigned char>(right->getNominalSize()), static_cast<unsigned char>(left->getSecondarySize())));
} else if (!left->isMatrix() && !right->isMatrix()) { } else if (!left->isMatrix() && !right->isMatrix()) {
if (left->isVector() && right->isVector()) { if (left->isVector() && right->isVector()) {
// leave as component product // leave as component product
} else if (left->isVector() || right->isVector()) { } else if (left->isVector() || right->isVector()) {
op = EOpVectorTimesScalar; op = EOpVectorTimesScalar;
setType(TType(basicType, higherPrecision, EvqTemporary, primarySize, 1)); setType(TType(basicType, higherPrecision, EvqTemporary,
static_cast<unsigned char>(primarySize), 1));
} }
} else { } else {
infoSink.info.message(EPrefixInternalError, "Missing elses", getLine()); infoSink.info.message(EPrefixInternalError, "Missing elses", getLine());
return false; return false;
} }
if(!ValidateMultiplication(op, left->getType(), right->getType()))
{
return false;
}
break; break;
case EOpMulAssign: case EOpMulAssign:
if (!left->isMatrix() && right->isMatrix()) { if (!left->isMatrix() && right->isMatrix()) {
...@@ -858,6 +890,8 @@ bool TIntermBinary::promote(TInfoSink& infoSink) ...@@ -858,6 +890,8 @@ bool TIntermBinary::promote(TInfoSink& infoSink)
} }
} else if (left->isMatrix() && right->isMatrix()) { } else if (left->isMatrix() && right->isMatrix()) {
op = EOpMatrixTimesMatrixAssign; op = EOpMatrixTimesMatrixAssign;
setType(TType(basicType, higherPrecision, EvqTemporary,
static_cast<unsigned char>(right->getNominalSize()), static_cast<unsigned char>(left->getSecondarySize())));
} else if (!left->isMatrix() && !right->isMatrix()) { } else if (!left->isMatrix() && !right->isMatrix()) {
if (left->isVector() && right->isVector()) { if (left->isVector() && right->isVector()) {
// leave as component product // leave as component product
...@@ -865,16 +899,27 @@ bool TIntermBinary::promote(TInfoSink& infoSink) ...@@ -865,16 +899,27 @@ bool TIntermBinary::promote(TInfoSink& infoSink)
if (! left->isVector()) if (! left->isVector())
return false; return false;
op = EOpVectorTimesScalarAssign; op = EOpVectorTimesScalarAssign;
setType(TType(basicType, higherPrecision, EvqTemporary, primarySize, 1)); setType(TType(basicType, higherPrecision, EvqTemporary,
static_cast<unsigned char>(left->getNominalSize()), 1));
} }
} else { } else {
infoSink.info.message(EPrefixInternalError, "Missing elses", getLine()); infoSink.info.message(EPrefixInternalError, "Missing elses", getLine());
return false; return false;
} }
if(!ValidateMultiplication(op, left->getType(), right->getType()))
{
return false;
}
break; break;
case EOpAssign: case EOpAssign:
case EOpInitialize: case EOpInitialize:
// No more additional checks are needed.
if ((left->getNominalSize() != right->getNominalSize()) ||
(left->getSecondarySize() != right->getSecondarySize()))
return false;
break;
case EOpAdd: case EOpAdd:
case EOpSub: case EOpSub:
case EOpDiv: case EOpDiv:
...@@ -915,6 +960,8 @@ bool TIntermBinary::promote(TInfoSink& infoSink) ...@@ -915,6 +960,8 @@ bool TIntermBinary::promote(TInfoSink& infoSink)
} }
{ {
const int secondarySize = std::max(
left->getSecondarySize(), right->getSecondarySize());
setType(TType(basicType, higherPrecision, EvqTemporary, setType(TType(basicType, higherPrecision, EvqTemporary,
static_cast<unsigned char>(primarySize), static_cast<unsigned char>(secondarySize))); static_cast<unsigned char>(primarySize), static_cast<unsigned char>(secondarySize)));
if(left->isArray()) if(left->isArray())
...@@ -923,8 +970,6 @@ bool TIntermBinary::promote(TInfoSink& infoSink) ...@@ -923,8 +970,6 @@ bool TIntermBinary::promote(TInfoSink& infoSink)
type.setArraySize(left->getArraySize()); type.setArraySize(left->getArraySize());
} }
} }
setType(TType(basicType, higherPrecision, EvqTemporary, primarySize, secondarySize));
break; break;
case EOpEqual: case EOpEqual:
...@@ -933,8 +978,8 @@ bool TIntermBinary::promote(TInfoSink& infoSink) ...@@ -933,8 +978,8 @@ bool TIntermBinary::promote(TInfoSink& infoSink)
case EOpGreaterThan: case EOpGreaterThan:
case EOpLessThanEqual: case EOpLessThanEqual:
case EOpGreaterThanEqual: case EOpGreaterThanEqual:
if ((left->isMatrix() && right->isVector()) || if ((left->getNominalSize() != right->getNominalSize()) ||
(left->isVector() && right->isMatrix())) (left->getSecondarySize() != right->getSecondarySize()))
return false; return false;
setType(TType(EbtBool, EbpUndefined)); setType(TType(EbtBool, EbpUndefined));
break; break;
...@@ -1056,16 +1101,29 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod ...@@ -1056,16 +1101,29 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod
return 0; return 0;
} }
{// support MSVC++6.0 {// support MSVC++6.0
int size = getNominalSize(); int leftNumCols = getNominalSize();
tempConstArray = new ConstantUnion[size*size]; int leftNumRows = getSecondarySize();
for (int row = 0; row < size; row++) { int rightNumCols = node->getNominalSize();
for (int column = 0; column < size; column++) { int rightNumRows = node->getSecondarySize();
tempConstArray[size * column + row].setFConst(0.0f); if(leftNumCols != rightNumRows) {
for (int i = 0; i < size; i++) { infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for matrix multiply", getLine());
tempConstArray[size * column + row].setFConst(tempConstArray[size * column + row].getFConst() + unionArray[i * size + row].getFConst() * (rightUnionArray[column * size + i].getFConst())); return 0;
}
int tempNumCols = rightNumCols;
int tempNumRows = leftNumRows;
int tempNumAdds = leftNumCols;
tempConstArray = new ConstantUnion[tempNumCols*tempNumRows];
for (int row = 0; row < tempNumRows; row++) {
for (int column = 0; column < tempNumCols; column++) {
tempConstArray[tempNumRows * column + row].setFConst(0.0f);
for (int i = 0; i < tempNumAdds; i++) {
tempConstArray[tempNumRows * column + row].setFConst(tempConstArray[tempNumRows * column + row].getFConst() + unionArray[i * leftNumRows + row].getFConst() * (rightUnionArray[column * rightNumRows + i].getFConst()));
} }
} }
} }
// update return type for matrix product
returnType.setNominalSize(static_cast<unsigned char>(tempNumCols));
returnType.setSecondarySize(static_cast<unsigned char>(tempNumRows));
} }
break; break;
case EOpDiv: case EOpDiv:
......
...@@ -1430,7 +1430,7 @@ namespace glsl ...@@ -1430,7 +1430,7 @@ namespace glsl
} }
else if(type.isMatrix()) else if(type.isMatrix())
{ {
return registers * type.getNominalSize(); return registers * type.getSecondarySize();
} }
UNREACHABLE(); UNREACHABLE();
...@@ -1446,7 +1446,7 @@ namespace glsl ...@@ -1446,7 +1446,7 @@ namespace glsl
return registerSize(*type.getStruct()->begin()->type, 0); return registerSize(*type.getStruct()->begin()->type, 0);
} }
return type.getNominalSize(); return type.isMatrix() ? type.getSecondarySize() : type.getNominalSize();
} }
if(type.isArray() && registers >= type.elementRegisterCount()) if(type.isArray() && registers >= type.elementRegisterCount())
...@@ -1590,7 +1590,7 @@ namespace glsl ...@@ -1590,7 +1590,7 @@ namespace glsl
{ {
if(src && if(src &&
((src->isVector() && (!dst->isVector() || (dst->getNominalSize() != dst->getNominalSize()))) || ((src->isVector() && (!dst->isVector() || (dst->getNominalSize() != dst->getNominalSize()))) ||
(src->isMatrix() && (!dst->isMatrix() || (src->getNominalSize() != dst->getNominalSize()))))) (src->isMatrix() && (!dst->isMatrix() || (src->getNominalSize() != dst->getNominalSize()) || (src->getSecondarySize() != dst->getSecondarySize())))))
{ {
return mContext.error(src->getLine(), "Result type should match the l-value type in compound assignment", src->isVector() ? "vector" : "matrix"); return mContext.error(src->getLine(), "Result type should match the l-value type in compound assignment", src->isVector() ? "vector" : "matrix");
} }
......
...@@ -114,7 +114,7 @@ bool TParseContext::parseVectorFields(const TString& compString, int vecSize, TV ...@@ -114,7 +114,7 @@ bool TParseContext::parseVectorFields(const TString& compString, int vecSize, TV
// Look at a '.' field selector string and change it into offsets // Look at a '.' field selector string and change it into offsets
// for a matrix. // for a matrix.
// //
bool TParseContext::parseMatrixFields(const TString& compString, int matSize, TMatrixFields& fields, int line) bool TParseContext::parseMatrixFields(const TString& compString, int matCols, int matRows, TMatrixFields& fields, int line)
{ {
fields.wholeRow = false; fields.wholeRow = false;
fields.wholeCol = false; fields.wholeCol = false;
...@@ -150,7 +150,7 @@ bool TParseContext::parseMatrixFields(const TString& compString, int matSize, TM ...@@ -150,7 +150,7 @@ bool TParseContext::parseMatrixFields(const TString& compString, int matSize, TM
fields.col = compString[1] - '0'; fields.col = compString[1] - '0';
} }
if (fields.row >= matSize || fields.col >= matSize) { if (fields.row >= matRows || fields.col >= matCols) {
error(line, "matrix field selection out of range", compString.c_str()); error(line, "matrix field selection out of range", compString.c_str());
return false; return false;
} }
......
...@@ -76,7 +76,7 @@ struct TParseContext { ...@@ -76,7 +76,7 @@ struct TParseContext {
void recover(); void recover();
bool parseVectorFields(const TString&, int vecSize, TVectorFields&, int line); bool parseVectorFields(const TString&, int vecSize, TVectorFields&, int line);
bool parseMatrixFields(const TString&, int matSize, TMatrixFields&, int line); bool parseMatrixFields(const TString&, int matCols, int matRows, TMatrixFields&, int line);
bool reservedErrorCheck(int line, const TString& identifier); bool reservedErrorCheck(int line, const TString& identifier);
void assignError(int line, const char* op, TString left, TString right); void assignError(int line, const char* op, TString left, TString right);
......
...@@ -323,9 +323,9 @@ postfix_expression ...@@ -323,9 +323,9 @@ postfix_expression
if ($1->getType().getQualifier() == EvqConstExpr) if ($1->getType().getQualifier() == EvqConstExpr)
$$->getTypePointer()->setQualifier(EvqConstExpr); $$->getTypePointer()->setQualifier(EvqConstExpr);
} else if ($1->isMatrix() && $1->getType().getQualifier() == EvqConstExpr) } else if ($1->isMatrix() && $1->getType().getQualifier() == EvqConstExpr)
$$->setType(TType($1->getBasicType(), $1->getPrecision(), EvqConstExpr, $1->getNominalSize())); $$->setType(TType($1->getBasicType(), $1->getPrecision(), EvqConstExpr, $1->getSecondarySize()));
else if ($1->isMatrix()) else if ($1->isMatrix())
$$->setType(TType($1->getBasicType(), $1->getPrecision(), EvqTemporary, $1->getNominalSize())); $$->setType(TType($1->getBasicType(), $1->getPrecision(), EvqTemporary, $1->getSecondarySize()));
else if ($1->isVector() && $1->getType().getQualifier() == EvqConstExpr) else if ($1->isVector() && $1->getType().getQualifier() == EvqConstExpr)
$$->setType(TType($1->getBasicType(), $1->getPrecision(), EvqConstExpr)); $$->setType(TType($1->getBasicType(), $1->getPrecision(), EvqConstExpr));
else if ($1->isVector()) else if ($1->isVector())
...@@ -366,7 +366,7 @@ postfix_expression ...@@ -366,7 +366,7 @@ postfix_expression
} }
} else if ($1->isMatrix()) { } else if ($1->isMatrix()) {
TMatrixFields fields; TMatrixFields fields;
if (! context->parseMatrixFields(*$3.string, $1->getNominalSize(), fields, $3.line)) { if (! context->parseMatrixFields(*$3.string, $1->getNominalSize(), $1->getSecondarySize(), fields, $3.line)) {
fields.wholeRow = false; fields.wholeRow = false;
fields.wholeCol = false; fields.wholeCol = false;
fields.row = 0; fields.row = 0;
......
...@@ -2465,9 +2465,9 @@ yyreduce: ...@@ -2465,9 +2465,9 @@ yyreduce:
if ((yyvsp[(1) - (4)].interm.intermTypedNode)->getType().getQualifier() == EvqConstExpr) if ((yyvsp[(1) - (4)].interm.intermTypedNode)->getType().getQualifier() == EvqConstExpr)
(yyval.interm.intermTypedNode)->getTypePointer()->setQualifier(EvqConstExpr); (yyval.interm.intermTypedNode)->getTypePointer()->setQualifier(EvqConstExpr);
} else if ((yyvsp[(1) - (4)].interm.intermTypedNode)->isMatrix() && (yyvsp[(1) - (4)].interm.intermTypedNode)->getType().getQualifier() == EvqConstExpr) } else if ((yyvsp[(1) - (4)].interm.intermTypedNode)->isMatrix() && (yyvsp[(1) - (4)].interm.intermTypedNode)->getType().getQualifier() == EvqConstExpr)
(yyval.interm.intermTypedNode)->setType(TType((yyvsp[(1) - (4)].interm.intermTypedNode)->getBasicType(), (yyvsp[(1) - (4)].interm.intermTypedNode)->getPrecision(), EvqConstExpr, (yyvsp[(1) - (4)].interm.intermTypedNode)->getNominalSize())); (yyval.interm.intermTypedNode)->setType(TType((yyvsp[(1) - (4)].interm.intermTypedNode)->getBasicType(), (yyvsp[(1) - (4)].interm.intermTypedNode)->getPrecision(), EvqConstExpr, (yyvsp[(1) - (4)].interm.intermTypedNode)->getSecondarySize()));
else if ((yyvsp[(1) - (4)].interm.intermTypedNode)->isMatrix()) else if ((yyvsp[(1) - (4)].interm.intermTypedNode)->isMatrix())
(yyval.interm.intermTypedNode)->setType(TType((yyvsp[(1) - (4)].interm.intermTypedNode)->getBasicType(), (yyvsp[(1) - (4)].interm.intermTypedNode)->getPrecision(), EvqTemporary, (yyvsp[(1) - (4)].interm.intermTypedNode)->getNominalSize())); (yyval.interm.intermTypedNode)->setType(TType((yyvsp[(1) - (4)].interm.intermTypedNode)->getBasicType(), (yyvsp[(1) - (4)].interm.intermTypedNode)->getPrecision(), EvqTemporary, (yyvsp[(1) - (4)].interm.intermTypedNode)->getSecondarySize()));
else if ((yyvsp[(1) - (4)].interm.intermTypedNode)->isVector() && (yyvsp[(1) - (4)].interm.intermTypedNode)->getType().getQualifier() == EvqConstExpr) else if ((yyvsp[(1) - (4)].interm.intermTypedNode)->isVector() && (yyvsp[(1) - (4)].interm.intermTypedNode)->getType().getQualifier() == EvqConstExpr)
(yyval.interm.intermTypedNode)->setType(TType((yyvsp[(1) - (4)].interm.intermTypedNode)->getBasicType(), (yyvsp[(1) - (4)].interm.intermTypedNode)->getPrecision(), EvqConstExpr)); (yyval.interm.intermTypedNode)->setType(TType((yyvsp[(1) - (4)].interm.intermTypedNode)->getBasicType(), (yyvsp[(1) - (4)].interm.intermTypedNode)->getPrecision(), EvqConstExpr));
else if ((yyvsp[(1) - (4)].interm.intermTypedNode)->isVector()) else if ((yyvsp[(1) - (4)].interm.intermTypedNode)->isVector())
...@@ -2516,7 +2516,7 @@ yyreduce: ...@@ -2516,7 +2516,7 @@ yyreduce:
} }
} else if ((yyvsp[(1) - (3)].interm.intermTypedNode)->isMatrix()) { } else if ((yyvsp[(1) - (3)].interm.intermTypedNode)->isMatrix()) {
TMatrixFields fields; TMatrixFields fields;
if (! context->parseMatrixFields(*(yyvsp[(3) - (3)].lex).string, (yyvsp[(1) - (3)].interm.intermTypedNode)->getNominalSize(), fields, (yyvsp[(3) - (3)].lex).line)) { if (! context->parseMatrixFields(*(yyvsp[(3) - (3)].lex).string, (yyvsp[(1) - (3)].interm.intermTypedNode)->getNominalSize(), (yyvsp[(1) - (3)].interm.intermTypedNode)->getSecondarySize(), fields, (yyvsp[(3) - (3)].lex).line)) {
fields.wholeRow = false; fields.wholeRow = false;
fields.wholeCol = false; fields.wholeCol = false;
fields.row = 0; fields.row = 0;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment