tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

RewriteDfdy.cpp (5192B)


      1 //
      2 // Copyright 2019 The ANGLE Project Authors. All rights reserved.
      3 // Use of this source code is governed by a BSD-style license that can be
      4 // found in the LICENSE file.
      5 //
      6 // Implementation of dFdy viewport transformation.
      7 // See header for more info.
      8 
      9 #include "compiler/translator/tree_ops/RewriteDfdy.h"
     10 
     11 #include "common/angleutils.h"
     12 #include "compiler/translator/SymbolTable.h"
     13 #include "compiler/translator/TranslatorVulkan.h"
     14 #include "compiler/translator/tree_util/DriverUniform.h"
     15 #include "compiler/translator/tree_util/IntermNode_util.h"
     16 #include "compiler/translator/tree_util/IntermTraverse.h"
     17 #include "compiler/translator/tree_util/SpecializationConstant.h"
     18 
     19 namespace sh
     20 {
     21 
     22 namespace
     23 {
     24 
     25 class Traverser : public TIntermTraverser
     26 {
     27  public:
     28    Traverser(TSymbolTable *symbolTable, SpecConst *specConst, const DriverUniform *driverUniforms);
     29 
     30  private:
     31    bool visitAggregate(Visit visit, TIntermAggregate *node) override;
     32 
     33    SpecConst *mSpecConst                = nullptr;
     34    const DriverUniform *mDriverUniforms = nullptr;
     35 };
     36 
     37 Traverser::Traverser(TSymbolTable *symbolTable,
     38                     SpecConst *specConst,
     39                     const DriverUniform *driverUniforms)
     40    : TIntermTraverser(true, false, false, symbolTable),
     41      mSpecConst(specConst),
     42      mDriverUniforms(driverUniforms)
     43 {}
     44 
     45 bool Traverser::visitAggregate(Visit visit, TIntermAggregate *node)
     46 {
     47    // Decide if the node represents a call to dFdx() or dFdy()
     48    if (node->getOp() != EOpDFdx && node->getOp() != EOpDFdy)
     49    {
     50        return true;
     51    }
     52 
     53    const bool isDFdx = node->getOp() == EOpDFdx;
     54 
     55    // Two transformations are done on dFdx and dFdy:
     56    //
     57    // - If pre-rotation is applied, dFdx and dFdy may need to swap their axis based on the degree
     58    //   of rotation.  dFdx becomes dFdy if rotation is 90 or 270 degrees.  Similarly, dFdy becomes
     59    //   dFdx.
     60    // - The result is potentially negated.  This could be due to viewport y-flip or pre-rotation.
     61    //
     62    // Accordingly, there are two variables controlling the above transformations:
     63    //
     64    // - Rotation: A vec2 that is either (0, 1) or (1, 0).  dFdx and dFdy are replaced with:
     65    //
     66    //       dFdx * Rotation.x + dFdy * Rotation.y
     67    //
     68    // - Scale: A vec2 with -1 or 1 for either x or y components.  The previous result is multiplied
     69    //   by this.
     70    //
     71    // Together, the above operations account for the combinations of 4 possible rotations and
     72    // y-flip.
     73 
     74    // Get the results of dFdx(operand) and dFdy(operand), and multiply them by the swizzles
     75    TIntermTyped *operand = node->getChildNode(0)->getAsTyped();
     76 
     77    TIntermTyped *dFdx = CreateBuiltInUnaryFunctionCallNode("dFdx", operand, *mSymbolTable, 300);
     78    TIntermTyped *dFdy =
     79        CreateBuiltInUnaryFunctionCallNode("dFdy", operand->deepCopy(), *mSymbolTable, 300);
     80 
     81    // Get rotation multiplier
     82    TIntermTyped *swapXY = mSpecConst->getSwapXY();
     83    if (swapXY == nullptr)
     84    {
     85        swapXY = mDriverUniforms->getSwapXY();
     86    }
     87 
     88    TIntermTyped *swapXMultiplier = MakeSwapXMultiplier(swapXY);
     89    TIntermTyped *swapYMultiplier = MakeSwapYMultiplier(swapXY->deepCopy());
     90 
     91    // Get flip multiplier
     92    TIntermTyped *flipXY = mDriverUniforms->getFlipXY(mSymbolTable, DriverUniformFlip::Fragment);
     93 
     94    // Multiply the flip and rotation multipliers
     95    TIntermTyped *xMultiplier =
     96        new TIntermBinary(EOpMul, isDFdx ? swapXMultiplier : swapYMultiplier,
     97                          (new TIntermSwizzle(flipXY->deepCopy(), {0}))->fold(nullptr));
     98    TIntermTyped *yMultiplier =
     99        new TIntermBinary(EOpMul, isDFdx ? swapYMultiplier : swapXMultiplier,
    100                          (new TIntermSwizzle(flipXY->deepCopy(), {1}))->fold(nullptr));
    101 
    102    const TOperator mulOp            = dFdx->getType().isVector() ? EOpVectorTimesScalar : EOpMul;
    103    TIntermTyped *rotatedFlippedDfdx = new TIntermBinary(mulOp, dFdx, xMultiplier);
    104    TIntermTyped *rotatedFlippedDfdy = new TIntermBinary(mulOp, dFdy, yMultiplier);
    105 
    106    // Sum them together into the result
    107    TIntermBinary *rotatedFlippedResult =
    108        new TIntermBinary(EOpAdd, rotatedFlippedDfdx, rotatedFlippedDfdy);
    109 
    110    // Replace the old dFdx() or dFdy() node with the new node that contains the corrected value
    111    //
    112    // Note the following bugs (anglebug.com/7346):
    113    //
    114    // - Side effects of operand are duplicated with the above
    115    // - If the direct child of this node is itself dFdx/y, its queueReplacement will not be
    116    //   effective as the parent is also replaced.
    117    queueReplacement(rotatedFlippedResult, OriginalNode::IS_DROPPED);
    118 
    119    return true;
    120 }
    121 }  // anonymous namespace
    122 
    123 bool RewriteDfdy(TCompiler *compiler,
    124                 TIntermBlock *root,
    125                 TSymbolTable *symbolTable,
    126                 int shaderVersion,
    127                 SpecConst *specConst,
    128                 const DriverUniform *driverUniforms)
    129 {
    130    // dFdx/dFdy is only valid in GLSL 3.0 and later.
    131    if (shaderVersion < 300)
    132    {
    133        return true;
    134    }
    135 
    136    Traverser traverser(symbolTable, specConst, driverUniforms);
    137    root->traverse(&traverser);
    138    return traverser.updateTree(compiler, root);
    139 }
    140 
    141 }  // namespace sh