SPV: Implement specialization constants for ?:.

This commit is contained in:
John Kessenich 2017-01-28 19:29:42 -07:00
parent 433e9ff896
commit 8e6c6cef6a
5 changed files with 73 additions and 12 deletions

View file

@ -155,14 +155,10 @@ TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIn
return folded;
}
// If either is a specialization constant, while the other is
// a constant (or specialization constant), the result is still
// a specialization constant, if the operation is an allowed
// specialization-constant operation.
if (( left->getType().getQualifier().isSpecConstant() && right->getType().getQualifier().isConstant()) ||
(right->getType().getQualifier().isSpecConstant() && left->getType().getQualifier().isConstant()))
if (isSpecializationOperation(*node))
node->getWritableType().getQualifier().makeSpecConstant();
// If can propagate spec-constantness and if the operation is an allowed
// specialization-constant operation, make a spec-constant.
if (specConstantPropagates(*left, *right) && isSpecializationOperation(*node))
node->getWritableType().getQualifier().makeSpecConstant();
return node;
}
@ -1277,6 +1273,9 @@ TIntermTyped* TIntermediate::addMethod(TIntermTyped* object, const TType& type,
// a true path, and a false path. The two paths are specified
// as separate parameters.
//
// Specialization constant operations include
// - The ternary operator ( ? : )
//
// Returns the selection node created, or nullptr if one could not be.
//
TIntermTyped* TIntermediate::addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, const TSourceLoc& loc)
@ -1320,10 +1319,16 @@ TIntermTyped* TIntermediate::addSelection(TIntermTyped* cond, TIntermTyped* true
// Make a selection node.
//
TIntermSelection* node = new TIntermSelection(cond, trueBlock, falseBlock, trueBlock->getType());
node->getQualifier().makeTemporary();
node->setLoc(loc);
node->getQualifier().precision = std::max(trueBlock->getQualifier().precision, falseBlock->getQualifier().precision);
if ((cond->getQualifier().isConstant() && specConstantPropagates(*trueBlock, *falseBlock)) ||
(cond->getQualifier().isSpecConstant() && trueBlock->getQualifier().isConstant() &&
falseBlock->getQualifier().isConstant()))
node->getQualifier().makeSpecConstant();
else
node->getQualifier().makeTemporary();
return node;
}
@ -2645,4 +2650,13 @@ void TIntermAggregate::addToPragmaTable(const TPragmaTable& pTable)
*pragmaTable = pTable;
}
// If either node is a specialization constant, while the other is
// a constant (or specialization constant), the result is still
// a specialization constant.
bool TIntermediate::specConstantPropagates(const TIntermTyped& node1, const TIntermTyped& node2)
{
return (node1.getType().getQualifier().isSpecConstant() && node2.getType().getQualifier().isConstant()) ||
(node2.getType().getQualifier().isSpecConstant() && node1.getType().getQualifier().isConstant());
}
} // end namespace glslang