diff options
Diffstat (limited to 'src/3rdparty/angle/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.cpp')
-rw-r--r-- | src/3rdparty/angle/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.cpp | 266 |
1 files changed, 266 insertions, 0 deletions
diff --git a/src/3rdparty/angle/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.cpp b/src/3rdparty/angle/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.cpp new file mode 100644 index 0000000000..3a179f7499 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.cpp @@ -0,0 +1,266 @@ +// +// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/translator/ScalarizeVecAndMatConstructorArgs.h" +#include "compiler/translator/compilerdebug.h" + +#include <algorithm> + +#include "common/angleutils.h" + +namespace +{ + +bool ContainsMatrixNode(const TIntermSequence &sequence) +{ + for (size_t ii = 0; ii < sequence.size(); ++ii) + { + TIntermTyped *node = sequence[ii]->getAsTyped(); + if (node && node->isMatrix()) + return true; + } + return false; +} + +bool ContainsVectorNode(const TIntermSequence &sequence) +{ + for (size_t ii = 0; ii < sequence.size(); ++ii) + { + TIntermTyped *node = sequence[ii]->getAsTyped(); + if (node && node->isVector()) + return true; + } + return false; +} + +TIntermConstantUnion *ConstructIndexNode(int index) +{ + ConstantUnion *u = new ConstantUnion[1]; + u[0].setIConst(index); + + TType type(EbtInt, EbpUndefined, EvqConst, 1); + TIntermConstantUnion *node = new TIntermConstantUnion(u, type); + return node; +} + +TIntermBinary *ConstructVectorIndexBinaryNode(TIntermSymbol *symbolNode, int index) +{ + TIntermBinary *binary = new TIntermBinary(EOpIndexDirect); + binary->setLeft(symbolNode); + TIntermConstantUnion *indexNode = ConstructIndexNode(index); + binary->setRight(indexNode); + return binary; +} + +TIntermBinary *ConstructMatrixIndexBinaryNode( + TIntermSymbol *symbolNode, int colIndex, int rowIndex) +{ + TIntermBinary *colVectorNode = + ConstructVectorIndexBinaryNode(symbolNode, colIndex); + + TIntermBinary *binary = new TIntermBinary(EOpIndexDirect); + binary->setLeft(colVectorNode); + TIntermConstantUnion *rowIndexNode = ConstructIndexNode(rowIndex); + binary->setRight(rowIndexNode); + return binary; +} + +} // namespace anonymous + +bool ScalarizeVecAndMatConstructorArgs::visitAggregate(Visit visit, TIntermAggregate *node) +{ + if (visit == PreVisit) + { + switch (node->getOp()) + { + case EOpSequence: + mSequenceStack.push_back(TIntermSequence()); + { + for (TIntermSequence::const_iterator iter = node->getSequence()->begin(); + iter != node->getSequence()->end(); ++iter) + { + TIntermNode *child = *iter; + ASSERT(child != NULL); + child->traverse(this); + mSequenceStack.back().push_back(child); + } + } + if (mSequenceStack.back().size() > node->getSequence()->size()) + { + node->getSequence()->clear(); + *(node->getSequence()) = mSequenceStack.back(); + } + mSequenceStack.pop_back(); + return false; + case EOpConstructVec2: + case EOpConstructVec3: + case EOpConstructVec4: + case EOpConstructBVec2: + case EOpConstructBVec3: + case EOpConstructBVec4: + case EOpConstructIVec2: + case EOpConstructIVec3: + case EOpConstructIVec4: + if (ContainsMatrixNode(*(node->getSequence()))) + scalarizeArgs(node, false, true); + break; + case EOpConstructMat2: + case EOpConstructMat3: + case EOpConstructMat4: + if (ContainsVectorNode(*(node->getSequence()))) + scalarizeArgs(node, true, false); + break; + default: + break; + } + } + return true; +} + +void ScalarizeVecAndMatConstructorArgs::scalarizeArgs( + TIntermAggregate *aggregate, bool scalarizeVector, bool scalarizeMatrix) +{ + ASSERT(aggregate); + int size = 0; + switch (aggregate->getOp()) + { + case EOpConstructVec2: + case EOpConstructBVec2: + case EOpConstructIVec2: + size = 2; + break; + case EOpConstructVec3: + case EOpConstructBVec3: + case EOpConstructIVec3: + size = 3; + break; + case EOpConstructVec4: + case EOpConstructBVec4: + case EOpConstructIVec4: + case EOpConstructMat2: + size = 4; + break; + case EOpConstructMat3: + size = 9; + break; + case EOpConstructMat4: + size = 16; + break; + default: + break; + } + TIntermSequence *sequence = aggregate->getSequence(); + TIntermSequence original(*sequence); + sequence->clear(); + for (size_t ii = 0; ii < original.size(); ++ii) + { + ASSERT(size > 0); + TIntermTyped *node = original[ii]->getAsTyped(); + ASSERT(node); + TString varName = createTempVariable(node); + if (node->isScalar()) + { + TIntermSymbol *symbolNode = + new TIntermSymbol(-1, varName, node->getType()); + sequence->push_back(symbolNode); + size--; + } + else if (node->isVector()) + { + if (scalarizeVector) + { + int repeat = std::min(size, node->getNominalSize()); + size -= repeat; + for (int index = 0; index < repeat; ++index) + { + TIntermSymbol *symbolNode = + new TIntermSymbol(-1, varName, node->getType()); + TIntermBinary *newNode = ConstructVectorIndexBinaryNode( + symbolNode, index); + sequence->push_back(newNode); + } + } + else + { + TIntermSymbol *symbolNode = + new TIntermSymbol(-1, varName, node->getType()); + sequence->push_back(symbolNode); + size -= node->getNominalSize(); + } + } + else + { + ASSERT(node->isMatrix()); + if (scalarizeMatrix) + { + int colIndex = 0, rowIndex = 0; + int repeat = std::min(size, node->getCols() * node->getRows()); + size -= repeat; + while (repeat > 0) + { + TIntermSymbol *symbolNode = + new TIntermSymbol(-1, varName, node->getType()); + TIntermBinary *newNode = ConstructMatrixIndexBinaryNode( + symbolNode, colIndex, rowIndex); + sequence->push_back(newNode); + rowIndex++; + if (rowIndex >= node->getRows()) + { + rowIndex = 0; + colIndex++; + } + repeat--; + } + } + else + { + TIntermSymbol *symbolNode = + new TIntermSymbol(-1, varName, node->getType()); + sequence->push_back(symbolNode); + size -= node->getCols() * node->getRows(); + } + } + } +} + +TString ScalarizeVecAndMatConstructorArgs::createTempVariable(TIntermTyped *original) +{ + TString tempVarName = "_webgl_tmp_"; + if (original->isScalar()) + { + tempVarName += "scalar_"; + } + else if (original->isVector()) + { + tempVarName += "vec_"; + } + else + { + ASSERT(original->isMatrix()); + tempVarName += "mat_"; + } + tempVarName += Str(mTempVarCount).c_str(); + mTempVarCount++; + + ASSERT(original); + TType type = original->getType(); + type.setQualifier(EvqTemporary); + + TIntermBinary *init = new TIntermBinary(EOpInitialize); + TIntermSymbol *symbolNode = new TIntermSymbol(-1, tempVarName, type); + init->setLeft(symbolNode); + init->setRight(original); + init->setType(type); + + TIntermAggregate *decl = new TIntermAggregate(EOpDeclaration); + decl->getSequence()->push_back(init); + + ASSERT(mSequenceStack.size() > 0); + TIntermSequence &sequence = mSequenceStack.back(); + sequence.push_back(decl); + + return tempVarName; +} |