tor-browser

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

ReplaceClipCullDistanceVariable.cpp (22288B)


      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 // ReplaceClipCullDistanceVariable.cpp: Find any references to gl_ClipDistance or gl_CullDistance
      7 // and replace it with ANGLEClipDistance or ANGLECullDistance.
      8 //
      9 
     10 #include "compiler/translator/tree_util/ReplaceClipCullDistanceVariable.h"
     11 
     12 #include "common/bitset_utils.h"
     13 #include "common/debug.h"
     14 #include "common/utilities.h"
     15 #include "compiler/translator/Compiler.h"
     16 #include "compiler/translator/SymbolTable.h"
     17 #include "compiler/translator/tree_util/BuiltIn.h"
     18 #include "compiler/translator/tree_util/IntermNode_util.h"
     19 #include "compiler/translator/tree_util/IntermTraverse.h"
     20 #include "compiler/translator/tree_util/ReplaceVariable.h"
     21 #include "compiler/translator/tree_util/RunAtTheBeginningOfShader.h"
     22 #include "compiler/translator/tree_util/RunAtTheEndOfShader.h"
     23 
     24 namespace sh
     25 {
     26 namespace
     27 {
     28 
     29 using ClipCullDistanceIdxSet = angle::BitSet<32>;
     30 
     31 typedef TIntermNode *AssignFunc(const unsigned int index,
     32                                TIntermSymbol *left,
     33                                TIntermSymbol *right,
     34                                const TIntermTyped *enableFlags);
     35 
     36 template <typename Variable>
     37 const Variable *FindVariable(const std::vector<Variable> &mVars, const ImmutableString &name)
     38 {
     39    for (const Variable &var : mVars)
     40    {
     41        if (name == var.instanceName)
     42        {
     43            return &var;
     44        }
     45    }
     46 
     47    return nullptr;
     48 }
     49 
     50 // Traverse the tree and collect the redeclaration and all constant index references of
     51 // gl_ClipDistance/gl_CullDistance
     52 class GLClipCullDistanceReferenceTraverser : public TIntermTraverser
     53 {
     54  public:
     55    GLClipCullDistanceReferenceTraverser(const TIntermSymbol **redeclaredSymOut,
     56                                         bool *nonConstIdxUsedOut,
     57                                         unsigned int *maxConstIdxOut,
     58                                         ClipCullDistanceIdxSet *constIndicesOut,
     59                                         TQualifier targetQualifier)
     60        : TIntermTraverser(true, false, false),
     61          mRedeclaredSym(redeclaredSymOut),
     62          mUseNonConstClipCullDistanceIndex(nonConstIdxUsedOut),
     63          mMaxConstClipCullDistanceIndex(maxConstIdxOut),
     64          mConstClipCullDistanceIndices(constIndicesOut),
     65          mTargetQualifier(targetQualifier)
     66    {
     67        *mRedeclaredSym                    = nullptr;
     68        *mUseNonConstClipCullDistanceIndex = false;
     69        *mMaxConstClipCullDistanceIndex    = 0;
     70        mConstClipCullDistanceIndices->reset();
     71    }
     72 
     73    bool visitDeclaration(Visit visit, TIntermDeclaration *node) override
     74    {
     75        // If gl_ClipDistance/gl_CullDistance is redeclared, we need to collect its information
     76        const TIntermSequence &sequence = *(node->getSequence());
     77 
     78        if (sequence.size() != 1)
     79        {
     80            return true;
     81        }
     82 
     83        TIntermSymbol *variable = sequence.front()->getAsSymbolNode();
     84        if (variable == nullptr || variable->getType().getQualifier() != mTargetQualifier)
     85        {
     86            return true;
     87        }
     88 
     89        *mRedeclaredSym = variable->getAsSymbolNode();
     90 
     91        return true;
     92    }
     93 
     94    bool visitBinary(Visit visit, TIntermBinary *node) override
     95    {
     96        TOperator op = node->getOp();
     97        if (op != EOpIndexDirect && op != EOpIndexIndirect)
     98        {
     99            return true;
    100        }
    101 
    102        // gl_ClipDistance / gl_CullDistance
    103        TIntermTyped *left = node->getLeft()->getAsTyped();
    104        if (!left)
    105        {
    106            return true;
    107        }
    108 
    109        ASSERT(op == EOpIndexDirect || op == EOpIndexIndirect);
    110 
    111        TIntermSymbol *clipCullDistance = left->getAsSymbolNode();
    112        if (!clipCullDistance)
    113        {
    114            return true;
    115        }
    116        if (clipCullDistance->getType().getQualifier() != mTargetQualifier)
    117        {
    118            return true;
    119        }
    120 
    121        const TConstantUnion *constIdx = node->getRight()->getConstantValue();
    122        if (!constIdx)
    123        {
    124            *mUseNonConstClipCullDistanceIndex = true;
    125        }
    126        else
    127        {
    128            unsigned int idx = 0;
    129            switch (constIdx->getType())
    130            {
    131                case EbtInt:
    132                    idx = constIdx->getIConst();
    133                    break;
    134                case EbtUInt:
    135                    idx = constIdx->getUConst();
    136                    break;
    137                case EbtFloat:
    138                    idx = static_cast<unsigned int>(constIdx->getFConst());
    139                    break;
    140                case EbtBool:
    141                    idx = constIdx->getBConst() ? 1 : 0;
    142                    break;
    143                default:
    144                    UNREACHABLE();
    145                    break;
    146            }
    147            ASSERT(idx < mConstClipCullDistanceIndices->size());
    148            mConstClipCullDistanceIndices->set(idx);
    149 
    150            *mMaxConstClipCullDistanceIndex = std::max(*mMaxConstClipCullDistanceIndex, idx);
    151        }
    152 
    153        return true;
    154    }
    155 
    156  private:
    157    const TIntermSymbol **mRedeclaredSym;
    158    // Flag indicating whether there is at least one reference of gl_ClipDistance with non-constant
    159    // index
    160    bool *mUseNonConstClipCullDistanceIndex;
    161    // Max constant index that is used to reference gl_ClipDistance
    162    unsigned int *mMaxConstClipCullDistanceIndex;
    163    // List of constant index reference of gl_ClipDistance
    164    ClipCullDistanceIdxSet *mConstClipCullDistanceIndices;
    165    // Qualifier for gl_ClipDistance/gl_CullDistance
    166    const TQualifier mTargetQualifier;
    167 };
    168 
    169 // Replace all symbolic occurrences of given variables except one symbol.
    170 class ReplaceVariableExceptOneTraverser : public TIntermTraverser
    171 {
    172  public:
    173    ReplaceVariableExceptOneTraverser(const TVariable *toBeReplaced,
    174                                      const TIntermTyped *replacement,
    175                                      const TIntermSymbol *exception)
    176        : TIntermTraverser(true, false, false),
    177          mToBeReplaced(toBeReplaced),
    178          mException(exception),
    179          mReplacement(replacement)
    180    {}
    181 
    182    void visitSymbol(TIntermSymbol *node) override
    183    {
    184        if (&node->variable() == mToBeReplaced && node != mException)
    185        {
    186            queueReplacement(mReplacement->deepCopy(), OriginalNode::IS_DROPPED);
    187        }
    188    }
    189 
    190  private:
    191    const TVariable *const mToBeReplaced;
    192    const TIntermSymbol *const mException;
    193    const TIntermTyped *const mReplacement;
    194 };
    195 
    196 TIntermNode *simpleAssignFunc(const unsigned int index,
    197                              TIntermSymbol *leftSymbol,
    198                              TIntermSymbol *rightSymbol,
    199                              const TIntermTyped * /*enableFlags*/)
    200 {
    201    // leftSymbol[index] = rightSymbol[index]
    202    // E.g., ANGLEClipDistance[index] = gl_ClipDistance[index]
    203    TIntermBinary *left =
    204        new TIntermBinary(EOpIndexDirect, leftSymbol->deepCopy(), CreateIndexNode(index));
    205    TIntermBinary *right =
    206        new TIntermBinary(EOpIndexDirect, rightSymbol->deepCopy(), CreateIndexNode(index));
    207 
    208    return new TIntermBinary(EOpAssign, left, right);
    209 }
    210 
    211 // This is only used for gl_ClipDistance
    212 TIntermNode *assignFuncWithEnableFlags(const unsigned int index,
    213                                       TIntermSymbol *leftSymbol,
    214                                       TIntermSymbol *rightSymbol,
    215                                       const TIntermTyped *enableFlags)
    216 {
    217    //  if (ANGLEUniforms.clipDistancesEnabled & (0x1 << index))
    218    //      gl_ClipDistance[index] = ANGLEClipDistance[index];
    219    //  else
    220    //      gl_ClipDistance[index] = 0;
    221    TIntermConstantUnion *bitMask = CreateUIntNode(0x1 << index);
    222    TIntermBinary *bitwiseAnd = new TIntermBinary(EOpBitwiseAnd, enableFlags->deepCopy(), bitMask);
    223    TIntermBinary *nonZero    = new TIntermBinary(EOpNotEqual, bitwiseAnd, CreateUIntNode(0));
    224 
    225    TIntermBinary *left =
    226        new TIntermBinary(EOpIndexDirect, leftSymbol->deepCopy(), CreateIndexNode(index));
    227    TIntermBinary *right =
    228        new TIntermBinary(EOpIndexDirect, rightSymbol->deepCopy(), CreateIndexNode(index));
    229    TIntermBinary *assignment = new TIntermBinary(EOpAssign, left, right);
    230    TIntermBlock *trueBlock   = new TIntermBlock();
    231    trueBlock->appendStatement(assignment);
    232 
    233    TIntermBinary *zeroAssignment =
    234        new TIntermBinary(EOpAssign, left->deepCopy(), CreateFloatNode(0, EbpMedium));
    235    TIntermBlock *falseBlock = new TIntermBlock();
    236    falseBlock->appendStatement(zeroAssignment);
    237 
    238    return new TIntermIfElse(nonZero, trueBlock, falseBlock);
    239 }
    240 
    241 class ReplaceClipCullDistanceAssignments : angle::NonCopyable
    242 {
    243  public:
    244    ReplaceClipCullDistanceAssignments(TCompiler *compiler,
    245                                       TIntermBlock *root,
    246                                       TSymbolTable *symbolTable,
    247                                       const TVariable *glClipCullDistanceVar,
    248                                       const TIntermSymbol *redeclaredGlClipDistance,
    249                                       const ImmutableString &angleVarName)
    250        : mCompiler(compiler),
    251          mRoot(root),
    252          mSymbolTable(symbolTable),
    253          mGlVar(glClipCullDistanceVar),
    254          mRedeclaredGLVar(redeclaredGlClipDistance),
    255          mANGLEVarName(angleVarName)
    256    {
    257        mEnabledDistances = 0;
    258    }
    259 
    260    unsigned int getEnabledClipCullDistance(const bool useNonConstIndex,
    261                                            const unsigned int maxConstIndex);
    262    const TVariable *declareANGLEVariable(const TVariable *originalVariable);
    263    bool assignOriginalValueToANGLEVariable(const GLenum shaderType);
    264    bool assignANGLEValueToOriginalVariable(const GLenum shaderType,
    265                                            const bool isRedeclared,
    266                                            const TIntermTyped *enableFlags,
    267                                            const ClipCullDistanceIdxSet *constIndices);
    268 
    269  private:
    270    bool assignOriginalValueToANGLEVariableImpl();
    271    bool assignANGLEValueToOriginalVariableImpl(const bool isRedeclared,
    272                                                const TIntermTyped *enableFlags,
    273                                                const ClipCullDistanceIdxSet *constIndices,
    274                                                AssignFunc assignFunc);
    275 
    276    // Common variables for replacing gl_Clip/CullDistances with ANGLEClip/CullDistances
    277    TCompiler *mCompiler;
    278    TIntermBlock *mRoot;
    279    TSymbolTable *mSymbolTable;
    280 
    281    const TVariable *mGlVar;
    282    const TIntermSymbol *mRedeclaredGLVar;
    283    const ImmutableString mANGLEVarName;
    284 
    285    unsigned int mEnabledDistances;
    286    const TVariable *mANGLEVar;
    287 };
    288 
    289 unsigned int ReplaceClipCullDistanceAssignments::getEnabledClipCullDistance(
    290    const bool useNonConstIndex,
    291    const unsigned int maxConstIndex)
    292 {
    293    if (mRedeclaredGLVar)
    294    {
    295        // If array is redeclared by user, use that redeclared size.
    296        mEnabledDistances = mRedeclaredGLVar->getType().getOutermostArraySize();
    297    }
    298    else if (!useNonConstIndex)
    299    {
    300        ASSERT(maxConstIndex < mGlVar->getType().getOutermostArraySize());
    301        // Only use constant index, then use max array index used.
    302        mEnabledDistances = maxConstIndex + 1;
    303    }
    304 
    305    return mEnabledDistances;
    306 }
    307 
    308 const TVariable *ReplaceClipCullDistanceAssignments::declareANGLEVariable(
    309    const TVariable *originalVariable)
    310 {
    311    ASSERT(mEnabledDistances > 0);
    312 
    313    TType *clipCullDistanceType = new TType(originalVariable->getType());
    314    clipCullDistanceType->setQualifier(EvqGlobal);
    315    clipCullDistanceType->toArrayBaseType();
    316    clipCullDistanceType->makeArray(mEnabledDistances);
    317 
    318    mANGLEVar =
    319        new TVariable(mSymbolTable, mANGLEVarName, clipCullDistanceType, SymbolType::AngleInternal);
    320 
    321    TIntermSymbol *clipCullDistanceDeclarator = new TIntermSymbol(mANGLEVar);
    322    TIntermDeclaration *clipCullDistanceDecl  = new TIntermDeclaration;
    323    clipCullDistanceDecl->appendDeclarator(clipCullDistanceDeclarator);
    324 
    325    // Must declare ANGLEClipdistance/ANGLECullDistance before any function, since
    326    // gl_ClipDistance/gl_CullDistance might be accessed within a function declared before main.
    327    mRoot->insertStatement(0, clipCullDistanceDecl);
    328 
    329    return mANGLEVar;
    330 }
    331 
    332 bool ReplaceClipCullDistanceAssignments::assignOriginalValueToANGLEVariableImpl()
    333 {
    334    ASSERT(mEnabledDistances > 0);
    335 
    336    TIntermBlock *readBlock                 = new TIntermBlock;
    337    TIntermSymbol *glClipCullDistanceSymbol = new TIntermSymbol(mGlVar);
    338    TIntermSymbol *clipCullDistanceSymbol   = new TIntermSymbol(mANGLEVar);
    339 
    340    for (unsigned int i = 0; i < mEnabledDistances; i++)
    341    {
    342        readBlock->appendStatement(
    343            simpleAssignFunc(i, clipCullDistanceSymbol, glClipCullDistanceSymbol, nullptr));
    344    }
    345 
    346    return RunAtTheBeginningOfShader(mCompiler, mRoot, readBlock);
    347 }
    348 
    349 bool ReplaceClipCullDistanceAssignments::assignANGLEValueToOriginalVariableImpl(
    350    const bool isRedeclared,
    351    const TIntermTyped *enableFlags,
    352    const ClipCullDistanceIdxSet *constIndices,
    353    AssignFunc assignFunc)
    354 {
    355    ASSERT(mEnabledDistances > 0);
    356 
    357    TIntermBlock *assignBlock               = new TIntermBlock;
    358    TIntermSymbol *glClipCullDistanceSymbol = new TIntermSymbol(mGlVar);
    359    TIntermSymbol *clipCullDistanceSymbol   = new TIntermSymbol(mANGLEVar);
    360 
    361    // The array size is decided by either redeclaring the variable or accessing the variable with a
    362    // integral constant index. And this size is the count of the enabled value. So, if the index
    363    // which is greater than the array size, is used to access the variable, this access will be
    364    // ignored.
    365    if (isRedeclared || !constIndices)
    366    {
    367        for (unsigned int i = 0; i < mEnabledDistances; ++i)
    368        {
    369            assignBlock->appendStatement(
    370                assignFunc(i, glClipCullDistanceSymbol, clipCullDistanceSymbol, enableFlags));
    371        }
    372    }
    373    else
    374    {
    375        // Assign ANGLEClip/CullDistance[i]'s value to gl_Clip/CullDistance[i] if i is in the
    376        // constant indices list. Those elements whose index is not in the constant index list will
    377        // be zeroise for initialization.
    378        for (unsigned int i = 0; i < mEnabledDistances; ++i)
    379        {
    380            if (constIndices->test(i))
    381            {
    382                assignBlock->appendStatement(
    383                    assignFunc(i, glClipCullDistanceSymbol, clipCullDistanceSymbol, enableFlags));
    384            }
    385            else
    386            {
    387                // gl_Clip/CullDistance[i] = 0;
    388                TIntermBinary *left = new TIntermBinary(
    389                    EOpIndexDirect, glClipCullDistanceSymbol->deepCopy(), CreateIndexNode(i));
    390                TIntermBinary *zeroAssignment =
    391                    new TIntermBinary(EOpAssign, left, CreateFloatNode(0, EbpMedium));
    392                assignBlock->appendStatement(zeroAssignment);
    393            }
    394        }
    395    }
    396 
    397    return RunAtTheEndOfShader(mCompiler, mRoot, assignBlock, mSymbolTable);
    398 }
    399 
    400 [[nodiscard]] bool ReplaceClipCullDistanceAssignments::assignOriginalValueToANGLEVariable(
    401    const GLenum shaderType)
    402 {
    403    switch (shaderType)
    404    {
    405        case GL_VERTEX_SHADER:
    406            // Vertex shader can use gl_Clip/CullDistance as a output only
    407            break;
    408        case GL_FRAGMENT_SHADER:
    409        {
    410            // These shader types can use gl_Clip/CullDistance as input
    411            if (!assignOriginalValueToANGLEVariableImpl())
    412            {
    413                return false;
    414            }
    415            break;
    416        }
    417        default:
    418        {
    419            UNREACHABLE();
    420            return false;
    421        }
    422    }
    423 
    424    return true;
    425 }
    426 
    427 [[nodiscard]] bool ReplaceClipCullDistanceAssignments::assignANGLEValueToOriginalVariable(
    428    const GLenum shaderType,
    429    const bool isRedeclared,
    430    const TIntermTyped *enableFlags,
    431    const ClipCullDistanceIdxSet *constIndices)
    432 {
    433    switch (shaderType)
    434    {
    435        case GL_VERTEX_SHADER:
    436        {
    437            // Vertex shader can use gl_Clip/CullDistance as output.
    438            // If the enabled gl_Clip/CullDistances are not initialized, results are undefined.
    439            // EXT_clip_cull_distance spec :
    440            // The shader must also set all values in gl_ClipDistance that have been enabled via the
    441            // OpenGL ES API, or results are undefined. Values written into gl_ClipDistance for
    442            // planes that are not enabled have no effect.
    443            // ...
    444            // Shaders writing gl_CullDistance must write all enabled distances, or culling results
    445            // are undefined.
    446            if (!assignANGLEValueToOriginalVariableImpl(
    447                    isRedeclared, enableFlags, constIndices,
    448                    enableFlags ? assignFuncWithEnableFlags : simpleAssignFunc))
    449            {
    450                return false;
    451            }
    452            break;
    453        }
    454        case GL_FRAGMENT_SHADER:
    455            // Fragment shader can use gl_Clip/CullDistance as input only
    456            break;
    457        default:
    458        {
    459            UNREACHABLE();
    460            return false;
    461        }
    462    }
    463 
    464    return true;
    465 }
    466 
    467 // Common code to transform gl_ClipDistance and gl_CullDistance.  Comments reference
    468 // gl_ClipDistance, but are also applicable to gl_CullDistance.
    469 [[nodiscard]] bool ReplaceClipCullDistanceAssignmentsImpl(
    470    TCompiler *compiler,
    471    TIntermBlock *root,
    472    TSymbolTable *symbolTable,
    473    const GLenum shaderType,
    474    const TIntermTyped *clipDistanceEnableFlags,
    475    const char *builtInName,
    476    const char *replacementName,
    477    TQualifier builtInQualifier)
    478 {
    479    // Collect all constant index references of gl_ClipDistance
    480    ImmutableString name(builtInName);
    481    ClipCullDistanceIdxSet constIndices;
    482    bool useNonConstIndex                  = false;
    483    const TIntermSymbol *redeclaredBuiltIn = nullptr;
    484    unsigned int maxConstIndex             = 0;
    485    GLClipCullDistanceReferenceTraverser indexTraverser(
    486        &redeclaredBuiltIn, &useNonConstIndex, &maxConstIndex, &constIndices, builtInQualifier);
    487    root->traverse(&indexTraverser);
    488    if (!useNonConstIndex && constIndices.none())
    489    {
    490        // No references of gl_ClipDistance
    491        return true;
    492    }
    493 
    494    // Retrieve gl_ClipDistance variable reference
    495    // Search user redeclared gl_ClipDistance first
    496    const TVariable *builtInVar = nullptr;
    497    if (redeclaredBuiltIn)
    498    {
    499        builtInVar = &redeclaredBuiltIn->variable();
    500    }
    501    else
    502    {
    503        // User defined not found, find in built-in table
    504        builtInVar = static_cast<const TVariable *>(
    505            symbolTable->findBuiltIn(name, compiler->getShaderVersion()));
    506    }
    507    if (!builtInVar)
    508    {
    509        return false;
    510    }
    511 
    512    ReplaceClipCullDistanceAssignments replacementUtils(compiler, root, symbolTable, builtInVar,
    513                                                        redeclaredBuiltIn,
    514                                                        ImmutableString(replacementName));
    515 
    516    // Declare a global variable substituting gl_ClipDistance
    517    unsigned int enabledClipDistances =
    518        replacementUtils.getEnabledClipCullDistance(useNonConstIndex, maxConstIndex);
    519    if (!enabledClipDistances)
    520    {
    521        // Spec :
    522        // The gl_ClipDistance array is predeclared as unsized and must be explicitly sized by the
    523        // shader either redeclaring it with a size or implicitly sized by indexing it only with
    524        // integral constant expressions.
    525        return false;
    526    }
    527 
    528    const TVariable *replacementVar = replacementUtils.declareANGLEVariable(builtInVar);
    529 
    530    // Replace gl_ClipDistance reference with ANGLEClipDistance, except the declaration
    531    ReplaceVariableExceptOneTraverser replaceTraverser(builtInVar,
    532                                                       new TIntermSymbol(replacementVar),
    533                                                       /** exception */ redeclaredBuiltIn);
    534    root->traverse(&replaceTraverser);
    535    if (!replaceTraverser.updateTree(compiler, root))
    536    {
    537        return false;
    538    }
    539 
    540    // Read gl_ClipDistance to ANGLEClipDistance for getting a original data
    541    if (!replacementUtils.assignOriginalValueToANGLEVariable(shaderType))
    542    {
    543        return false;
    544    }
    545 
    546    // Reassign ANGLEClipDistance to gl_ClipDistance but ignore those that are disabled
    547    const bool isRedeclared = redeclaredBuiltIn != nullptr;
    548    if (!replacementUtils.assignANGLEValueToOriginalVariable(
    549            shaderType, isRedeclared, clipDistanceEnableFlags, &constIndices))
    550    {
    551        return false;
    552    }
    553 
    554    // If not redeclared, replace the built-in with one that is appropriately sized
    555    if (!isRedeclared)
    556    {
    557        TType *resizedType = new TType(builtInVar->getType());
    558        resizedType->setArraySize(0, enabledClipDistances);
    559 
    560        TVariable *resizedVar = new TVariable(symbolTable, name, resizedType, SymbolType::BuiltIn);
    561 
    562        return ReplaceVariable(compiler, root, builtInVar, resizedVar);
    563    }
    564 
    565    return true;
    566 }
    567 
    568 }  // anonymous namespace
    569 
    570 [[nodiscard]] bool ReplaceClipDistanceAssignments(TCompiler *compiler,
    571                                                  TIntermBlock *root,
    572                                                  TSymbolTable *symbolTable,
    573                                                  const GLenum shaderType,
    574                                                  const TIntermTyped *clipDistanceEnableFlags)
    575 {
    576    return ReplaceClipCullDistanceAssignmentsImpl(compiler, root, symbolTable, shaderType,
    577                                                  clipDistanceEnableFlags, "gl_ClipDistance",
    578                                                  "ANGLEClipDistance", EvqClipDistance);
    579 }
    580 
    581 [[nodiscard]] bool ReplaceCullDistanceAssignments(TCompiler *compiler,
    582                                                  TIntermBlock *root,
    583                                                  TSymbolTable *symbolTable,
    584                                                  const GLenum shaderType)
    585 {
    586    return ReplaceClipCullDistanceAssignmentsImpl(compiler, root, symbolTable, shaderType, nullptr,
    587                                                  "gl_CullDistance", "ANGLECullDistance",
    588                                                  EvqCullDistance);
    589 }
    590 
    591 }  // namespace sh