Note: This affects any downstream consumers of glslang's traverser. Let me know if there are any issues. Essentially, you will need to change the functions that were pointed to into overriding base-class members instead. See the examples in this check in. git-svn-id: https://cvs.khronos.org/svn/repos/ogl/trunk/ecosystem/public/sdk/tools/glslang@24740 e7fa87d3-cd2b-0410-9028-fcbf551c1848
204 lines
6.9 KiB
C++
204 lines
6.9 KiB
C++
//
|
|
//Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
|
|
//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.
|
|
//
|
|
|
|
//
|
|
// Travarse a tree of constants to create a single folded constant.
|
|
// It should only be used when the whole tree is known to be constant.
|
|
//
|
|
|
|
#include "ParseHelper.h"
|
|
|
|
namespace glslang {
|
|
|
|
class TConstTraverser : public TIntermTraverser {
|
|
public:
|
|
TConstTraverser(const TConstUnionArray& cUnion, bool singleConstParam, TOperator constructType, const TType& t)
|
|
: unionArray(cUnion), type(t),
|
|
constructorType(constructType), singleConstantParam(singleConstParam), error(false), isMatrix(false),
|
|
matrixCols(0), matrixRows(0) { index = 0; tOp = EOpNull; }
|
|
|
|
virtual void visitConstantUnion(TIntermConstantUnion* node);
|
|
virtual bool visitAggregate(TVisit, TIntermAggregate* node);
|
|
|
|
int index;
|
|
TConstUnionArray unionArray;
|
|
TOperator tOp;
|
|
const TType& type;
|
|
TOperator constructorType;
|
|
bool singleConstantParam;
|
|
bool error;
|
|
int size; // size of the constructor ( 4 for vec4)
|
|
bool isMatrix;
|
|
int matrixCols;
|
|
int matrixRows;
|
|
};
|
|
|
|
bool TConstTraverser::visitAggregate(TVisit /* visit */, TIntermAggregate* node)
|
|
{
|
|
if (! node->isConstructor() && node->getOp() != EOpComma) {
|
|
error = true;
|
|
|
|
return false;
|
|
}
|
|
|
|
if (node->getSequence().size() == 0) {
|
|
error = true;
|
|
|
|
return false;
|
|
}
|
|
|
|
bool flag = node->getSequence().size() == 1 && node->getSequence()[0]->getAsTyped()->getAsConstantUnion();
|
|
if (flag) {
|
|
singleConstantParam = true;
|
|
constructorType = node->getOp();
|
|
size = node->getType().getObjectSize();
|
|
|
|
if (node->getType().isMatrix()) {
|
|
isMatrix = true;
|
|
matrixCols = node->getType().getMatrixCols();
|
|
matrixRows = node->getType().getMatrixRows();
|
|
}
|
|
}
|
|
|
|
for (TIntermSequence::iterator p = node->getSequence().begin();
|
|
p != node->getSequence().end(); p++) {
|
|
|
|
if (node->getOp() == EOpComma)
|
|
index = 0;
|
|
|
|
(*p)->traverse(this);
|
|
}
|
|
if (flag)
|
|
{
|
|
singleConstantParam = false;
|
|
constructorType = EOpNull;
|
|
size = 0;
|
|
isMatrix = false;
|
|
matrixCols = 0;
|
|
matrixRows = 0;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void TConstTraverser::visitConstantUnion(TIntermConstantUnion* node)
|
|
{
|
|
TConstUnionArray leftUnionArray(unionArray);
|
|
int instanceSize = type.getObjectSize();
|
|
|
|
if (index >= instanceSize)
|
|
return;
|
|
|
|
if (! singleConstantParam) {
|
|
int rightUnionSize = node->getType().getObjectSize();
|
|
|
|
const TConstUnionArray& rightUnionArray = node->getConstArray();
|
|
for (int i = 0; i < rightUnionSize; i++) {
|
|
if (index >= instanceSize)
|
|
return;
|
|
leftUnionArray[index] = rightUnionArray[i];
|
|
|
|
index++;
|
|
}
|
|
} else {
|
|
int endIndex = index + size;
|
|
const TConstUnionArray& rightUnionArray = node->getConstArray();
|
|
if (! isMatrix) {
|
|
int count = 0;
|
|
for (int i = index; i < endIndex; i++) {
|
|
if (i >= instanceSize)
|
|
return;
|
|
|
|
leftUnionArray[i] = rightUnionArray[count];
|
|
|
|
(index)++;
|
|
|
|
if (node->getType().getObjectSize() > 1)
|
|
count++;
|
|
}
|
|
} else {
|
|
// constructing a matrix, but from what?
|
|
if (node->isMatrix()) {
|
|
// Matrix from a matrix; this has the outer matrix, node is the argument matrix.
|
|
// Traverse the outer, potentially bigger matrix, fill in missing pieces with the
|
|
// identity matrix.
|
|
for (int c = 0; c < matrixCols; ++c) {
|
|
for (int r = 0; r < matrixRows; ++r) {
|
|
int targetOffset = index + c * matrixRows + r;
|
|
if (r < node->getType().getMatrixRows() && c < node->getType().getMatrixCols()) {
|
|
int srcOffset = c * node->getType().getMatrixRows() + r;
|
|
leftUnionArray[targetOffset] = rightUnionArray[srcOffset];
|
|
} else if (r == c)
|
|
leftUnionArray[targetOffset].setDConst(1.0);
|
|
else
|
|
leftUnionArray[targetOffset].setDConst(0.0);
|
|
}
|
|
}
|
|
} else {
|
|
// matrix from vector
|
|
int count = 0;
|
|
const int startIndex = index;
|
|
for (int i = startIndex; i < endIndex; i++) {
|
|
if (i >= instanceSize)
|
|
return;
|
|
if (i == startIndex || (i - startIndex) % (matrixRows + 1) == 0 )
|
|
leftUnionArray[i] = rightUnionArray[count];
|
|
else
|
|
leftUnionArray[i].setDConst(0.0);
|
|
|
|
index++;
|
|
|
|
if (node->getType().getObjectSize() > 1)
|
|
count++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
bool TIntermediate::parseConstTree(TIntermNode* root, TConstUnionArray unionArray, TOperator constructorType, const TType& t, bool singleConstantParam)
|
|
{
|
|
if (root == 0)
|
|
return false;
|
|
|
|
TConstTraverser it(unionArray, singleConstantParam, constructorType, t);
|
|
|
|
root->traverse(&it);
|
|
if (it.error)
|
|
return true;
|
|
else
|
|
return false;
|
|
}
|
|
|
|
} // end namespace glslang
|