Front-end: Implement 2nd task of issue #400; precision of result and operation.

From the ES spec + Bugzilla 15931 and GL_KHR_vulkan_glsl:
- Update precision qualifiers for all built-in function prototypes.
- Implement the new algorithm used to distinguish built-in function
  operation precisions from result precisions.
Also add tracking of separate result and operation precisions, and
use that in generating SPIR-V.
(SPIR-V cares about precision of operation, while the front-end
cares about precision of result, for propagation.)
This commit is contained in:
John Kessenich 2016-08-01 19:44:00 -06:00
parent 6c136223ed
commit f6640761c4
18 changed files with 408 additions and 308 deletions

View file

@ -341,35 +341,11 @@ TIntermTyped* TIntermediate::addBuiltInFunctionCall(const TSourceLoc& loc, TOper
node->setOperand(child);
node->setType(returnType);
// propagate precision up from child
if (profile == EEsProfile && returnType.getQualifier().precision == EpqNone && returnType.getBasicType() != EbtBool)
node->getQualifier().precision = child->getQualifier().precision;
// propagate precision down to child
if (node->getQualifier().precision != EpqNone)
child->propagatePrecision(node->getQualifier().precision);
return node;
} else {
// setAggregateOperater() calls fold() for constant folding
TIntermTyped* node = setAggregateOperator(childNode, op, returnType, loc);
// if not folded, we'll still have an aggregate node to propagate precision with
if (node->getAsAggregate()) {
TPrecisionQualifier correctPrecision = returnType.getQualifier().precision;
if (correctPrecision == EpqNone && profile == EEsProfile) {
// find the maximum precision from the arguments, for the built-in's return precision
TIntermSequence& sequence = node->getAsAggregate()->getSequence();
for (unsigned int arg = 0; arg < sequence.size(); ++arg)
correctPrecision = std::max(correctPrecision, sequence[arg]->getAsTyped()->getQualifier().precision);
}
// Propagate precision through this node and its children. That algorithm stops
// when a precision is found, so start by clearing this subroot precision
node->getQualifier().precision = EpqNone;
node->propagatePrecision(correctPrecision);
}
return node;
}
}