tor-browser

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

RewriteTexelFetchOffset.cpp (5098B)


      1 //
      2 // Copyright 2016 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 texelFetchOffset translation issue workaround.
      7 // See header for more info.
      8 
      9 #include "compiler/translator/tree_ops/RewriteTexelFetchOffset.h"
     10 
     11 #include "common/angleutils.h"
     12 #include "compiler/translator/SymbolTable.h"
     13 #include "compiler/translator/tree_util/IntermNode_util.h"
     14 #include "compiler/translator/tree_util/IntermTraverse.h"
     15 
     16 namespace sh
     17 {
     18 
     19 namespace
     20 {
     21 
     22 class Traverser : public TIntermTraverser
     23 {
     24  public:
     25    [[nodiscard]] static bool Apply(TCompiler *compiler,
     26                                    TIntermNode *root,
     27                                    const TSymbolTable &symbolTable,
     28                                    int shaderVersion);
     29 
     30  private:
     31    Traverser(const TSymbolTable &symbolTable, int shaderVersion);
     32    bool visitAggregate(Visit visit, TIntermAggregate *node) override;
     33    void nextIteration();
     34 
     35    const TSymbolTable *symbolTable;
     36    const int shaderVersion;
     37    bool mFound = false;
     38 };
     39 
     40 Traverser::Traverser(const TSymbolTable &symbolTable, int shaderVersion)
     41    : TIntermTraverser(true, false, false), symbolTable(&symbolTable), shaderVersion(shaderVersion)
     42 {}
     43 
     44 // static
     45 bool Traverser::Apply(TCompiler *compiler,
     46                      TIntermNode *root,
     47                      const TSymbolTable &symbolTable,
     48                      int shaderVersion)
     49 {
     50    Traverser traverser(symbolTable, shaderVersion);
     51    do
     52    {
     53        traverser.nextIteration();
     54        root->traverse(&traverser);
     55        if (traverser.mFound)
     56        {
     57            if (!traverser.updateTree(compiler, root))
     58            {
     59                return false;
     60            }
     61        }
     62    } while (traverser.mFound);
     63 
     64    return true;
     65 }
     66 
     67 void Traverser::nextIteration()
     68 {
     69    mFound = false;
     70 }
     71 
     72 bool Traverser::visitAggregate(Visit visit, TIntermAggregate *node)
     73 {
     74    if (mFound)
     75    {
     76        return false;
     77    }
     78 
     79    // Decide if the node represents the call of texelFetchOffset.
     80    if (!BuiltInGroup::IsBuiltIn(node->getOp()))
     81    {
     82        return true;
     83    }
     84 
     85    ASSERT(node->getFunction()->symbolType() == SymbolType::BuiltIn);
     86    if (node->getFunction()->name() != "texelFetchOffset")
     87    {
     88        return true;
     89    }
     90 
     91    // Potential problem case detected, apply workaround.
     92    const TIntermSequence *sequence = node->getSequence();
     93    ASSERT(sequence->size() == 4u);
     94 
     95    // Decide if the sampler is a 2DArray sampler. In that case position is ivec3 and offset is
     96    // ivec2.
     97    bool is2DArray = sequence->at(1)->getAsTyped()->getNominalSize() == 3 &&
     98                     sequence->at(3)->getAsTyped()->getNominalSize() == 2;
     99 
    100    // Create new node that represents the call of function texelFetch.
    101    // Its argument list will be: texelFetch(sampler, Position+offset, lod).
    102 
    103    TIntermSequence texelFetchArguments;
    104 
    105    // sampler
    106    texelFetchArguments.push_back(sequence->at(0));
    107 
    108    // Position
    109    TIntermTyped *texCoordNode = sequence->at(1)->getAsTyped();
    110    ASSERT(texCoordNode);
    111 
    112    // offset
    113    TIntermTyped *offsetNode = nullptr;
    114    ASSERT(sequence->at(3)->getAsTyped());
    115    if (is2DArray)
    116    {
    117        // For 2DArray samplers, Position is ivec3 and offset is ivec2;
    118        // So offset must be converted into an ivec3 before being added to Position.
    119        TIntermSequence constructOffsetIvecArguments;
    120        constructOffsetIvecArguments.push_back(sequence->at(3)->getAsTyped());
    121 
    122        TIntermTyped *zeroNode = CreateZeroNode(TType(EbtInt));
    123        constructOffsetIvecArguments.push_back(zeroNode);
    124 
    125        offsetNode = TIntermAggregate::CreateConstructor(texCoordNode->getType(),
    126                                                         &constructOffsetIvecArguments);
    127        offsetNode->setLine(texCoordNode->getLine());
    128    }
    129    else
    130    {
    131        offsetNode = sequence->at(3)->getAsTyped();
    132    }
    133 
    134    // Position+offset
    135    TIntermBinary *add = new TIntermBinary(EOpAdd, texCoordNode, offsetNode);
    136    add->setLine(texCoordNode->getLine());
    137    texelFetchArguments.push_back(add);
    138 
    139    // lod
    140    texelFetchArguments.push_back(sequence->at(2));
    141 
    142    ASSERT(texelFetchArguments.size() == 3u);
    143 
    144    TIntermTyped *texelFetchNode = CreateBuiltInFunctionCallNode("texelFetch", &texelFetchArguments,
    145                                                                 *symbolTable, shaderVersion);
    146    texelFetchNode->setLine(node->getLine());
    147 
    148    // Replace the old node by this new node.
    149    queueReplacement(texelFetchNode, OriginalNode::IS_DROPPED);
    150    mFound = true;
    151    return false;
    152 }
    153 
    154 }  // anonymous namespace
    155 
    156 bool RewriteTexelFetchOffset(TCompiler *compiler,
    157                             TIntermNode *root,
    158                             const TSymbolTable &symbolTable,
    159                             int shaderVersion)
    160 {
    161    // texelFetchOffset is only valid in GLSL 3.0 and later.
    162    if (shaderVersion < 300)
    163        return true;
    164 
    165    return Traverser::Apply(compiler, root, symbolTable, shaderVersion);
    166 }
    167 
    168 }  // namespace sh