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