Add a secondary size field to the shader language types, to account for matrix rows. Also add some extra logic
to the promote method to check that the sizes of the arguments to multiplications are properly formed.
We require this extra information for non-square matrix support.
TRAC #23081
Signed-off-by: Geoff Lang
Signed-off-by: Nicolas Capens
Author: Jamie Madill
git-svn-id: https://angleproject.googlecode.com/svn/branches/es3proto@2392 736b8ea6-26fd-11df-bfd4-992fa37f6226
diff --git a/src/common/version.h b/src/common/version.h
index ca4134d..dad770b 100644
--- a/src/common/version.h
+++ b/src/common/version.h
@@ -1,7 +1,7 @@
#define MAJOR_VERSION 1
#define MINOR_VERSION 1
#define BUILD_VERSION 0
-#define BUILD_REVISION 1991
+#define BUILD_REVISION 1992
#define STRINGIFY(x) #x
#define MACRO_STRINGIFY(x) STRINGIFY(x)
diff --git a/src/compiler/BuiltInFunctionEmulator.cpp b/src/compiler/BuiltInFunctionEmulator.cpp
index 1c4b25f..5e651b7 100644
--- a/src/compiler/BuiltInFunctionEmulator.cpp
+++ b/src/compiler/BuiltInFunctionEmulator.cpp
@@ -327,7 +327,7 @@
BuiltInFunctionEmulator::IdentifyFunction(
TOperator op, const TType& param)
{
- if (param.getNominalSize() > 4)
+ if (param.getNominalSize() > 4 || param.getSecondarySize() > 4)
return TFunctionUnknown;
unsigned int function = TFunctionUnknown;
switch (op) {
@@ -356,9 +356,9 @@
{
// Right now for all the emulated functions with two parameters, the two
// parameters have the same type.
- if (param1.isVector() != param2.isVector() ||
- param1.getNominalSize() != param2.getNominalSize() ||
- param1.getNominalSize() > 4)
+ if (param1.getNominalSize() != param2.getNominalSize() ||
+ param1.getSecondarySize() != param2.getSecondarySize() ||
+ param1.getNominalSize() > 4 || param1.getSecondarySize() > 4)
return TFunctionUnknown;
unsigned int function = TFunctionUnknown;
diff --git a/src/compiler/Initialize.cpp b/src/compiler/Initialize.cpp
index 4188316..887fde8 100644
--- a/src/compiler/Initialize.cpp
+++ b/src/compiler/Initialize.cpp
@@ -619,7 +619,7 @@
symbolTable.insert(ESSL1_BUILTINS, *new TVariable(NewPoolTString("gl_FragData[gl_MaxDrawBuffers]"), TType(EbtFloat, EbpMedium, EvqFragData, 4)));
} else {
symbolTable.insert(ESSL1_BUILTINS, *new TVariable(NewPoolTString("css_MixColor"), TType(EbtFloat, EbpMedium, EvqGlobal, 4)));
- symbolTable.insert(ESSL1_BUILTINS, *new TVariable(NewPoolTString("css_ColorMatrix"), TType(EbtFloat, EbpMedium, EvqGlobal, 4, true)));
+ symbolTable.insert(ESSL1_BUILTINS, *new TVariable(NewPoolTString("css_ColorMatrix"), TType(EbtFloat, EbpMedium, EvqGlobal, 4, 4)));
}
break;
@@ -717,7 +717,7 @@
case SH_FRAGMENT_SHADER:
if (spec != SH_CSS_SHADERS_SPEC) {
// Set up gl_FragData. The array size.
- TType fragData(EbtFloat, EbpMedium, EvqFragData, 4, false, true);
+ TType fragData(EbtFloat, EbpMedium, EvqFragData, 4, 1, true);
fragData.setArraySize(resources.MaxDrawBuffers);
symbolTable.insert(ESSL1_BUILTINS, *new TVariable(NewPoolTString("gl_FragData"), fragData));
}
diff --git a/src/compiler/Intermediate.cpp b/src/compiler/Intermediate.cpp
index 458989b..e06a7a6 100644
--- a/src/compiler/Intermediate.cpp
+++ b/src/compiler/Intermediate.cpp
@@ -323,7 +323,7 @@
if (newType != EbtVoid) {
child = addConversion(op, TType(newType, child->getPrecision(), EvqTemporary,
child->getNominalSize(),
- child->isMatrix(),
+ child->getSecondarySize(),
child->isArray()),
child);
if (child == 0)
@@ -519,7 +519,7 @@
return 0;
}
- TType type(promoteTo, node->getPrecision(), EvqTemporary, node->getNominalSize(), node->isMatrix(), node->isArray());
+ TType type(promoteTo, node->getPrecision(), EvqTemporary, node->getNominalSize(), node->getSecondarySize(), node->isArray());
newNode = new TIntermUnary(newOp, type);
newNode->setLine(node->getLine());
newNode->setOperand(node);
@@ -852,6 +852,36 @@
return true;
}
+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.getRows();
+ case EOpVectorTimesMatrixAssign:
+ return left.getNominalSize() == right.getRows() && left.getNominalSize() == right.getCols();
+ case EOpMatrixTimesVector:
+ return left.getCols() == right.getNominalSize();
+ case EOpMatrixTimesScalar:
+ case EOpMatrixTimesScalarAssign:
+ return true;
+ case EOpMatrixTimesMatrix:
+ return left.getCols() == right.getRows();
+ case EOpMatrixTimesMatrixAssign:
+ return left.getCols() == right.getCols() && left.getRows() == right.getRows();
+
+ default:
+ UNREACHABLE();
+ return false;
+ }
+}
+
//
// Establishes the type of the resultant operation, as well as
// makes the operator the correct one for the operands.
@@ -889,12 +919,12 @@
getTypePointer()->setQualifier(EvqTemporary);
}
- int size = std::max(left->getNominalSize(), right->getNominalSize());
+ const int nominalSize = std::max(left->getNominalSize(), right->getNominalSize());
//
- // All scalars. Code after this test assumes this case is removed!
+ // All scalars or structs. Code after this test assumes this case is removed!
//
- if (size == 1)
+ if (nominalSize == 1)
{
switch (op)
{
@@ -931,20 +961,6 @@
// If we reach here, at least one of the operands is 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;
- }
-
- //
// Can these two operands be combined?
//
TBasicType basicType = left->getBasicType();
@@ -960,7 +976,7 @@
else
{
op = EOpMatrixTimesScalar;
- setType(TType(basicType, higherPrecision, EvqTemporary, size, true));
+ setType(TType(basicType, higherPrecision, EvqTemporary, right->getCols(), right->getRows()));
}
}
else if (left->isMatrix() && !right->isMatrix())
@@ -968,7 +984,7 @@
if (right->isVector())
{
op = EOpMatrixTimesVector;
- setType(TType(basicType, higherPrecision, EvqTemporary, size, false));
+ setType(TType(basicType, higherPrecision, EvqTemporary, left->getRows(), 1));
}
else
{
@@ -988,7 +1004,7 @@
else if (left->isVector() || right->isVector())
{
op = EOpVectorTimesScalar;
- setType(TType(basicType, higherPrecision, EvqTemporary, size, false));
+ setType(TType(basicType, higherPrecision, EvqTemporary, nominalSize, 1));
}
}
else
@@ -996,7 +1012,13 @@
infoSink.info.message(EPrefixInternalError, "Missing elses", getLine());
return false;
}
+
+ if (!validateMultiplication(op, left->getType(), right->getType()))
+ {
+ return false;
+ }
break;
+
case EOpMulAssign:
if (!left->isMatrix() && right->isMatrix())
{
@@ -1035,7 +1057,7 @@
if (! left->isVector())
return false;
op = EOpVectorTimesScalarAssign;
- setType(TType(basicType, higherPrecision, EvqTemporary, size, false));
+ setType(TType(basicType, higherPrecision, EvqTemporary, left->getNominalSize(), 1));
}
}
else
@@ -1043,6 +1065,11 @@
infoSink.info.message(EPrefixInternalError, "Missing elses", getLine());
return false;
}
+
+ if (!validateMultiplication(op, left->getType(), right->getType()))
+ {
+ return false;
+ }
break;
case EOpAssign:
@@ -1053,10 +1080,28 @@
case EOpAddAssign:
case EOpSubAssign:
case EOpDivAssign:
- if ((left->isMatrix() && right->isVector()) ||
- (left->isVector() && right->isMatrix()))
- return false;
- setType(TType(basicType, higherPrecision, EvqTemporary, size, left->isMatrix() || right->isMatrix()));
+ {
+ if ((left->isMatrix() && right->isVector()) ||
+ (left->isVector() && right->isMatrix()))
+ return false;
+
+ // Are the sizes compatible?
+ if (left->getNominalSize() != right->getNominalSize() || left->getSecondarySize() != right->getSecondarySize())
+ {
+ // If the nominal size of operands do not match:
+ // One of them must be scalar.
+ if (!left->isScalar() && !right->isScalar())
+ return false;
+
+ // Operator cannot be of type pure assignment.
+ if (op == EOpAssign || op == EOpInitialize)
+ return false;
+ }
+
+ const int secondarySize = std::max(left->getSecondarySize(), right->getSecondarySize());
+
+ setType(TType(basicType, higherPrecision, EvqTemporary, nominalSize, secondarySize));
+ }
break;
case EOpEqual:
@@ -1065,8 +1110,8 @@
case EOpGreaterThan:
case EOpLessThanEqual:
case EOpGreaterThanEqual:
- if ((left->isMatrix() && right->isVector()) ||
- (left->isVector() && right->isMatrix()))
+ if ((left->getNominalSize() != right->getNominalSize()) ||
+ (left->getSecondarySize() != right->getSecondarySize()))
return false;
setType(TType(EbtBool, EbpUndefined));
break;
@@ -1188,13 +1233,14 @@
return 0;
}
{// support MSVC++6.0
- int size = getNominalSize();
- tempConstArray = new ConstantUnion[size*size];
- for (int row = 0; row < size; row++) {
- for (int column = 0; column < size; column++) {
- tempConstArray[size * column + row].setFConst(0.0f);
- for (int i = 0; i < size; i++) {
- tempConstArray[size * column + row].setFConst(tempConstArray[size * column + row].getFConst() + unionArray[i * size + row].getFConst() * (rightUnionArray[column * size + i].getFConst()));
+ int cols = getCols();
+ int rows = getRows();
+ tempConstArray = new ConstantUnion[cols*rows];
+ for (int row = 0; row < rows; row++) {
+ for (int column = 0; column < cols; column++) {
+ tempConstArray[rows * column + row].setFConst(0.0f);
+ for (int i = 0; i < cols; i++) {
+ tempConstArray[rows * column + row].setFConst(tempConstArray[rows * column + row].getFConst() + unionArray[i * rows + row].getFConst() * (rightUnionArray[column * rows + i].getFConst()));
}
}
}
@@ -1488,7 +1534,7 @@
const TType& t = node->getType();
- return addConstantUnion(leftUnionArray, TType(promoteTo, t.getPrecision(), t.getQualifier(), t.getNominalSize(), t.isMatrix(), t.isArray()), node->getLine());
+ return addConstantUnion(leftUnionArray, TType(promoteTo, t.getPrecision(), t.getQualifier(), t.getNominalSize(), t.getSecondarySize(), t.isArray()), node->getLine());
}
// static
diff --git a/src/compiler/OutputHLSL.cpp b/src/compiler/OutputHLSL.cpp
index 0992c97..d54d3db 100644
--- a/src/compiler/OutputHLSL.cpp
+++ b/src/compiler/OutputHLSL.cpp
@@ -150,7 +150,7 @@
int OutputHLSL::vectorSize(const TType &type) const
{
- int elementSize = type.isMatrix() ? type.getNominalSize() : 1;
+ int elementSize = type.isMatrix() ? type.getRows() : 1;
int arraySize = type.isArray() ? type.getArraySize() : 1;
return elementSize * arraySize;
@@ -1573,7 +1573,7 @@
{
if (node->getLeft()->isMatrix())
{
- switch (node->getLeft()->getNominalSize())
+ switch (node->getLeft()->getRows())
{
case 2: mUsesEqualMat2 = true; break;
case 3: mUsesEqualMat3 = true; break;
@@ -2210,8 +2210,9 @@
case EOpMod:
{
// We need to look at the number of components in both arguments
- switch (node->getSequence()[0]->getAsTyped()->getNominalSize() * 10
- + node->getSequence()[1]->getAsTyped()->getNominalSize())
+ const int modValue = node->getSequence()[0]->getAsTyped()->getNominalSize() * 10
+ + node->getSequence()[1]->getAsTyped()->getNominalSize();
+ switch (modValue)
{
case 11: mUsesMod1 = true; break;
case 22: mUsesMod2v = true; break;
@@ -2525,7 +2526,7 @@
if (symbol && constant)
{
- if (constant->getBasicType() == EbtInt && constant->getNominalSize() == 1)
+ if (constant->getBasicType() == EbtInt && constant->isScalar())
{
index = symbol;
initial = constant->getIConst(0);
@@ -2547,7 +2548,7 @@
if (constant)
{
- if (constant->getBasicType() == EbtInt && constant->getNominalSize() == 1)
+ if (constant->getBasicType() == EbtInt && constant->isScalar())
{
comparator = test->getOp();
limit = constant->getIConst(0);
@@ -2569,7 +2570,7 @@
if (constant)
{
- if (constant->getBasicType() == EbtInt && constant->getNominalSize() == 1)
+ if (constant->getBasicType() == EbtInt && constant->isScalar())
{
int value = constant->getIConst(0);
@@ -2815,7 +2816,7 @@
}
else if (type.isMatrix())
{
- switch (type.getNominalSize())
+ switch (type.getRows())
{
case 2: return "float2x2";
case 3: return "float3x3";
@@ -3015,18 +3016,19 @@
if (ctorType.isMatrix() && ctorParameters.size() == 1)
{
- int dim = ctorType.getNominalSize();
+ int rows = ctorType.getRows();
+ int cols = ctorType.getCols();
const TType ¶meter = ctorParameters[0];
if (parameter.isScalar())
{
- for (int row = 0; row < dim; row++)
+ for (int row = 0; row < rows; row++)
{
- for (int col = 0; col < dim; col++)
+ for (int col = 0; col < cols; col++)
{
constructor += TString((row == col) ? "x0" : "0.0");
- if (row < dim - 1 || col < dim - 1)
+ if (row < rows - 1 || col < cols - 1)
{
constructor += ", ";
}
@@ -3035,11 +3037,11 @@
}
else if (parameter.isMatrix())
{
- for (int row = 0; row < dim; row++)
+ for (int row = 0; row < rows; row++)
{
- for (int col = 0; col < dim; col++)
+ for (int col = 0; col < cols; col++)
{
- if (row < parameter.getNominalSize() && col < parameter.getNominalSize())
+ if (row < parameter.getRows() && col < parameter.getCols())
{
constructor += TString("x0") + "[" + str(row) + "]" + "[" + str(col) + "]";
}
@@ -3048,7 +3050,7 @@
constructor += TString((row == col) ? "1.0" : "0.0");
}
- if (row < dim - 1 || col < dim - 1)
+ if (row < rows - 1 || col < cols - 1)
{
constructor += ", ";
}
@@ -3079,7 +3081,7 @@
{
remainingComponents -= parameter.getObjectSize();
}
- else if (remainingComponents < parameter.getNominalSize())
+ else if (remainingComponents < parameter.getCols())
{
switch (remainingComponents)
{
@@ -3350,7 +3352,7 @@
}
else if (type.isMatrix())
{
- switch(type.getNominalSize())
+ switch(type.getRows())
{
case 2: return GL_FLOAT_MAT2;
case 3: return GL_FLOAT_MAT3;
diff --git a/src/compiler/ParseHelper.cpp b/src/compiler/ParseHelper.cpp
index 9295e0b..abae00b 100644
--- a/src/compiler/ParseHelper.cpp
+++ b/src/compiler/ParseHelper.cpp
@@ -115,7 +115,7 @@
// Look at a '.' field selector string and change it into offsets
// 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.wholeCol = false;
@@ -151,7 +151,7 @@
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());
return false;
}
@@ -396,7 +396,7 @@
//
bool TParseContext::integerErrorCheck(TIntermTyped* node, const char* token)
{
- if (node->getBasicType() == EbtInt && node->getNominalSize() == 1)
+ if (node->getBasicType() == EbtInt && node->isScalar())
return false;
error(node->getLine(), "integer expression required", token);
@@ -599,7 +599,7 @@
//
bool TParseContext::boolErrorCheck(int line, const TPublicType& pType)
{
- if (pType.type != EbtBool || pType.array || pType.matrix || (pType.size > 1)) {
+ if (pType.type != EbtBool || pType.isAggregate()) {
error(line, "boolean expression expected", "");
return true;
}
@@ -1355,7 +1355,7 @@
TIntermTyped* typedNode;
TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion();
- if (index >= node->getType().getNominalSize()) {
+ if (index >= node->getType().getRows()) {
std::stringstream extraInfoStream;
extraInfoStream << "matrix field selection out of range '" << index << "'";
std::string extraInfo = extraInfoStream.str();
@@ -1366,7 +1366,7 @@
if (tempConstantNode) {
ConstantUnion* unionArray = tempConstantNode->getUnionArrayPointer();
- int size = tempConstantNode->getType().getNominalSize();
+ int size = tempConstantNode->getType().getCols();
typedNode = intermediate.addConstantUnion(&unionArray[size*index], tempConstantNode->getType(), line);
} else {
error(line, "Cannot offset into the matrix", "Error");
@@ -1642,7 +1642,11 @@
{
if (indexExpression->getQualifier() == EvqConst)
{
- if ((baseExpression->isVector() || baseExpression->isMatrix()) && baseExpression->getType().getNominalSize() <= indexExpression->getAsConstantUnion()->getIConst(0) && !baseExpression->isArray() )
+ const bool isMatrixOrVector = (baseExpression->isVector() || baseExpression->isMatrix());
+ const bool indexOOR = (isMatrixOrVector && baseExpression->getType().getNominalSize() <= indexExpression->getAsConstantUnion()->getIConst(0));
+
+ // check for index out-of-range
+ if (indexOOR && !baseExpression->isArray())
{
std::stringstream extraInfoStream;
extraInfoStream << "field selection out of range '" << indexExpression->getAsConstantUnion()->getIConst(0) << "'";
@@ -1711,7 +1715,7 @@
}
else
{
- indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision(), EvqTemporary, baseExpression->getNominalSize(), baseExpression->isMatrix()));
+ indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision(), EvqTemporary, baseExpression->getNominalSize(), baseExpression->getSecondarySize()));
}
if (baseExpression->getType().getQualifier() == EvqConst)
@@ -1721,11 +1725,11 @@
}
else if (baseExpression->isMatrix() && baseExpression->getType().getQualifier() == EvqConst)
{
- indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision(), EvqConst, baseExpression->getNominalSize()));
+ indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision(), EvqConst, baseExpression->getRows()));
}
else if (baseExpression->isMatrix())
{
- indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision(), EvqTemporary, baseExpression->getNominalSize()));
+ indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision(), EvqTemporary, baseExpression->getRows()));
}
else if (baseExpression->isVector() && baseExpression->getType().getQualifier() == EvqConst)
{
@@ -1788,7 +1792,7 @@
else if (baseExpression->isMatrix())
{
TMatrixFields fields;
- if (!parseMatrixFields(fieldString, baseExpression->getNominalSize(), fields, fieldLocation))
+ if (!parseMatrixFields(fieldString, baseExpression->getCols(), baseExpression->getRows(), fields, fieldLocation))
{
fields.wholeRow = false;
fields.wholeCol = false;
@@ -1805,12 +1809,12 @@
unionArray->setIConst(0);
TIntermTyped* index = intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), fieldLocation);
indexedExpression = intermediate.addIndex(EOpIndexDirect, baseExpression, index, dotLocation);
- indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision(),EvqTemporary, baseExpression->getNominalSize()));
+ indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision(),EvqTemporary, baseExpression->getCols(), baseExpression->getRows()));
}
else
{
ConstantUnion *unionArray = new ConstantUnion[1];
- unionArray->setIConst(fields.col * baseExpression->getNominalSize() + fields.row);
+ unionArray->setIConst(fields.col * baseExpression->getRows() + fields.row);
TIntermTyped* index = intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), fieldLocation);
indexedExpression = intermediate.addIndex(EOpIndexDirect, baseExpression, index, dotLocation);
indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision()));
@@ -1938,8 +1942,8 @@
//
TType* type = (*typeList)[i].type;
type->setBasicType(typeSpecifier.type);
- type->setNominalSize(typeSpecifier.size);
- type->setMatrix(typeSpecifier.matrix);
+ type->setPrimarySize(typeSpecifier.primarySize);
+ type->setSecondarySize(typeSpecifier.secondarySize);
type->setPrecision(typeSpecifier.precision);
type->setQualifier(typeSpecifier.qualifier);
diff --git a/src/compiler/ParseHelper.h b/src/compiler/ParseHelper.h
index db748d4..88fd8e0 100644
--- a/src/compiler/ParseHelper.h
+++ b/src/compiler/ParseHelper.h
@@ -79,7 +79,7 @@
void recover();
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);
void assignError(int line, const char* op, TString left, TString right);
diff --git a/src/compiler/SymbolTable.cpp b/src/compiler/SymbolTable.cpp
index ae1d7f2..c6e9fcb 100644
--- a/src/compiler/SymbolTable.cpp
+++ b/src/compiler/SymbolTable.cpp
@@ -21,7 +21,7 @@
#include "common/angleutils.h"
TType::TType(const TPublicType &p) :
- type(p.type), precision(p.precision), qualifier(p.qualifier), size(p.size), matrix(p.matrix), array(p.array), arraySize(p.arraySize),
+ type(p.type), precision(p.precision), qualifier(p.qualifier), primarySize(p.primarySize), secondarySize(p.secondarySize), array(p.array), arraySize(p.arraySize),
maxArraySize(0), arrayInformationType(0), interfaceBlockType(0), structure(0), structureSize(0), deepestStructNesting(0), fieldName(0), mangled(0), typeName(0)
{
if (p.userDef) {
@@ -76,7 +76,16 @@
break;
}
- mangledName += static_cast<char>('0' + getNominalSize());
+ if (isMatrix())
+ {
+ mangledName += static_cast<char>('0' + getCols());
+ mangledName += static_cast<char>('x');
+ mangledName += static_cast<char>('0' + getRows());
+ }
+ else
+ {
+ mangledName += static_cast<char>('0' + getNominalSize());
+ }
if (isArray()) {
char buf[20];
snprintf(buf, sizeof(buf), "%d", arraySize);
diff --git a/src/compiler/SymbolTable.h b/src/compiler/SymbolTable.h
index 1d526cf..8ad6633 100644
--- a/src/compiler/SymbolTable.h
+++ b/src/compiler/SymbolTable.h
@@ -333,7 +333,7 @@
return true; // Skip sampler types for the time being
if (type.type != EbtFloat && type.type != EbtInt)
return false; // Only set default precision for int/float
- if (type.size != 1 || type.matrix || type.array)
+ if (type.isAggregate())
return false; // Not allowed to set for aggregate types
int indexOfLastElement = static_cast<int>(precisionStack.size()) - 1;
precisionStack[indexOfLastElement][type.type] = prec; // Uses map operator [], overwrites the current value
diff --git a/src/compiler/Types.h b/src/compiler/Types.h
index 7124cd6..ecc9e8a 100644
--- a/src/compiler/Types.h
+++ b/src/compiler/Types.h
@@ -40,14 +40,14 @@
public:
POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)
TType() {}
- TType(TBasicType t, TPrecision p, TQualifier q = EvqTemporary, int s = 1, bool m = false, bool a = false) :
- type(t), precision(p), qualifier(q), size(s), matrix(m), array(a), arraySize(0),
+ TType(TBasicType t, TPrecision p, TQualifier q = EvqTemporary, int ps = 1, int ss = 1, bool a = false) :
+ type(t), precision(p), qualifier(q), primarySize(ps), secondarySize(ss), array(a), arraySize(0),
maxArraySize(0), arrayInformationType(0), interfaceBlockType(0), structure(0), structureSize(0), deepestStructNesting(0), fieldName(0), mangled(0), typeName(0), instanceName(0)
{
}
explicit TType(const TPublicType &p);
TType(TTypeList* userDef, const TString& n, TPrecision p = EbpUndefined) :
- type(EbtStruct), precision(p), qualifier(EvqTemporary), size(1), matrix(false), array(false), arraySize(0),
+ type(EbtStruct), precision(p), qualifier(EvqTemporary), primarySize(1), secondarySize(1), array(false), arraySize(0),
maxArraySize(0), arrayInformationType(0), interfaceBlockType(0), structure(userDef), structureSize(0), deepestStructNesting(0), fieldName(0), mangled(0), instanceName(0)
{
typeName = NewPoolTString(n.c_str());
@@ -58,8 +58,8 @@
type = copyOf.type;
precision = copyOf.precision;
qualifier = copyOf.qualifier;
- size = copyOf.size;
- matrix = copyOf.matrix;
+ primarySize = copyOf.primarySize;
+ secondarySize = copyOf.secondarySize;
array = copyOf.array;
arraySize = copyOf.arraySize;
@@ -120,9 +120,13 @@
TQualifier getQualifier() const { return qualifier; }
void setQualifier(TQualifier q) { qualifier = q; }
- // One-dimensional size of single instance type
- int getNominalSize() const { return size; }
- void setNominalSize(int s) { size = s; }
+ int getNominalSize() const { return primarySize; }
+ int getSecondarySize() const { return secondarySize; }
+ int getCols() const { ASSERT(isMatrix()); return primarySize; }
+ int getRows() const { ASSERT(isMatrix()); return secondarySize; }
+ void setPrimarySize(int ps) { primarySize = ps; }
+ void setSecondarySize(int ss) { secondarySize = ss; }
+
// Full size of single instance of type
int getObjectSize() const
{
@@ -130,10 +134,8 @@
if (getBasicType() == EbtStruct)
totalSize = getStructSize();
- else if (matrix)
- totalSize = size * size;
else
- totalSize = size;
+ totalSize = primarySize * secondarySize;
if (isArray())
totalSize *= std::max(getArraySize(), getMaxArraySize());
@@ -158,7 +160,7 @@
}
else if (isMatrix())
{
- return getNominalSize();
+ return getRows();
}
else
{
@@ -178,9 +180,7 @@
}
}
- bool isMatrix() const { return matrix ? true : false; }
- void setMatrix(bool m) { matrix = m; }
-
+ bool isMatrix() const { return primarySize > 1 && secondarySize > 1; }
bool isArray() const { return array ? true : false; }
int getArraySize() const { return arraySize; }
void setArraySize(int s) { array = true; arraySize = s; }
@@ -193,8 +193,8 @@
TType* getInterfaceBlockType() const { return interfaceBlockType; }
bool isInterfaceBlockMember() const { return interfaceBlockType != NULL; }
- bool isVector() const { return size > 1 && !matrix; }
- bool isScalar() const { return size == 1 && !matrix && !structure; }
+ bool isVector() const { return primarySize > 1 && secondarySize == 1; }
+ bool isScalar() const { return primarySize == 1 && secondarySize == 1 && !structure; }
TTypeList* getStruct() const { return structure; }
void setStruct(TTypeList* s) { structure = s; computeDeepestStructNesting(); }
@@ -250,16 +250,16 @@
}
bool sameElementType(const TType& right) const {
- return type == right.type &&
- size == right.size &&
- matrix == right.matrix &&
+ return type == right.type &&
+ primarySize == right.primarySize &&
+ secondarySize == right.secondarySize &&
structure == right.structure;
}
bool operator==(const TType& right) const {
- return type == right.type &&
- size == right.size &&
- matrix == right.matrix &&
- array == right.array && (!array || arraySize == right.arraySize) &&
+ return type == right.type &&
+ primarySize == right.primarySize &&
+ secondarySize == right.secondarySize &&
+ array == right.array && (!array || arraySize == right.arraySize) &&
structure == right.structure;
// don't check the qualifier, it's not ever what's being sought after
}
@@ -268,8 +268,8 @@
}
bool operator<(const TType& right) const {
if (type != right.type) return type < right.type;
- if (size != right.size) return size < right.size;
- if (matrix != right.matrix) return matrix < right.matrix;
+ if (primarySize != right.primarySize) return primarySize < right.primarySize;
+ if (secondarySize != right.secondarySize) return secondarySize < right.secondarySize;
if (array != right.array) return array < right.array;
if (arraySize != right.arraySize) return arraySize < right.arraySize;
if (structure != right.structure) return structure < right.structure;
@@ -306,9 +306,9 @@
TBasicType type : 6;
TPrecision precision : 4;
TQualifier qualifier : 7;
- int size : 8; // size of vector or matrix, not size of array
- unsigned int matrix : 1;
unsigned int array : 1;
+ int primarySize; // size of vector or cols matrix
+ int secondarySize; // rows of a matrix
int arraySize;
int maxArraySize;
TType* arrayInformationType;
@@ -338,8 +338,8 @@
TBasicType type;
TQualifier qualifier;
TPrecision precision;
- int size; // size of vector or matrix, not size of array
- bool matrix;
+ int primarySize; // size of vector or cols of matrix
+ int secondarySize; // rows of matrix
bool array;
int arraySize;
TType* userDef;
@@ -350,18 +350,24 @@
type = bt;
qualifier = q;
precision = EbpUndefined;
- size = 1;
- matrix = false;
+ primarySize = 1;
+ secondarySize = 1;
array = false;
arraySize = 0;
userDef = 0;
line = ln;
}
- void setAggregate(int s, bool m = false)
+ void setAggregate(int size)
{
- size = s;
- matrix = m;
+ primarySize = size;
+ }
+
+ void setMatrix(int c, int r)
+ {
+ ASSERT(c > 1 && r > 1 && c <= 4 && r <= 4);
+ primarySize = c;
+ secondarySize = r;
}
void setArray(bool a, int s = 0)
@@ -379,6 +385,38 @@
return userDef->isStructureContainingArrays();
}
+
+ bool isMatrix() const
+ {
+ return primarySize > 1 && secondarySize > 1;
+ }
+
+ bool isVector() const
+ {
+ return primarySize > 1 && secondarySize == 1;
+ }
+
+ int getCols() const
+ {
+ ASSERT(isMatrix());
+ return primarySize;
+ }
+
+ int getRows() const
+ {
+ ASSERT(isMatrix());
+ return secondarySize;
+ }
+
+ int getNominalSize() const
+ {
+ return primarySize;
+ }
+
+ bool isAggregate() const
+ {
+ return array || isMatrix() || isVector();
+ }
};
#endif // _TYPES_INCLUDED_
diff --git a/src/compiler/VariableInfo.cpp b/src/compiler/VariableInfo.cpp
index bf7a13e..a1f41ad 100644
--- a/src/compiler/VariableInfo.cpp
+++ b/src/compiler/VariableInfo.cpp
@@ -19,7 +19,7 @@
switch (type.getBasicType()) {
case EbtFloat:
if (type.isMatrix()) {
- switch (type.getNominalSize()) {
+ switch (type.getRows()) {
case 2: return SH_FLOAT_MAT2;
case 3: return SH_FLOAT_MAT3;
case 4: return SH_FLOAT_MAT4;
diff --git a/src/compiler/glslang.y b/src/compiler/glslang.y
index 7c9352c..93ec4a0 100644
--- a/src/compiler/glslang.y
+++ b/src/compiler/glslang.y
@@ -459,14 +459,14 @@
} else {
switch ($1.type) {
case EbtFloat:
- if ($1.matrix) {
- switch($1.size) {
+ if ($1.isMatrix()) {
+ switch($1.getCols()) {
case 2: op = EOpConstructMat2; break;
case 3: op = EOpConstructMat3; break;
case 4: op = EOpConstructMat4; break;
}
} else {
- switch($1.size) {
+ switch($1.getNominalSize()) {
case 1: op = EOpConstructFloat; break;
case 2: op = EOpConstructVec2; break;
case 3: op = EOpConstructVec3; break;
@@ -475,7 +475,7 @@
}
break;
case EbtInt:
- switch($1.size) {
+ switch($1.getNominalSize()) {
case 1: op = EOpConstructInt; break;
case 2: FRAG_VERT_ONLY("ivec2", $1.line); op = EOpConstructIVec2; break;
case 3: FRAG_VERT_ONLY("ivec3", $1.line); op = EOpConstructIVec3; break;
@@ -483,7 +483,7 @@
}
break;
case EbtBool:
- switch($1.size) {
+ switch($1.getNominalSize()) {
case 1: op = EOpConstructBool; break;
case 2: FRAG_VERT_ONLY("bvec2", $1.line); op = EOpConstructBVec2; break;
case 3: FRAG_VERT_ONLY("bvec3", $1.line); op = EOpConstructBVec3; break;
@@ -1592,19 +1592,19 @@
FRAG_VERT_ONLY("mat2", $1.line);
TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
$$.setBasic(EbtFloat, qual, $1.line);
- $$.setAggregate(2, true);
+ $$.setMatrix(2, 2);
}
| MATRIX3 {
FRAG_VERT_ONLY("mat3", $1.line);
TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
$$.setBasic(EbtFloat, qual, $1.line);
- $$.setAggregate(3, true);
+ $$.setMatrix(3, 3);
}
| MATRIX4 {
FRAG_VERT_ONLY("mat4", $1.line);
TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
$$.setBasic(EbtFloat, qual, $1.line);
- $$.setAggregate(4, true);
+ $$.setMatrix(4, 4);
}
| SAMPLER2D {
FRAG_VERT_ONLY("sampler2D", $1.line);
diff --git a/src/compiler/glslang_tab.cpp b/src/compiler/glslang_tab.cpp
index b97405f..7504bca 100644
--- a/src/compiler/glslang_tab.cpp
+++ b/src/compiler/glslang_tab.cpp
@@ -2540,14 +2540,14 @@
} else {
switch ((yyvsp[(1) - (1)].interm.type).type) {
case EbtFloat:
- if ((yyvsp[(1) - (1)].interm.type).matrix) {
- switch((yyvsp[(1) - (1)].interm.type).size) {
+ if ((yyvsp[(1) - (1)].interm.type).isMatrix()) {
+ switch((yyvsp[(1) - (1)].interm.type).getCols()) {
case 2: op = EOpConstructMat2; break;
case 3: op = EOpConstructMat3; break;
case 4: op = EOpConstructMat4; break;
}
} else {
- switch((yyvsp[(1) - (1)].interm.type).size) {
+ switch((yyvsp[(1) - (1)].interm.type).getNominalSize()) {
case 1: op = EOpConstructFloat; break;
case 2: op = EOpConstructVec2; break;
case 3: op = EOpConstructVec3; break;
@@ -2556,7 +2556,7 @@
}
break;
case EbtInt:
- switch((yyvsp[(1) - (1)].interm.type).size) {
+ switch((yyvsp[(1) - (1)].interm.type).getNominalSize()) {
case 1: op = EOpConstructInt; break;
case 2: FRAG_VERT_ONLY("ivec2", (yyvsp[(1) - (1)].interm.type).line); op = EOpConstructIVec2; break;
case 3: FRAG_VERT_ONLY("ivec3", (yyvsp[(1) - (1)].interm.type).line); op = EOpConstructIVec3; break;
@@ -2564,7 +2564,7 @@
}
break;
case EbtBool:
- switch((yyvsp[(1) - (1)].interm.type).size) {
+ switch((yyvsp[(1) - (1)].interm.type).getNominalSize()) {
case 1: op = EOpConstructBool; break;
case 2: FRAG_VERT_ONLY("bvec2", (yyvsp[(1) - (1)].interm.type).line); op = EOpConstructBVec2; break;
case 3: FRAG_VERT_ONLY("bvec3", (yyvsp[(1) - (1)].interm.type).line); op = EOpConstructBVec3; break;
@@ -3940,7 +3940,7 @@
FRAG_VERT_ONLY("mat2", (yyvsp[(1) - (1)].lex).line);
TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
(yyval.interm.type).setBasic(EbtFloat, qual, (yyvsp[(1) - (1)].lex).line);
- (yyval.interm.type).setAggregate(2, true);
+ (yyval.interm.type).setMatrix(2, 2);
}
break;
@@ -3950,7 +3950,7 @@
FRAG_VERT_ONLY("mat3", (yyvsp[(1) - (1)].lex).line);
TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
(yyval.interm.type).setBasic(EbtFloat, qual, (yyvsp[(1) - (1)].lex).line);
- (yyval.interm.type).setAggregate(3, true);
+ (yyval.interm.type).setMatrix(3, 3);
}
break;
@@ -3960,7 +3960,7 @@
FRAG_VERT_ONLY("mat4", (yyvsp[(1) - (1)].lex).line);
TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
(yyval.interm.type).setBasic(EbtFloat, qual, (yyvsp[(1) - (1)].lex).line);
- (yyval.interm.type).setAggregate(4, true);
+ (yyval.interm.type).setMatrix(4, 4);
}
break;
diff --git a/src/compiler/intermOut.cpp b/src/compiler/intermOut.cpp
index be4358c..c3a442a 100644
--- a/src/compiler/intermOut.cpp
+++ b/src/compiler/intermOut.cpp
@@ -43,10 +43,10 @@
stream << getQualifierString() << " " << getPrecisionString() << " ";
if (array)
stream << "array[" << getArraySize() << "] of ";
- if (matrix)
- stream << size << "X" << size << " matrix of ";
- else if (size > 1)
- stream << size << "-component vector of ";
+ if (isMatrix())
+ stream << getCols() << "X" << getRows() << " matrix of ";
+ else if (isVector())
+ stream << getNominalSize() << "-component vector of ";
stream << getBasicString();
return stream.str();
diff --git a/src/compiler/intermediate.h b/src/compiler/intermediate.h
index 6834c84..e980ac4 100644
--- a/src/compiler/intermediate.h
+++ b/src/compiler/intermediate.h
@@ -250,7 +250,10 @@
TBasicType getBasicType() const { return type.getBasicType(); }
TQualifier getQualifier() const { return type.getQualifier(); }
TPrecision getPrecision() const { return type.getPrecision(); }
+ int getCols() const { return type.getCols(); }
+ int getRows() const { return type.getRows(); }
int getNominalSize() const { return type.getNominalSize(); }
+ int getSecondarySize() const { return type.getSecondarySize(); }
bool isMatrix() const { return type.isMatrix(); }
bool isArray() const { return type.isArray(); }
diff --git a/src/compiler/parseConst.cpp b/src/compiler/parseConst.cpp
index 421d31f..d7b3498 100644
--- a/src/compiler/parseConst.cpp
+++ b/src/compiler/parseConst.cpp
@@ -119,7 +119,7 @@
if (node->getType().isMatrix()) {
isMatrix = true;
- matrixSize = node->getType().getNominalSize();
+ matrixSize = node->getType().getRows();
}
}
@@ -165,10 +165,10 @@
return;
if (!singleConstantParam) {
- int size = node->getType().getObjectSize();
+ int objectSize = node->getType().getObjectSize();
ConstantUnion *rightUnionArray = node->getUnionArrayPointer();
- for (int i=0; i < size; i++) {
+ for (int i=0; i < objectSize; i++) {
if (index >= instanceSize)
return;
leftUnionArray[index] = rightUnionArray[i];