diff options
Diffstat (limited to 'src/3rdparty/angle/src/compiler/translator/VectorizeVectorScalarArithmetic.cpp')
-rw-r--r-- | src/3rdparty/angle/src/compiler/translator/VectorizeVectorScalarArithmetic.cpp | 284 |
1 files changed, 0 insertions, 284 deletions
diff --git a/src/3rdparty/angle/src/compiler/translator/VectorizeVectorScalarArithmetic.cpp b/src/3rdparty/angle/src/compiler/translator/VectorizeVectorScalarArithmetic.cpp deleted file mode 100644 index 1e79a60991..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/VectorizeVectorScalarArithmetic.cpp +++ /dev/null @@ -1,284 +0,0 @@ -// Copyright (c) 2017 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. -// -// VectorizeVectorScalarArithmetic.cpp: Turn some arithmetic operations that operate on a float -// vector-scalar pair into vector-vector operations. This is done recursively. Some scalar binary -// operations inside vector constructors are also turned into vector operations. -// -// This is targeted to work around a bug in NVIDIA OpenGL drivers that was reproducible on NVIDIA -// driver version 387.92. It works around the most common occurrences of the bug. - -#include "compiler/translator/VectorizeVectorScalarArithmetic.h" - -#include <set> - -#include "compiler/translator/IntermNode.h" -#include "compiler/translator/IntermTraverse.h" - -namespace sh -{ - -namespace -{ - -class VectorizeVectorScalarArithmeticTraverser : public TIntermTraverser -{ - public: - VectorizeVectorScalarArithmeticTraverser(TSymbolTable *symbolTable) - : TIntermTraverser(true, false, false, symbolTable), mReplaced(false) - { - } - - bool didReplaceScalarsWithVectors() { return mReplaced; } - void nextIteration() - { - mReplaced = false; - mModifiedBlocks.clear(); - } - - protected: - bool visitBinary(Visit visit, TIntermBinary *node) override; - bool visitAggregate(Visit visit, TIntermAggregate *node) override; - - private: - // These helpers should only be called from visitAggregate when visiting a constructor. - // argBinary is the only argument of the constructor. - void replaceMathInsideConstructor(TIntermAggregate *node, TIntermBinary *argBinary); - void replaceAssignInsideConstructor(const TIntermAggregate *node, - const TIntermBinary *argBinary); - - static TIntermTyped *Vectorize(TIntermTyped *node, - TType vectorType, - TIntermTraverser::OriginalNode *originalNodeFate); - - bool mReplaced; - std::set<const TIntermBlock *> mModifiedBlocks; -}; - -TIntermTyped *VectorizeVectorScalarArithmeticTraverser::Vectorize( - TIntermTyped *node, - TType vectorType, - TIntermTraverser::OriginalNode *originalNodeFate) -{ - ASSERT(node->isScalar()); - vectorType.setQualifier(EvqTemporary); - TIntermSequence vectorConstructorArgs; - vectorConstructorArgs.push_back(node); - TIntermAggregate *vectorized = - TIntermAggregate::CreateConstructor(vectorType, &vectorConstructorArgs); - TIntermTyped *vectorizedFolded = vectorized->fold(nullptr); - if (originalNodeFate != nullptr) - { - if (vectorizedFolded != vectorized) - { - *originalNodeFate = OriginalNode::IS_DROPPED; - } - else - { - *originalNodeFate = OriginalNode::BECOMES_CHILD; - } - } - return vectorizedFolded; -} - -bool VectorizeVectorScalarArithmeticTraverser::visitBinary(Visit /*visit*/, TIntermBinary *node) -{ - TIntermTyped *left = node->getLeft(); - TIntermTyped *right = node->getRight(); - ASSERT(left); - ASSERT(right); - switch (node->getOp()) - { - case EOpAdd: - case EOpAddAssign: - // Only these specific ops are necessary to turn into vector ops. - break; - default: - return true; - } - if (node->getBasicType() != EbtFloat) - { - // Only float ops have reproduced the bug. - return true; - } - if (left->isScalar() && right->isVector()) - { - ASSERT(!node->isAssignment()); - ASSERT(!right->isArray()); - OriginalNode originalNodeFate; - TIntermTyped *leftVectorized = Vectorize(left, right->getType(), &originalNodeFate); - queueReplacementWithParent(node, left, leftVectorized, originalNodeFate); - mReplaced = true; - // Don't replace more nodes in the same subtree on this traversal. However, nodes elsewhere - // in the tree may still be replaced. - return false; - } - else if (left->isVector() && right->isScalar()) - { - OriginalNode originalNodeFate; - TIntermTyped *rightVectorized = Vectorize(right, left->getType(), &originalNodeFate); - queueReplacementWithParent(node, right, rightVectorized, originalNodeFate); - mReplaced = true; - // Don't replace more nodes in the same subtree on this traversal. However, nodes elsewhere - // in the tree may still be replaced. - return false; - } - return true; -} - -void VectorizeVectorScalarArithmeticTraverser::replaceMathInsideConstructor( - TIntermAggregate *node, - TIntermBinary *argBinary) -{ - // Turn: - // a * b - // into: - // gvec(a) * gvec(b) - - TIntermTyped *left = argBinary->getLeft(); - TIntermTyped *right = argBinary->getRight(); - ASSERT(left->isScalar() && right->isScalar()); - - TType leftVectorizedType = left->getType(); - leftVectorizedType.setPrimarySize(static_cast<unsigned char>(node->getType().getNominalSize())); - TIntermTyped *leftVectorized = Vectorize(left, leftVectorizedType, nullptr); - TType rightVectorizedType = right->getType(); - rightVectorizedType.setPrimarySize( - static_cast<unsigned char>(node->getType().getNominalSize())); - TIntermTyped *rightVectorized = Vectorize(right, rightVectorizedType, nullptr); - - TIntermBinary *newArg = new TIntermBinary(argBinary->getOp(), leftVectorized, rightVectorized); - queueReplacementWithParent(node, argBinary, newArg, OriginalNode::IS_DROPPED); -} - -void VectorizeVectorScalarArithmeticTraverser::replaceAssignInsideConstructor( - const TIntermAggregate *node, - const TIntermBinary *argBinary) -{ - // Turn: - // gvec(a *= b); - // into: - // // This is inserted into the parent block: - // gvec s0 = gvec(a); - // - // // This goes where the gvec constructor used to be: - // ((s0 *= b, a = s0.x), s0); - - TIntermTyped *left = argBinary->getLeft(); - TIntermTyped *right = argBinary->getRight(); - ASSERT(left->isScalar() && right->isScalar()); - ASSERT(!left->hasSideEffects()); - - TType vecType = node->getType(); - vecType.setQualifier(EvqTemporary); - - nextTemporaryId(); - // gvec s0 = gvec(a); - // s0 is called "tempAssignmentTarget" below. - TIntermTyped *tempAssignmentTargetInitializer = Vectorize(left->deepCopy(), vecType, nullptr); - TIntermDeclaration *tempAssignmentTargetDeclaration = - createTempInitDeclaration(tempAssignmentTargetInitializer); - - // s0 *= b - TOperator compoundAssignmentOp = argBinary->getOp(); - if (compoundAssignmentOp == EOpMulAssign) - { - compoundAssignmentOp = EOpVectorTimesScalarAssign; - } - TIntermBinary *replacementCompoundAssignment = - new TIntermBinary(compoundAssignmentOp, createTempSymbol(vecType), right->deepCopy()); - - // s0.x - TVector<int> swizzleXOffset; - swizzleXOffset.push_back(0); - TIntermSwizzle *tempAssignmentTargetX = - new TIntermSwizzle(createTempSymbol(vecType), swizzleXOffset); - // a = s0.x - TIntermBinary *replacementAssignBackToTarget = - new TIntermBinary(EOpAssign, left->deepCopy(), tempAssignmentTargetX); - - // s0 *= b, a = s0.x - TIntermBinary *replacementSequenceLeft = - new TIntermBinary(EOpComma, replacementCompoundAssignment, replacementAssignBackToTarget); - // (s0 *= b, a = s0.x), s0 - TIntermBinary *replacementSequence = - new TIntermBinary(EOpComma, replacementSequenceLeft, createTempSymbol(vecType)); - - insertStatementInParentBlock(tempAssignmentTargetDeclaration); - queueReplacement(replacementSequence, OriginalNode::IS_DROPPED); -} - -bool VectorizeVectorScalarArithmeticTraverser::visitAggregate(Visit /*visit*/, - TIntermAggregate *node) -{ - // Transform scalar binary expressions inside vector constructors. - if (!node->isConstructor() || !node->isVector() || node->getSequence()->size() != 1) - { - return true; - } - TIntermTyped *argument = node->getSequence()->back()->getAsTyped(); - ASSERT(argument); - if (!argument->isScalar() || argument->getBasicType() != EbtFloat) - { - return true; - } - TIntermBinary *argBinary = argument->getAsBinaryNode(); - if (!argBinary) - { - return true; - } - - // Only specific ops are necessary to change. - switch (argBinary->getOp()) - { - case EOpMul: - case EOpDiv: - { - replaceMathInsideConstructor(node, argBinary); - mReplaced = true; - // Don't replace more nodes in the same subtree on this traversal. However, nodes - // elsewhere in the tree may still be replaced. - return false; - } - case EOpMulAssign: - case EOpDivAssign: - { - // The case where the left side has side effects is too complicated to deal with, so we - // leave that be. - if (!argBinary->getLeft()->hasSideEffects()) - { - const TIntermBlock *parentBlock = getParentBlock(); - // We can't do more than one insertion to the same block on the same traversal. - if (mModifiedBlocks.find(parentBlock) == mModifiedBlocks.end()) - { - replaceAssignInsideConstructor(node, argBinary); - mModifiedBlocks.insert(parentBlock); - mReplaced = true; - // Don't replace more nodes in the same subtree on this traversal. - // However, nodes elsewhere in the tree may still be replaced. - return false; - } - } - break; - } - default: - return true; - } - return true; -} - -} // anonymous namespace - -void VectorizeVectorScalarArithmetic(TIntermBlock *root, TSymbolTable *symbolTable) -{ - VectorizeVectorScalarArithmeticTraverser traverser(symbolTable); - do - { - traverser.nextIteration(); - root->traverse(&traverser); - traverser.updateTree(); - } while (traverser.didReplaceScalarsWithVectors()); -} - -} // namespace sh
\ No newline at end of file |