tor-browser

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

ClampIndirectIndices.cpp (5007B)


      1 //
      2 // Copyright 2021 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 // ClampIndirectIndices.h: Add clamp to the indirect indices used on arrays.
      7 //
      8 
      9 #include "compiler/translator/tree_ops/ClampIndirectIndices.h"
     10 
     11 #include "compiler/translator/Compiler.h"
     12 #include "compiler/translator/StaticType.h"
     13 #include "compiler/translator/SymbolTable.h"
     14 #include "compiler/translator/tree_util/IntermNode_util.h"
     15 #include "compiler/translator/tree_util/IntermTraverse.h"
     16 
     17 namespace sh
     18 {
     19 namespace
     20 {
     21 // Traverser that finds EOpIndexIndirect nodes and applies a clamp to their right-hand side
     22 // expression.
     23 class ClampIndirectIndicesTraverser : public TIntermTraverser
     24 {
     25  public:
     26    ClampIndirectIndicesTraverser(TCompiler *compiler, TSymbolTable *symbolTable)
     27        : TIntermTraverser(true, false, false, symbolTable), mCompiler(compiler)
     28    {}
     29 
     30    bool visitBinary(Visit visit, TIntermBinary *node) override
     31    {
     32        ASSERT(visit == PreVisit);
     33 
     34        // Only interested in EOpIndexIndirect nodes.
     35        if (node->getOp() != EOpIndexIndirect)
     36        {
     37            return true;
     38        }
     39 
     40        // Apply the transformation to the left and right nodes
     41        bool valid = ClampIndirectIndices(mCompiler, node->getLeft(), mSymbolTable);
     42        ASSERT(valid);
     43        valid = ClampIndirectIndices(mCompiler, node->getRight(), mSymbolTable);
     44        ASSERT(valid);
     45 
     46        // Generate clamp(right, 0, N), where N is the size of the array being indexed minus 1.  If
     47        // the array is runtime-sized, the length() method is called on it.
     48        const TType &leftType  = node->getLeft()->getType();
     49        const TType &rightType = node->getRight()->getType();
     50 
     51        // Don't clamp indirect indices on unsized arrays in buffer blocks.  They are covered by the
     52        // relevant robust access behavior of the backend.
     53        if (leftType.isUnsizedArray())
     54        {
     55            return true;
     56        }
     57 
     58        // On GLSL es 100, clamp is only defined for float, so float arguments are used.
     59        //
     60        // However, float clamp is unconditionally emitted to workaround driver bugs with integer
     61        // clamp on Qualcomm.  http://crbug.com/1217167
     62        //
     63        // const bool useFloatClamp = mCompiler->getShaderVersion() == 100;
     64        const bool useFloatClamp = true;
     65 
     66        TIntermConstantUnion *zero = createClampValue(0, useFloatClamp);
     67        TIntermTyped *max;
     68 
     69        if (leftType.isArray())
     70        {
     71            max = createClampValue(static_cast<int>(leftType.getOutermostArraySize()) - 1,
     72                                   useFloatClamp);
     73        }
     74        else
     75        {
     76            ASSERT(leftType.isVector() || leftType.isMatrix());
     77            max = createClampValue(leftType.getNominalSize() - 1, useFloatClamp);
     78        }
     79 
     80        TIntermTyped *index = node->getRight();
     81        // If the index node is not an int (i.e. it's a uint), or a float (if using float clamp),
     82        // cast it.
     83        const TBasicType requiredBasicType = useFloatClamp ? EbtFloat : EbtInt;
     84        if (rightType.getBasicType() != requiredBasicType)
     85        {
     86            const TType *clampType = useFloatClamp ? StaticType::GetBasic<EbtFloat, EbpHigh>()
     87                                                   : StaticType::GetBasic<EbtInt, EbpHigh>();
     88            TIntermSequence constructorArgs = {index};
     89            index = TIntermAggregate::CreateConstructor(*clampType, &constructorArgs);
     90        }
     91 
     92        // min(gl_PointSize, maxPointSize)
     93        TIntermSequence args;
     94        args.push_back(index);
     95        args.push_back(zero);
     96        args.push_back(max);
     97        TIntermTyped *clamped =
     98            CreateBuiltInFunctionCallNode("clamp", &args, *mSymbolTable, useFloatClamp ? 100 : 300);
     99 
    100        // Cast back to int if float clamp was used.
    101        if (useFloatClamp)
    102        {
    103            TIntermSequence constructorArgs = {clamped};
    104            clamped = TIntermAggregate::CreateConstructor(*StaticType::GetBasic<EbtInt, EbpHigh>(),
    105                                                          &constructorArgs);
    106        }
    107 
    108        // Replace the right node (the index) with the clamped result.
    109        queueReplacementWithParent(node, node->getRight(), clamped, OriginalNode::IS_DROPPED);
    110 
    111        // Don't recurse as left and right nodes are already processed.
    112        return false;
    113    }
    114 
    115  private:
    116    TIntermConstantUnion *createClampValue(int value, bool useFloat)
    117    {
    118        if (useFloat)
    119        {
    120            return CreateFloatNode(static_cast<float>(value), EbpHigh);
    121        }
    122        return CreateIndexNode(value);
    123    }
    124 
    125    TCompiler *mCompiler;
    126 };
    127 }  // anonymous namespace
    128 
    129 bool ClampIndirectIndices(TCompiler *compiler, TIntermNode *root, TSymbolTable *symbolTable)
    130 {
    131    ClampIndirectIndicesTraverser traverser(compiler, symbolTable);
    132    root->traverse(&traverser);
    133    return traverser.updateTree(compiler, root);
    134 }
    135 
    136 }  // namespace sh