Add support for constant folding of clamp()
Fixes: dEQP-GLES3.functional.shaders.constant_expressions.other.complex*
Bug: b/116598062
Change-Id: Ife2dd2edad17d6ebbd02653f484637672ce6af0a
Reviewed-on: https://swiftshader-review.googlesource.com/20828
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
Tested-by: Chris Forbes <chrisforbes@google.com>
diff --git a/src/OpenGL/compiler/ParseHelper.cpp b/src/OpenGL/compiler/ParseHelper.cpp
index b795c06..bf731ea 100644
--- a/src/OpenGL/compiler/ParseHelper.cpp
+++ b/src/OpenGL/compiler/ParseHelper.cpp
@@ -3629,24 +3629,48 @@
callNode = aggregate;
- if(fnCandidate->getParamCount() == 2)
+ if(op == EOpClamp)
{
+ // Special case for clamp -- try to fold it as min(max(t, minVal), maxVal)
TIntermSequence ¶meters = paramNode->getAsAggregate()->getSequence();
- TIntermTyped *left = parameters[0]->getAsTyped();
- TIntermTyped *right = parameters[1]->getAsTyped();
+ TIntermConstantUnion *valConstant = parameters[0]->getAsTyped()->getAsConstantUnion();
+ TIntermConstantUnion *minConstant = parameters[1]->getAsTyped()->getAsConstantUnion();
+ TIntermConstantUnion *maxConstant = parameters[2]->getAsTyped()->getAsConstantUnion();
- TIntermConstantUnion *leftTempConstant = left->getAsConstantUnion();
- TIntermConstantUnion *rightTempConstant = right->getAsConstantUnion();
- if (leftTempConstant && rightTempConstant)
+ if (valConstant && minConstant && maxConstant)
{
- TIntermTyped *typedReturnNode = leftTempConstant->fold(op, rightTempConstant, infoSink());
-
- if(typedReturnNode)
+ TIntermTyped *typedReturnNode = valConstant->fold(EOpMax, minConstant, infoSink());
+ if (typedReturnNode && typedReturnNode->getAsConstantUnion())
+ {
+ typedReturnNode = maxConstant->fold(EOpMin, typedReturnNode->getAsConstantUnion(), infoSink());
+ }
+ if (typedReturnNode)
{
callNode = typedReturnNode;
}
}
}
+ else
+ {
+ if(fnCandidate->getParamCount() == 2)
+ {
+ TIntermSequence ¶meters = paramNode->getAsAggregate()->getSequence();
+ TIntermTyped *left = parameters[0]->getAsTyped();
+ TIntermTyped *right = parameters[1]->getAsTyped();
+
+ TIntermConstantUnion *leftTempConstant = left->getAsConstantUnion();
+ TIntermConstantUnion *rightTempConstant = right->getAsConstantUnion();
+ if (leftTempConstant && rightTempConstant)
+ {
+ TIntermTyped *typedReturnNode = leftTempConstant->fold(op, rightTempConstant, infoSink());
+
+ if(typedReturnNode)
+ {
+ callNode = typedReturnNode;
+ }
+ }
+ }
+ }
}
}
else