Make aggregate node creation more robust
Now aggregate nodes are always built with their return type, op and
arguments set. They'll determine their qualifier and precision
automatically.
This fixes setting of gotPrecisionFromChildren in a few cases.
This will also make it easier to split TIntermAggregate further into
specialized classes if that is desired.
BUG=angleproject:1490
TEST=angle_unittests
Change-Id: I1fbe0c75679c517a22d44dfc1ea160ad7a7fdfda
Reviewed-on: https://chromium-review.googlesource.com/433468
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Jamie Madill <jmadill@chromium.org>
Commit-Queue: Olli Etuaho <oetuaho@nvidia.com>
diff --git a/src/compiler/translator/IntermNode.cpp b/src/compiler/translator/IntermNode.cpp
index 6bf2aa8..276b653 100644
--- a/src/compiler/translator/IntermNode.cpp
+++ b/src/compiler/translator/IntermNode.cpp
@@ -272,12 +272,48 @@
return true;
}
+TIntermAggregate::TIntermAggregate(const TType &type, TOperator op, TIntermSequence *arguments)
+ : TIntermOperator(op), mUseEmulatedFunction(false), mGotPrecisionFromChildren(false)
+{
+ if (arguments != nullptr)
+ {
+ mArguments.swap(*arguments);
+ }
+ setTypePrecisionAndQualifier(type);
+}
+
+void TIntermAggregate::setTypePrecisionAndQualifier(const TType &type)
+{
+ setType(type);
+ mType.setQualifier(EvqTemporary);
+ if (!isFunctionCall())
+ {
+ if (isConstructor())
+ {
+ // Structs should not be precision qualified, the individual members may be.
+ // Built-in types on the other hand should be precision qualified.
+ if (mOp != EOpConstructStruct)
+ {
+ setPrecisionFromChildren();
+ }
+ }
+ else
+ {
+ setPrecisionForBuiltInOp();
+ }
+ if (areChildrenConstQualified())
+ {
+ mType.setQualifier(EvqConst);
+ }
+ }
+}
+
bool TIntermAggregate::areChildrenConstQualified()
{
- for (TIntermNode *&child : mSequence)
+ for (TIntermNode *&arg : mArguments)
{
- TIntermTyped *typed = child->getAsTyped();
- if (typed && typed->getQualifier() != EvqConst)
+ TIntermTyped *typedArg = arg->getAsTyped();
+ if (typedArg && typedArg->getQualifier() != EvqConst)
{
return false;
}
@@ -295,8 +331,8 @@
}
TPrecision precision = EbpUndefined;
- TIntermSequence::iterator childIter = mSequence.begin();
- while (childIter != mSequence.end())
+ TIntermSequence::iterator childIter = mArguments.begin();
+ while (childIter != mArguments.end())
{
TIntermTyped *typed = (*childIter)->getAsTyped();
if (typed)
@@ -321,11 +357,13 @@
switch (mOp)
{
case EOpBitfieldExtract:
- mType.setPrecision(mSequence[0]->getAsTyped()->getPrecision());
+ mType.setPrecision(mArguments[0]->getAsTyped()->getPrecision());
+ mGotPrecisionFromChildren = true;
return true;
case EOpBitfieldInsert:
- mType.setPrecision(GetHigherPrecision(mSequence[0]->getAsTyped()->getPrecision(),
- mSequence[1]->getAsTyped()->getPrecision()));
+ mType.setPrecision(GetHigherPrecision(mArguments[0]->getAsTyped()->getPrecision(),
+ mArguments[1]->getAsTyped()->getPrecision()));
+ mGotPrecisionFromChildren = true;
return true;
case EOpUaddCarry:
case EOpUsubBorrow:
@@ -342,18 +380,16 @@
ASSERT(getBasicType() != EbtBool);
ASSERT(mOp == EOpCallBuiltInFunction);
- TPrecision precision = EbpUndefined;
- TIntermSequence::iterator childIter = mSequence.begin();
- while (childIter != mSequence.end())
+ TPrecision precision = EbpUndefined;
+ for (TIntermNode *arg : mArguments)
{
- TIntermTyped *typed = (*childIter)->getAsTyped();
+ TIntermTyped *typed = arg->getAsTyped();
// ESSL spec section 8: texture functions get their precision from the sampler.
if (typed && IsSampler(typed->getBasicType()))
{
precision = typed->getPrecision();
break;
}
- ++childIter;
}
// ESSL 3.0 spec section 8: textureSize always gets highp precision.
// All other functions that take a sampler are assumed to be texture functions.
@@ -497,8 +533,7 @@
return node;
}
- TIntermAggregate *constructor = new TIntermAggregate(sh::TypeToConstructorOperator(type));
- constructor->setType(constType);
+ TIntermSequence *arguments = new TIntermSequence();
if (type.isArray())
{
@@ -508,7 +543,7 @@
size_t arraySize = type.getArraySize();
for (size_t i = 0; i < arraySize; ++i)
{
- constructor->getSequence()->push_back(CreateZero(elementType));
+ arguments->push_back(CreateZero(elementType));
}
}
else
@@ -518,11 +553,11 @@
TStructure *structure = type.getStruct();
for (const auto &field : structure->fields())
{
- constructor->getSequence()->push_back(CreateZero(*field->type()));
+ arguments->push_back(CreateZero(*field->type()));
}
}
- return constructor;
+ return new TIntermAggregate(constType, sh::TypeToConstructorOperator(type), arguments);
}
// static
@@ -553,12 +588,12 @@
mGotPrecisionFromChildren(node.mGotPrecisionFromChildren),
mFunctionInfo(node.mFunctionInfo)
{
- for (TIntermNode *child : node.mSequence)
+ for (TIntermNode *arg : node.mArguments)
{
- TIntermTyped *typedChild = child->getAsTyped();
- ASSERT(typedChild != nullptr);
- TIntermTyped *childCopy = typedChild->deepCopy();
- mSequence.push_back(childCopy);
+ TIntermTyped *typedArg = arg->getAsTyped();
+ ASSERT(typedArg != nullptr);
+ TIntermTyped *argCopy = typedArg->deepCopy();
+ mArguments.push_back(argCopy);
}
}
@@ -1308,8 +1343,7 @@
constArray = TIntermConstantUnion::FoldAggregateBuiltIn(this, diagnostics);
// Nodes may be constant folded without being qualified as constant.
- TQualifier resultQualifier = areChildrenConstQualified() ? EvqConst : EvqTemporary;
- return CreateFoldedNode(constArray, this, resultQualifier);
+ return CreateFoldedNode(constArray, this, getQualifier());
}
//
@@ -2417,32 +2451,32 @@
TDiagnostics *diagnostics)
{
TOperator op = aggregate->getOp();
- TIntermSequence *sequence = aggregate->getSequence();
- unsigned int paramsCount = static_cast<unsigned int>(sequence->size());
- std::vector<const TConstantUnion *> unionArrays(paramsCount);
- std::vector<size_t> objectSizes(paramsCount);
+ TIntermSequence *arguments = aggregate->getSequence();
+ unsigned int argsCount = static_cast<unsigned int>(arguments->size());
+ std::vector<const TConstantUnion *> unionArrays(argsCount);
+ std::vector<size_t> objectSizes(argsCount);
size_t maxObjectSize = 0;
TBasicType basicType = EbtVoid;
TSourceLoc loc;
- for (unsigned int i = 0; i < paramsCount; i++)
+ for (unsigned int i = 0; i < argsCount; i++)
{
- TIntermConstantUnion *paramConstant = (*sequence)[i]->getAsConstantUnion();
- ASSERT(paramConstant != nullptr); // Should be checked already.
+ TIntermConstantUnion *argConstant = (*arguments)[i]->getAsConstantUnion();
+ ASSERT(argConstant != nullptr); // Should be checked already.
if (i == 0)
{
- basicType = paramConstant->getType().getBasicType();
- loc = paramConstant->getLine();
+ basicType = argConstant->getType().getBasicType();
+ loc = argConstant->getLine();
}
- unionArrays[i] = paramConstant->getUnionArrayPointer();
- objectSizes[i] = paramConstant->getType().getObjectSize();
+ unionArrays[i] = argConstant->getUnionArrayPointer();
+ objectSizes[i] = argConstant->getType().getObjectSize();
if (objectSizes[i] > maxObjectSize)
maxObjectSize = objectSizes[i];
}
- if (!(*sequence)[0]->getAsTyped()->isMatrix() && aggregate->getOp() != EOpOuterProduct)
+ if (!(*arguments)[0]->getAsTyped()->isMatrix() && aggregate->getOp() != EOpOuterProduct)
{
- for (unsigned int i = 0; i < paramsCount; i++)
+ for (unsigned int i = 0; i < argsCount; i++)
if (objectSizes[i] != maxObjectSize)
unionArrays[i] = Vectorize(*unionArrays[i], maxObjectSize);
}
@@ -2791,11 +2825,11 @@
case EOpMulMatrixComponentWise:
{
- ASSERT(basicType == EbtFloat && (*sequence)[0]->getAsTyped()->isMatrix() &&
- (*sequence)[1]->getAsTyped()->isMatrix());
+ ASSERT(basicType == EbtFloat && (*arguments)[0]->getAsTyped()->isMatrix() &&
+ (*arguments)[1]->getAsTyped()->isMatrix());
// Perform component-wise matrix multiplication.
resultArray = new TConstantUnion[maxObjectSize];
- int size = (*sequence)[0]->getAsTyped()->getNominalSize();
+ int size = (*arguments)[0]->getAsTyped()->getNominalSize();
angle::Matrix<float> result =
GetMatrix(unionArrays[0], size).compMult(GetMatrix(unionArrays[1], size));
SetUnionArrayFromMatrix(result, resultArray);
@@ -2805,8 +2839,8 @@
case EOpOuterProduct:
{
ASSERT(basicType == EbtFloat);
- size_t numRows = (*sequence)[0]->getAsTyped()->getType().getObjectSize();
- size_t numCols = (*sequence)[1]->getAsTyped()->getType().getObjectSize();
+ size_t numRows = (*arguments)[0]->getAsTyped()->getType().getObjectSize();
+ size_t numCols = (*arguments)[1]->getAsTyped()->getType().getObjectSize();
resultArray = new TConstantUnion[numRows * numCols];
angle::Matrix<float> result =
GetMatrix(unionArrays[0], static_cast<int>(numRows), 1)
@@ -2878,7 +2912,7 @@
{
float x = unionArrays[0][i].getFConst();
float y = unionArrays[1][i].getFConst();
- TBasicType type = (*sequence)[2]->getAsTyped()->getType().getBasicType();
+ TBasicType type = (*arguments)[2]->getAsTyped()->getType().getBasicType();
if (type == EbtFloat)
{
// Returns the linear blend of x and y, i.e., x * (1 - a) + y * a.