| // |
| // Copyright 2019 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. |
| // |
| // Implementation of dFdy viewport transformation. |
| // See header for more info. |
| |
| #include "compiler/translator/tree_ops/RewriteDfdy.h" |
| |
| #include "common/angleutils.h" |
| #include "compiler/translator/SymbolTable.h" |
| #include "compiler/translator/tree_util/IntermNode_util.h" |
| #include "compiler/translator/tree_util/IntermTraverse.h" |
| |
| namespace sh |
| { |
| |
| namespace |
| { |
| |
| class Traverser : public TIntermTraverser |
| { |
| public: |
| ANGLE_NO_DISCARD static bool Apply(TCompiler *compiler, |
| TIntermNode *root, |
| const TSymbolTable &symbolTable, |
| TIntermBinary *viewportYScale); |
| |
| private: |
| Traverser(TIntermBinary *viewportYScale, TSymbolTable *symbolTable); |
| bool visitUnary(Visit visit, TIntermUnary *node) override; |
| |
| TIntermBinary *mViewportYScale = nullptr; |
| }; |
| |
| Traverser::Traverser(TIntermBinary *viewportYScale, TSymbolTable *symbolTable) |
| : TIntermTraverser(true, false, false, symbolTable), mViewportYScale(viewportYScale) |
| {} |
| |
| // static |
| bool Traverser::Apply(TCompiler *compiler, |
| TIntermNode *root, |
| const TSymbolTable &symbolTable, |
| TIntermBinary *viewportYScale) |
| { |
| TSymbolTable *pSymbolTable = const_cast<TSymbolTable *>(&symbolTable); |
| Traverser traverser(viewportYScale, pSymbolTable); |
| root->traverse(&traverser); |
| return traverser.updateTree(compiler, root); |
| } |
| |
| bool Traverser::visitUnary(Visit visit, TIntermUnary *node) |
| { |
| // Decide if the node represents a call to dFdy() |
| if (node->getOp() != EOpDFdy) |
| { |
| return true; |
| } |
| |
| // Copy the dFdy node so we can replace it with the corrected value |
| TIntermUnary *newDfdy = node->deepCopy()->getAsUnaryNode(); |
| |
| size_t objectSize = node->getType().getObjectSize(); |
| TOperator multiplyOp = (objectSize == 1) ? EOpMul : EOpVectorTimesScalar; |
| |
| // Correct dFdy()'s value: |
| // (dFdy() * ANGLEUniforms.viewportYScale) |
| TIntermBinary *correctedDfdy = |
| new TIntermBinary(multiplyOp, newDfdy, mViewportYScale->deepCopy()); |
| |
| // Replace the old dFdy node with the new node that contains the corrected value |
| queueReplacement(correctedDfdy, OriginalNode::IS_DROPPED); |
| |
| return true; |
| } |
| |
| } // anonymous namespace |
| |
| bool RewriteDfdy(TCompiler *compiler, |
| TIntermNode *root, |
| const TSymbolTable &symbolTable, |
| int shaderVersion, |
| TIntermBinary *viewportYScale) |
| { |
| // dFdy is only valid in GLSL 3.0 and later. |
| if (shaderVersion < 300) |
| return true; |
| |
| return Traverser::Apply(compiler, root, symbolTable, viewportYScale); |
| } |
| |
| } // namespace sh |