Add precision qualifier propagation for swizzling, texture lookups, built-in funtions mapped to operators, comma op, and more robustly propagate for all binary/unary ops.
git-svn-id: https://cvs.khronos.org/svn/repos/ogl/trunk/ecosystem/public/sdk/tools/glslang@21622 e7fa87d3-cd2b-0410-9028-fcbf551c1848
This commit is contained in:
parent
61f205ecd8
commit
2d0f1e5424
@ -10,6 +10,10 @@ lowp vec2 foo(mediump vec3 mv3)
|
|||||||
|
|
||||||
int global_medium;
|
int global_medium;
|
||||||
|
|
||||||
|
uniform lowp sampler2D samplerLow;
|
||||||
|
uniform mediump sampler2D samplerMed;
|
||||||
|
uniform highp sampler2D samplerHigh;
|
||||||
|
|
||||||
precision highp int;
|
precision highp int;
|
||||||
precision highp ivec2; // ERROR
|
precision highp ivec2; // ERROR
|
||||||
precision mediump int[2]; // ERROR
|
precision mediump int[2]; // ERROR
|
||||||
@ -59,4 +63,8 @@ void main()
|
|||||||
sum += level1_low3;
|
sum += level1_low3;
|
||||||
|
|
||||||
sum += 4 + ((ivec2(level1_low3) * ivec2(level1_high) + ivec2((/* comma operator */level1_low3, level1_high)))).x;
|
sum += 4 + ((ivec2(level1_low3) * ivec2(level1_high) + ivec2((/* comma operator */level1_low3, level1_high)))).x;
|
||||||
|
|
||||||
|
texture2D(samplerLow, vec2(0.1, 0.2));
|
||||||
|
texture2D(samplerMed, vec2(0.1, 0.2));
|
||||||
|
texture2D(samplerHigh, vec2(0.1, 0.2));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -482,6 +482,7 @@ public:
|
|||||||
virtual TIntermTyped* getRight() const { return right; }
|
virtual TIntermTyped* getRight() const { return right; }
|
||||||
virtual TIntermBinary* getAsBinaryNode() { return this; }
|
virtual TIntermBinary* getAsBinaryNode() { return this; }
|
||||||
virtual bool promote(TInfoSink&);
|
virtual bool promote(TInfoSink&);
|
||||||
|
virtual void updatePrecision();
|
||||||
protected:
|
protected:
|
||||||
TIntermTyped* left;
|
TIntermTyped* left;
|
||||||
TIntermTyped* right;
|
TIntermTyped* right;
|
||||||
@ -499,6 +500,7 @@ public:
|
|||||||
virtual TIntermTyped* getOperand() { return operand; }
|
virtual TIntermTyped* getOperand() { return operand; }
|
||||||
virtual TIntermUnary* getAsUnaryNode() { return this; }
|
virtual TIntermUnary* getAsUnaryNode() { return this; }
|
||||||
virtual bool promote(TInfoSink&);
|
virtual bool promote(TInfoSink&);
|
||||||
|
virtual void updatePrecision();
|
||||||
protected:
|
protected:
|
||||||
TIntermTyped* operand;
|
TIntermTyped* operand;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -126,6 +126,8 @@ TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIn
|
|||||||
node->setRight(right);
|
node->setRight(right);
|
||||||
if (! node->promote(infoSink))
|
if (! node->promote(infoSink))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
node->updatePrecision();
|
||||||
|
|
||||||
//
|
//
|
||||||
// If they are both constants, they must be folded.
|
// If they are both constants, they must be folded.
|
||||||
@ -169,6 +171,8 @@ TIntermTyped* TIntermediate::addAssign(TOperator op, TIntermTyped* left, TInterm
|
|||||||
if (! node->promote(infoSink))
|
if (! node->promote(infoSink))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
node->updatePrecision();
|
||||||
|
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -274,6 +278,8 @@ TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermNode* childNode,
|
|||||||
if (! node->promote(infoSink))
|
if (! node->promote(infoSink))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
node->updatePrecision();
|
||||||
|
|
||||||
if (child->getAsConstantUnion())
|
if (child->getAsConstantUnion())
|
||||||
return child->getAsConstantUnion()->fold(op, node->getType(), infoSink);
|
return child->getAsConstantUnion()->fold(op, node->getType(), infoSink);
|
||||||
|
|
||||||
@ -309,31 +315,26 @@ TIntermTyped* TIntermediate::addBuiltInFunctionCall(TOperator op, bool unary, TI
|
|||||||
node->getQualifier().precision = child->getQualifier().precision;
|
node->getQualifier().precision = child->getQualifier().precision;
|
||||||
|
|
||||||
// propagate precision down to child
|
// propagate precision down to child
|
||||||
if (node->getQualifier().precision != EpqNone &&
|
if (node->getQualifier().precision != EpqNone)
|
||||||
child->getQualifier().precision == EpqNone)
|
child->propagatePrecision(node->getQualifier().precision);
|
||||||
child->getQualifier().precision = node->getQualifier().precision;
|
|
||||||
|
|
||||||
return node;
|
return node;
|
||||||
} else {
|
} else {
|
||||||
// setAggregateOperater() calls fold() for constant folding
|
// setAggregateOperater() calls fold() for constant folding
|
||||||
TIntermTyped* node = setAggregateOperator(childNode, op, returnType, childNode->getLine());
|
TIntermTyped* node = setAggregateOperator(childNode, op, returnType, childNode->getLine());
|
||||||
|
|
||||||
if (returnType.getQualifier().precision == EpqNone && profile == EEsProfile) {
|
TPrecisionQualifier correctPrecision = returnType.getQualifier().precision;
|
||||||
// get maximum precision from arguments, for the built-in's return 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();
|
|
||||||
TPrecisionQualifier maxPq = EpqNone;
|
|
||||||
for (unsigned int arg = 0; arg < sequence.size(); ++arg)
|
|
||||||
maxPq = std::max(maxPq, sequence[arg]->getAsTyped()->getQualifier().precision);
|
|
||||||
node->getQualifier().precision = maxPq;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (node->getQualifier().precision != EpqNone) {
|
|
||||||
TIntermSequence& sequence = node->getAsAggregate()->getSequence();
|
TIntermSequence& sequence = node->getAsAggregate()->getSequence();
|
||||||
for (unsigned int arg = 0; arg < sequence.size(); ++arg)
|
for (unsigned int arg = 0; arg < sequence.size(); ++arg)
|
||||||
if (sequence[arg]->getAsTyped()->getQualifier().precision == EpqNone)
|
correctPrecision = std::max(correctPrecision, sequence[arg]->getAsTyped()->getQualifier().precision);
|
||||||
sequence[arg]->getAsTyped()->getQualifier().precision = node->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;
|
return node;
|
||||||
}
|
}
|
||||||
@ -725,12 +726,15 @@ TIntermTyped* TIntermediate::addComma(TIntermTyped* left, TIntermTyped* right, T
|
|||||||
{
|
{
|
||||||
if (left->getType().getQualifier().storage == EvqConst &&
|
if (left->getType().getQualifier().storage == EvqConst &&
|
||||||
right->getType().getQualifier().storage == EvqConst) {
|
right->getType().getQualifier().storage == EvqConst) {
|
||||||
|
|
||||||
return right;
|
return right;
|
||||||
} else {
|
} else {
|
||||||
TIntermTyped *commaAggregate = growAggregate(left, right, line);
|
TIntermTyped *commaAggregate = growAggregate(left, right, line);
|
||||||
commaAggregate->getAsAggregate()->setOperator(EOpComma);
|
commaAggregate->getAsAggregate()->setOperator(EOpComma);
|
||||||
commaAggregate->setType(right->getType());
|
commaAggregate->setType(right->getType());
|
||||||
commaAggregate->getTypePointer()->getQualifier().storage = EvqTemporary;
|
commaAggregate->getTypePointer()->getQualifier().storage = EvqTemporary;
|
||||||
|
commaAggregate->getTypePointer()->getQualifier().precision = right->getTypePointer()->getQualifier().precision;
|
||||||
|
|
||||||
return commaAggregate;
|
return commaAggregate;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -782,6 +786,7 @@ TIntermTyped* TIntermediate::addSelection(TIntermTyped* cond, TIntermTyped* true
|
|||||||
//
|
//
|
||||||
TIntermSelection* node = new TIntermSelection(cond, trueBlock, falseBlock, trueBlock->getType());
|
TIntermSelection* node = new TIntermSelection(cond, trueBlock, falseBlock, trueBlock->getType());
|
||||||
node->setLine(line);
|
node->setLine(line);
|
||||||
|
node->getQualifier().precision = std::max(trueBlock->getQualifier().precision, falseBlock->getQualifier().precision);
|
||||||
|
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
@ -966,6 +971,14 @@ bool TIntermUnary::promote(TInfoSink&)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TIntermUnary::updatePrecision()
|
||||||
|
{
|
||||||
|
if (getBasicType() == EbtInt || getBasicType() == EbtUint || getBasicType() == EbtFloat) {
|
||||||
|
if (operand->getQualifier().precision > getQualifier().precision)
|
||||||
|
getQualifier().precision = operand->getQualifier().precision;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Establishes the type of the resultant operation, as well as
|
// Establishes the type of the resultant operation, as well as
|
||||||
// makes the operator the correct one for the operands.
|
// makes the operator the correct one for the operands.
|
||||||
@ -987,21 +1000,11 @@ bool TIntermBinary::promote(TInfoSink& infoSink)
|
|||||||
setType(left->getType());
|
setType(left->getType());
|
||||||
type.getQualifier().storage = EvqTemporary;
|
type.getQualifier().storage = EvqTemporary;
|
||||||
|
|
||||||
// Fix precision qualifiers
|
|
||||||
if (right->getQualifier().precision > getQualifier().precision)
|
|
||||||
getQualifier().precision = right->getQualifier().precision;
|
|
||||||
if (getQualifier().precision != EpqNone) {
|
|
||||||
left->propagatePrecision(getQualifier().precision);
|
|
||||||
right->propagatePrecision(getQualifier().precision);
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Array operations.
|
// Array operations.
|
||||||
//
|
//
|
||||||
if (left->isArray()) {
|
if (left->isArray()) {
|
||||||
|
|
||||||
switch (op) {
|
switch (op) {
|
||||||
|
|
||||||
//
|
//
|
||||||
// Promote to conditional
|
// Promote to conditional
|
||||||
//
|
//
|
||||||
@ -1229,6 +1232,17 @@ bool TIntermBinary::promote(TInfoSink& infoSink)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TIntermBinary::updatePrecision()
|
||||||
|
{
|
||||||
|
if (getBasicType() == EbtInt || getBasicType() == EbtUint || getBasicType() == EbtFloat) {
|
||||||
|
getQualifier().precision = std::max(right->getQualifier().precision, left->getQualifier().precision);
|
||||||
|
if (getQualifier().precision != EpqNone) {
|
||||||
|
left->propagatePrecision(getQualifier().precision);
|
||||||
|
right->propagatePrecision(getQualifier().precision);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void TIntermTyped::propagatePrecision(TPrecisionQualifier newPrecision)
|
void TIntermTyped::propagatePrecision(TPrecisionQualifier newPrecision)
|
||||||
{
|
{
|
||||||
if (getQualifier().precision != EpqNone || (getBasicType() != EbtInt && getBasicType() != EbtUint && getBasicType() != EbtFloat))
|
if (getQualifier().precision != EpqNone || (getBasicType() != EbtInt && getBasicType() != EbtUint && getBasicType() != EbtFloat))
|
||||||
@ -1240,12 +1254,17 @@ void TIntermTyped::propagatePrecision(TPrecisionQualifier newPrecision)
|
|||||||
if (binaryNode) {
|
if (binaryNode) {
|
||||||
binaryNode->getLeft()->propagatePrecision(newPrecision);
|
binaryNode->getLeft()->propagatePrecision(newPrecision);
|
||||||
binaryNode->getRight()->propagatePrecision(newPrecision);
|
binaryNode->getRight()->propagatePrecision(newPrecision);
|
||||||
|
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
TIntermUnary* unaryNode = getAsUnaryNode();
|
TIntermUnary* unaryNode = getAsUnaryNode();
|
||||||
if (unaryNode)
|
if (unaryNode) {
|
||||||
unaryNode->getOperand()->propagatePrecision(newPrecision);
|
unaryNode->getOperand()->propagatePrecision(newPrecision);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
TIntermAggregate* aggregateNode = getAsAggregate();
|
TIntermAggregate* aggregateNode = getAsAggregate();
|
||||||
if (aggregateNode) {
|
if (aggregateNode) {
|
||||||
TIntermSequence operands = aggregateNode->getSequence();
|
TIntermSequence operands = aggregateNode->getSequence();
|
||||||
@ -1255,6 +1274,8 @@ void TIntermTyped::propagatePrecision(TPrecisionQualifier newPrecision)
|
|||||||
break;
|
break;
|
||||||
typedNode->propagatePrecision(newPrecision);
|
typedNode->propagatePrecision(newPrecision);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
TIntermSelection* selectionNode = getAsSelectionNode();
|
TIntermSelection* selectionNode = getAsSelectionNode();
|
||||||
@ -1266,14 +1287,9 @@ void TIntermTyped::propagatePrecision(TPrecisionQualifier newPrecision)
|
|||||||
if (typedNode)
|
if (typedNode)
|
||||||
typedNode->propagatePrecision(newPrecision);
|
typedNode->propagatePrecision(newPrecision);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: functionality: propagate precision for
|
return;
|
||||||
// comma operator: just through the last operand
|
}
|
||||||
// ":?" and ",": where is this triggered?
|
|
||||||
// built-in function calls: how much to propagate to arguments?
|
|
||||||
// length()?
|
|
||||||
// indexing?
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TIntermTyped* TIntermediate::promoteConstantUnion(TBasicType promoteTo, TIntermConstantUnion* node)
|
TIntermTyped* TIntermediate::promoteConstantUnion(TBasicType promoteTo, TIntermConstantUnion* node)
|
||||||
|
|||||||
@ -410,12 +410,12 @@ postfix_expression
|
|||||||
unionArray->setIConst(fields.offsets[0]);
|
unionArray->setIConst(fields.offsets[0]);
|
||||||
TIntermTyped* index = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtInt, EvqConst), $3.line);
|
TIntermTyped* index = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtInt, EvqConst), $3.line);
|
||||||
$$ = parseContext.intermediate.addIndex(EOpIndexDirect, $1, index, $2.line);
|
$$ = parseContext.intermediate.addIndex(EOpIndexDirect, $1, index, $2.line);
|
||||||
$$->setType(TType($1->getBasicType()));
|
$$->setType(TType($1->getBasicType(), EvqTemporary, $1->getType().getQualifier().precision));
|
||||||
} else {
|
} else {
|
||||||
TString vectorString = *$3.string;
|
TString vectorString = *$3.string;
|
||||||
TIntermTyped* index = parseContext.intermediate.addSwizzle(fields, $3.line);
|
TIntermTyped* index = parseContext.intermediate.addSwizzle(fields, $3.line);
|
||||||
$$ = parseContext.intermediate.addIndex(EOpVectorSwizzle, $1, index, $2.line);
|
$$ = parseContext.intermediate.addIndex(EOpVectorSwizzle, $1, index, $2.line);
|
||||||
$$->setType(TType($1->getBasicType(), EvqTemporary, (int) vectorString.size()));
|
$$->setType(TType($1->getBasicType(), EvqTemporary, $1->getType().getQualifier().precision, (int) vectorString.size()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if ($1->isMatrix()) {
|
} else if ($1->isMatrix()) {
|
||||||
@ -582,6 +582,11 @@ function_call
|
|||||||
}
|
}
|
||||||
qualifierList.push_back(qual);
|
qualifierList.push_back(qual);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// built-in texturing functions get their return value precision from the precision of the sampler
|
||||||
|
if (builtIn && fnCandidate->getReturnType().getQualifier().precision == EpqNone &&
|
||||||
|
fnCandidate->getParamCount() > 0 && (*fnCandidate)[0].type->getBasicType() == EbtSampler)
|
||||||
|
$$->getQualifier().precision = $$->getAsAggregate()->getSequence()[0]->getAsTyped()->getQualifier().precision;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// error message was put out by PaFindFunction()
|
// error message was put out by PaFindFunction()
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user