summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/angle/src/compiler/translator/VectorizeVectorScalarArithmetic.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/3rdparty/angle/src/compiler/translator/VectorizeVectorScalarArithmetic.cpp')
-rw-r--r--src/3rdparty/angle/src/compiler/translator/VectorizeVectorScalarArithmetic.cpp284
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