Commit 51182ab9 by Olli Etuaho Committed by Commit Bot

Clean up TIntermAggregate folding

The division between 2- and 3-parameter built-ins is superfluous and can be removed. Also folding support for ESSL 3.00 is complete, so the comments about needing to add folding support for more functions can be removed. BUG=angleproject:1730 TEST=angle_unittests Change-Id: I5ca93a957a98a7740eca506e44af48e7b4b83bad Reviewed-on: https://chromium-review.googlesource.com/431108Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarCorentin Wallez <cwallez@chromium.org> Commit-Queue: Olli Etuaho <oetuaho@nvidia.com>
parent a2aff2a4
...@@ -2313,558 +2313,531 @@ TConstantUnion *TIntermConstantUnion::FoldAggregateBuiltIn(TIntermAggregate *agg ...@@ -2313,558 +2313,531 @@ TConstantUnion *TIntermConstantUnion::FoldAggregateBuiltIn(TIntermAggregate *agg
} }
TConstantUnion *resultArray = nullptr; TConstantUnion *resultArray = nullptr;
if (paramsCount == 2)
switch (op)
{ {
// case EOpAtan:
// Binary built-in
//
switch (op)
{ {
case EOpAtan: ASSERT(basicType == EbtFloat);
resultArray = new TConstantUnion[maxObjectSize];
for (size_t i = 0; i < maxObjectSize; i++)
{ {
ASSERT(basicType == EbtFloat); float y = unionArrays[0][i].getFConst();
resultArray = new TConstantUnion[maxObjectSize]; float x = unionArrays[1][i].getFConst();
for (size_t i = 0; i < maxObjectSize; i++) // Results are undefined if x and y are both 0.
{ if (x == 0.0f && y == 0.0f)
float y = unionArrays[0][i].getFConst(); UndefinedConstantFoldingError(loc, op, basicType, diagnostics, &resultArray[i]);
float x = unionArrays[1][i].getFConst(); else
// Results are undefined if x and y are both 0. resultArray[i].setFConst(atan2f(y, x));
if (x == 0.0f && y == 0.0f)
UndefinedConstantFoldingError(loc, op, basicType, diagnostics,
&resultArray[i]);
else
resultArray[i].setFConst(atan2f(y, x));
}
break;
} }
break;
}
case EOpPow: case EOpPow:
{
ASSERT(basicType == EbtFloat);
resultArray = new TConstantUnion[maxObjectSize];
for (size_t i = 0; i < maxObjectSize; i++)
{ {
ASSERT(basicType == EbtFloat); float x = unionArrays[0][i].getFConst();
resultArray = new TConstantUnion[maxObjectSize]; float y = unionArrays[1][i].getFConst();
for (size_t i = 0; i < maxObjectSize; i++) // Results are undefined if x < 0.
{ // Results are undefined if x = 0 and y <= 0.
float x = unionArrays[0][i].getFConst(); if (x < 0.0f)
float y = unionArrays[1][i].getFConst(); UndefinedConstantFoldingError(loc, op, basicType, diagnostics, &resultArray[i]);
// Results are undefined if x < 0. else if (x == 0.0f && y <= 0.0f)
// Results are undefined if x = 0 and y <= 0. UndefinedConstantFoldingError(loc, op, basicType, diagnostics, &resultArray[i]);
if (x < 0.0f) else
UndefinedConstantFoldingError(loc, op, basicType, diagnostics, resultArray[i].setFConst(powf(x, y));
&resultArray[i]);
else if (x == 0.0f && y <= 0.0f)
UndefinedConstantFoldingError(loc, op, basicType, diagnostics,
&resultArray[i]);
else
resultArray[i].setFConst(powf(x, y));
}
break;
} }
break;
}
case EOpMod: case EOpMod:
{
ASSERT(basicType == EbtFloat);
resultArray = new TConstantUnion[maxObjectSize];
for (size_t i = 0; i < maxObjectSize; i++)
{ {
ASSERT(basicType == EbtFloat); float x = unionArrays[0][i].getFConst();
resultArray = new TConstantUnion[maxObjectSize]; float y = unionArrays[1][i].getFConst();
for (size_t i = 0; i < maxObjectSize; i++) resultArray[i].setFConst(x - y * floorf(x / y));
{
float x = unionArrays[0][i].getFConst();
float y = unionArrays[1][i].getFConst();
resultArray[i].setFConst(x - y * floorf(x / y));
}
break;
} }
break;
}
case EOpMin: case EOpMin:
{
resultArray = new TConstantUnion[maxObjectSize];
for (size_t i = 0; i < maxObjectSize; i++)
{ {
resultArray = new TConstantUnion[maxObjectSize]; switch (basicType)
for (size_t i = 0; i < maxObjectSize; i++)
{ {
switch (basicType) case EbtFloat:
{ resultArray[i].setFConst(
case EbtFloat: std::min(unionArrays[0][i].getFConst(), unionArrays[1][i].getFConst()));
resultArray[i].setFConst(std::min(unionArrays[0][i].getFConst(), break;
unionArrays[1][i].getFConst())); case EbtInt:
break; resultArray[i].setIConst(
case EbtInt: std::min(unionArrays[0][i].getIConst(), unionArrays[1][i].getIConst()));
resultArray[i].setIConst(std::min(unionArrays[0][i].getIConst(), break;
unionArrays[1][i].getIConst())); case EbtUInt:
break; resultArray[i].setUConst(
case EbtUInt: std::min(unionArrays[0][i].getUConst(), unionArrays[1][i].getUConst()));
resultArray[i].setUConst(std::min(unionArrays[0][i].getUConst(), break;
unionArrays[1][i].getUConst())); default:
break; UNREACHABLE();
default: break;
UNREACHABLE();
break;
}
} }
break;
} }
break;
}
case EOpMax: case EOpMax:
{
resultArray = new TConstantUnion[maxObjectSize];
for (size_t i = 0; i < maxObjectSize; i++)
{ {
resultArray = new TConstantUnion[maxObjectSize]; switch (basicType)
for (size_t i = 0; i < maxObjectSize; i++)
{ {
switch (basicType) case EbtFloat:
{ resultArray[i].setFConst(
case EbtFloat: std::max(unionArrays[0][i].getFConst(), unionArrays[1][i].getFConst()));
resultArray[i].setFConst(std::max(unionArrays[0][i].getFConst(), break;
unionArrays[1][i].getFConst())); case EbtInt:
break; resultArray[i].setIConst(
case EbtInt: std::max(unionArrays[0][i].getIConst(), unionArrays[1][i].getIConst()));
resultArray[i].setIConst(std::max(unionArrays[0][i].getIConst(), break;
unionArrays[1][i].getIConst())); case EbtUInt:
break; resultArray[i].setUConst(
case EbtUInt: std::max(unionArrays[0][i].getUConst(), unionArrays[1][i].getUConst()));
resultArray[i].setUConst(std::max(unionArrays[0][i].getUConst(), break;
unionArrays[1][i].getUConst())); default:
break; UNREACHABLE();
default: break;
UNREACHABLE();
break;
}
} }
break;
} }
break;
}
case EOpStep: case EOpStep:
{ {
ASSERT(basicType == EbtFloat); ASSERT(basicType == EbtFloat);
resultArray = new TConstantUnion[maxObjectSize]; resultArray = new TConstantUnion[maxObjectSize];
for (size_t i = 0; i < maxObjectSize; i++) for (size_t i = 0; i < maxObjectSize; i++)
resultArray[i].setFConst( resultArray[i].setFConst(
unionArrays[1][i].getFConst() < unionArrays[0][i].getFConst() ? 0.0f unionArrays[1][i].getFConst() < unionArrays[0][i].getFConst() ? 0.0f : 1.0f);
: 1.0f); break;
break; }
}
case EOpLessThanComponentWise: case EOpLessThanComponentWise:
{
resultArray = new TConstantUnion[maxObjectSize];
for (size_t i = 0; i < maxObjectSize; i++)
{ {
resultArray = new TConstantUnion[maxObjectSize]; switch (basicType)
for (size_t i = 0; i < maxObjectSize; i++)
{ {
switch (basicType) case EbtFloat:
{ resultArray[i].setBConst(unionArrays[0][i].getFConst() <
case EbtFloat: unionArrays[1][i].getFConst());
resultArray[i].setBConst(unionArrays[0][i].getFConst() < break;
unionArrays[1][i].getFConst()); case EbtInt:
break; resultArray[i].setBConst(unionArrays[0][i].getIConst() <
case EbtInt: unionArrays[1][i].getIConst());
resultArray[i].setBConst(unionArrays[0][i].getIConst() < break;
unionArrays[1][i].getIConst()); case EbtUInt:
break; resultArray[i].setBConst(unionArrays[0][i].getUConst() <
case EbtUInt: unionArrays[1][i].getUConst());
resultArray[i].setBConst(unionArrays[0][i].getUConst() < break;
unionArrays[1][i].getUConst()); default:
break; UNREACHABLE();
default: break;
UNREACHABLE();
break;
}
} }
break;
} }
break;
}
case EOpLessThanEqualComponentWise: case EOpLessThanEqualComponentWise:
{
resultArray = new TConstantUnion[maxObjectSize];
for (size_t i = 0; i < maxObjectSize; i++)
{ {
resultArray = new TConstantUnion[maxObjectSize]; switch (basicType)
for (size_t i = 0; i < maxObjectSize; i++)
{ {
switch (basicType) case EbtFloat:
{ resultArray[i].setBConst(unionArrays[0][i].getFConst() <=
case EbtFloat: unionArrays[1][i].getFConst());
resultArray[i].setBConst(unionArrays[0][i].getFConst() <= break;
unionArrays[1][i].getFConst()); case EbtInt:
break; resultArray[i].setBConst(unionArrays[0][i].getIConst() <=
case EbtInt: unionArrays[1][i].getIConst());
resultArray[i].setBConst(unionArrays[0][i].getIConst() <= break;
unionArrays[1][i].getIConst()); case EbtUInt:
break; resultArray[i].setBConst(unionArrays[0][i].getUConst() <=
case EbtUInt: unionArrays[1][i].getUConst());
resultArray[i].setBConst(unionArrays[0][i].getUConst() <= break;
unionArrays[1][i].getUConst()); default:
break; UNREACHABLE();
default: break;
UNREACHABLE();
break;
}
} }
break;
} }
break;
}
case EOpGreaterThanComponentWise: case EOpGreaterThanComponentWise:
{ {
resultArray = new TConstantUnion[maxObjectSize]; resultArray = new TConstantUnion[maxObjectSize];
for (size_t i = 0; i < maxObjectSize; i++) for (size_t i = 0; i < maxObjectSize; i++)
{
switch (basicType)
{
case EbtFloat:
resultArray[i].setBConst(unionArrays[0][i].getFConst() >
unionArrays[1][i].getFConst());
break;
case EbtInt:
resultArray[i].setBConst(unionArrays[0][i].getIConst() >
unionArrays[1][i].getIConst());
break;
case EbtUInt:
resultArray[i].setBConst(unionArrays[0][i].getUConst() >
unionArrays[1][i].getUConst());
break;
default:
UNREACHABLE();
break;
}
}
break;
}
case EOpGreaterThanEqualComponentWise:
{ {
resultArray = new TConstantUnion[maxObjectSize]; switch (basicType)
for (size_t i = 0; i < maxObjectSize; i++)
{ {
switch (basicType) case EbtFloat:
{ resultArray[i].setBConst(unionArrays[0][i].getFConst() >
case EbtFloat: unionArrays[1][i].getFConst());
resultArray[i].setBConst(unionArrays[0][i].getFConst() >= break;
unionArrays[1][i].getFConst()); case EbtInt:
break; resultArray[i].setBConst(unionArrays[0][i].getIConst() >
case EbtInt: unionArrays[1][i].getIConst());
resultArray[i].setBConst(unionArrays[0][i].getIConst() >= break;
unionArrays[1][i].getIConst()); case EbtUInt:
break; resultArray[i].setBConst(unionArrays[0][i].getUConst() >
case EbtUInt: unionArrays[1][i].getUConst());
resultArray[i].setBConst(unionArrays[0][i].getUConst() >= break;
unionArrays[1][i].getUConst()); default:
break; UNREACHABLE();
default: break;
UNREACHABLE();
break;
}
} }
} }
break; break;
}
case EOpEqualComponentWise: case EOpGreaterThanEqualComponentWise:
{
resultArray = new TConstantUnion[maxObjectSize];
for (size_t i = 0; i < maxObjectSize; i++)
{ {
resultArray = new TConstantUnion[maxObjectSize]; switch (basicType)
for (size_t i = 0; i < maxObjectSize; i++)
{ {
switch (basicType) case EbtFloat:
{ resultArray[i].setBConst(unionArrays[0][i].getFConst() >=
case EbtFloat: unionArrays[1][i].getFConst());
resultArray[i].setBConst(unionArrays[0][i].getFConst() == break;
unionArrays[1][i].getFConst()); case EbtInt:
break; resultArray[i].setBConst(unionArrays[0][i].getIConst() >=
case EbtInt: unionArrays[1][i].getIConst());
resultArray[i].setBConst(unionArrays[0][i].getIConst() == break;
unionArrays[1][i].getIConst()); case EbtUInt:
break; resultArray[i].setBConst(unionArrays[0][i].getUConst() >=
case EbtUInt: unionArrays[1][i].getUConst());
resultArray[i].setBConst(unionArrays[0][i].getUConst() == break;
unionArrays[1][i].getUConst()); default:
break; UNREACHABLE();
case EbtBool: break;
resultArray[i].setBConst(unionArrays[0][i].getBConst() ==
unionArrays[1][i].getBConst());
break;
default:
UNREACHABLE();
break;
}
} }
break;
} }
}
break;
case EOpNotEqualComponentWise: case EOpEqualComponentWise:
{
resultArray = new TConstantUnion[maxObjectSize];
for (size_t i = 0; i < maxObjectSize; i++)
{ {
resultArray = new TConstantUnion[maxObjectSize]; switch (basicType)
for (size_t i = 0; i < maxObjectSize; i++)
{ {
switch (basicType) case EbtFloat:
{ resultArray[i].setBConst(unionArrays[0][i].getFConst() ==
case EbtFloat: unionArrays[1][i].getFConst());
resultArray[i].setBConst(unionArrays[0][i].getFConst() != break;
unionArrays[1][i].getFConst()); case EbtInt:
break; resultArray[i].setBConst(unionArrays[0][i].getIConst() ==
case EbtInt: unionArrays[1][i].getIConst());
resultArray[i].setBConst(unionArrays[0][i].getIConst() != break;
unionArrays[1][i].getIConst()); case EbtUInt:
break; resultArray[i].setBConst(unionArrays[0][i].getUConst() ==
case EbtUInt: unionArrays[1][i].getUConst());
resultArray[i].setBConst(unionArrays[0][i].getUConst() != break;
unionArrays[1][i].getUConst()); case EbtBool:
break; resultArray[i].setBConst(unionArrays[0][i].getBConst() ==
case EbtBool: unionArrays[1][i].getBConst());
resultArray[i].setBConst(unionArrays[0][i].getBConst() != break;
unionArrays[1][i].getBConst()); default:
break; UNREACHABLE();
default: break;
UNREACHABLE();
break;
}
} }
break;
} }
break;
}
case EOpDistance: case EOpNotEqualComponentWise:
{
resultArray = new TConstantUnion[maxObjectSize];
for (size_t i = 0; i < maxObjectSize; i++)
{ {
ASSERT(basicType == EbtFloat); switch (basicType)
TConstantUnion *distanceArray = new TConstantUnion[maxObjectSize];
resultArray = new TConstantUnion();
for (size_t i = 0; i < maxObjectSize; i++)
{ {
float x = unionArrays[0][i].getFConst(); case EbtFloat:
float y = unionArrays[1][i].getFConst(); resultArray[i].setBConst(unionArrays[0][i].getFConst() !=
distanceArray[i].setFConst(x - y); unionArrays[1][i].getFConst());
break;
case EbtInt:
resultArray[i].setBConst(unionArrays[0][i].getIConst() !=
unionArrays[1][i].getIConst());
break;
case EbtUInt:
resultArray[i].setBConst(unionArrays[0][i].getUConst() !=
unionArrays[1][i].getUConst());
break;
case EbtBool:
resultArray[i].setBConst(unionArrays[0][i].getBConst() !=
unionArrays[1][i].getBConst());
break;
default:
UNREACHABLE();
break;
} }
resultArray->setFConst(VectorLength(distanceArray, maxObjectSize));
break;
} }
break;
}
case EOpDot: case EOpDistance:
ASSERT(basicType == EbtFloat); {
resultArray = new TConstantUnion(); ASSERT(basicType == EbtFloat);
resultArray->setFConst( TConstantUnion *distanceArray = new TConstantUnion[maxObjectSize];
VectorDotProduct(unionArrays[0], unionArrays[1], maxObjectSize)); resultArray = new TConstantUnion();
break; for (size_t i = 0; i < maxObjectSize; i++)
case EOpCross:
{ {
ASSERT(basicType == EbtFloat && maxObjectSize == 3); float x = unionArrays[0][i].getFConst();
resultArray = new TConstantUnion[maxObjectSize]; float y = unionArrays[1][i].getFConst();
float x0 = unionArrays[0][0].getFConst(); distanceArray[i].setFConst(x - y);
float x1 = unionArrays[0][1].getFConst();
float x2 = unionArrays[0][2].getFConst();
float y0 = unionArrays[1][0].getFConst();
float y1 = unionArrays[1][1].getFConst();
float y2 = unionArrays[1][2].getFConst();
resultArray[0].setFConst(x1 * y2 - y1 * x2);
resultArray[1].setFConst(x2 * y0 - y2 * x0);
resultArray[2].setFConst(x0 * y1 - y0 * x1);
break;
} }
resultArray->setFConst(VectorLength(distanceArray, maxObjectSize));
break;
}
case EOpReflect: case EOpDot:
{ ASSERT(basicType == EbtFloat);
ASSERT(basicType == EbtFloat); resultArray = new TConstantUnion();
// genType reflect (genType I, genType N) : resultArray->setFConst(VectorDotProduct(unionArrays[0], unionArrays[1], maxObjectSize));
// For the incident vector I and surface orientation N, returns the reflection break;
// direction:
// I - 2 * dot(N, I) * N.
resultArray = new TConstantUnion[maxObjectSize];
float dotProduct = VectorDotProduct(unionArrays[1], unionArrays[0], maxObjectSize);
for (size_t i = 0; i < maxObjectSize; i++)
{
float result = unionArrays[0][i].getFConst() -
2.0f * dotProduct * unionArrays[1][i].getFConst();
resultArray[i].setFConst(result);
}
break;
}
case EOpMulMatrixComponentWise: case EOpCross:
{ {
ASSERT(basicType == EbtFloat && (*sequence)[0]->getAsTyped()->isMatrix() && ASSERT(basicType == EbtFloat && maxObjectSize == 3);
(*sequence)[1]->getAsTyped()->isMatrix()); resultArray = new TConstantUnion[maxObjectSize];
// Perform component-wise matrix multiplication. float x0 = unionArrays[0][0].getFConst();
resultArray = new TConstantUnion[maxObjectSize]; float x1 = unionArrays[0][1].getFConst();
int size = (*sequence)[0]->getAsTyped()->getNominalSize(); float x2 = unionArrays[0][2].getFConst();
angle::Matrix<float> result = float y0 = unionArrays[1][0].getFConst();
GetMatrix(unionArrays[0], size).compMult(GetMatrix(unionArrays[1], size)); float y1 = unionArrays[1][1].getFConst();
SetUnionArrayFromMatrix(result, resultArray); float y2 = unionArrays[1][2].getFConst();
break; resultArray[0].setFConst(x1 * y2 - y1 * x2);
} resultArray[1].setFConst(x2 * y0 - y2 * x0);
resultArray[2].setFConst(x0 * y1 - y0 * x1);
break;
}
case EOpOuterProduct: case EOpReflect:
{
ASSERT(basicType == EbtFloat);
// genType reflect (genType I, genType N) :
// For the incident vector I and surface orientation N, returns the reflection
// direction:
// I - 2 * dot(N, I) * N.
resultArray = new TConstantUnion[maxObjectSize];
float dotProduct = VectorDotProduct(unionArrays[1], unionArrays[0], maxObjectSize);
for (size_t i = 0; i < maxObjectSize; i++)
{ {
ASSERT(basicType == EbtFloat); float result = unionArrays[0][i].getFConst() -
size_t numRows = (*sequence)[0]->getAsTyped()->getType().getObjectSize(); 2.0f * dotProduct * unionArrays[1][i].getFConst();
size_t numCols = (*sequence)[1]->getAsTyped()->getType().getObjectSize(); resultArray[i].setFConst(result);
resultArray = new TConstantUnion[numRows * numCols];
angle::Matrix<float> result =
GetMatrix(unionArrays[0], static_cast<int>(numRows), 1)
.outerProduct(GetMatrix(unionArrays[1], 1, static_cast<int>(numCols)));
SetUnionArrayFromMatrix(result, resultArray);
break;
} }
break;
}
default: case EOpMulMatrixComponentWise:
UNREACHABLE(); {
// TODO: Add constant folding support for other built-in operations that take 2 ASSERT(basicType == EbtFloat && (*sequence)[0]->getAsTyped()->isMatrix() &&
// parameters and not handled above. (*sequence)[1]->getAsTyped()->isMatrix());
return nullptr; // Perform component-wise matrix multiplication.
resultArray = new TConstantUnion[maxObjectSize];
int size = (*sequence)[0]->getAsTyped()->getNominalSize();
angle::Matrix<float> result =
GetMatrix(unionArrays[0], size).compMult(GetMatrix(unionArrays[1], size));
SetUnionArrayFromMatrix(result, resultArray);
break;
} }
}
else if (paramsCount == 3) case EOpOuterProduct:
{
//
// Ternary built-in
//
switch (op)
{ {
case EOpClamp: ASSERT(basicType == EbtFloat);
size_t numRows = (*sequence)[0]->getAsTyped()->getType().getObjectSize();
size_t numCols = (*sequence)[1]->getAsTyped()->getType().getObjectSize();
resultArray = new TConstantUnion[numRows * numCols];
angle::Matrix<float> result =
GetMatrix(unionArrays[0], static_cast<int>(numRows), 1)
.outerProduct(GetMatrix(unionArrays[1], 1, static_cast<int>(numCols)));
SetUnionArrayFromMatrix(result, resultArray);
break;
}
case EOpClamp:
{
resultArray = new TConstantUnion[maxObjectSize];
for (size_t i = 0; i < maxObjectSize; i++)
{ {
resultArray = new TConstantUnion[maxObjectSize]; switch (basicType)
for (size_t i = 0; i < maxObjectSize; i++)
{ {
switch (basicType) case EbtFloat:
{ {
case EbtFloat: float x = unionArrays[0][i].getFConst();
{ float min = unionArrays[1][i].getFConst();
float x = unionArrays[0][i].getFConst(); float max = unionArrays[2][i].getFConst();
float min = unionArrays[1][i].getFConst(); // Results are undefined if min > max.
float max = unionArrays[2][i].getFConst(); if (min > max)
// Results are undefined if min > max. UndefinedConstantFoldingError(loc, op, basicType, diagnostics,
if (min > max) &resultArray[i]);
UndefinedConstantFoldingError(loc, op, basicType, diagnostics, else
&resultArray[i]); resultArray[i].setFConst(gl::clamp(x, min, max));
else break;
resultArray[i].setFConst(gl::clamp(x, min, max));
break;
}
case EbtInt:
{
int x = unionArrays[0][i].getIConst();
int min = unionArrays[1][i].getIConst();
int max = unionArrays[2][i].getIConst();
// Results are undefined if min > max.
if (min > max)
UndefinedConstantFoldingError(loc, op, basicType, diagnostics,
&resultArray[i]);
else
resultArray[i].setIConst(gl::clamp(x, min, max));
break;
}
case EbtUInt:
{
unsigned int x = unionArrays[0][i].getUConst();
unsigned int min = unionArrays[1][i].getUConst();
unsigned int max = unionArrays[2][i].getUConst();
// Results are undefined if min > max.
if (min > max)
UndefinedConstantFoldingError(loc, op, basicType, diagnostics,
&resultArray[i]);
else
resultArray[i].setUConst(gl::clamp(x, min, max));
break;
}
default:
UNREACHABLE();
break;
} }
}
break;
}
case EOpMix: case EbtInt:
{
ASSERT(basicType == EbtFloat);
resultArray = 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. int x = unionArrays[0][i].getIConst();
float a = unionArrays[2][i].getFConst(); int min = unionArrays[1][i].getIConst();
resultArray[i].setFConst(x * (1.0f - a) + y * a); int max = unionArrays[2][i].getIConst();
// Results are undefined if min > max.
if (min > max)
UndefinedConstantFoldingError(loc, op, basicType, diagnostics,
&resultArray[i]);
else
resultArray[i].setIConst(gl::clamp(x, min, max));
break;
} }
else // 3rd parameter is EbtBool case EbtUInt:
{ {
ASSERT(type == EbtBool); unsigned int x = unionArrays[0][i].getUConst();
// Selects which vector each returned component comes from. unsigned int min = unionArrays[1][i].getUConst();
// For a component of a that is false, the corresponding component of x is unsigned int max = unionArrays[2][i].getUConst();
// returned. // Results are undefined if min > max.
// For a component of a that is true, the corresponding component of y is if (min > max)
// returned. UndefinedConstantFoldingError(loc, op, basicType, diagnostics,
bool a = unionArrays[2][i].getBConst(); &resultArray[i]);
resultArray[i].setFConst(a ? y : x); else
resultArray[i].setUConst(gl::clamp(x, min, max));
break;
} }
default:
UNREACHABLE();
break;
} }
break;
} }
break;
}
case EOpSmoothStep: case EOpMix:
{
ASSERT(basicType == EbtFloat);
resultArray = new TConstantUnion[maxObjectSize];
for (size_t i = 0; i < maxObjectSize; i++)
{ {
ASSERT(basicType == EbtFloat); float x = unionArrays[0][i].getFConst();
resultArray = new TConstantUnion[maxObjectSize]; float y = unionArrays[1][i].getFConst();
for (size_t i = 0; i < maxObjectSize; i++) TBasicType type = (*sequence)[2]->getAsTyped()->getType().getBasicType();
if (type == EbtFloat)
{ {
float edge0 = unionArrays[0][i].getFConst(); // Returns the linear blend of x and y, i.e., x * (1 - a) + y * a.
float edge1 = unionArrays[1][i].getFConst(); float a = unionArrays[2][i].getFConst();
float x = unionArrays[2][i].getFConst(); resultArray[i].setFConst(x * (1.0f - a) + y * a);
// Results are undefined if edge0 >= edge1. }
if (edge0 >= edge1) else // 3rd parameter is EbtBool
{ {
UndefinedConstantFoldingError(loc, op, basicType, diagnostics, ASSERT(type == EbtBool);
&resultArray[i]); // Selects which vector each returned component comes from.
} // For a component of a that is false, the corresponding component of x is
else // returned.
{ // For a component of a that is true, the corresponding component of y is
// Returns 0.0 if x <= edge0 and 1.0 if x >= edge1 and performs smooth // returned.
// Hermite interpolation between 0 and 1 when edge0 < x < edge1. bool a = unionArrays[2][i].getBConst();
float t = gl::clamp((x - edge0) / (edge1 - edge0), 0.0f, 1.0f); resultArray[i].setFConst(a ? y : x);
resultArray[i].setFConst(t * t * (3.0f - 2.0f * t));
}
} }
break;
} }
break;
}
case EOpFaceForward: case EOpSmoothStep:
{
ASSERT(basicType == EbtFloat);
resultArray = new TConstantUnion[maxObjectSize];
for (size_t i = 0; i < maxObjectSize; i++)
{ {
ASSERT(basicType == EbtFloat); float edge0 = unionArrays[0][i].getFConst();
// genType faceforward(genType N, genType I, genType Nref) : float edge1 = unionArrays[1][i].getFConst();
// If dot(Nref, I) < 0 return N, otherwise return -N. float x = unionArrays[2][i].getFConst();
resultArray = new TConstantUnion[maxObjectSize]; // Results are undefined if edge0 >= edge1.
float dotProduct = VectorDotProduct(unionArrays[2], unionArrays[1], maxObjectSize); if (edge0 >= edge1)
for (size_t i = 0; i < maxObjectSize; i++)
{ {
if (dotProduct < 0) UndefinedConstantFoldingError(loc, op, basicType, diagnostics, &resultArray[i]);
resultArray[i].setFConst(unionArrays[0][i].getFConst()); }
else else
resultArray[i].setFConst(-unionArrays[0][i].getFConst()); {
// 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);
resultArray[i].setFConst(t * t * (3.0f - 2.0f * t));
} }
break;
} }
break;
}
case EOpRefract: case EOpFaceForward:
{
ASSERT(basicType == EbtFloat);
// genType faceforward(genType N, genType I, genType Nref) :
// If dot(Nref, I) < 0 return N, otherwise return -N.
resultArray = new TConstantUnion[maxObjectSize];
float dotProduct = VectorDotProduct(unionArrays[2], unionArrays[1], maxObjectSize);
for (size_t i = 0; i < maxObjectSize; i++)
{ {
ASSERT(basicType == EbtFloat); if (dotProduct < 0)
// genType refract(genType I, genType N, float eta) : resultArray[i].setFConst(unionArrays[0][i].getFConst());
// For the incident vector I and surface normal N, and the ratio of indices of else
// refraction eta, resultArray[i].setFConst(-unionArrays[0][i].getFConst());
// return the refraction vector. The result is computed by
// k = 1.0 - eta * eta * (1.0 - dot(N, I) * dot(N, I))
// if (k < 0.0)
// return genType(0.0)
// else
// return eta * I - (eta * dot(N, I) + sqrt(k)) * N
resultArray = new TConstantUnion[maxObjectSize];
float dotProduct = VectorDotProduct(unionArrays[1], unionArrays[0], maxObjectSize);
for (size_t i = 0; i < maxObjectSize; i++)
{
float eta = unionArrays[2][i].getFConst();
float k = 1.0f - eta * eta * (1.0f - dotProduct * dotProduct);
if (k < 0.0f)
resultArray[i].setFConst(0.0f);
else
resultArray[i].setFConst(eta * unionArrays[0][i].getFConst() -
(eta * dotProduct + sqrtf(k)) *
unionArrays[1][i].getFConst());
}
break;
} }
break;
}
default: case EOpRefract:
UNREACHABLE(); {
// TODO: Add constant folding support for other built-in operations that take 3 ASSERT(basicType == EbtFloat);
// parameters and not handled above. // genType refract(genType I, genType N, float eta) :
return nullptr; // For the incident vector I and surface normal N, and the ratio of indices of
// refraction eta,
// return the refraction vector. The result is computed by
// k = 1.0 - eta * eta * (1.0 - dot(N, I) * dot(N, I))
// if (k < 0.0)
// return genType(0.0)
// else
// return eta * I - (eta * dot(N, I) + sqrt(k)) * N
resultArray = new TConstantUnion[maxObjectSize];
float dotProduct = VectorDotProduct(unionArrays[1], unionArrays[0], maxObjectSize);
for (size_t i = 0; i < maxObjectSize; i++)
{
float eta = unionArrays[2][i].getFConst();
float k = 1.0f - eta * eta * (1.0f - dotProduct * dotProduct);
if (k < 0.0f)
resultArray[i].setFConst(0.0f);
else
resultArray[i].setFConst(eta * unionArrays[0][i].getFConst() -
(eta * dotProduct + sqrtf(k)) *
unionArrays[1][i].getFConst());
}
break;
} }
default:
UNREACHABLE();
return nullptr;
} }
return resultArray; return resultArray;
} }
......
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