Commit bf790420 by Arun Patole Committed by Olli Etuaho

Add constant folding support for more built-ins

This change adds constant folding support for following built-ins: - atan(two arguments), pow, mod, mix, step and smoothstep. BUG=angleproject:913 TEST=dEQP tests Following 80 tests from dEQP-GLES3.functional.shaders.constant_expressions started passing with this change: - builtin_functions.angle_and_trigonometry.atan_separate* - builtin_functions.exponential.pow_* - builtin_functions.common.mod_* - builtin_functions.common.mix_* - builtin_functions.common.step_* - builtin_functions.common.smoothstep_* Change-Id: I70f0a8837a82c480da8cff3f1382c6252a486fe4 Reviewed-on: https://chromium-review.googlesource.com/271753Reviewed-by: 's avatarOlli Etuaho <oetuaho@nvidia.com> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Tested-by: 's avatarJamie Madill <jmadill@chromium.org> Tested-by: 's avatarOlli Etuaho <oetuaho@nvidia.com>
parent 7467b2b1
...@@ -141,6 +141,33 @@ TConstantUnion *Vectorize(const TConstantUnion &constant, size_t size) ...@@ -141,6 +141,33 @@ TConstantUnion *Vectorize(const TConstantUnion &constant, size_t size)
return constUnion; return constUnion;
} }
void UndefinedConstantFoldingError(const TSourceLoc &loc, TOperator op, TBasicType basicType,
TInfoSink &infoSink, TConstantUnion *result)
{
std::stringstream constantFoldingErrorStream;
constantFoldingErrorStream << "'" << GetOperatorString(op)
<< "' operation result is undefined for the values passed in";
infoSink.info.message(EPrefixWarning, loc, constantFoldingErrorStream.str().c_str());
switch (basicType)
{
case EbtFloat :
result->setFConst(0.0f);
break;
case EbtInt:
result->setIConst(0);
break;
case EbtUInt:
result->setUConst(0u);
break;
case EbtBool:
result->setBConst(false);
break;
default:
break;
}
}
} // namespace anonymous } // namespace anonymous
...@@ -1493,7 +1520,7 @@ bool TIntermConstantUnion::foldFloatTypeUnary(const TConstantUnion &parameter, F ...@@ -1493,7 +1520,7 @@ bool TIntermConstantUnion::foldFloatTypeUnary(const TConstantUnion &parameter, F
} }
// static // static
TIntermTyped *TIntermConstantUnion::FoldAggregateBuiltIn(TOperator op, TIntermAggregate *aggregate) TIntermTyped *TIntermConstantUnion::FoldAggregateBuiltIn(TOperator op, TIntermAggregate *aggregate, TInfoSink &infoSink)
{ {
TIntermSequence *sequence = aggregate->getSequence(); TIntermSequence *sequence = aggregate->getSequence();
unsigned int paramsCount = sequence->size(); unsigned int paramsCount = sequence->size();
...@@ -1535,6 +1562,68 @@ TIntermTyped *TIntermConstantUnion::FoldAggregateBuiltIn(TOperator op, TIntermAg ...@@ -1535,6 +1562,68 @@ TIntermTyped *TIntermConstantUnion::FoldAggregateBuiltIn(TOperator op, TIntermAg
// //
switch (op) switch (op)
{ {
case EOpAtan:
{
if (basicType == EbtFloat)
{
tempConstArray = new TConstantUnion[maxObjectSize];
for (size_t i = 0; i < maxObjectSize; i++)
{
float y = unionArrays[0][i].getFConst();
float x = unionArrays[1][i].getFConst();
// Results are undefined if x and y are both 0.
if (x == 0.0f && y == 0.0f)
UndefinedConstantFoldingError(loc, op, basicType, infoSink, &tempConstArray[i]);
else
tempConstArray[i].setFConst(atan2f(y, x));
}
}
else
UNREACHABLE();
}
break;
case EOpPow:
{
if (basicType == EbtFloat)
{
tempConstArray = new TConstantUnion[maxObjectSize];
for (size_t i = 0; i < maxObjectSize; i++)
{
float x = unionArrays[0][i].getFConst();
float y = unionArrays[1][i].getFConst();
// Results are undefined if x < 0.
// Results are undefined if x = 0 and y <= 0.
if (x < 0.0f)
UndefinedConstantFoldingError(loc, op, basicType, infoSink, &tempConstArray[i]);
else if (x == 0.0f && y <= 0.0f)
UndefinedConstantFoldingError(loc, op, basicType, infoSink, &tempConstArray[i]);
else
tempConstArray[i].setFConst(powf(x, y));
}
}
else
UNREACHABLE();
}
break;
case EOpMod:
{
if (basicType == EbtFloat)
{
tempConstArray = new TConstantUnion[maxObjectSize];
for (size_t i = 0; i < maxObjectSize; i++)
{
float x = unionArrays[0][i].getFConst();
float y = unionArrays[1][i].getFConst();
tempConstArray[i].setFConst(x - y * floorf(x / y));
}
}
else
UNREACHABLE();
}
break;
case EOpMin: case EOpMin:
{ {
tempConstArray = new TConstantUnion[maxObjectSize]; tempConstArray = new TConstantUnion[maxObjectSize];
...@@ -1583,6 +1672,19 @@ TIntermTyped *TIntermConstantUnion::FoldAggregateBuiltIn(TOperator op, TIntermAg ...@@ -1583,6 +1672,19 @@ TIntermTyped *TIntermConstantUnion::FoldAggregateBuiltIn(TOperator op, TIntermAg
} }
break; break;
case EOpStep:
{
if (basicType == EbtFloat)
{
tempConstArray = new TConstantUnion[maxObjectSize];
for (size_t i = 0; i < maxObjectSize; i++)
tempConstArray[i].setFConst(unionArrays[1][i].getFConst() < unionArrays[0][i].getFConst() ? 0.0f : 1.0f);
}
else
UNREACHABLE();
}
break;
default: default:
UNREACHABLE(); UNREACHABLE();
// TODO: Add constant folding support for other built-in operations that take 2 parameters and not handled above. // TODO: Add constant folding support for other built-in operations that take 2 parameters and not handled above.
...@@ -1647,6 +1749,67 @@ TIntermTyped *TIntermConstantUnion::FoldAggregateBuiltIn(TOperator op, TIntermAg ...@@ -1647,6 +1749,67 @@ TIntermTyped *TIntermConstantUnion::FoldAggregateBuiltIn(TOperator op, TIntermAg
} }
break; break;
case EOpMix:
{
if (basicType == EbtFloat)
{
tempConstArray = new TConstantUnion[maxObjectSize];
for (size_t i = 0; i < maxObjectSize; i++)
{
float x = unionArrays[0][i].getFConst();
float y = unionArrays[1][i].getFConst();
TBasicType type = (*sequence)[2]->getAsTyped()->getType().getBasicType();
if (type == EbtFloat)
{
// Returns the linear blend of x and y, i.e., x * (1 - a) + y * a.
float a = unionArrays[2][i].getFConst();
tempConstArray[i].setFConst(x * (1.0f - a) + y * a);
}
else // 3rd parameter is EbtBool
{
ASSERT(type == EbtBool);
// Selects which vector each returned component comes from.
// For a component of a that is false, the corresponding component of x is returned.
// For a component of a that is true, the corresponding component of y is returned.
bool a = unionArrays[2][i].getBConst();
tempConstArray[i].setFConst(a ? y : x);
}
}
}
else
UNREACHABLE();
}
break;
case EOpSmoothStep:
{
if (basicType == EbtFloat)
{
tempConstArray = new TConstantUnion[maxObjectSize];
for (size_t i = 0; i < maxObjectSize; i++)
{
float edge0 = unionArrays[0][i].getFConst();
float edge1 = unionArrays[1][i].getFConst();
float x = unionArrays[2][i].getFConst();
// Results are undefined if edge0 >= edge1.
if (edge0 >= edge1)
{
UndefinedConstantFoldingError(loc, op, basicType, infoSink, &tempConstArray[i]);
}
else
{
// Returns 0.0 if x <= edge0 and 1.0 if x >= edge1 and performs smooth
// Hermite interpolation between 0 and 1 when edge0 < x < edge1.
float t = gl::clamp((x - edge0) / (edge1 - edge0), 0.0f, 1.0f);
tempConstArray[i].setFConst(t * t * (3.0f - 2.0f * t));
}
}
}
else
UNREACHABLE();
}
break;
default: default:
UNREACHABLE(); UNREACHABLE();
// TODO: Add constant folding support for other built-in operations that take 3 parameters and not handled above. // TODO: Add constant folding support for other built-in operations that take 3 parameters and not handled above.
......
...@@ -301,7 +301,7 @@ class TIntermConstantUnion : public TIntermTyped ...@@ -301,7 +301,7 @@ class TIntermConstantUnion : public TIntermTyped
TIntermTyped *fold(TOperator op, TIntermConstantUnion *rightNode, TInfoSink &infoSink); TIntermTyped *fold(TOperator op, TIntermConstantUnion *rightNode, TInfoSink &infoSink);
static TIntermTyped *FoldAggregateBuiltIn(TOperator op, TIntermAggregate *aggregate); static TIntermTyped *FoldAggregateBuiltIn(TOperator op, TIntermAggregate *aggregate, TInfoSink &infoSink);
protected: protected:
TConstantUnion *mUnionArrayPointer; TConstantUnion *mUnionArrayPointer;
......
...@@ -462,10 +462,16 @@ TIntermTyped *TIntermediate::foldAggregateBuiltIn(TOperator op, TIntermAggregate ...@@ -462,10 +462,16 @@ TIntermTyped *TIntermediate::foldAggregateBuiltIn(TOperator op, TIntermAggregate
{ {
switch (op) switch (op)
{ {
case EOpAtan:
case EOpPow:
case EOpMod:
case EOpMin: case EOpMin:
case EOpMax: case EOpMax:
case EOpClamp: case EOpClamp:
return TIntermConstantUnion::FoldAggregateBuiltIn(op, aggregate); case EOpMix:
case EOpStep:
case EOpSmoothStep:
return TIntermConstantUnion::FoldAggregateBuiltIn(op, aggregate, mInfoSink);
default: default:
// Constant folding not supported for the built-in. // Constant folding not supported for the built-in.
return nullptr; return nullptr;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment