• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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>
FindVariable(const std::vector<Variable> & mVars,const ImmutableString & name)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:
GLClipCullDistanceReferenceTraverser(const TIntermSymbol ** redeclaredSymOut,bool * nonConstIdxUsedOut,unsigned int * maxConstIdxOut,ClipCullDistanceIdxSet * constIndicesOut,TQualifier targetQualifier)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 
visitDeclaration(Visit visit,TIntermDeclaration * node)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 
visitBinary(Visit visit,TIntermBinary * node)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:
ReplaceVariableExceptOneTraverser(const TVariable * toBeReplaced,const TIntermTyped * replacement,const TIntermSymbol * exception)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 
visitSymbol(TIntermSymbol * node)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 
simpleAssignFunc(const unsigned int index,TIntermSymbol * leftSymbol,TIntermSymbol * rightSymbol,const TIntermTyped *)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
assignFuncWithEnableFlags(const unsigned int index,TIntermSymbol * leftSymbol,TIntermSymbol * rightSymbol,const TIntermTyped * enableFlags)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:
ReplaceClipCullDistanceAssignments(TCompiler * compiler,TIntermBlock * root,TSymbolTable * symbolTable,const TVariable * glClipCullDistanceVar,const TIntermSymbol * redeclaredGlClipDistance,const ImmutableString & angleVarName)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 
getEnabledClipCullDistance(const bool useNonConstIndex,const unsigned int maxConstIndex)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 
declareANGLEVariable(const TVariable * originalVariable)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 
assignOriginalValueToANGLEVariableImpl()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 
assignANGLEValueToOriginalVariableImpl(const bool isRedeclared,const TIntermTyped * enableFlags,const ClipCullDistanceIdxSet * constIndices,AssignFunc assignFunc)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 
assignOriginalValueToANGLEVariable(const GLenum shaderType)400 ANGLE_NO_DISCARD 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 
assignANGLEValueToOriginalVariable(const GLenum shaderType,const bool isRedeclared,const TIntermTyped * enableFlags,const ClipCullDistanceIdxSet * constIndices)427 ANGLE_NO_DISCARD 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.
ReplaceClipCullDistanceAssignmentsImpl(TCompiler * compiler,TIntermBlock * root,TSymbolTable * symbolTable,const GLenum shaderType,const TIntermTyped * clipDistanceEnableFlags,const char * builtInName,const char * replacementName,TQualifier builtInQualifier)469 ANGLE_NO_DISCARD 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 
ReplaceClipDistanceAssignments(TCompiler * compiler,TIntermBlock * root,TSymbolTable * symbolTable,const GLenum shaderType,const TIntermTyped * clipDistanceEnableFlags)570 ANGLE_NO_DISCARD 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 
ReplaceCullDistanceAssignments(TCompiler * compiler,TIntermBlock * root,TSymbolTable * symbolTable,const GLenum shaderType)581 ANGLE_NO_DISCARD 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
592