Commit ab2b9a23 by Arun Patole Committed by Jamie Madill

Refactor unary operation constant folding code

This change splits TIntermConstantUnion::foldUnary into two functions: - foldUnaryWithDifferentReturnType: - Handles constant folding of operations where the return type has a different number of components compared to the operand type. - foldUnaryWithSameReturnType: - Handles constant folding of unary operations where the return type is the same as operand type. BUG=angleproject:913 TEST=angle_unittests, dEQP Tests (dEQP-GLES3.functional.shaders.constant_expressions.builtin_functions.*) Change-Id: I675891138d4e17fd2390c03e9f710e0be0b7c7b6 Reviewed-on: https://chromium-review.googlesource.com/283464Reviewed-by: 's avatarOlli Etuaho <oetuaho@nvidia.com> Tested-by: 's avatarOlli Etuaho <oetuaho@nvidia.com> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent cdfa8f50
......@@ -810,7 +810,28 @@ TIntermTyped *TIntermUnary::fold(TInfoSink &infoSink)
{
return nullptr;
}
TConstantUnion *constArray = operandConstant->foldUnary(mOp, infoSink);
TConstantUnion *constArray = nullptr;
switch (mOp)
{
case EOpAny:
case EOpAll:
case EOpLength:
case EOpTranspose:
case EOpDeterminant:
case EOpInverse:
case EOpPackSnorm2x16:
case EOpUnpackSnorm2x16:
case EOpPackUnorm2x16:
case EOpUnpackUnorm2x16:
case EOpPackHalf2x16:
case EOpUnpackHalf2x16:
constArray = operandConstant->foldUnaryWithDifferentReturnType(mOp, infoSink);
break;
default:
constArray = operandConstant->foldUnaryWithSameReturnType(mOp, infoSink);
break;
}
return CreateFoldedNode(constArray, this);
}
......@@ -1178,582 +1199,586 @@ TConstantUnion *TIntermConstantUnion::foldBinary(TOperator op, TIntermConstantUn
//
// Returns the constant value to keep using or nullptr.
//
TConstantUnion *TIntermConstantUnion::foldUnary(TOperator op, TInfoSink &infoSink)
TConstantUnion *TIntermConstantUnion::foldUnaryWithDifferentReturnType(TOperator op, TInfoSink &infoSink)
{
TConstantUnion *operandArray = getUnionArrayPointer();
//
// Do operations where the return type has a different number of components compared to the operand type.
//
TConstantUnion *operandArray = getUnionArrayPointer();
if (!operandArray)
return nullptr;
size_t objectSize = getType().getObjectSize();
if (op == EOpAny || op == EOpAll || op == EOpLength || op == EOpTranspose || op == EOpDeterminant ||
op == EOpInverse || op == EOpPackSnorm2x16 || op == EOpUnpackSnorm2x16 || op == EOpPackUnorm2x16 ||
op == EOpUnpackUnorm2x16 || op == EOpPackHalf2x16 || op == EOpUnpackHalf2x16)
TConstantUnion *resultArray = nullptr;
switch (op)
{
// Do operations where the return type has a different number of components compared to the operand type.
TConstantUnion *resultArray = nullptr;
switch (op)
case EOpAny:
if (getType().getBasicType() == EbtBool)
{
case EOpAny:
if (getType().getBasicType() == EbtBool)
resultArray = new TConstantUnion();
resultArray->setBConst(false);
for (size_t i = 0; i < objectSize; i++)
{
resultArray = new TConstantUnion();
resultArray->setBConst(false);
for (size_t i = 0; i < objectSize; i++)
if (operandArray[i].getBConst())
{
if (operandArray[i].getBConst())
{
resultArray->setBConst(true);
break;
}
resultArray->setBConst(true);
break;
}
break;
}
else
{
infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
return nullptr;
}
break;
}
else
{
infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
return nullptr;
}
case EOpAll:
if (getType().getBasicType() == EbtBool)
case EOpAll:
if (getType().getBasicType() == EbtBool)
{
resultArray = new TConstantUnion();
resultArray->setBConst(true);
for (size_t i = 0; i < objectSize; i++)
{
resultArray = new TConstantUnion();
resultArray->setBConst(true);
for (size_t i = 0; i < objectSize; i++)
if (!operandArray[i].getBConst())
{
if (!operandArray[i].getBConst())
{
resultArray->setBConst(false);
break;
}
resultArray->setBConst(false);
break;
}
break;
}
else
{
infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
return nullptr;
}
case EOpLength:
if (getType().getBasicType() == EbtFloat)
{
resultArray = new TConstantUnion();
resultArray->setFConst(VectorLength(operandArray, objectSize));
break;
}
else
{
infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
return nullptr;
}
break;
}
else
{
infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
return nullptr;
}
case EOpTranspose:
if (getType().getBasicType() == EbtFloat)
{
resultArray = new TConstantUnion[objectSize];
angle::Matrix<float> result =
GetMatrix(operandArray, getType().getNominalSize(), getType().getSecondarySize()).transpose();
SetUnionArrayFromMatrix(result, resultArray);
break;
}
else
{
infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
return nullptr;
}
case EOpLength:
if (getType().getBasicType() == EbtFloat)
{
resultArray = new TConstantUnion();
resultArray->setFConst(VectorLength(operandArray, objectSize));
break;
}
else
{
infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
return nullptr;
}
case EOpDeterminant:
if (getType().getBasicType() == EbtFloat)
{
unsigned int size = getType().getNominalSize();
ASSERT(size >= 2 && size <= 4);
resultArray = new TConstantUnion();
resultArray->setFConst(GetMatrix(operandArray, size).determinant());
break;
}
else
{
infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
return nullptr;
}
case EOpTranspose:
if (getType().getBasicType() == EbtFloat)
{
resultArray = new TConstantUnion[objectSize];
angle::Matrix<float> result =
GetMatrix(operandArray, getType().getNominalSize(), getType().getSecondarySize()).transpose();
SetUnionArrayFromMatrix(result, resultArray);
break;
}
else
{
infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
return nullptr;
}
case EOpInverse:
if (getType().getBasicType() == EbtFloat)
{
unsigned int size = getType().getNominalSize();
ASSERT(size >= 2 && size <= 4);
resultArray = new TConstantUnion[objectSize];
angle::Matrix<float> result = GetMatrix(operandArray, size).inverse();
SetUnionArrayFromMatrix(result, resultArray);
break;
}
else
{
infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
return nullptr;
}
case EOpDeterminant:
if (getType().getBasicType() == EbtFloat)
{
unsigned int size = getType().getNominalSize();
ASSERT(size >= 2 && size <= 4);
resultArray = new TConstantUnion();
resultArray->setFConst(GetMatrix(operandArray, size).determinant());
break;
}
else
{
infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
return nullptr;
}
case EOpPackSnorm2x16:
if (getType().getBasicType() == EbtFloat)
{
ASSERT(getType().getNominalSize() == 2);
resultArray = new TConstantUnion();
resultArray->setUConst(gl::packSnorm2x16(operandArray[0].getFConst(), operandArray[1].getFConst()));
break;
}
else
{
infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
return nullptr;
}
case EOpInverse:
if (getType().getBasicType() == EbtFloat)
{
unsigned int size = getType().getNominalSize();
ASSERT(size >= 2 && size <= 4);
resultArray = new TConstantUnion[objectSize];
angle::Matrix<float> result = GetMatrix(operandArray, size).inverse();
SetUnionArrayFromMatrix(result, resultArray);
break;
}
else
{
infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
return nullptr;
}
case EOpUnpackSnorm2x16:
if (getType().getBasicType() == EbtUInt)
{
resultArray = new TConstantUnion[2];
float f1, f2;
gl::unpackSnorm2x16(operandArray[0].getUConst(), &f1, &f2);
resultArray[0].setFConst(f1);
resultArray[1].setFConst(f2);
break;
}
else
{
infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
return nullptr;
}
case EOpPackSnorm2x16:
if (getType().getBasicType() == EbtFloat)
{
ASSERT(getType().getNominalSize() == 2);
resultArray = new TConstantUnion();
resultArray->setUConst(gl::packSnorm2x16(operandArray[0].getFConst(), operandArray[1].getFConst()));
break;
}
else
{
infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
return nullptr;
}
case EOpPackUnorm2x16:
if (getType().getBasicType() == EbtFloat)
{
ASSERT(getType().getNominalSize() == 2);
resultArray = new TConstantUnion();
resultArray->setUConst(gl::packUnorm2x16(operandArray[0].getFConst(), operandArray[1].getFConst()));
break;
}
else
{
infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
return nullptr;
}
case EOpUnpackSnorm2x16:
if (getType().getBasicType() == EbtUInt)
{
resultArray = new TConstantUnion[2];
float f1, f2;
gl::unpackSnorm2x16(operandArray[0].getUConst(), &f1, &f2);
resultArray[0].setFConst(f1);
resultArray[1].setFConst(f2);
break;
}
else
{
infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
return nullptr;
}
case EOpUnpackUnorm2x16:
if (getType().getBasicType() == EbtUInt)
{
resultArray = new TConstantUnion[2];
float f1, f2;
gl::unpackUnorm2x16(operandArray[0].getUConst(), &f1, &f2);
resultArray[0].setFConst(f1);
resultArray[1].setFConst(f2);
break;
}
else
{
infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
return nullptr;
}
case EOpPackUnorm2x16:
if (getType().getBasicType() == EbtFloat)
{
ASSERT(getType().getNominalSize() == 2);
resultArray = new TConstantUnion();
resultArray->setUConst(gl::packUnorm2x16(operandArray[0].getFConst(), operandArray[1].getFConst()));
break;
}
else
{
infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
return nullptr;
}
case EOpPackHalf2x16:
if (getType().getBasicType() == EbtFloat)
{
ASSERT(getType().getNominalSize() == 2);
resultArray = new TConstantUnion();
resultArray->setUConst(gl::packHalf2x16(operandArray[0].getFConst(), operandArray[1].getFConst()));
break;
}
else
{
infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
return nullptr;
}
case EOpUnpackUnorm2x16:
if (getType().getBasicType() == EbtUInt)
{
resultArray = new TConstantUnion[2];
float f1, f2;
gl::unpackUnorm2x16(operandArray[0].getUConst(), &f1, &f2);
resultArray[0].setFConst(f1);
resultArray[1].setFConst(f2);
break;
}
else
{
infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
return nullptr;
}
case EOpUnpackHalf2x16:
if (getType().getBasicType() == EbtUInt)
{
resultArray = new TConstantUnion[2];
float f1, f2;
gl::unpackHalf2x16(operandArray[0].getUConst(), &f1, &f2);
resultArray[0].setFConst(f1);
resultArray[1].setFConst(f2);
break;
}
else
{
infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
return nullptr;
}
case EOpPackHalf2x16:
if (getType().getBasicType() == EbtFloat)
{
ASSERT(getType().getNominalSize() == 2);
resultArray = new TConstantUnion();
resultArray->setUConst(gl::packHalf2x16(operandArray[0].getFConst(), operandArray[1].getFConst()));
break;
}
else
{
infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
return nullptr;
}
default:
case EOpUnpackHalf2x16:
if (getType().getBasicType() == EbtUInt)
{
resultArray = new TConstantUnion[2];
float f1, f2;
gl::unpackHalf2x16(operandArray[0].getUConst(), &f1, &f2);
resultArray[0].setFConst(f1);
resultArray[1].setFConst(f2);
break;
}
else
{
infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
return nullptr;
}
break;
return resultArray;
default:
break;
}
else
return resultArray;
}
TConstantUnion *TIntermConstantUnion::foldUnaryWithSameReturnType(TOperator op, TInfoSink &infoSink)
{
//
// Do unary operations where the return type is the same as operand type.
//
TConstantUnion *operandArray = getUnionArrayPointer();
if (!operandArray)
return nullptr;
size_t objectSize = getType().getObjectSize();
TConstantUnion *resultArray = new TConstantUnion[objectSize];
for (size_t i = 0; i < objectSize; i++)
{
//
// Do unary operations where the return type is the same as operand type.
//
TConstantUnion *resultArray = new TConstantUnion[objectSize];
for (size_t i = 0; i < objectSize; i++)
switch(op)
{
switch(op)
case EOpNegative:
switch (getType().getBasicType())
{
case EOpNegative:
switch (getType().getBasicType())
{
case EbtFloat:
resultArray[i].setFConst(-operandArray[i].getFConst());
break;
case EbtInt:
resultArray[i].setIConst(-operandArray[i].getIConst());
break;
case EbtUInt:
resultArray[i].setUConst(static_cast<unsigned int>(
-static_cast<int>(operandArray[i].getUConst())));
break;
default:
infoSink.info.message(
EPrefixInternalError, getLine(),
"Unary operation not folded into constant");
return nullptr;
}
case EbtFloat:
resultArray[i].setFConst(-operandArray[i].getFConst());
break;
case EOpPositive:
switch (getType().getBasicType())
{
case EbtFloat:
resultArray[i].setFConst(operandArray[i].getFConst());
break;
case EbtInt:
resultArray[i].setIConst(operandArray[i].getIConst());
break;
case EbtUInt:
resultArray[i].setUConst(static_cast<unsigned int>(
static_cast<int>(operandArray[i].getUConst())));
break;
default:
infoSink.info.message(
EPrefixInternalError, getLine(),
"Unary operation not folded into constant");
return nullptr;
}
case EbtInt:
resultArray[i].setIConst(-operandArray[i].getIConst());
break;
case EOpLogicalNot:
// this code is written for possible future use,
// will not get executed currently
switch (getType().getBasicType())
{
case EbtBool:
resultArray[i].setBConst(!operandArray[i].getBConst());
break;
default:
infoSink.info.message(
EPrefixInternalError, getLine(),
"Unary operation not folded into constant");
return nullptr;
}
case EbtUInt:
resultArray[i].setUConst(static_cast<unsigned int>(
-static_cast<int>(operandArray[i].getUConst())));
break;
default:
infoSink.info.message(
EPrefixInternalError, getLine(),
"Unary operation not folded into constant");
return nullptr;
}
break;
case EOpBitwiseNot:
switch (getType().getBasicType())
{
case EbtInt:
resultArray[i].setIConst(~operandArray[i].getIConst());
break;
case EbtUInt:
resultArray[i].setUConst(~operandArray[i].getUConst());
break;
default:
infoSink.info.message(
EPrefixInternalError, getLine(),
"Unary operation not folded into constant");
return nullptr;
}
case EOpPositive:
switch (getType().getBasicType())
{
case EbtFloat:
resultArray[i].setFConst(operandArray[i].getFConst());
break;
case EOpRadians:
if (getType().getBasicType() == EbtFloat)
{
resultArray[i].setFConst(kDegreesToRadiansMultiplier * operandArray[i].getFConst());
break;
}
case EbtInt:
resultArray[i].setIConst(operandArray[i].getIConst());
break;
case EbtUInt:
resultArray[i].setUConst(static_cast<unsigned int>(
static_cast<int>(operandArray[i].getUConst())));
break;
default:
infoSink.info.message(
EPrefixInternalError, getLine(),
"Unary operation not folded into constant");
return nullptr;
}
break;
case EOpDegrees:
if (getType().getBasicType() == EbtFloat)
{
resultArray[i].setFConst(kRadiansToDegreesMultiplier * operandArray[i].getFConst());
break;
}
case EOpLogicalNot:
// this code is written for possible future use,
// will not get executed currently
switch (getType().getBasicType())
{
case EbtBool:
resultArray[i].setBConst(!operandArray[i].getBConst());
break;
default:
infoSink.info.message(
EPrefixInternalError, getLine(),
"Unary operation not folded into constant");
return nullptr;
}
break;
case EOpSin:
if (!foldFloatTypeUnary(operandArray[i], &sinf, infoSink, &resultArray[i]))
return nullptr;
case EOpBitwiseNot:
switch (getType().getBasicType())
{
case EbtInt:
resultArray[i].setIConst(~operandArray[i].getIConst());
break;
case EOpCos:
if (!foldFloatTypeUnary(operandArray[i], &cosf, infoSink, &resultArray[i]))
return nullptr;
case EbtUInt:
resultArray[i].setUConst(~operandArray[i].getUConst());
break;
default:
infoSink.info.message(
EPrefixInternalError, getLine(),
"Unary operation not folded into constant");
return nullptr;
}
break;
case EOpTan:
if (!foldFloatTypeUnary(operandArray[i], &tanf, infoSink, &resultArray[i]))
return nullptr;
case EOpRadians:
if (getType().getBasicType() == EbtFloat)
{
resultArray[i].setFConst(kDegreesToRadiansMultiplier * operandArray[i].getFConst());
break;
}
infoSink.info.message(
EPrefixInternalError, getLine(),
"Unary operation not folded into constant");
return nullptr;
case EOpAsin:
// For asin(x), results are undefined if |x| > 1, we are choosing to set result to 0.
if (getType().getBasicType() == EbtFloat && fabsf(operandArray[i].getFConst()) > 1.0f)
UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(), infoSink, &resultArray[i]);
else if (!foldFloatTypeUnary(operandArray[i], &asinf, infoSink, &resultArray[i]))
return nullptr;
case EOpDegrees:
if (getType().getBasicType() == EbtFloat)
{
resultArray[i].setFConst(kRadiansToDegreesMultiplier * operandArray[i].getFConst());
break;
}
infoSink.info.message(
EPrefixInternalError, getLine(),
"Unary operation not folded into constant");
return nullptr;
case EOpAcos:
// For acos(x), results are undefined if |x| > 1, we are choosing to set result to 0.
if (getType().getBasicType() == EbtFloat && fabsf(operandArray[i].getFConst()) > 1.0f)
UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(), infoSink, &resultArray[i]);
else if (!foldFloatTypeUnary(operandArray[i], &acosf, infoSink, &resultArray[i]))
return nullptr;
break;
case EOpSin:
if (!foldFloatTypeUnary(operandArray[i], &sinf, infoSink, &resultArray[i]))
return nullptr;
break;
case EOpAtan:
if (!foldFloatTypeUnary(operandArray[i], &atanf, infoSink, &resultArray[i]))
return nullptr;
break;
case EOpCos:
if (!foldFloatTypeUnary(operandArray[i], &cosf, infoSink, &resultArray[i]))
return nullptr;
break;
case EOpSinh:
if (!foldFloatTypeUnary(operandArray[i], &sinhf, infoSink, &resultArray[i]))
return nullptr;
break;
case EOpTan:
if (!foldFloatTypeUnary(operandArray[i], &tanf, infoSink, &resultArray[i]))
return nullptr;
break;
case EOpCosh:
if (!foldFloatTypeUnary(operandArray[i], &coshf, infoSink, &resultArray[i]))
return nullptr;
break;
case EOpAsin:
// For asin(x), results are undefined if |x| > 1, we are choosing to set result to 0.
if (getType().getBasicType() == EbtFloat && fabsf(operandArray[i].getFConst()) > 1.0f)
UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(), infoSink, &resultArray[i]);
else if (!foldFloatTypeUnary(operandArray[i], &asinf, infoSink, &resultArray[i]))
return nullptr;
break;
case EOpTanh:
if (!foldFloatTypeUnary(operandArray[i], &tanhf, infoSink, &resultArray[i]))
return nullptr;
break;
case EOpAcos:
// For acos(x), results are undefined if |x| > 1, we are choosing to set result to 0.
if (getType().getBasicType() == EbtFloat && fabsf(operandArray[i].getFConst()) > 1.0f)
UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(), infoSink, &resultArray[i]);
else if (!foldFloatTypeUnary(operandArray[i], &acosf, infoSink, &resultArray[i]))
return nullptr;
break;
case EOpAsinh:
if (!foldFloatTypeUnary(operandArray[i], &asinhf, infoSink, &resultArray[i]))
return nullptr;
break;
case EOpAtan:
if (!foldFloatTypeUnary(operandArray[i], &atanf, infoSink, &resultArray[i]))
return nullptr;
break;
case EOpAcosh:
// For acosh(x), results are undefined if x < 1, we are choosing to set result to 0.
if (getType().getBasicType() == EbtFloat && operandArray[i].getFConst() < 1.0f)
UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(), infoSink, &resultArray[i]);
else if (!foldFloatTypeUnary(operandArray[i], &acoshf, infoSink, &resultArray[i]))
return nullptr;
break;
case EOpSinh:
if (!foldFloatTypeUnary(operandArray[i], &sinhf, infoSink, &resultArray[i]))
return nullptr;
break;
case EOpAtanh:
// For atanh(x), results are undefined if |x| >= 1, we are choosing to set result to 0.
if (getType().getBasicType() == EbtFloat && fabsf(operandArray[i].getFConst()) >= 1.0f)
UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(), infoSink, &resultArray[i]);
else if (!foldFloatTypeUnary(operandArray[i], &atanhf, infoSink, &resultArray[i]))
return nullptr;
break;
case EOpCosh:
if (!foldFloatTypeUnary(operandArray[i], &coshf, infoSink, &resultArray[i]))
return nullptr;
break;
case EOpAbs:
switch (getType().getBasicType())
{
case EbtFloat:
resultArray[i].setFConst(fabsf(operandArray[i].getFConst()));
break;
case EbtInt:
resultArray[i].setIConst(abs(operandArray[i].getIConst()));
break;
default:
infoSink.info.message(
EPrefixInternalError, getLine(),
"Unary operation not folded into constant");
return nullptr;
}
break;
case EOpTanh:
if (!foldFloatTypeUnary(operandArray[i], &tanhf, infoSink, &resultArray[i]))
return nullptr;
break;
case EOpSign:
switch (getType().getBasicType())
{
case EbtFloat:
{
float fConst = operandArray[i].getFConst();
float fResult = 0.0f;
if (fConst > 0.0f)
fResult = 1.0f;
else if (fConst < 0.0f)
fResult = -1.0f;
resultArray[i].setFConst(fResult);
}
break;
case EbtInt:
{
int iConst = operandArray[i].getIConst();
int iResult = 0;
if (iConst > 0)
iResult = 1;
else if (iConst < 0)
iResult = -1;
resultArray[i].setIConst(iResult);
}
break;
default:
infoSink.info.message(
EPrefixInternalError, getLine(),
"Unary operation not folded into constant");
return nullptr;
}
break;
case EOpAsinh:
if (!foldFloatTypeUnary(operandArray[i], &asinhf, infoSink, &resultArray[i]))
return nullptr;
break;
case EOpFloor:
if (!foldFloatTypeUnary(operandArray[i], &floorf, infoSink, &resultArray[i]))
return nullptr;
break;
case EOpAcosh:
// For acosh(x), results are undefined if x < 1, we are choosing to set result to 0.
if (getType().getBasicType() == EbtFloat && operandArray[i].getFConst() < 1.0f)
UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(), infoSink, &resultArray[i]);
else if (!foldFloatTypeUnary(operandArray[i], &acoshf, infoSink, &resultArray[i]))
return nullptr;
break;
case EOpTrunc:
if (!foldFloatTypeUnary(operandArray[i], &truncf, infoSink, &resultArray[i]))
return nullptr;
break;
case EOpAtanh:
// For atanh(x), results are undefined if |x| >= 1, we are choosing to set result to 0.
if (getType().getBasicType() == EbtFloat && fabsf(operandArray[i].getFConst()) >= 1.0f)
UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(), infoSink, &resultArray[i]);
else if (!foldFloatTypeUnary(operandArray[i], &atanhf, infoSink, &resultArray[i]))
return nullptr;
break;
case EOpRound:
if (!foldFloatTypeUnary(operandArray[i], &roundf, infoSink, &resultArray[i]))
return nullptr;
case EOpAbs:
switch (getType().getBasicType())
{
case EbtFloat:
resultArray[i].setFConst(fabsf(operandArray[i].getFConst()));
break;
case EOpRoundEven:
if (getType().getBasicType() == EbtFloat)
{
float x = operandArray[i].getFConst();
float result;
float fractPart = modff(x, &result);
if (fabsf(fractPart) == 0.5f)
result = 2.0f * roundf(x / 2.0f);
else
result = roundf(x);
resultArray[i].setFConst(result);
break;
}
case EbtInt:
resultArray[i].setIConst(abs(operandArray[i].getIConst()));
break;
default:
infoSink.info.message(
EPrefixInternalError, getLine(),
"Unary operation not folded into constant");
return nullptr;
}
break;
case EOpCeil:
if (!foldFloatTypeUnary(operandArray[i], &ceilf, infoSink, &resultArray[i]))
return nullptr;
case EOpSign:
switch (getType().getBasicType())
{
case EbtFloat:
{
float fConst = operandArray[i].getFConst();
float fResult = 0.0f;
if (fConst > 0.0f)
fResult = 1.0f;
else if (fConst < 0.0f)
fResult = -1.0f;
resultArray[i].setFConst(fResult);
}
break;
case EOpFract:
if (getType().getBasicType() == EbtFloat)
case EbtInt:
{
float x = operandArray[i].getFConst();
resultArray[i].setFConst(x - floorf(x));
break;
int iConst = operandArray[i].getIConst();
int iResult = 0;
if (iConst > 0)
iResult = 1;
else if (iConst < 0)
iResult = -1;
resultArray[i].setIConst(iResult);
}
break;
default:
infoSink.info.message(
EPrefixInternalError, getLine(),
"Unary operation not folded into constant");
return nullptr;
}
break;
case EOpExp:
if (!foldFloatTypeUnary(operandArray[i], &expf, infoSink, &resultArray[i]))
return nullptr;
break;
case EOpFloor:
if (!foldFloatTypeUnary(operandArray[i], &floorf, infoSink, &resultArray[i]))
return nullptr;
break;
case EOpLog:
// For log(x), results are undefined if x <= 0, we are choosing to set result to 0.
if (getType().getBasicType() == EbtFloat && operandArray[i].getFConst() <= 0.0f)
UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(), infoSink, &resultArray[i]);
else if (!foldFloatTypeUnary(operandArray[i], &logf, infoSink, &resultArray[i]))
return nullptr;
break;
case EOpTrunc:
if (!foldFloatTypeUnary(operandArray[i], &truncf, infoSink, &resultArray[i]))
return nullptr;
break;
case EOpExp2:
if (!foldFloatTypeUnary(operandArray[i], &exp2f, infoSink, &resultArray[i]))
return nullptr;
break;
case EOpRound:
if (!foldFloatTypeUnary(operandArray[i], &roundf, infoSink, &resultArray[i]))
return nullptr;
break;
case EOpLog2:
// For log2(x), results are undefined if x <= 0, we are choosing to set result to 0.
// And log2f is not available on some plarforms like old android, so just using log(x)/log(2) here.
if (getType().getBasicType() == EbtFloat && operandArray[i].getFConst() <= 0.0f)
UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(), infoSink, &resultArray[i]);
else if (!foldFloatTypeUnary(operandArray[i], &logf, infoSink, &resultArray[i]))
return nullptr;
case EOpRoundEven:
if (getType().getBasicType() == EbtFloat)
{
float x = operandArray[i].getFConst();
float result;
float fractPart = modff(x, &result);
if (fabsf(fractPart) == 0.5f)
result = 2.0f * roundf(x / 2.0f);
else
resultArray[i].setFConst(resultArray[i].getFConst() / logf(2.0f));
result = roundf(x);
resultArray[i].setFConst(result);
break;
}
infoSink.info.message(
EPrefixInternalError, getLine(),
"Unary operation not folded into constant");
return nullptr;
case EOpSqrt:
// For sqrt(x), results are undefined if x < 0, we are choosing to set result to 0.
if (getType().getBasicType() == EbtFloat && operandArray[i].getFConst() < 0.0f)
UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(), infoSink, &resultArray[i]);
else if (!foldFloatTypeUnary(operandArray[i], &sqrtf, infoSink, &resultArray[i]))
return nullptr;
break;
case EOpCeil:
if (!foldFloatTypeUnary(operandArray[i], &ceilf, infoSink, &resultArray[i]))
return nullptr;
break;
case EOpInverseSqrt:
// There is no stdlib built-in function equavalent for GLES built-in inversesqrt(),
// so getting the square root first using builtin function sqrt() and then taking its inverse.
// Also, for inversesqrt(x), results are undefined if x <= 0, we are choosing to set result to 0.
if (getType().getBasicType() == EbtFloat && operandArray[i].getFConst() <= 0.0f)
UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(), infoSink, &resultArray[i]);
else if (!foldFloatTypeUnary(operandArray[i], &sqrtf, infoSink, &resultArray[i]))
return nullptr;
else
resultArray[i].setFConst(1.0f / resultArray[i].getFConst());
case EOpFract:
if (getType().getBasicType() == EbtFloat)
{
float x = operandArray[i].getFConst();
resultArray[i].setFConst(x - floorf(x));
break;
}
infoSink.info.message(
EPrefixInternalError, getLine(),
"Unary operation not folded into constant");
return nullptr;
case EOpVectorLogicalNot:
if (getType().getBasicType() == EbtBool)
{
resultArray[i].setBConst(!operandArray[i].getBConst());
break;
}
infoSink.info.message(
EPrefixInternalError, getLine(),
"Unary operation not folded into constant");
case EOpExp:
if (!foldFloatTypeUnary(operandArray[i], &expf, infoSink, &resultArray[i]))
return nullptr;
break;
case EOpLog:
// For log(x), results are undefined if x <= 0, we are choosing to set result to 0.
if (getType().getBasicType() == EbtFloat && operandArray[i].getFConst() <= 0.0f)
UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(), infoSink, &resultArray[i]);
else if (!foldFloatTypeUnary(operandArray[i], &logf, infoSink, &resultArray[i]))
return nullptr;
break;
case EOpNormalize:
if (getType().getBasicType() == EbtFloat)
{
float x = operandArray[i].getFConst();
float length = VectorLength(operandArray, objectSize);
if (length)
resultArray[i].setFConst(x / length);
else
UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(), infoSink,
&resultArray[i]);
break;
}
infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
case EOpExp2:
if (!foldFloatTypeUnary(operandArray[i], &exp2f, infoSink, &resultArray[i]))
return nullptr;
break;
default:
case EOpLog2:
// For log2(x), results are undefined if x <= 0, we are choosing to set result to 0.
// And log2f is not available on some plarforms like old android, so just using log(x)/log(2) here.
if (getType().getBasicType() == EbtFloat && operandArray[i].getFConst() <= 0.0f)
UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(), infoSink, &resultArray[i]);
else if (!foldFloatTypeUnary(operandArray[i], &logf, infoSink, &resultArray[i]))
return nullptr;
else
resultArray[i].setFConst(resultArray[i].getFConst() / logf(2.0f));
break;
case EOpSqrt:
// For sqrt(x), results are undefined if x < 0, we are choosing to set result to 0.
if (getType().getBasicType() == EbtFloat && operandArray[i].getFConst() < 0.0f)
UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(), infoSink, &resultArray[i]);
else if (!foldFloatTypeUnary(operandArray[i], &sqrtf, infoSink, &resultArray[i]))
return nullptr;
break;
case EOpInverseSqrt:
// There is no stdlib built-in function equavalent for GLES built-in inversesqrt(),
// so getting the square root first using builtin function sqrt() and then taking its inverse.
// Also, for inversesqrt(x), results are undefined if x <= 0, we are choosing to set result to 0.
if (getType().getBasicType() == EbtFloat && operandArray[i].getFConst() <= 0.0f)
UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(), infoSink, &resultArray[i]);
else if (!foldFloatTypeUnary(operandArray[i], &sqrtf, infoSink, &resultArray[i]))
return nullptr;
else
resultArray[i].setFConst(1.0f / resultArray[i].getFConst());
break;
case EOpVectorLogicalNot:
if (getType().getBasicType() == EbtBool)
{
resultArray[i].setBConst(!operandArray[i].getBConst());
break;
}
infoSink.info.message(
EPrefixInternalError, getLine(),
"Unary operation not folded into constant");
return nullptr;
case EOpNormalize:
if (getType().getBasicType() == EbtFloat)
{
float x = operandArray[i].getFConst();
float length = VectorLength(operandArray, objectSize);
if (length)
resultArray[i].setFConst(x / length);
else
UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(), infoSink,
&resultArray[i]);
break;
}
infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
return nullptr;
default:
return nullptr;
}
return resultArray;
}
return resultArray;
}
bool TIntermConstantUnion::foldFloatTypeUnary(const TConstantUnion &parameter, FloatTypeUnaryFunc builtinFunc,
......
......@@ -300,7 +300,8 @@ class TIntermConstantUnion : public TIntermTyped
virtual bool replaceChildNode(TIntermNode *, TIntermNode *) { return false; }
TConstantUnion *foldBinary(TOperator op, TIntermConstantUnion *rightNode, TInfoSink &infoSink);
TConstantUnion *foldUnary(TOperator op, TInfoSink &infoSink);
TConstantUnion *foldUnaryWithDifferentReturnType(TOperator op, TInfoSink &infoSink);
TConstantUnion *foldUnaryWithSameReturnType(TOperator op, TInfoSink &infoSink);
static TConstantUnion *FoldAggregateBuiltIn(TIntermAggregate *aggregate, TInfoSink &infoSink);
......
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