tor-browser

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

ValidateClipCullDistance.cpp (6029B)


      1 //
      2 // Copyright 2020 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 // The ValidateClipCullDistance function checks if the sum of array sizes for gl_ClipDistance and
      7 // gl_CullDistance exceeds gl_MaxCombinedClipAndCullDistances
      8 //
      9 
     10 #include "ValidateClipCullDistance.h"
     11 
     12 #include "compiler/translator/Diagnostics.h"
     13 #include "compiler/translator/SymbolTable.h"
     14 #include "compiler/translator/tree_util/IntermTraverse.h"
     15 #include "compiler/translator/util.h"
     16 
     17 namespace sh
     18 {
     19 
     20 namespace
     21 {
     22 
     23 void error(const TIntermSymbol &symbol, const char *reason, TDiagnostics *diagnostics)
     24 {
     25    diagnostics->error(symbol.getLine(), reason, symbol.getName().data());
     26 }
     27 
     28 class ValidateClipCullDistanceTraverser : public TIntermTraverser
     29 {
     30  public:
     31    ValidateClipCullDistanceTraverser();
     32    void validate(TDiagnostics *diagnostics, const unsigned int maxCombinedClipAndCullDistances);
     33 
     34  private:
     35    bool visitDeclaration(Visit visit, TIntermDeclaration *node) override;
     36    bool visitBinary(Visit visit, TIntermBinary *node) override;
     37 
     38    unsigned int mClipDistanceSize;
     39    unsigned int mCullDistanceSize;
     40 
     41    unsigned int mMaxClipDistanceIndex;
     42    unsigned int mMaxCullDistanceIndex;
     43 
     44    const TIntermSymbol *mClipDistance;
     45    const TIntermSymbol *mCullDistance;
     46 };
     47 
     48 ValidateClipCullDistanceTraverser::ValidateClipCullDistanceTraverser()
     49    : TIntermTraverser(true, false, false),
     50      mClipDistanceSize(0),
     51      mCullDistanceSize(0),
     52      mMaxClipDistanceIndex(0),
     53      mMaxCullDistanceIndex(0),
     54      mClipDistance(nullptr),
     55      mCullDistance(nullptr)
     56 {}
     57 
     58 bool ValidateClipCullDistanceTraverser::visitDeclaration(Visit visit, TIntermDeclaration *node)
     59 {
     60    const TIntermSequence &sequence = *(node->getSequence());
     61 
     62    if (sequence.size() != 1)
     63    {
     64        return true;
     65    }
     66 
     67    const TIntermSymbol *symbol = sequence.front()->getAsSymbolNode();
     68    if (symbol == nullptr)
     69    {
     70        return true;
     71    }
     72 
     73    if (symbol->getName() == "gl_ClipDistance")
     74    {
     75        mClipDistanceSize = symbol->getOutermostArraySize();
     76        mClipDistance     = symbol;
     77    }
     78    else if (symbol->getName() == "gl_CullDistance")
     79    {
     80        mCullDistanceSize = symbol->getOutermostArraySize();
     81        mCullDistance     = symbol;
     82    }
     83 
     84    return true;
     85 }
     86 
     87 bool ValidateClipCullDistanceTraverser::visitBinary(Visit visit, TIntermBinary *node)
     88 {
     89    TOperator op = node->getOp();
     90    if (op != EOpIndexDirect && op != EOpIndexIndirect)
     91    {
     92        return true;
     93    }
     94 
     95    TIntermSymbol *left = node->getLeft()->getAsSymbolNode();
     96    if (!left)
     97    {
     98        return true;
     99    }
    100 
    101    ImmutableString varName(left->getName());
    102    if (varName != "gl_ClipDistance" && varName != "gl_CullDistance")
    103    {
    104        return true;
    105    }
    106 
    107    const TConstantUnion *constIdx = node->getRight()->getConstantValue();
    108    if (constIdx)
    109    {
    110        unsigned int idx = 0;
    111        switch (constIdx->getType())
    112        {
    113            case EbtInt:
    114                idx = constIdx->getIConst();
    115                break;
    116            case EbtUInt:
    117                idx = constIdx->getUConst();
    118                break;
    119            case EbtFloat:
    120                idx = static_cast<unsigned int>(constIdx->getFConst());
    121                break;
    122            case EbtBool:
    123                idx = constIdx->getBConst() ? 1 : 0;
    124                break;
    125            default:
    126                UNREACHABLE();
    127                break;
    128        }
    129 
    130        if (varName == "gl_ClipDistance")
    131        {
    132            if (idx > mMaxClipDistanceIndex)
    133            {
    134                mMaxClipDistanceIndex = idx;
    135                if (!mClipDistance)
    136                {
    137                    mClipDistance = left;
    138                }
    139            }
    140        }
    141        else
    142        {
    143            ASSERT(varName == "gl_CullDistance");
    144            if (idx > mMaxCullDistanceIndex)
    145            {
    146                mMaxCullDistanceIndex = idx;
    147                if (!mCullDistance)
    148                {
    149                    mCullDistance = left;
    150                }
    151            }
    152        }
    153    }
    154 
    155    return true;
    156 }
    157 
    158 void ValidateClipCullDistanceTraverser::validate(TDiagnostics *diagnostics,
    159                                                 const unsigned int maxCombinedClipAndCullDistances)
    160 {
    161    ASSERT(diagnostics);
    162 
    163    unsigned int enabledClipDistances =
    164        (mClipDistanceSize > 0 ? mClipDistanceSize
    165                               : (mClipDistance ? mMaxClipDistanceIndex + 1 : 0));
    166    unsigned int enabledCullDistances =
    167        (mCullDistanceSize > 0 ? mCullDistanceSize
    168                               : (mCullDistance ? mMaxCullDistanceIndex + 1 : 0));
    169    unsigned int combinedClipAndCullDistances =
    170        (enabledClipDistances > 0 && enabledCullDistances > 0
    171             ? enabledClipDistances + enabledCullDistances
    172             : 0);
    173 
    174    if (combinedClipAndCullDistances > maxCombinedClipAndCullDistances)
    175    {
    176        const TIntermSymbol *greaterSymbol =
    177            (enabledClipDistances >= enabledCullDistances ? mClipDistance : mCullDistance);
    178 
    179        std::stringstream strstr = sh::InitializeStream<std::stringstream>();
    180        strstr << "The sum of 'gl_ClipDistance' and 'gl_CullDistance' size is greater than "
    181                  "gl_MaxCombinedClipAndCullDistances ("
    182               << combinedClipAndCullDistances << " > " << maxCombinedClipAndCullDistances << ")";
    183        error(*greaterSymbol, strstr.str().c_str(), diagnostics);
    184    }
    185 }
    186 
    187 }  // anonymous namespace
    188 
    189 bool ValidateClipCullDistance(TIntermBlock *root,
    190                              TDiagnostics *diagnostics,
    191                              const unsigned int maxCombinedClipAndCullDistances)
    192 {
    193    ValidateClipCullDistanceTraverser varyingValidator;
    194    root->traverse(&varyingValidator);
    195    int numErrorsBefore = diagnostics->numErrors();
    196    varyingValidator.validate(diagnostics, maxCombinedClipAndCullDistances);
    197    return (diagnostics->numErrors() == numErrorsBefore);
    198 }
    199 
    200 }  // namespace sh