Hash :
b980c563
Author :
Date :
2018-11-27T11:34:27
Reformat all cpp and h files. This applies git cl format --full to all ANGLE sources. Bug: angleproject:2986 Change-Id: Ib504e618c1589332a37e97696cdc3515d739308f Reviewed-on: https://chromium-review.googlesource.com/c/1351367 Reviewed-by: Jamie Madill <jmadill@chromium.org> Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
//
// Copyright (c) 2002-2015 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.
//
// RemovePow is an AST traverser to convert pow(x, y) built-in calls where y is a
// constant to exp2(y * log2(x)). This works around an issue in NVIDIA 311 series
// OpenGL drivers.
//
#include "compiler/translator/tree_ops/RemovePow.h"
#include "compiler/translator/InfoSink.h"
#include "compiler/translator/tree_util/IntermNode_util.h"
#include "compiler/translator/tree_util/IntermTraverse.h"
namespace sh
{
namespace
{
bool IsProblematicPow(TIntermTyped *node)
{
TIntermAggregate *agg = node->getAsAggregate();
if (agg != nullptr && agg->getOp() == EOpPow)
{
ASSERT(agg->getSequence()->size() == 2);
return agg->getSequence()->at(1)->getAsConstantUnion() != nullptr;
}
return false;
}
// Traverser that converts all pow operations simultaneously.
class RemovePowTraverser : public TIntermTraverser
{
public:
RemovePowTraverser(TSymbolTable *symbolTable);
bool visitAggregate(Visit visit, TIntermAggregate *node) override;
void nextIteration() { mNeedAnotherIteration = false; }
bool needAnotherIteration() const { return mNeedAnotherIteration; }
protected:
bool mNeedAnotherIteration;
};
RemovePowTraverser::RemovePowTraverser(TSymbolTable *symbolTable)
: TIntermTraverser(true, false, false, symbolTable), mNeedAnotherIteration(false)
{}
bool RemovePowTraverser::visitAggregate(Visit visit, TIntermAggregate *node)
{
if (IsProblematicPow(node))
{
TIntermTyped *x = node->getSequence()->at(0)->getAsTyped();
TIntermTyped *y = node->getSequence()->at(1)->getAsTyped();
TIntermSequence *logArgs = new TIntermSequence();
logArgs->push_back(x);
TIntermTyped *log = CreateBuiltInFunctionCallNode("log2", logArgs, *mSymbolTable, 100);
log->setLine(node->getLine());
TOperator op = TIntermBinary::GetMulOpBasedOnOperands(y->getType(), log->getType());
TIntermBinary *mul = new TIntermBinary(op, y, log);
mul->setLine(node->getLine());
TIntermSequence *expArgs = new TIntermSequence();
expArgs->push_back(mul);
TIntermTyped *exp = CreateBuiltInFunctionCallNode("exp2", expArgs, *mSymbolTable, 100);
exp->setLine(node->getLine());
queueReplacement(exp, OriginalNode::IS_DROPPED);
// If the x parameter also needs to be replaced, we need to do that in another traversal,
// since it's parent node will change in a way that's not handled correctly by updateTree().
if (IsProblematicPow(x))
{
mNeedAnotherIteration = true;
return false;
}
}
return true;
}
} // namespace
void RemovePow(TIntermNode *root, TSymbolTable *symbolTable)
{
RemovePowTraverser traverser(symbolTable);
// Iterate as necessary, and reset the traverser between iterations.
do
{
traverser.nextIteration();
root->traverse(&traverser);
traverser.updateTree();
} while (traverser.needAnotherIteration());
}
} // namespace sh