diff --git a/Test/precision.frag b/Test/precision.frag index f0ea6598..c9b1d7ab 100644 --- a/Test/precision.frag +++ b/Test/precision.frag @@ -35,17 +35,19 @@ void main() int level2_high; sum += level2_high; do { - if (1) { + if (true) { precision mediump int; int level4_medium; sum += level4_medium; } int level3_high; sum += level3_high; - } while (1); + } while (true); int level2_high2; sum += level2_high2; } int level1_low3; sum += level1_low3; + + sum += 4 + ((ivec2(level1_low3) * ivec2(level1_high) + ivec2((/* comma operator */level1_low3, level1_high)))).x; } diff --git a/glslang/Include/intermediate.h b/glslang/Include/intermediate.h index cbab65d0..c6e234c6 100644 --- a/glslang/Include/intermediate.h +++ b/glslang/Include/intermediate.h @@ -231,6 +231,7 @@ enum TOperator { class TIntermTraverser; class TIntermAggregate; +class TIntermUnary; class TIntermBinary; class TIntermConstantUnion; class TIntermSelection; @@ -253,6 +254,7 @@ public: virtual TIntermTyped* getAsTyped() { return 0; } virtual TIntermConstantUnion* getAsConstantUnion() { return 0; } virtual TIntermAggregate* getAsAggregate() { return 0; } + virtual TIntermUnary* getAsUnaryNode() { return 0; } virtual TIntermBinary* getAsBinaryNode() { return 0; } virtual TIntermSelection* getAsSelectionNode() { return 0; } virtual TIntermMethod* getAsMethodNode() { return 0; } @@ -270,9 +272,6 @@ struct TIntermNodePair { TIntermNode* node2; }; -class TIntermSymbol; -class TIntermBinary; - // // Intermediate class for nodes that have a type. // @@ -286,6 +285,7 @@ public: virtual TBasicType getBasicType() const { return type.getBasicType(); } virtual TQualifier& getQualifier() { return type.getQualifier(); } + virtual void propagatePrecision(TPrecisionQualifier); virtual int getNominalSize() const { return type.getNominalSize(); } virtual int getSize() const { return type.getInstanceSize(); } virtual bool isMatrix() const { return type.isMatrix(); } @@ -428,6 +428,7 @@ public: virtual void traverse(TIntermTraverser*); virtual void setOperand(TIntermTyped* o) { operand = o; } virtual TIntermTyped* getOperand() { return operand; } + virtual TIntermUnary* getAsUnaryNode() { return this; } virtual bool promote(TInfoSink&); protected: TIntermTyped* operand; diff --git a/glslang/MachineIndependent/Intermediate.cpp b/glslang/MachineIndependent/Intermediate.cpp index 040de594..389d4a9b 100644 --- a/glslang/MachineIndependent/Intermediate.cpp +++ b/glslang/MachineIndependent/Intermediate.cpp @@ -836,6 +836,8 @@ bool TIntermBinary::promote(TInfoSink& infoSink) // Fix precision qualifiers if (right->getQualifier().precision > getQualifier().precision) getQualifier().precision = right->getQualifier().precision; + left->propagatePrecision(getQualifier().precision); + right->propagatePrecision(getQualifier().precision); // // Array operations. @@ -1078,7 +1080,53 @@ bool CompareStruct(const TType& leftNodeType, constUnion* rightUnionArray, const } } return true; -} +} + +void TIntermTyped::propagatePrecision(TPrecisionQualifier newPrecision) +{ + if (getQualifier().precision != EpqNone || (getBasicType() != EbtInt && getBasicType() != EbtFloat)) + return; + + getQualifier().precision = newPrecision; + + TIntermBinary* binaryNode = getAsBinaryNode(); + if (binaryNode) { + binaryNode->getLeft()->propagatePrecision(newPrecision); + binaryNode->getRight()->propagatePrecision(newPrecision); + } + + TIntermUnary* unaryNode = getAsUnaryNode(); + if (unaryNode) + unaryNode->getOperand()->propagatePrecision(newPrecision); + + TIntermAggregate* aggregateNode = getAsAggregate(); + if (aggregateNode) { + TIntermSequence operands = aggregateNode->getSequence(); + for (unsigned int i = 0; i < operands.size(); ++i) { + TIntermTyped* typedNode = operands[i]->getAsTyped(); + if (! typedNode) + break; + typedNode->propagatePrecision(newPrecision); + } + } + + TIntermSelection* selectionNode = getAsSelectionNode(); + if (selectionNode) { + TIntermTyped* typedNode = selectionNode->getTrueBlock()->getAsTyped(); + if (typedNode) { + typedNode->propagatePrecision(newPrecision); + typedNode = selectionNode->getFalseBlock()->getAsTyped(); + if (typedNode) + typedNode->propagatePrecision(newPrecision); + } + } + + // TODO: propagate precision for + // comma operator: just through the last operand + // ":?" and ",": where is this triggered? + // built-in function calls: how much to propagate to arguments? + // performance: don't do this for desktop profiles +} bool CompareStructure(const TType& leftNodeType, constUnion* rightUnionArray, constUnion* leftUnionArray) { diff --git a/glslang/MachineIndependent/ParseHelper.cpp b/glslang/MachineIndependent/ParseHelper.cpp index 797ec251..13b3bc3d 100644 --- a/glslang/MachineIndependent/ParseHelper.cpp +++ b/glslang/MachineIndependent/ParseHelper.cpp @@ -60,7 +60,6 @@ TParseContext::TParseContext(TSymbolTable& symt, TIntermediate& interm, EShLangu defaultPrecision[EbtVoid] = EpqNone; defaultPrecision[EbtDouble] = EpqNone; defaultPrecision[EbtBool] = EpqNone; - defaultPrecision[EbtVoid] = EpqNone; } // diff --git a/glslang/MachineIndependent/intermOut.cpp b/glslang/MachineIndependent/intermOut.cpp index 42252f8c..df07121e 100644 --- a/glslang/MachineIndependent/intermOut.cpp +++ b/glslang/MachineIndependent/intermOut.cpp @@ -258,11 +258,11 @@ bool OutputAggregate(bool /* preVisit */, TIntermAggregate* node, TIntermTravers OutputTreeText(out, node, oit->depth); switch (node->getOp()) { - case EOpSequence: out.debug << "Sequence\n"; return true; - case EOpComma: out.debug << "Comma\n"; return true; + case EOpSequence: out.debug << "Sequence\n"; return true; + case EOpComma: out.debug << "Comma"; break; case EOpFunction: out.debug << "Function Definition: " << node->getName(); break; - case EOpFunctionCall: out.debug << "Function Call: " << node->getName(); break; - case EOpParameters: out.debug << "Function Parameters: "; break; + case EOpFunctionCall: out.debug << "Function Call: " << node->getName(); break; + case EOpParameters: out.debug << "Function Parameters: "; break; case EOpConstructFloat: out.debug << "Construct float"; break; case EOpConstructVec2: out.debug << "Construct vec2"; break;