mirror of
https://github.com/ZDoom/ZDRay.git
synced 2024-11-29 23:22:14 +00:00
1399 lines
60 KiB
C++
1399 lines
60 KiB
C++
//
|
|
// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
|
|
// Copyright (C) 2012-2013 LunarG, Inc.
|
|
// Copyright (C) 2017 ARM Limited.
|
|
// Copyright (C) 2018 Google, Inc.
|
|
//
|
|
// All rights reserved.
|
|
//
|
|
// Redistribution and use in source and binary forms, with or without
|
|
// modification, are permitted provided that the following conditions
|
|
// are met:
|
|
//
|
|
// Redistributions of source code must retain the above copyright
|
|
// notice, this list of conditions and the following disclaimer.
|
|
//
|
|
// Redistributions in binary form must reproduce the above
|
|
// copyright notice, this list of conditions and the following
|
|
// disclaimer in the documentation and/or other materials provided
|
|
// with the distribution.
|
|
//
|
|
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
|
|
// contributors may be used to endorse or promote products derived
|
|
// from this software without specific prior written permission.
|
|
//
|
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
|
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
// POSSIBILITY OF SUCH DAMAGE.
|
|
//
|
|
|
|
#include "localintermediate.h"
|
|
#include <cmath>
|
|
#include <cfloat>
|
|
#include <cstdlib>
|
|
#include <climits>
|
|
|
|
namespace {
|
|
|
|
using namespace glslang;
|
|
|
|
typedef union {
|
|
double d;
|
|
int i[2];
|
|
} DoubleIntUnion;
|
|
|
|
// Some helper functions
|
|
|
|
bool isNan(double x)
|
|
{
|
|
DoubleIntUnion u;
|
|
// tough to find a platform independent library function, do it directly
|
|
u.d = x;
|
|
int bitPatternL = u.i[0];
|
|
int bitPatternH = u.i[1];
|
|
return (bitPatternH & 0x7ff80000) == 0x7ff80000 &&
|
|
((bitPatternH & 0xFFFFF) != 0 || bitPatternL != 0);
|
|
}
|
|
|
|
bool isInf(double x)
|
|
{
|
|
DoubleIntUnion u;
|
|
// tough to find a platform independent library function, do it directly
|
|
u.d = x;
|
|
int bitPatternL = u.i[0];
|
|
int bitPatternH = u.i[1];
|
|
return (bitPatternH & 0x7ff00000) == 0x7ff00000 &&
|
|
(bitPatternH & 0xFFFFF) == 0 && bitPatternL == 0;
|
|
}
|
|
|
|
const double pi = 3.1415926535897932384626433832795;
|
|
|
|
} // end anonymous namespace
|
|
|
|
|
|
namespace glslang {
|
|
|
|
//
|
|
// The fold functions see if an operation on a constant can be done in place,
|
|
// without generating run-time code.
|
|
//
|
|
// Returns the node to keep using, which may or may not be the node passed in.
|
|
//
|
|
// Note: As of version 1.2, all constant operations must be folded. It is
|
|
// not opportunistic, but rather a semantic requirement.
|
|
//
|
|
|
|
//
|
|
// Do folding between a pair of nodes.
|
|
// 'this' is the left-hand operand and 'rightConstantNode' is the right-hand operand.
|
|
//
|
|
// Returns a new node representing the result.
|
|
//
|
|
TIntermTyped* TIntermConstantUnion::fold(TOperator op, const TIntermTyped* rightConstantNode) const
|
|
{
|
|
// For most cases, the return type matches the argument type, so set that
|
|
// up and just code to exceptions below.
|
|
TType returnType;
|
|
returnType.shallowCopy(getType());
|
|
|
|
//
|
|
// A pair of nodes is to be folded together
|
|
//
|
|
|
|
const TIntermConstantUnion *rightNode = rightConstantNode->getAsConstantUnion();
|
|
TConstUnionArray leftUnionArray = getConstArray();
|
|
TConstUnionArray rightUnionArray = rightNode->getConstArray();
|
|
|
|
// Figure out the size of the result
|
|
int newComps;
|
|
int constComps;
|
|
switch(op) {
|
|
case EOpMatrixTimesMatrix:
|
|
newComps = rightNode->getMatrixCols() * getMatrixRows();
|
|
break;
|
|
case EOpMatrixTimesVector:
|
|
newComps = getMatrixRows();
|
|
break;
|
|
case EOpVectorTimesMatrix:
|
|
newComps = rightNode->getMatrixCols();
|
|
break;
|
|
default:
|
|
newComps = getType().computeNumComponents();
|
|
constComps = rightConstantNode->getType().computeNumComponents();
|
|
if (constComps == 1 && newComps > 1) {
|
|
// for a case like vec4 f = vec4(2,3,4,5) + 1.2;
|
|
TConstUnionArray smearedArray(newComps, rightNode->getConstArray()[0]);
|
|
rightUnionArray = smearedArray;
|
|
} else if (constComps > 1 && newComps == 1) {
|
|
// for a case like vec4 f = 1.2 + vec4(2,3,4,5);
|
|
newComps = constComps;
|
|
rightUnionArray = rightNode->getConstArray();
|
|
TConstUnionArray smearedArray(newComps, getConstArray()[0]);
|
|
leftUnionArray = smearedArray;
|
|
returnType.shallowCopy(rightNode->getType());
|
|
}
|
|
break;
|
|
}
|
|
|
|
TConstUnionArray newConstArray(newComps);
|
|
TType constBool(EbtBool, EvqConst);
|
|
|
|
switch(op) {
|
|
case EOpAdd:
|
|
for (int i = 0; i < newComps; i++)
|
|
newConstArray[i] = leftUnionArray[i] + rightUnionArray[i];
|
|
break;
|
|
case EOpSub:
|
|
for (int i = 0; i < newComps; i++)
|
|
newConstArray[i] = leftUnionArray[i] - rightUnionArray[i];
|
|
break;
|
|
|
|
case EOpMul:
|
|
case EOpVectorTimesScalar:
|
|
case EOpMatrixTimesScalar:
|
|
for (int i = 0; i < newComps; i++)
|
|
newConstArray[i] = leftUnionArray[i] * rightUnionArray[i];
|
|
break;
|
|
case EOpMatrixTimesMatrix:
|
|
for (int row = 0; row < getMatrixRows(); row++) {
|
|
for (int column = 0; column < rightNode->getMatrixCols(); column++) {
|
|
double sum = 0.0f;
|
|
for (int i = 0; i < rightNode->getMatrixRows(); i++)
|
|
sum += leftUnionArray[i * getMatrixRows() + row].getDConst() * rightUnionArray[column * rightNode->getMatrixRows() + i].getDConst();
|
|
newConstArray[column * getMatrixRows() + row].setDConst(sum);
|
|
}
|
|
}
|
|
returnType.shallowCopy(TType(getType().getBasicType(), EvqConst, 0, rightNode->getMatrixCols(), getMatrixRows()));
|
|
break;
|
|
case EOpDiv:
|
|
for (int i = 0; i < newComps; i++) {
|
|
switch (getType().getBasicType()) {
|
|
case EbtDouble:
|
|
case EbtFloat:
|
|
case EbtFloat16:
|
|
if (rightUnionArray[i].getDConst() != 0.0)
|
|
newConstArray[i].setDConst(leftUnionArray[i].getDConst() / rightUnionArray[i].getDConst());
|
|
else if (leftUnionArray[i].getDConst() > 0.0)
|
|
newConstArray[i].setDConst((double)INFINITY);
|
|
else if (leftUnionArray[i].getDConst() < 0.0)
|
|
newConstArray[i].setDConst(-(double)INFINITY);
|
|
else
|
|
newConstArray[i].setDConst((double)NAN);
|
|
break;
|
|
case EbtInt8:
|
|
if (rightUnionArray[i] == (signed char)0)
|
|
newConstArray[i].setI8Const((signed char)0x7F);
|
|
else if (rightUnionArray[i].getI8Const() == (signed char)-1 && leftUnionArray[i].getI8Const() == (signed char)-0x80)
|
|
newConstArray[i].setI8Const((signed char)-0x80);
|
|
else
|
|
newConstArray[i].setI8Const(leftUnionArray[i].getI8Const() / rightUnionArray[i].getI8Const());
|
|
break;
|
|
|
|
case EbtUint8:
|
|
if (rightUnionArray[i] == (unsigned char)0u)
|
|
newConstArray[i].setU8Const((unsigned char)0xFFu);
|
|
else
|
|
newConstArray[i].setU8Const(leftUnionArray[i].getU8Const() / rightUnionArray[i].getU8Const());
|
|
break;
|
|
|
|
case EbtInt16:
|
|
if (rightUnionArray[i] == (signed short)0)
|
|
newConstArray[i].setI16Const((signed short)0x7FFF);
|
|
else if (rightUnionArray[i].getI16Const() == (signed short)-1 && leftUnionArray[i].getI16Const() == (signed short)-0x8000)
|
|
newConstArray[i].setI16Const((signed short)-0x8000);
|
|
else
|
|
newConstArray[i].setI16Const(leftUnionArray[i].getI16Const() / rightUnionArray[i].getI16Const());
|
|
break;
|
|
|
|
case EbtUint16:
|
|
if (rightUnionArray[i] == (unsigned short)0u)
|
|
newConstArray[i].setU16Const((unsigned short)0xFFFFu);
|
|
else
|
|
newConstArray[i].setU16Const(leftUnionArray[i].getU16Const() / rightUnionArray[i].getU16Const());
|
|
break;
|
|
|
|
case EbtInt:
|
|
if (rightUnionArray[i] == 0)
|
|
newConstArray[i].setIConst(0x7FFFFFFF);
|
|
else if (rightUnionArray[i].getIConst() == -1 && leftUnionArray[i].getIConst() == (int)-0x80000000ll)
|
|
newConstArray[i].setIConst((int)-0x80000000ll);
|
|
else
|
|
newConstArray[i].setIConst(leftUnionArray[i].getIConst() / rightUnionArray[i].getIConst());
|
|
break;
|
|
|
|
case EbtUint:
|
|
if (rightUnionArray[i] == 0u)
|
|
newConstArray[i].setUConst(0xFFFFFFFFu);
|
|
else
|
|
newConstArray[i].setUConst(leftUnionArray[i].getUConst() / rightUnionArray[i].getUConst());
|
|
break;
|
|
|
|
case EbtInt64:
|
|
if (rightUnionArray[i] == 0ll)
|
|
newConstArray[i].setI64Const(0x7FFFFFFFFFFFFFFFll);
|
|
else if (rightUnionArray[i].getI64Const() == -1 && leftUnionArray[i].getI64Const() == -(long long)0x8000000000000000ll)
|
|
newConstArray[i].setI64Const(-(long long)0x8000000000000000ll);
|
|
else
|
|
newConstArray[i].setI64Const(leftUnionArray[i].getI64Const() / rightUnionArray[i].getI64Const());
|
|
break;
|
|
|
|
case EbtUint64:
|
|
if (rightUnionArray[i] == 0ull)
|
|
newConstArray[i].setU64Const(0xFFFFFFFFFFFFFFFFull);
|
|
else
|
|
newConstArray[i].setU64Const(leftUnionArray[i].getU64Const() / rightUnionArray[i].getU64Const());
|
|
break;
|
|
default:
|
|
return 0;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case EOpMatrixTimesVector:
|
|
for (int i = 0; i < getMatrixRows(); i++) {
|
|
double sum = 0.0f;
|
|
for (int j = 0; j < rightNode->getVectorSize(); j++) {
|
|
sum += leftUnionArray[j*getMatrixRows() + i].getDConst() * rightUnionArray[j].getDConst();
|
|
}
|
|
newConstArray[i].setDConst(sum);
|
|
}
|
|
|
|
returnType.shallowCopy(TType(getBasicType(), EvqConst, getMatrixRows()));
|
|
break;
|
|
|
|
case EOpVectorTimesMatrix:
|
|
for (int i = 0; i < rightNode->getMatrixCols(); i++) {
|
|
double sum = 0.0f;
|
|
for (int j = 0; j < getVectorSize(); j++)
|
|
sum += leftUnionArray[j].getDConst() * rightUnionArray[i*rightNode->getMatrixRows() + j].getDConst();
|
|
newConstArray[i].setDConst(sum);
|
|
}
|
|
|
|
returnType.shallowCopy(TType(getBasicType(), EvqConst, rightNode->getMatrixCols()));
|
|
break;
|
|
|
|
case EOpMod:
|
|
for (int i = 0; i < newComps; i++) {
|
|
if (rightUnionArray[i] == 0)
|
|
newConstArray[i] = leftUnionArray[i];
|
|
else {
|
|
switch (getType().getBasicType()) {
|
|
case EbtInt:
|
|
if (rightUnionArray[i].getIConst() == -1 && leftUnionArray[i].getIConst() == INT_MIN) {
|
|
newConstArray[i].setIConst(0);
|
|
break;
|
|
} else goto modulo_default;
|
|
|
|
case EbtInt64:
|
|
if (rightUnionArray[i].getI64Const() == -1 && leftUnionArray[i].getI64Const() == LLONG_MIN) {
|
|
newConstArray[i].setI64Const(0);
|
|
break;
|
|
} else goto modulo_default;
|
|
#ifdef AMD_EXTENSIONS
|
|
case EbtInt16:
|
|
if (rightUnionArray[i].getIConst() == -1 && leftUnionArray[i].getIConst() == SHRT_MIN) {
|
|
newConstArray[i].setIConst(0);
|
|
break;
|
|
} else goto modulo_default;
|
|
#endif
|
|
default:
|
|
modulo_default:
|
|
newConstArray[i] = leftUnionArray[i] % rightUnionArray[i];
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case EOpRightShift:
|
|
for (int i = 0; i < newComps; i++)
|
|
newConstArray[i] = leftUnionArray[i] >> rightUnionArray[i];
|
|
break;
|
|
|
|
case EOpLeftShift:
|
|
for (int i = 0; i < newComps; i++)
|
|
newConstArray[i] = leftUnionArray[i] << rightUnionArray[i];
|
|
break;
|
|
|
|
case EOpAnd:
|
|
for (int i = 0; i < newComps; i++)
|
|
newConstArray[i] = leftUnionArray[i] & rightUnionArray[i];
|
|
break;
|
|
case EOpInclusiveOr:
|
|
for (int i = 0; i < newComps; i++)
|
|
newConstArray[i] = leftUnionArray[i] | rightUnionArray[i];
|
|
break;
|
|
case EOpExclusiveOr:
|
|
for (int i = 0; i < newComps; i++)
|
|
newConstArray[i] = leftUnionArray[i] ^ rightUnionArray[i];
|
|
break;
|
|
|
|
case EOpLogicalAnd: // this code is written for possible future use, will not get executed currently
|
|
for (int i = 0; i < newComps; i++)
|
|
newConstArray[i] = leftUnionArray[i] && rightUnionArray[i];
|
|
break;
|
|
|
|
case EOpLogicalOr: // this code is written for possible future use, will not get executed currently
|
|
for (int i = 0; i < newComps; i++)
|
|
newConstArray[i] = leftUnionArray[i] || rightUnionArray[i];
|
|
break;
|
|
|
|
case EOpLogicalXor:
|
|
for (int i = 0; i < newComps; i++) {
|
|
switch (getType().getBasicType()) {
|
|
case EbtBool: newConstArray[i].setBConst((leftUnionArray[i] == rightUnionArray[i]) ? false : true); break;
|
|
default: assert(false && "Default missing");
|
|
}
|
|
}
|
|
break;
|
|
|
|
case EOpLessThan:
|
|
newConstArray[0].setBConst(leftUnionArray[0] < rightUnionArray[0]);
|
|
returnType.shallowCopy(constBool);
|
|
break;
|
|
case EOpGreaterThan:
|
|
newConstArray[0].setBConst(leftUnionArray[0] > rightUnionArray[0]);
|
|
returnType.shallowCopy(constBool);
|
|
break;
|
|
case EOpLessThanEqual:
|
|
newConstArray[0].setBConst(! (leftUnionArray[0] > rightUnionArray[0]));
|
|
returnType.shallowCopy(constBool);
|
|
break;
|
|
case EOpGreaterThanEqual:
|
|
newConstArray[0].setBConst(! (leftUnionArray[0] < rightUnionArray[0]));
|
|
returnType.shallowCopy(constBool);
|
|
break;
|
|
case EOpEqual:
|
|
newConstArray[0].setBConst(rightNode->getConstArray() == leftUnionArray);
|
|
returnType.shallowCopy(constBool);
|
|
break;
|
|
case EOpNotEqual:
|
|
newConstArray[0].setBConst(rightNode->getConstArray() != leftUnionArray);
|
|
returnType.shallowCopy(constBool);
|
|
break;
|
|
|
|
default:
|
|
return 0;
|
|
}
|
|
|
|
TIntermConstantUnion *newNode = new TIntermConstantUnion(newConstArray, returnType);
|
|
newNode->setLoc(getLoc());
|
|
|
|
return newNode;
|
|
}
|
|
|
|
//
|
|
// Do single unary node folding
|
|
//
|
|
// Returns a new node representing the result.
|
|
//
|
|
TIntermTyped* TIntermConstantUnion::fold(TOperator op, const TType& returnType) const
|
|
{
|
|
// First, size the result, which is mostly the same as the argument's size,
|
|
// but not always, and classify what is componentwise.
|
|
// Also, eliminate cases that can't be compile-time constant.
|
|
int resultSize;
|
|
bool componentWise = true;
|
|
|
|
int objectSize = getType().computeNumComponents();
|
|
switch (op) {
|
|
case EOpDeterminant:
|
|
case EOpAny:
|
|
case EOpAll:
|
|
case EOpLength:
|
|
componentWise = false;
|
|
resultSize = 1;
|
|
break;
|
|
|
|
case EOpEmitStreamVertex:
|
|
case EOpEndStreamPrimitive:
|
|
// These don't actually fold
|
|
return 0;
|
|
|
|
case EOpPackSnorm2x16:
|
|
case EOpPackUnorm2x16:
|
|
case EOpPackHalf2x16:
|
|
componentWise = false;
|
|
resultSize = 1;
|
|
break;
|
|
|
|
case EOpUnpackSnorm2x16:
|
|
case EOpUnpackUnorm2x16:
|
|
case EOpUnpackHalf2x16:
|
|
componentWise = false;
|
|
resultSize = 2;
|
|
break;
|
|
|
|
case EOpPack16:
|
|
case EOpPack32:
|
|
case EOpPack64:
|
|
case EOpUnpack32:
|
|
case EOpUnpack16:
|
|
case EOpUnpack8:
|
|
case EOpNormalize:
|
|
componentWise = false;
|
|
resultSize = objectSize;
|
|
break;
|
|
|
|
default:
|
|
resultSize = objectSize;
|
|
break;
|
|
}
|
|
|
|
// Set up for processing
|
|
TConstUnionArray newConstArray(resultSize);
|
|
const TConstUnionArray& unionArray = getConstArray();
|
|
|
|
// Process non-component-wise operations
|
|
switch (op) {
|
|
case EOpLength:
|
|
case EOpNormalize:
|
|
{
|
|
double sum = 0;
|
|
for (int i = 0; i < objectSize; i++)
|
|
sum += unionArray[i].getDConst() * unionArray[i].getDConst();
|
|
double length = sqrt(sum);
|
|
if (op == EOpLength)
|
|
newConstArray[0].setDConst(length);
|
|
else {
|
|
for (int i = 0; i < objectSize; i++)
|
|
newConstArray[i].setDConst(unionArray[i].getDConst() / length);
|
|
}
|
|
break;
|
|
}
|
|
|
|
case EOpAny:
|
|
{
|
|
bool result = false;
|
|
for (int i = 0; i < objectSize; i++) {
|
|
if (unionArray[i].getBConst())
|
|
result = true;
|
|
}
|
|
newConstArray[0].setBConst(result);
|
|
break;
|
|
}
|
|
case EOpAll:
|
|
{
|
|
bool result = true;
|
|
for (int i = 0; i < objectSize; i++) {
|
|
if (! unionArray[i].getBConst())
|
|
result = false;
|
|
}
|
|
newConstArray[0].setBConst(result);
|
|
break;
|
|
}
|
|
|
|
// TODO: 3.0 Functionality: unary constant folding: the rest of the ops have to be fleshed out
|
|
|
|
case EOpPackSnorm2x16:
|
|
case EOpPackUnorm2x16:
|
|
case EOpPackHalf2x16:
|
|
case EOpPack16:
|
|
case EOpPack32:
|
|
case EOpPack64:
|
|
case EOpUnpack32:
|
|
case EOpUnpack16:
|
|
case EOpUnpack8:
|
|
|
|
case EOpUnpackSnorm2x16:
|
|
case EOpUnpackUnorm2x16:
|
|
case EOpUnpackHalf2x16:
|
|
|
|
case EOpDeterminant:
|
|
case EOpMatrixInverse:
|
|
case EOpTranspose:
|
|
return 0;
|
|
|
|
default:
|
|
assert(componentWise);
|
|
break;
|
|
}
|
|
|
|
// Turn off the componentwise loop
|
|
if (! componentWise)
|
|
objectSize = 0;
|
|
|
|
// Process component-wise operations
|
|
for (int i = 0; i < objectSize; i++) {
|
|
switch (op) {
|
|
case EOpNegative:
|
|
switch (getType().getBasicType()) {
|
|
case EbtDouble:
|
|
case EbtFloat16:
|
|
case EbtFloat: newConstArray[i].setDConst(-unionArray[i].getDConst()); break;
|
|
case EbtInt8: newConstArray[i].setI8Const(-unionArray[i].getI8Const()); break;
|
|
case EbtUint8: newConstArray[i].setU8Const(static_cast<unsigned int>(-static_cast<signed int>(unionArray[i].getU8Const()))); break;
|
|
case EbtInt16: newConstArray[i].setI16Const(-unionArray[i].getI16Const()); break;
|
|
case EbtUint16:newConstArray[i].setU16Const(static_cast<unsigned int>(-static_cast<signed int>(unionArray[i].getU16Const()))); break;
|
|
case EbtInt: newConstArray[i].setIConst(-unionArray[i].getIConst()); break;
|
|
case EbtUint: newConstArray[i].setUConst(static_cast<unsigned int>(-static_cast<int>(unionArray[i].getUConst()))); break;
|
|
case EbtInt64: newConstArray[i].setI64Const(-unionArray[i].getI64Const()); break;
|
|
case EbtUint64: newConstArray[i].setU64Const(static_cast<unsigned long long>(-static_cast<long long>(unionArray[i].getU64Const()))); break;
|
|
default:
|
|
return 0;
|
|
}
|
|
break;
|
|
case EOpLogicalNot:
|
|
case EOpVectorLogicalNot:
|
|
switch (getType().getBasicType()) {
|
|
case EbtBool: newConstArray[i].setBConst(!unionArray[i].getBConst()); break;
|
|
default:
|
|
return 0;
|
|
}
|
|
break;
|
|
case EOpBitwiseNot:
|
|
newConstArray[i] = ~unionArray[i];
|
|
break;
|
|
case EOpRadians:
|
|
newConstArray[i].setDConst(unionArray[i].getDConst() * pi / 180.0);
|
|
break;
|
|
case EOpDegrees:
|
|
newConstArray[i].setDConst(unionArray[i].getDConst() * 180.0 / pi);
|
|
break;
|
|
case EOpSin:
|
|
newConstArray[i].setDConst(sin(unionArray[i].getDConst()));
|
|
break;
|
|
case EOpCos:
|
|
newConstArray[i].setDConst(cos(unionArray[i].getDConst()));
|
|
break;
|
|
case EOpTan:
|
|
newConstArray[i].setDConst(tan(unionArray[i].getDConst()));
|
|
break;
|
|
case EOpAsin:
|
|
newConstArray[i].setDConst(asin(unionArray[i].getDConst()));
|
|
break;
|
|
case EOpAcos:
|
|
newConstArray[i].setDConst(acos(unionArray[i].getDConst()));
|
|
break;
|
|
case EOpAtan:
|
|
newConstArray[i].setDConst(atan(unionArray[i].getDConst()));
|
|
break;
|
|
|
|
case EOpDPdx:
|
|
case EOpDPdy:
|
|
case EOpFwidth:
|
|
case EOpDPdxFine:
|
|
case EOpDPdyFine:
|
|
case EOpFwidthFine:
|
|
case EOpDPdxCoarse:
|
|
case EOpDPdyCoarse:
|
|
case EOpFwidthCoarse:
|
|
// The derivatives are all mandated to create a constant 0.
|
|
newConstArray[i].setDConst(0.0);
|
|
break;
|
|
|
|
case EOpExp:
|
|
newConstArray[i].setDConst(exp(unionArray[i].getDConst()));
|
|
break;
|
|
case EOpLog:
|
|
newConstArray[i].setDConst(log(unionArray[i].getDConst()));
|
|
break;
|
|
case EOpExp2:
|
|
{
|
|
const double inv_log2_e = 0.69314718055994530941723212145818;
|
|
newConstArray[i].setDConst(exp(unionArray[i].getDConst() * inv_log2_e));
|
|
break;
|
|
}
|
|
case EOpLog2:
|
|
{
|
|
const double log2_e = 1.4426950408889634073599246810019;
|
|
newConstArray[i].setDConst(log2_e * log(unionArray[i].getDConst()));
|
|
break;
|
|
}
|
|
case EOpSqrt:
|
|
newConstArray[i].setDConst(sqrt(unionArray[i].getDConst()));
|
|
break;
|
|
case EOpInverseSqrt:
|
|
newConstArray[i].setDConst(1.0 / sqrt(unionArray[i].getDConst()));
|
|
break;
|
|
|
|
case EOpAbs:
|
|
if (unionArray[i].getType() == EbtDouble)
|
|
newConstArray[i].setDConst(fabs(unionArray[i].getDConst()));
|
|
else if (unionArray[i].getType() == EbtInt)
|
|
newConstArray[i].setIConst(abs(unionArray[i].getIConst()));
|
|
else
|
|
newConstArray[i] = unionArray[i];
|
|
break;
|
|
case EOpSign:
|
|
#define SIGN(X) (X == 0 ? 0 : (X < 0 ? -1 : 1))
|
|
if (unionArray[i].getType() == EbtDouble)
|
|
newConstArray[i].setDConst(SIGN(unionArray[i].getDConst()));
|
|
else
|
|
newConstArray[i].setIConst(SIGN(unionArray[i].getIConst()));
|
|
break;
|
|
case EOpFloor:
|
|
newConstArray[i].setDConst(floor(unionArray[i].getDConst()));
|
|
break;
|
|
case EOpTrunc:
|
|
if (unionArray[i].getDConst() > 0)
|
|
newConstArray[i].setDConst(floor(unionArray[i].getDConst()));
|
|
else
|
|
newConstArray[i].setDConst(ceil(unionArray[i].getDConst()));
|
|
break;
|
|
case EOpRound:
|
|
newConstArray[i].setDConst(floor(0.5 + unionArray[i].getDConst()));
|
|
break;
|
|
case EOpRoundEven:
|
|
{
|
|
double flr = floor(unionArray[i].getDConst());
|
|
bool even = flr / 2.0 == floor(flr / 2.0);
|
|
double rounded = even ? ceil(unionArray[i].getDConst() - 0.5) : floor(unionArray[i].getDConst() + 0.5);
|
|
newConstArray[i].setDConst(rounded);
|
|
break;
|
|
}
|
|
case EOpCeil:
|
|
newConstArray[i].setDConst(ceil(unionArray[i].getDConst()));
|
|
break;
|
|
case EOpFract:
|
|
{
|
|
double x = unionArray[i].getDConst();
|
|
newConstArray[i].setDConst(x - floor(x));
|
|
break;
|
|
}
|
|
|
|
case EOpIsNan:
|
|
{
|
|
newConstArray[i].setBConst(isNan(unionArray[i].getDConst()));
|
|
break;
|
|
}
|
|
case EOpIsInf:
|
|
{
|
|
newConstArray[i].setBConst(isInf(unionArray[i].getDConst()));
|
|
break;
|
|
}
|
|
|
|
case EOpConvInt8ToBool:
|
|
newConstArray[i].setBConst(unionArray[i].getI8Const() != 0); break;
|
|
case EOpConvUint8ToBool:
|
|
newConstArray[i].setBConst(unionArray[i].getU8Const() != 0); break;
|
|
case EOpConvInt16ToBool:
|
|
newConstArray[i].setBConst(unionArray[i].getI16Const() != 0); break;
|
|
case EOpConvUint16ToBool:
|
|
newConstArray[i].setBConst(unionArray[i].getU16Const() != 0); break;
|
|
case EOpConvIntToBool:
|
|
newConstArray[i].setBConst(unionArray[i].getIConst() != 0); break;
|
|
case EOpConvUintToBool:
|
|
newConstArray[i].setBConst(unionArray[i].getUConst() != 0); break;
|
|
case EOpConvInt64ToBool:
|
|
newConstArray[i].setBConst(unionArray[i].getI64Const() != 0); break;
|
|
case EOpConvUint64ToBool:
|
|
newConstArray[i].setBConst(unionArray[i].getI64Const() != 0); break;
|
|
case EOpConvFloat16ToBool:
|
|
newConstArray[i].setBConst(unionArray[i].getDConst() != 0); break;
|
|
case EOpConvFloatToBool:
|
|
newConstArray[i].setBConst(unionArray[i].getDConst() != 0); break;
|
|
case EOpConvDoubleToBool:
|
|
newConstArray[i].setBConst(unionArray[i].getDConst() != 0); break;
|
|
|
|
case EOpConvBoolToInt8:
|
|
newConstArray[i].setI8Const(unionArray[i].getBConst()); break;
|
|
case EOpConvBoolToUint8:
|
|
newConstArray[i].setU8Const(unionArray[i].getBConst()); break;
|
|
case EOpConvBoolToInt16:
|
|
newConstArray[i].setI16Const(unionArray[i].getBConst()); break;
|
|
case EOpConvBoolToUint16:
|
|
newConstArray[i].setU16Const(unionArray[i].getBConst()); break;
|
|
case EOpConvBoolToInt:
|
|
newConstArray[i].setIConst(unionArray[i].getBConst()); break;
|
|
case EOpConvBoolToUint:
|
|
newConstArray[i].setUConst(unionArray[i].getBConst()); break;
|
|
case EOpConvBoolToInt64:
|
|
newConstArray[i].setI64Const(unionArray[i].getBConst()); break;
|
|
case EOpConvBoolToUint64:
|
|
newConstArray[i].setU64Const(unionArray[i].getBConst()); break;
|
|
case EOpConvBoolToFloat16:
|
|
newConstArray[i].setDConst(unionArray[i].getBConst()); break;
|
|
case EOpConvBoolToFloat:
|
|
newConstArray[i].setDConst(unionArray[i].getBConst()); break;
|
|
case EOpConvBoolToDouble:
|
|
newConstArray[i].setDConst(unionArray[i].getBConst()); break;
|
|
|
|
case EOpConvInt8ToInt16:
|
|
newConstArray[i].setI16Const(unionArray[i].getI8Const()); break;
|
|
case EOpConvInt8ToInt:
|
|
newConstArray[i].setIConst(unionArray[i].getI8Const()); break;
|
|
case EOpConvInt8ToInt64:
|
|
newConstArray[i].setI64Const(unionArray[i].getI8Const()); break;
|
|
case EOpConvInt8ToUint8:
|
|
newConstArray[i].setU8Const(unionArray[i].getI8Const()); break;
|
|
case EOpConvInt8ToUint16:
|
|
newConstArray[i].setU16Const(unionArray[i].getI8Const()); break;
|
|
case EOpConvInt8ToUint:
|
|
newConstArray[i].setUConst(unionArray[i].getI8Const()); break;
|
|
case EOpConvInt8ToUint64:
|
|
newConstArray[i].setU64Const(unionArray[i].getI8Const()); break;
|
|
case EOpConvUint8ToInt8:
|
|
newConstArray[i].setI8Const(unionArray[i].getU8Const()); break;
|
|
case EOpConvUint8ToInt16:
|
|
newConstArray[i].setI16Const(unionArray[i].getU8Const()); break;
|
|
case EOpConvUint8ToInt:
|
|
newConstArray[i].setIConst(unionArray[i].getU8Const()); break;
|
|
case EOpConvUint8ToInt64:
|
|
newConstArray[i].setI64Const(unionArray[i].getU8Const()); break;
|
|
case EOpConvUint8ToUint16:
|
|
newConstArray[i].setU16Const(unionArray[i].getU8Const()); break;
|
|
case EOpConvUint8ToUint:
|
|
newConstArray[i].setUConst(unionArray[i].getU8Const()); break;
|
|
case EOpConvUint8ToUint64:
|
|
newConstArray[i].setU64Const(unionArray[i].getU8Const()); break;
|
|
case EOpConvInt8ToFloat16:
|
|
newConstArray[i].setDConst(unionArray[i].getI8Const()); break;
|
|
case EOpConvInt8ToFloat:
|
|
newConstArray[i].setDConst(unionArray[i].getI8Const()); break;
|
|
case EOpConvInt8ToDouble:
|
|
newConstArray[i].setDConst(unionArray[i].getI8Const()); break;
|
|
case EOpConvUint8ToFloat16:
|
|
newConstArray[i].setDConst(unionArray[i].getU8Const()); break;
|
|
case EOpConvUint8ToFloat:
|
|
newConstArray[i].setDConst(unionArray[i].getU8Const()); break;
|
|
case EOpConvUint8ToDouble:
|
|
newConstArray[i].setDConst(unionArray[i].getU8Const()); break;
|
|
|
|
case EOpConvInt16ToInt8:
|
|
newConstArray[i].setI8Const(static_cast<signed char>(unionArray[i].getI16Const())); break;
|
|
case EOpConvInt16ToInt:
|
|
newConstArray[i].setIConst(unionArray[i].getI16Const()); break;
|
|
case EOpConvInt16ToInt64:
|
|
newConstArray[i].setI64Const(unionArray[i].getI16Const()); break;
|
|
case EOpConvInt16ToUint8:
|
|
newConstArray[i].setU8Const(static_cast<unsigned char>(unionArray[i].getI16Const())); break;
|
|
case EOpConvInt16ToUint16:
|
|
newConstArray[i].setU16Const(unionArray[i].getI16Const()); break;
|
|
case EOpConvInt16ToUint:
|
|
newConstArray[i].setUConst(unionArray[i].getI16Const()); break;
|
|
case EOpConvInt16ToUint64:
|
|
newConstArray[i].setU64Const(unionArray[i].getI16Const()); break;
|
|
case EOpConvUint16ToInt8:
|
|
newConstArray[i].setI8Const(static_cast<signed char>(unionArray[i].getU16Const())); break;
|
|
case EOpConvUint16ToInt16:
|
|
newConstArray[i].setI16Const(unionArray[i].getU16Const()); break;
|
|
case EOpConvUint16ToInt:
|
|
newConstArray[i].setIConst(unionArray[i].getU16Const()); break;
|
|
case EOpConvUint16ToInt64:
|
|
newConstArray[i].setI64Const(unionArray[i].getU16Const()); break;
|
|
case EOpConvUint16ToUint8:
|
|
newConstArray[i].setU8Const(static_cast<unsigned char>(unionArray[i].getU16Const())); break;
|
|
|
|
case EOpConvUint16ToUint:
|
|
newConstArray[i].setUConst(unionArray[i].getU16Const()); break;
|
|
case EOpConvUint16ToUint64:
|
|
newConstArray[i].setU64Const(unionArray[i].getU16Const()); break;
|
|
case EOpConvInt16ToFloat16:
|
|
newConstArray[i].setDConst(unionArray[i].getI16Const()); break;
|
|
case EOpConvInt16ToFloat:
|
|
newConstArray[i].setDConst(unionArray[i].getI16Const()); break;
|
|
case EOpConvInt16ToDouble:
|
|
newConstArray[i].setDConst(unionArray[i].getI16Const()); break;
|
|
case EOpConvUint16ToFloat16:
|
|
newConstArray[i].setDConst(unionArray[i].getU16Const()); break;
|
|
case EOpConvUint16ToFloat:
|
|
newConstArray[i].setDConst(unionArray[i].getU16Const()); break;
|
|
case EOpConvUint16ToDouble:
|
|
newConstArray[i].setDConst(unionArray[i].getU16Const()); break;
|
|
|
|
case EOpConvIntToInt8:
|
|
newConstArray[i].setI8Const((signed char)unionArray[i].getIConst()); break;
|
|
case EOpConvIntToInt16:
|
|
newConstArray[i].setI16Const((signed short)unionArray[i].getIConst()); break;
|
|
case EOpConvIntToInt64:
|
|
newConstArray[i].setI64Const(unionArray[i].getIConst()); break;
|
|
case EOpConvIntToUint8:
|
|
newConstArray[i].setU8Const((unsigned char)unionArray[i].getIConst()); break;
|
|
case EOpConvIntToUint16:
|
|
newConstArray[i].setU16Const((unsigned char)unionArray[i].getIConst()); break;
|
|
case EOpConvIntToUint:
|
|
newConstArray[i].setUConst(unionArray[i].getIConst()); break;
|
|
case EOpConvIntToUint64:
|
|
newConstArray[i].setU64Const(unionArray[i].getIConst()); break;
|
|
|
|
case EOpConvUintToInt8:
|
|
newConstArray[i].setI8Const((signed char)unionArray[i].getUConst()); break;
|
|
case EOpConvUintToInt16:
|
|
newConstArray[i].setI16Const((signed short)unionArray[i].getUConst()); break;
|
|
case EOpConvUintToInt:
|
|
newConstArray[i].setIConst(unionArray[i].getUConst()); break;
|
|
case EOpConvUintToInt64:
|
|
newConstArray[i].setI64Const(unionArray[i].getUConst()); break;
|
|
case EOpConvUintToUint8:
|
|
newConstArray[i].setU8Const((unsigned char)unionArray[i].getUConst()); break;
|
|
case EOpConvUintToUint16:
|
|
newConstArray[i].setU16Const((unsigned short)unionArray[i].getUConst()); break;
|
|
case EOpConvUintToUint64:
|
|
newConstArray[i].setU64Const(unionArray[i].getUConst()); break;
|
|
case EOpConvIntToFloat16:
|
|
newConstArray[i].setDConst(unionArray[i].getIConst()); break;
|
|
case EOpConvIntToFloat:
|
|
newConstArray[i].setDConst(unionArray[i].getIConst()); break;
|
|
case EOpConvIntToDouble:
|
|
newConstArray[i].setDConst(unionArray[i].getIConst()); break;
|
|
case EOpConvUintToFloat16:
|
|
newConstArray[i].setDConst(unionArray[i].getUConst()); break;
|
|
case EOpConvUintToFloat:
|
|
newConstArray[i].setDConst(unionArray[i].getUConst()); break;
|
|
case EOpConvUintToDouble:
|
|
newConstArray[i].setDConst(unionArray[i].getUConst()); break;
|
|
case EOpConvInt64ToInt8:
|
|
newConstArray[i].setI8Const(static_cast<signed char>(unionArray[i].getI64Const())); break;
|
|
case EOpConvInt64ToInt16:
|
|
newConstArray[i].setI16Const(static_cast<signed short>(unionArray[i].getI64Const())); break;
|
|
case EOpConvInt64ToInt:
|
|
newConstArray[i].setIConst(static_cast<int>(unionArray[i].getI64Const())); break;
|
|
case EOpConvInt64ToUint8:
|
|
newConstArray[i].setU8Const(static_cast<unsigned char>(unionArray[i].getI64Const())); break;
|
|
case EOpConvInt64ToUint16:
|
|
newConstArray[i].setU16Const(static_cast<unsigned short>(unionArray[i].getI64Const())); break;
|
|
case EOpConvInt64ToUint:
|
|
newConstArray[i].setUConst(static_cast<unsigned int>(unionArray[i].getI64Const())); break;
|
|
case EOpConvInt64ToUint64:
|
|
newConstArray[i].setU64Const(unionArray[i].getI64Const()); break;
|
|
case EOpConvUint64ToInt8:
|
|
newConstArray[i].setI8Const(static_cast<signed char>(unionArray[i].getU64Const())); break;
|
|
case EOpConvUint64ToInt16:
|
|
newConstArray[i].setI16Const(static_cast<signed short>(unionArray[i].getU64Const())); break;
|
|
case EOpConvUint64ToInt:
|
|
newConstArray[i].setIConst(static_cast<int>(unionArray[i].getU64Const())); break;
|
|
case EOpConvUint64ToInt64:
|
|
newConstArray[i].setI64Const(unionArray[i].getU64Const()); break;
|
|
case EOpConvUint64ToUint8:
|
|
newConstArray[i].setU8Const(static_cast<unsigned char>(unionArray[i].getU64Const())); break;
|
|
case EOpConvUint64ToUint16:
|
|
newConstArray[i].setU16Const(static_cast<unsigned short>(unionArray[i].getU64Const())); break;
|
|
case EOpConvUint64ToUint:
|
|
newConstArray[i].setUConst(static_cast<unsigned int>(unionArray[i].getU64Const())); break;
|
|
case EOpConvInt64ToFloat16:
|
|
newConstArray[i].setDConst(static_cast<double>(unionArray[i].getI64Const())); break;
|
|
case EOpConvInt64ToFloat:
|
|
newConstArray[i].setDConst(static_cast<double>(unionArray[i].getI64Const())); break;
|
|
case EOpConvInt64ToDouble:
|
|
newConstArray[i].setDConst(static_cast<double>(unionArray[i].getI64Const())); break;
|
|
case EOpConvUint64ToFloat16:
|
|
newConstArray[i].setDConst(static_cast<double>(unionArray[i].getU64Const())); break;
|
|
case EOpConvUint64ToFloat:
|
|
newConstArray[i].setDConst(static_cast<double>(unionArray[i].getU64Const())); break;
|
|
case EOpConvUint64ToDouble:
|
|
newConstArray[i].setDConst(static_cast<double>(unionArray[i].getU64Const())); break;
|
|
case EOpConvFloat16ToInt8:
|
|
newConstArray[i].setI8Const(static_cast<signed char>(unionArray[i].getDConst())); break;
|
|
case EOpConvFloat16ToInt16:
|
|
newConstArray[i].setI16Const(static_cast<signed short>(unionArray[i].getDConst())); break;
|
|
case EOpConvFloat16ToInt:
|
|
newConstArray[i].setIConst(static_cast<int>(unionArray[i].getDConst())); break;
|
|
case EOpConvFloat16ToInt64:
|
|
newConstArray[i].setI64Const(static_cast<long long>(unionArray[i].getDConst())); break;
|
|
case EOpConvFloat16ToUint8:
|
|
newConstArray[i].setU8Const(static_cast<unsigned char>(unionArray[i].getDConst())); break;
|
|
case EOpConvFloat16ToUint16:
|
|
newConstArray[i].setU16Const(static_cast<unsigned short>(unionArray[i].getDConst())); break;
|
|
case EOpConvFloat16ToUint:
|
|
newConstArray[i].setUConst(static_cast<unsigned int>(unionArray[i].getDConst())); break;
|
|
case EOpConvFloat16ToUint64:
|
|
newConstArray[i].setU64Const(static_cast<unsigned long long>(unionArray[i].getDConst())); break;
|
|
case EOpConvFloat16ToFloat:
|
|
newConstArray[i].setDConst(unionArray[i].getDConst()); break;
|
|
case EOpConvFloat16ToDouble:
|
|
newConstArray[i].setDConst(unionArray[i].getDConst()); break;
|
|
case EOpConvFloatToInt8:
|
|
newConstArray[i].setI8Const(static_cast<signed char>(unionArray[i].getDConst())); break;
|
|
case EOpConvFloatToInt16:
|
|
newConstArray[i].setI16Const(static_cast<signed short>(unionArray[i].getDConst())); break;
|
|
case EOpConvFloatToInt:
|
|
newConstArray[i].setIConst(static_cast<int>(unionArray[i].getDConst())); break;
|
|
case EOpConvFloatToInt64:
|
|
newConstArray[i].setI64Const(static_cast<long long>(unionArray[i].getDConst())); break;
|
|
case EOpConvFloatToUint8:
|
|
newConstArray[i].setU8Const(static_cast<unsigned char>(unionArray[i].getDConst())); break;
|
|
case EOpConvFloatToUint16:
|
|
newConstArray[i].setU16Const(static_cast<unsigned short>(unionArray[i].getDConst())); break;
|
|
case EOpConvFloatToUint:
|
|
newConstArray[i].setUConst(static_cast<unsigned int>(unionArray[i].getDConst())); break;
|
|
case EOpConvFloatToUint64:
|
|
newConstArray[i].setU64Const(static_cast<unsigned long long>(unionArray[i].getDConst())); break;
|
|
case EOpConvFloatToFloat16:
|
|
newConstArray[i].setDConst(unionArray[i].getDConst()); break;
|
|
case EOpConvFloatToDouble:
|
|
newConstArray[i].setDConst(unionArray[i].getDConst()); break;
|
|
case EOpConvDoubleToInt8:
|
|
newConstArray[i].setI8Const(static_cast<signed char>(unionArray[i].getDConst())); break;
|
|
case EOpConvDoubleToInt16:
|
|
newConstArray[i].setI16Const(static_cast<signed short>(unionArray[i].getDConst())); break;
|
|
case EOpConvDoubleToInt:
|
|
newConstArray[i].setIConst(static_cast<int>(unionArray[i].getDConst())); break;
|
|
case EOpConvDoubleToInt64:
|
|
newConstArray[i].setI64Const(static_cast<long long>(unionArray[i].getDConst())); break;
|
|
case EOpConvDoubleToUint8:
|
|
newConstArray[i].setU8Const(static_cast<unsigned char>(unionArray[i].getDConst())); break;
|
|
case EOpConvDoubleToUint16:
|
|
newConstArray[i].setU16Const(static_cast<unsigned short>(unionArray[i].getDConst())); break;
|
|
case EOpConvDoubleToUint:
|
|
newConstArray[i].setUConst(static_cast<unsigned int>(unionArray[i].getDConst())); break;
|
|
case EOpConvDoubleToUint64:
|
|
newConstArray[i].setU64Const(static_cast<unsigned long long>(unionArray[i].getDConst())); break;
|
|
case EOpConvDoubleToFloat16:
|
|
newConstArray[i].setDConst(unionArray[i].getDConst()); break;
|
|
case EOpConvDoubleToFloat:
|
|
newConstArray[i].setDConst(unionArray[i].getDConst()); break;
|
|
|
|
|
|
|
|
// TODO: 3.0 Functionality: unary constant folding: the rest of the ops have to be fleshed out
|
|
|
|
case EOpSinh:
|
|
case EOpCosh:
|
|
case EOpTanh:
|
|
case EOpAsinh:
|
|
case EOpAcosh:
|
|
case EOpAtanh:
|
|
|
|
case EOpFloatBitsToInt:
|
|
case EOpFloatBitsToUint:
|
|
case EOpIntBitsToFloat:
|
|
case EOpUintBitsToFloat:
|
|
case EOpDoubleBitsToInt64:
|
|
case EOpDoubleBitsToUint64:
|
|
case EOpInt64BitsToDouble:
|
|
case EOpUint64BitsToDouble:
|
|
case EOpFloat16BitsToInt16:
|
|
case EOpFloat16BitsToUint16:
|
|
case EOpInt16BitsToFloat16:
|
|
case EOpUint16BitsToFloat16:
|
|
default:
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
TIntermConstantUnion *newNode = new TIntermConstantUnion(newConstArray, returnType);
|
|
newNode->getWritableType().getQualifier().storage = EvqConst;
|
|
newNode->setLoc(getLoc());
|
|
|
|
return newNode;
|
|
}
|
|
|
|
//
|
|
// Do constant folding for an aggregate node that has all its children
|
|
// as constants and an operator that requires constant folding.
|
|
//
|
|
TIntermTyped* TIntermediate::fold(TIntermAggregate* aggrNode)
|
|
{
|
|
if (aggrNode == nullptr)
|
|
return aggrNode;
|
|
|
|
if (! areAllChildConst(aggrNode))
|
|
return aggrNode;
|
|
|
|
if (aggrNode->isConstructor())
|
|
return foldConstructor(aggrNode);
|
|
|
|
TIntermSequence& children = aggrNode->getSequence();
|
|
|
|
// First, see if this is an operation to constant fold, kick out if not,
|
|
// see what size the result is if so.
|
|
|
|
bool componentwise = false; // will also say componentwise if a scalar argument gets repeated to make per-component results
|
|
int objectSize;
|
|
switch (aggrNode->getOp()) {
|
|
case EOpAtan:
|
|
case EOpPow:
|
|
case EOpMin:
|
|
case EOpMax:
|
|
case EOpMix:
|
|
case EOpClamp:
|
|
case EOpLessThan:
|
|
case EOpGreaterThan:
|
|
case EOpLessThanEqual:
|
|
case EOpGreaterThanEqual:
|
|
case EOpVectorEqual:
|
|
case EOpVectorNotEqual:
|
|
componentwise = true;
|
|
objectSize = children[0]->getAsConstantUnion()->getType().computeNumComponents();
|
|
break;
|
|
case EOpCross:
|
|
case EOpReflect:
|
|
case EOpRefract:
|
|
case EOpFaceForward:
|
|
objectSize = children[0]->getAsConstantUnion()->getType().computeNumComponents();
|
|
break;
|
|
case EOpDistance:
|
|
case EOpDot:
|
|
objectSize = 1;
|
|
break;
|
|
case EOpOuterProduct:
|
|
objectSize = children[0]->getAsTyped()->getType().getVectorSize() *
|
|
children[1]->getAsTyped()->getType().getVectorSize();
|
|
break;
|
|
case EOpStep:
|
|
componentwise = true;
|
|
objectSize = std::max(children[0]->getAsTyped()->getType().getVectorSize(),
|
|
children[1]->getAsTyped()->getType().getVectorSize());
|
|
break;
|
|
case EOpSmoothStep:
|
|
componentwise = true;
|
|
objectSize = std::max(children[0]->getAsTyped()->getType().getVectorSize(),
|
|
children[2]->getAsTyped()->getType().getVectorSize());
|
|
break;
|
|
default:
|
|
return aggrNode;
|
|
}
|
|
TConstUnionArray newConstArray(objectSize);
|
|
|
|
TVector<TConstUnionArray> childConstUnions;
|
|
for (unsigned int arg = 0; arg < children.size(); ++arg)
|
|
childConstUnions.push_back(children[arg]->getAsConstantUnion()->getConstArray());
|
|
|
|
if (componentwise) {
|
|
for (int comp = 0; comp < objectSize; comp++) {
|
|
|
|
// some arguments are scalars instead of matching vectors; simulate a smear
|
|
int arg0comp = std::min(comp, children[0]->getAsTyped()->getType().getVectorSize() - 1);
|
|
int arg1comp = 0;
|
|
if (children.size() > 1)
|
|
arg1comp = std::min(comp, children[1]->getAsTyped()->getType().getVectorSize() - 1);
|
|
int arg2comp = 0;
|
|
if (children.size() > 2)
|
|
arg2comp = std::min(comp, children[2]->getAsTyped()->getType().getVectorSize() - 1);
|
|
|
|
switch (aggrNode->getOp()) {
|
|
case EOpAtan:
|
|
newConstArray[comp].setDConst(atan2(childConstUnions[0][arg0comp].getDConst(), childConstUnions[1][arg1comp].getDConst()));
|
|
break;
|
|
case EOpPow:
|
|
newConstArray[comp].setDConst(pow(childConstUnions[0][arg0comp].getDConst(), childConstUnions[1][arg1comp].getDConst()));
|
|
break;
|
|
case EOpMin:
|
|
switch(children[0]->getAsTyped()->getBasicType()) {
|
|
case EbtFloat16:
|
|
case EbtFloat:
|
|
case EbtDouble:
|
|
newConstArray[comp].setDConst(std::min(childConstUnions[0][arg0comp].getDConst(), childConstUnions[1][arg1comp].getDConst()));
|
|
break;
|
|
case EbtInt8:
|
|
newConstArray[comp].setI8Const(std::min(childConstUnions[0][arg0comp].getI8Const(), childConstUnions[1][arg1comp].getI8Const()));
|
|
break;
|
|
case EbtUint8:
|
|
newConstArray[comp].setU8Const(std::min(childConstUnions[0][arg0comp].getU8Const(), childConstUnions[1][arg1comp].getU8Const()));
|
|
break;
|
|
case EbtInt16:
|
|
newConstArray[comp].setI16Const(std::min(childConstUnions[0][arg0comp].getI16Const(), childConstUnions[1][arg1comp].getI16Const()));
|
|
break;
|
|
case EbtUint16:
|
|
newConstArray[comp].setU16Const(std::min(childConstUnions[0][arg0comp].getU16Const(), childConstUnions[1][arg1comp].getU16Const()));
|
|
break;
|
|
case EbtInt:
|
|
newConstArray[comp].setIConst(std::min(childConstUnions[0][arg0comp].getIConst(), childConstUnions[1][arg1comp].getIConst()));
|
|
break;
|
|
case EbtUint:
|
|
newConstArray[comp].setUConst(std::min(childConstUnions[0][arg0comp].getUConst(), childConstUnions[1][arg1comp].getUConst()));
|
|
break;
|
|
case EbtInt64:
|
|
newConstArray[comp].setI64Const(std::min(childConstUnions[0][arg0comp].getI64Const(), childConstUnions[1][arg1comp].getI64Const()));
|
|
break;
|
|
case EbtUint64:
|
|
newConstArray[comp].setU64Const(std::min(childConstUnions[0][arg0comp].getU64Const(), childConstUnions[1][arg1comp].getU64Const()));
|
|
break;
|
|
default: assert(false && "Default missing");
|
|
}
|
|
break;
|
|
case EOpMax:
|
|
switch(children[0]->getAsTyped()->getBasicType()) {
|
|
case EbtFloat16:
|
|
case EbtFloat:
|
|
case EbtDouble:
|
|
newConstArray[comp].setDConst(std::max(childConstUnions[0][arg0comp].getDConst(), childConstUnions[1][arg1comp].getDConst()));
|
|
break;
|
|
case EbtInt8:
|
|
newConstArray[comp].setI8Const(std::max(childConstUnions[0][arg0comp].getI8Const(), childConstUnions[1][arg1comp].getI8Const()));
|
|
break;
|
|
case EbtUint8:
|
|
newConstArray[comp].setU8Const(std::max(childConstUnions[0][arg0comp].getU8Const(), childConstUnions[1][arg1comp].getU8Const()));
|
|
break;
|
|
case EbtInt16:
|
|
newConstArray[comp].setI16Const(std::max(childConstUnions[0][arg0comp].getI16Const(), childConstUnions[1][arg1comp].getI16Const()));
|
|
break;
|
|
case EbtUint16:
|
|
newConstArray[comp].setU16Const(std::max(childConstUnions[0][arg0comp].getU16Const(), childConstUnions[1][arg1comp].getU16Const()));
|
|
break;
|
|
case EbtInt:
|
|
newConstArray[comp].setIConst(std::max(childConstUnions[0][arg0comp].getIConst(), childConstUnions[1][arg1comp].getIConst()));
|
|
break;
|
|
case EbtUint:
|
|
newConstArray[comp].setUConst(std::max(childConstUnions[0][arg0comp].getUConst(), childConstUnions[1][arg1comp].getUConst()));
|
|
break;
|
|
case EbtInt64:
|
|
newConstArray[comp].setI64Const(std::max(childConstUnions[0][arg0comp].getI64Const(), childConstUnions[1][arg1comp].getI64Const()));
|
|
break;
|
|
case EbtUint64:
|
|
newConstArray[comp].setU64Const(std::max(childConstUnions[0][arg0comp].getU64Const(), childConstUnions[1][arg1comp].getU64Const()));
|
|
break;
|
|
default: assert(false && "Default missing");
|
|
}
|
|
break;
|
|
case EOpClamp:
|
|
switch(children[0]->getAsTyped()->getBasicType()) {
|
|
case EbtFloat16:
|
|
case EbtFloat:
|
|
case EbtDouble:
|
|
newConstArray[comp].setDConst(std::min(std::max(childConstUnions[0][arg0comp].getDConst(), childConstUnions[1][arg1comp].getDConst()),
|
|
childConstUnions[2][arg2comp].getDConst()));
|
|
break;
|
|
case EbtInt8:
|
|
newConstArray[comp].setI8Const(std::min(std::max(childConstUnions[0][arg0comp].getI8Const(), childConstUnions[1][arg1comp].getI8Const()),
|
|
childConstUnions[2][arg2comp].getI8Const()));
|
|
break;
|
|
case EbtUint8:
|
|
newConstArray[comp].setU8Const(std::min(std::max(childConstUnions[0][arg0comp].getU8Const(), childConstUnions[1][arg1comp].getU8Const()),
|
|
childConstUnions[2][arg2comp].getU8Const()));
|
|
break;
|
|
case EbtInt16:
|
|
newConstArray[comp].setI16Const(std::min(std::max(childConstUnions[0][arg0comp].getI16Const(), childConstUnions[1][arg1comp].getI16Const()),
|
|
childConstUnions[2][arg2comp].getI16Const()));
|
|
break;
|
|
case EbtUint16:
|
|
newConstArray[comp].setU16Const(std::min(std::max(childConstUnions[0][arg0comp].getU16Const(), childConstUnions[1][arg1comp].getU16Const()),
|
|
childConstUnions[2][arg2comp].getU16Const()));
|
|
break;
|
|
case EbtInt:
|
|
newConstArray[comp].setIConst(std::min(std::max(childConstUnions[0][arg0comp].getIConst(), childConstUnions[1][arg1comp].getIConst()),
|
|
childConstUnions[2][arg2comp].getIConst()));
|
|
break;
|
|
case EbtUint:
|
|
newConstArray[comp].setUConst(std::min(std::max(childConstUnions[0][arg0comp].getUConst(), childConstUnions[1][arg1comp].getUConst()),
|
|
childConstUnions[2][arg2comp].getUConst()));
|
|
break;
|
|
case EbtInt64:
|
|
newConstArray[comp].setI64Const(std::min(std::max(childConstUnions[0][arg0comp].getI64Const(), childConstUnions[1][arg1comp].getI64Const()),
|
|
childConstUnions[2][arg2comp].getI64Const()));
|
|
break;
|
|
case EbtUint64:
|
|
newConstArray[comp].setU64Const(std::min(std::max(childConstUnions[0][arg0comp].getU64Const(), childConstUnions[1][arg1comp].getU64Const()),
|
|
childConstUnions[2][arg2comp].getU64Const()));
|
|
break;
|
|
default: assert(false && "Default missing");
|
|
}
|
|
break;
|
|
case EOpLessThan:
|
|
newConstArray[comp].setBConst(childConstUnions[0][arg0comp] < childConstUnions[1][arg1comp]);
|
|
break;
|
|
case EOpGreaterThan:
|
|
newConstArray[comp].setBConst(childConstUnions[0][arg0comp] > childConstUnions[1][arg1comp]);
|
|
break;
|
|
case EOpLessThanEqual:
|
|
newConstArray[comp].setBConst(! (childConstUnions[0][arg0comp] > childConstUnions[1][arg1comp]));
|
|
break;
|
|
case EOpGreaterThanEqual:
|
|
newConstArray[comp].setBConst(! (childConstUnions[0][arg0comp] < childConstUnions[1][arg1comp]));
|
|
break;
|
|
case EOpVectorEqual:
|
|
newConstArray[comp].setBConst(childConstUnions[0][arg0comp] == childConstUnions[1][arg1comp]);
|
|
break;
|
|
case EOpVectorNotEqual:
|
|
newConstArray[comp].setBConst(childConstUnions[0][arg0comp] != childConstUnions[1][arg1comp]);
|
|
break;
|
|
case EOpMix:
|
|
if (children[2]->getAsTyped()->getBasicType() == EbtBool)
|
|
newConstArray[comp].setDConst(childConstUnions[2][arg2comp].getBConst() ? childConstUnions[1][arg1comp].getDConst() :
|
|
childConstUnions[0][arg0comp].getDConst());
|
|
else
|
|
newConstArray[comp].setDConst(childConstUnions[0][arg0comp].getDConst() * (1.0 - childConstUnions[2][arg2comp].getDConst()) +
|
|
childConstUnions[1][arg1comp].getDConst() * childConstUnions[2][arg2comp].getDConst());
|
|
break;
|
|
case EOpStep:
|
|
newConstArray[comp].setDConst(childConstUnions[1][arg1comp].getDConst() < childConstUnions[0][arg0comp].getDConst() ? 0.0 : 1.0);
|
|
break;
|
|
case EOpSmoothStep:
|
|
{
|
|
double t = (childConstUnions[2][arg2comp].getDConst() - childConstUnions[0][arg0comp].getDConst()) /
|
|
(childConstUnions[1][arg1comp].getDConst() - childConstUnions[0][arg0comp].getDConst());
|
|
if (t < 0.0)
|
|
t = 0.0;
|
|
if (t > 1.0)
|
|
t = 1.0;
|
|
newConstArray[comp].setDConst(t * t * (3.0 - 2.0 * t));
|
|
break;
|
|
}
|
|
default:
|
|
return aggrNode;
|
|
}
|
|
}
|
|
} else {
|
|
// Non-componentwise...
|
|
|
|
int numComps = children[0]->getAsConstantUnion()->getType().computeNumComponents();
|
|
double dot;
|
|
|
|
switch (aggrNode->getOp()) {
|
|
case EOpDistance:
|
|
{
|
|
double sum = 0.0;
|
|
for (int comp = 0; comp < numComps; ++comp) {
|
|
double diff = childConstUnions[1][comp].getDConst() - childConstUnions[0][comp].getDConst();
|
|
sum += diff * diff;
|
|
}
|
|
newConstArray[0].setDConst(sqrt(sum));
|
|
break;
|
|
}
|
|
case EOpDot:
|
|
newConstArray[0].setDConst(childConstUnions[0].dot(childConstUnions[1]));
|
|
break;
|
|
case EOpCross:
|
|
newConstArray[0] = childConstUnions[0][1] * childConstUnions[1][2] - childConstUnions[0][2] * childConstUnions[1][1];
|
|
newConstArray[1] = childConstUnions[0][2] * childConstUnions[1][0] - childConstUnions[0][0] * childConstUnions[1][2];
|
|
newConstArray[2] = childConstUnions[0][0] * childConstUnions[1][1] - childConstUnions[0][1] * childConstUnions[1][0];
|
|
break;
|
|
case EOpFaceForward:
|
|
// If dot(Nref, I) < 0 return N, otherwise return -N: Arguments are (N, I, Nref).
|
|
dot = childConstUnions[1].dot(childConstUnions[2]);
|
|
for (int comp = 0; comp < numComps; ++comp) {
|
|
if (dot < 0.0)
|
|
newConstArray[comp] = childConstUnions[0][comp];
|
|
else
|
|
newConstArray[comp].setDConst(-childConstUnions[0][comp].getDConst());
|
|
}
|
|
break;
|
|
case EOpReflect:
|
|
// I - 2 * dot(N, I) * N: Arguments are (I, N).
|
|
dot = childConstUnions[0].dot(childConstUnions[1]);
|
|
dot *= 2.0;
|
|
for (int comp = 0; comp < numComps; ++comp)
|
|
newConstArray[comp].setDConst(childConstUnions[0][comp].getDConst() - dot * childConstUnions[1][comp].getDConst());
|
|
break;
|
|
case EOpRefract:
|
|
{
|
|
// Arguments are (I, N, eta).
|
|
// k = 1.0 - eta * eta * (1.0 - dot(N, I) * dot(N, I))
|
|
// if (k < 0.0)
|
|
// return dvec(0.0)
|
|
// else
|
|
// return eta * I - (eta * dot(N, I) + sqrt(k)) * N
|
|
dot = childConstUnions[0].dot(childConstUnions[1]);
|
|
double eta = childConstUnions[2][0].getDConst();
|
|
double k = 1.0 - eta * eta * (1.0 - dot * dot);
|
|
if (k < 0.0) {
|
|
for (int comp = 0; comp < numComps; ++comp)
|
|
newConstArray[comp].setDConst(0.0);
|
|
} else {
|
|
for (int comp = 0; comp < numComps; ++comp)
|
|
newConstArray[comp].setDConst(eta * childConstUnions[0][comp].getDConst() - (eta * dot + sqrt(k)) * childConstUnions[1][comp].getDConst());
|
|
}
|
|
break;
|
|
}
|
|
case EOpOuterProduct:
|
|
{
|
|
int numRows = numComps;
|
|
int numCols = children[1]->getAsConstantUnion()->getType().computeNumComponents();
|
|
for (int row = 0; row < numRows; ++row)
|
|
for (int col = 0; col < numCols; ++col)
|
|
newConstArray[col * numRows + row] = childConstUnions[0][row] * childConstUnions[1][col];
|
|
break;
|
|
}
|
|
default:
|
|
return aggrNode;
|
|
}
|
|
}
|
|
|
|
TIntermConstantUnion *newNode = new TIntermConstantUnion(newConstArray, aggrNode->getType());
|
|
newNode->getWritableType().getQualifier().storage = EvqConst;
|
|
newNode->setLoc(aggrNode->getLoc());
|
|
|
|
return newNode;
|
|
}
|
|
|
|
bool TIntermediate::areAllChildConst(TIntermAggregate* aggrNode)
|
|
{
|
|
bool allConstant = true;
|
|
|
|
// check if all the child nodes are constants so that they can be inserted into
|
|
// the parent node
|
|
if (aggrNode) {
|
|
TIntermSequence& childSequenceVector = aggrNode->getSequence();
|
|
for (TIntermSequence::iterator p = childSequenceVector.begin();
|
|
p != childSequenceVector.end(); p++) {
|
|
if (!(*p)->getAsTyped()->getAsConstantUnion())
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return allConstant;
|
|
}
|
|
|
|
TIntermTyped* TIntermediate::foldConstructor(TIntermAggregate* aggrNode)
|
|
{
|
|
bool error = false;
|
|
|
|
TConstUnionArray unionArray(aggrNode->getType().computeNumComponents());
|
|
if (aggrNode->getSequence().size() == 1)
|
|
error = parseConstTree(aggrNode, unionArray, aggrNode->getOp(), aggrNode->getType(), true);
|
|
else
|
|
error = parseConstTree(aggrNode, unionArray, aggrNode->getOp(), aggrNode->getType());
|
|
|
|
if (error)
|
|
return aggrNode;
|
|
|
|
return addConstantUnion(unionArray, aggrNode->getType(), aggrNode->getLoc());
|
|
}
|
|
|
|
//
|
|
// Constant folding of a bracket (array-style) dereference or struct-like dot
|
|
// dereference. Can handle anything except a multi-character swizzle, though
|
|
// all swizzles may go to foldSwizzle().
|
|
//
|
|
TIntermTyped* TIntermediate::foldDereference(TIntermTyped* node, int index, const TSourceLoc& loc)
|
|
{
|
|
TType dereferencedType(node->getType(), index);
|
|
dereferencedType.getQualifier().storage = EvqConst;
|
|
TIntermTyped* result = 0;
|
|
int size = dereferencedType.computeNumComponents();
|
|
|
|
// arrays, vectors, matrices, all use simple multiplicative math
|
|
// while structures need to add up heterogeneous members
|
|
int start;
|
|
if (node->isArray() || ! node->isStruct())
|
|
start = size * index;
|
|
else {
|
|
// it is a structure
|
|
assert(node->isStruct());
|
|
start = 0;
|
|
for (int i = 0; i < index; ++i)
|
|
start += (*node->getType().getStruct())[i].type->computeNumComponents();
|
|
}
|
|
|
|
result = addConstantUnion(TConstUnionArray(node->getAsConstantUnion()->getConstArray(), start, size), node->getType(), loc);
|
|
|
|
if (result == 0)
|
|
result = node;
|
|
else
|
|
result->setType(dereferencedType);
|
|
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Make a constant vector node or constant scalar node, representing a given
|
|
// constant vector and constant swizzle into it.
|
|
//
|
|
TIntermTyped* TIntermediate::foldSwizzle(TIntermTyped* node, TSwizzleSelectors<TVectorSelector>& selectors, const TSourceLoc& loc)
|
|
{
|
|
const TConstUnionArray& unionArray = node->getAsConstantUnion()->getConstArray();
|
|
TConstUnionArray constArray(selectors.size());
|
|
|
|
for (int i = 0; i < selectors.size(); i++)
|
|
constArray[i] = unionArray[selectors[i]];
|
|
|
|
TIntermTyped* result = addConstantUnion(constArray, node->getType(), loc);
|
|
|
|
if (result == 0)
|
|
result = node;
|
|
else
|
|
result->setType(TType(node->getBasicType(), EvqConst, selectors.size()));
|
|
|
|
return result;
|
|
}
|
|
|
|
} // end namespace glslang
|