• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2002 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 
7 #include "compiler/translator/Compiler.h"
8 
9 #include <sstream>
10 
11 #include "angle_gl.h"
12 #include "common/utilities.h"
13 #include "compiler/translator/CallDAG.h"
14 #include "compiler/translator/CollectVariables.h"
15 #include "compiler/translator/Initialize.h"
16 #include "compiler/translator/IsASTDepthBelowLimit.h"
17 #include "compiler/translator/OutputTree.h"
18 #include "compiler/translator/ParseContext.h"
19 #include "compiler/translator/ValidateBarrierFunctionCall.h"
20 #include "compiler/translator/ValidateClipCullDistance.h"
21 #include "compiler/translator/ValidateLimitations.h"
22 #include "compiler/translator/ValidateMaxParameters.h"
23 #include "compiler/translator/ValidateOutputs.h"
24 #include "compiler/translator/ValidateTypeSizeLimitations.h"
25 #include "compiler/translator/ValidateVaryingLocations.h"
26 #include "compiler/translator/VariablePacker.h"
27 #include "compiler/translator/tree_ops/ClampIndirectIndices.h"
28 #include "compiler/translator/tree_ops/ClampPointSize.h"
29 #include "compiler/translator/tree_ops/DeclareAndInitBuiltinsForInstancedMultiview.h"
30 #include "compiler/translator/tree_ops/DeferGlobalInitializers.h"
31 #include "compiler/translator/tree_ops/EmulateGLFragColorBroadcast.h"
32 #include "compiler/translator/tree_ops/EmulateMultiDrawShaderBuiltins.h"
33 #include "compiler/translator/tree_ops/FoldExpressions.h"
34 #include "compiler/translator/tree_ops/ForcePrecisionQualifier.h"
35 #include "compiler/translator/tree_ops/InitializeVariables.h"
36 #include "compiler/translator/tree_ops/PruneEmptyCases.h"
37 #include "compiler/translator/tree_ops/PruneNoOps.h"
38 #include "compiler/translator/tree_ops/RemoveArrayLengthMethod.h"
39 #include "compiler/translator/tree_ops/RemoveDynamicIndexing.h"
40 #include "compiler/translator/tree_ops/RemoveInvariantDeclaration.h"
41 #include "compiler/translator/tree_ops/RemoveUnreferencedVariables.h"
42 #include "compiler/translator/tree_ops/ScalarizeVecAndMatConstructorArgs.h"
43 #include "compiler/translator/tree_ops/SeparateDeclarations.h"
44 #include "compiler/translator/tree_ops/SimplifyLoopConditions.h"
45 #include "compiler/translator/tree_ops/SplitSequenceOperator.h"
46 #include "compiler/translator/tree_ops/apple/AddAndTrueToLoopCondition.h"
47 #include "compiler/translator/tree_ops/apple/RewriteDoWhile.h"
48 #include "compiler/translator/tree_ops/apple/UnfoldShortCircuitAST.h"
49 #include "compiler/translator/tree_ops/gl/ClampFragDepth.h"
50 #include "compiler/translator/tree_ops/gl/RegenerateStructNames.h"
51 #include "compiler/translator/tree_ops/gl/RewriteRepeatedAssignToSwizzled.h"
52 #include "compiler/translator/tree_ops/gl/UseInterfaceBlockFields.h"
53 #include "compiler/translator/tree_ops/vulkan/EarlyFragmentTestsOptimization.h"
54 #include "compiler/translator/tree_util/BuiltIn.h"
55 #include "compiler/translator/tree_util/IntermNodePatternMatcher.h"
56 #include "compiler/translator/tree_util/ReplaceShadowingVariables.h"
57 #include "compiler/translator/util.h"
58 
59 namespace sh
60 {
61 
62 namespace
63 {
64 // Helper that returns if a top-level node is unused.  If it's a function, the function prototype is
65 // returned as well.
IsTopLevelNodeUnusedFunction(const CallDAG & callDag,const std::vector<TFunctionMetadata> & metadata,TIntermNode * node,const TFunction ** functionOut)66 bool IsTopLevelNodeUnusedFunction(const CallDAG &callDag,
67                                   const std::vector<TFunctionMetadata> &metadata,
68                                   TIntermNode *node,
69                                   const TFunction **functionOut)
70 {
71     const TIntermFunctionPrototype *asFunctionPrototype   = node->getAsFunctionPrototypeNode();
72     const TIntermFunctionDefinition *asFunctionDefinition = node->getAsFunctionDefinition();
73 
74     *functionOut = nullptr;
75 
76     if (asFunctionDefinition)
77     {
78         *functionOut = asFunctionDefinition->getFunction();
79     }
80     else if (asFunctionPrototype)
81     {
82         *functionOut = asFunctionPrototype->getFunction();
83     }
84     if (*functionOut == nullptr)
85     {
86         return false;
87     }
88 
89     size_t callDagIndex = callDag.findIndex((*functionOut)->uniqueId());
90     if (callDagIndex == CallDAG::InvalidIndex)
91     {
92         // This happens only for unimplemented prototypes which are thus unused
93         ASSERT(asFunctionPrototype);
94         return true;
95     }
96 
97     ASSERT(callDagIndex < metadata.size());
98     return !metadata[callDagIndex].used;
99 }
100 
101 #if defined(ANGLE_ENABLE_FUZZER_CORPUS_OUTPUT)
DumpFuzzerCase(char const * const * shaderStrings,size_t numStrings,uint32_t type,uint32_t spec,uint32_t output,uint64_t options)102 void DumpFuzzerCase(char const *const *shaderStrings,
103                     size_t numStrings,
104                     uint32_t type,
105                     uint32_t spec,
106                     uint32_t output,
107                     uint64_t options)
108 {
109     static int fileIndex = 0;
110 
111     std::ostringstream o = sh::InitializeStream<std::ostringstream>();
112     o << "corpus/" << fileIndex++ << ".sample";
113     std::string s = o.str();
114 
115     // Must match the input format of the fuzzer
116     FILE *f = fopen(s.c_str(), "w");
117     fwrite(&type, sizeof(type), 1, f);
118     fwrite(&spec, sizeof(spec), 1, f);
119     fwrite(&output, sizeof(output), 1, f);
120     fwrite(&options, sizeof(options), 1, f);
121 
122     char zero[128 - 20] = {0};
123     fwrite(&zero, 128 - 20, 1, f);
124 
125     for (size_t i = 0; i < numStrings; i++)
126     {
127         fwrite(shaderStrings[i], sizeof(char), strlen(shaderStrings[i]), f);
128     }
129     fwrite(&zero, 1, 1, f);
130 
131     fclose(f);
132 }
133 #endif  // defined(ANGLE_ENABLE_FUZZER_CORPUS_OUTPUT)
134 }  // anonymous namespace
135 
IsGLSL130OrNewer(ShShaderOutput output)136 bool IsGLSL130OrNewer(ShShaderOutput output)
137 {
138     return (output == SH_GLSL_130_OUTPUT || output == SH_GLSL_140_OUTPUT ||
139             output == SH_GLSL_150_CORE_OUTPUT || output == SH_GLSL_330_CORE_OUTPUT ||
140             output == SH_GLSL_400_CORE_OUTPUT || output == SH_GLSL_410_CORE_OUTPUT ||
141             output == SH_GLSL_420_CORE_OUTPUT || output == SH_GLSL_430_CORE_OUTPUT ||
142             output == SH_GLSL_440_CORE_OUTPUT || output == SH_GLSL_450_CORE_OUTPUT);
143 }
144 
IsGLSL420OrNewer(ShShaderOutput output)145 bool IsGLSL420OrNewer(ShShaderOutput output)
146 {
147     return (output == SH_GLSL_420_CORE_OUTPUT || output == SH_GLSL_430_CORE_OUTPUT ||
148             output == SH_GLSL_440_CORE_OUTPUT || output == SH_GLSL_450_CORE_OUTPUT);
149 }
150 
IsGLSL410OrOlder(ShShaderOutput output)151 bool IsGLSL410OrOlder(ShShaderOutput output)
152 {
153     return (output == SH_GLSL_130_OUTPUT || output == SH_GLSL_140_OUTPUT ||
154             output == SH_GLSL_150_CORE_OUTPUT || output == SH_GLSL_330_CORE_OUTPUT ||
155             output == SH_GLSL_400_CORE_OUTPUT || output == SH_GLSL_410_CORE_OUTPUT);
156 }
157 
RemoveInvariant(sh::GLenum shaderType,int shaderVersion,ShShaderOutput outputType,ShCompileOptions compileOptions)158 bool RemoveInvariant(sh::GLenum shaderType,
159                      int shaderVersion,
160                      ShShaderOutput outputType,
161                      ShCompileOptions compileOptions)
162 {
163     if (shaderType == GL_FRAGMENT_SHADER && IsGLSL420OrNewer(outputType))
164         return true;
165 
166     if ((compileOptions & SH_REMOVE_INVARIANT_AND_CENTROID_FOR_ESSL3) != 0 &&
167         shaderVersion >= 300 && shaderType == GL_VERTEX_SHADER)
168         return true;
169 
170     return false;
171 }
172 
GetGlobalMaxTokenSize(ShShaderSpec spec)173 size_t GetGlobalMaxTokenSize(ShShaderSpec spec)
174 {
175     // WebGL defines a max token length of 256, while ES2 leaves max token
176     // size undefined. ES3 defines a max size of 1024 characters.
177     switch (spec)
178     {
179         case SH_WEBGL_SPEC:
180             return 256;
181         default:
182             return 1024;
183     }
184 }
185 
GetMaxUniformVectorsForShaderType(GLenum shaderType,const ShBuiltInResources & resources)186 int GetMaxUniformVectorsForShaderType(GLenum shaderType, const ShBuiltInResources &resources)
187 {
188     switch (shaderType)
189     {
190         case GL_VERTEX_SHADER:
191             return resources.MaxVertexUniformVectors;
192         case GL_FRAGMENT_SHADER:
193             return resources.MaxFragmentUniformVectors;
194 
195         // TODO (jiawei.shao@intel.com): check if we need finer-grained component counting
196         case GL_COMPUTE_SHADER:
197             return resources.MaxComputeUniformComponents / 4;
198         case GL_GEOMETRY_SHADER_EXT:
199             return resources.MaxGeometryUniformComponents / 4;
200         default:
201             UNREACHABLE();
202             return -1;
203     }
204 }
205 
206 namespace
207 {
208 
209 class ANGLE_NO_DISCARD TScopedPoolAllocator
210 {
211   public:
TScopedPoolAllocator(angle::PoolAllocator * allocator)212     TScopedPoolAllocator(angle::PoolAllocator *allocator) : mAllocator(allocator)
213     {
214         mAllocator->push();
215         SetGlobalPoolAllocator(mAllocator);
216     }
~TScopedPoolAllocator()217     ~TScopedPoolAllocator()
218     {
219         SetGlobalPoolAllocator(nullptr);
220         mAllocator->pop();
221     }
222 
223   private:
224     angle::PoolAllocator *mAllocator;
225 };
226 
227 class ANGLE_NO_DISCARD TScopedSymbolTableLevel
228 {
229   public:
TScopedSymbolTableLevel(TSymbolTable * table)230     TScopedSymbolTableLevel(TSymbolTable *table) : mTable(table)
231     {
232         ASSERT(mTable->isEmpty());
233         mTable->push();
234     }
~TScopedSymbolTableLevel()235     ~TScopedSymbolTableLevel()
236     {
237         while (!mTable->isEmpty())
238             mTable->pop();
239     }
240 
241   private:
242     TSymbolTable *mTable;
243 };
244 
GetMaxShaderVersionForSpec(ShShaderSpec spec)245 int GetMaxShaderVersionForSpec(ShShaderSpec spec)
246 {
247     switch (spec)
248     {
249         case SH_GLES2_SPEC:
250         case SH_WEBGL_SPEC:
251             return 100;
252         case SH_GLES3_SPEC:
253         case SH_WEBGL2_SPEC:
254             return 300;
255         case SH_GLES3_1_SPEC:
256         case SH_WEBGL3_SPEC:
257             return 310;
258         case SH_GLES3_2_SPEC:
259             return 320;
260         case SH_GL_CORE_SPEC:
261         case SH_GL_COMPATIBILITY_SPEC:
262             return 460;
263         default:
264             UNREACHABLE();
265             return 0;
266     }
267 }
268 
ValidateFragColorAndFragData(GLenum shaderType,int shaderVersion,const TSymbolTable & symbolTable,TDiagnostics * diagnostics)269 bool ValidateFragColorAndFragData(GLenum shaderType,
270                                   int shaderVersion,
271                                   const TSymbolTable &symbolTable,
272                                   TDiagnostics *diagnostics)
273 {
274     if (shaderVersion > 100 || shaderType != GL_FRAGMENT_SHADER)
275     {
276         return true;
277     }
278 
279     bool usesFragColor = false;
280     bool usesFragData  = false;
281     // This validation is a bit stricter than the spec - it's only an error to write to
282     // both FragData and FragColor. But because it's better not to have reads from undefined
283     // variables, we always return an error if they are both referenced, rather than only if they
284     // are written.
285     if (symbolTable.isStaticallyUsed(*BuiltInVariable::gl_FragColor()) ||
286         symbolTable.isStaticallyUsed(*BuiltInVariable::gl_SecondaryFragColorEXT()))
287     {
288         usesFragColor = true;
289     }
290     // Extension variables may not always be initialized (saves some time at symbol table init).
291     bool secondaryFragDataUsed =
292         symbolTable.gl_SecondaryFragDataEXT() != nullptr &&
293         symbolTable.isStaticallyUsed(*symbolTable.gl_SecondaryFragDataEXT());
294     if (symbolTable.isStaticallyUsed(*symbolTable.gl_FragData()) || secondaryFragDataUsed)
295     {
296         usesFragData = true;
297     }
298     if (usesFragColor && usesFragData)
299     {
300         const char *errorMessage = "cannot use both gl_FragData and gl_FragColor";
301         if (symbolTable.isStaticallyUsed(*BuiltInVariable::gl_SecondaryFragColorEXT()) ||
302             secondaryFragDataUsed)
303         {
304             errorMessage =
305                 "cannot use both output variable sets (gl_FragData, gl_SecondaryFragDataEXT)"
306                 " and (gl_FragColor, gl_SecondaryFragColorEXT)";
307         }
308         diagnostics->globalError(errorMessage);
309         return false;
310     }
311     return true;
312 }
313 
314 }  // namespace
315 
TShHandleBase()316 TShHandleBase::TShHandleBase()
317 {
318     allocator.push();
319     SetGlobalPoolAllocator(&allocator);
320 }
321 
~TShHandleBase()322 TShHandleBase::~TShHandleBase()
323 {
324     SetGlobalPoolAllocator(nullptr);
325     allocator.popAll();
326 }
327 
TCompiler(sh::GLenum type,ShShaderSpec spec,ShShaderOutput output)328 TCompiler::TCompiler(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output)
329     : mVariablesCollected(false),
330       mGLPositionInitialized(false),
331       mShaderType(type),
332       mShaderSpec(spec),
333       mOutputType(output),
334       mBuiltInFunctionEmulator(),
335       mDiagnostics(mInfoSink.info),
336       mSourcePath(nullptr),
337       mComputeShaderLocalSizeDeclared(false),
338       mComputeShaderLocalSize(1),
339       mGeometryShaderMaxVertices(-1),
340       mGeometryShaderInvocations(0),
341       mGeometryShaderInputPrimitiveType(EptUndefined),
342       mGeometryShaderOutputPrimitiveType(EptUndefined),
343       mTessControlShaderOutputVertices(0),
344       mTessEvaluationShaderInputPrimitiveType(EtetUndefined),
345       mTessEvaluationShaderInputVertexSpacingType(EtetUndefined),
346       mTessEvaluationShaderInputOrderingType(EtetUndefined),
347       mTessEvaluationShaderInputPointType(EtetUndefined),
348       mHasAnyPreciseType(false),
349       mAdvancedBlendEquations(0),
350       mCompileOptions(0)
351 {}
352 
~TCompiler()353 TCompiler::~TCompiler() {}
354 
isHighPrecisionSupported() const355 bool TCompiler::isHighPrecisionSupported() const
356 {
357     return mShaderVersion > 100 || mShaderType != GL_FRAGMENT_SHADER ||
358            mResources.FragmentPrecisionHigh == 1;
359 }
360 
shouldRunLoopAndIndexingValidation(ShCompileOptions compileOptions) const361 bool TCompiler::shouldRunLoopAndIndexingValidation(ShCompileOptions compileOptions) const
362 {
363     // If compiling an ESSL 1.00 shader for WebGL, or if its been requested through the API,
364     // validate loop and indexing as well (to verify that the shader only uses minimal functionality
365     // of ESSL 1.00 as in Appendix A of the spec).
366     return (IsWebGLBasedSpec(mShaderSpec) && mShaderVersion == 100) ||
367            (compileOptions & SH_VALIDATE_LOOP_INDEXING) != 0;
368 }
369 
shouldLimitTypeSizes() const370 bool TCompiler::shouldLimitTypeSizes() const
371 {
372     // WebGL shaders limit the size of variables' types in shaders,
373     // including arrays, structs and interface blocks.
374     return IsWebGLBasedSpec(mShaderSpec);
375 }
376 
Init(const ShBuiltInResources & resources)377 bool TCompiler::Init(const ShBuiltInResources &resources)
378 {
379     SetGlobalPoolAllocator(&allocator);
380 
381     // Generate built-in symbol table.
382     if (!initBuiltInSymbolTable(resources))
383         return false;
384 
385     mResources = resources;
386     setResourceString();
387 
388     InitExtensionBehavior(resources, mExtensionBehavior);
389     return true;
390 }
391 
compileTreeForTesting(const char * const shaderStrings[],size_t numStrings,ShCompileOptions compileOptions)392 TIntermBlock *TCompiler::compileTreeForTesting(const char *const shaderStrings[],
393                                                size_t numStrings,
394                                                ShCompileOptions compileOptions)
395 {
396     return compileTreeImpl(shaderStrings, numStrings, compileOptions);
397 }
398 
compileTreeImpl(const char * const shaderStrings[],size_t numStrings,const ShCompileOptions compileOptions)399 TIntermBlock *TCompiler::compileTreeImpl(const char *const shaderStrings[],
400                                          size_t numStrings,
401                                          const ShCompileOptions compileOptions)
402 {
403     // Remember the compile options for helper functions such as validateAST.
404     mCompileOptions = compileOptions;
405 
406     clearResults();
407 
408     ASSERT(numStrings > 0);
409     ASSERT(GetGlobalPoolAllocator());
410 
411     // Reset the extension behavior for each compilation unit.
412     ResetExtensionBehavior(mResources, mExtensionBehavior, compileOptions);
413 
414     // If gl_DrawID is not supported, remove it from the available extensions
415     // Currently we only allow emulation of gl_DrawID
416     const bool glDrawIDSupported = (compileOptions & SH_EMULATE_GL_DRAW_ID) != 0;
417     if (!glDrawIDSupported)
418     {
419         auto it = mExtensionBehavior.find(TExtension::ANGLE_multi_draw);
420         if (it != mExtensionBehavior.end())
421         {
422             mExtensionBehavior.erase(it);
423         }
424     }
425 
426     const bool glBaseVertexBaseInstanceSupported =
427         (compileOptions & SH_EMULATE_GL_BASE_VERTEX_BASE_INSTANCE) != 0;
428     if (!glBaseVertexBaseInstanceSupported)
429     {
430         auto it =
431             mExtensionBehavior.find(TExtension::ANGLE_base_vertex_base_instance_shader_builtin);
432         if (it != mExtensionBehavior.end())
433         {
434             mExtensionBehavior.erase(it);
435         }
436     }
437 
438     // First string is path of source file if flag is set. The actual source follows.
439     size_t firstSource = 0;
440     if ((compileOptions & SH_SOURCE_PATH) != 0)
441     {
442         mSourcePath = shaderStrings[0];
443         ++firstSource;
444     }
445 
446     TParseContext parseContext(mSymbolTable, mExtensionBehavior, mShaderType, mShaderSpec,
447                                compileOptions, !IsDesktopGLSpec(mShaderSpec), &mDiagnostics,
448                                getResources(), getOutputType());
449 
450     parseContext.setFragmentPrecisionHighOnESSL1(mResources.FragmentPrecisionHigh == 1);
451 
452     // We preserve symbols at the built-in level from compile-to-compile.
453     // Start pushing the user-defined symbols at global level.
454     TScopedSymbolTableLevel globalLevel(&mSymbolTable);
455     ASSERT(mSymbolTable.atGlobalLevel());
456 
457     // Parse shader.
458     if (PaParseStrings(numStrings - firstSource, &shaderStrings[firstSource], nullptr,
459                        &parseContext) != 0)
460     {
461         return nullptr;
462     }
463 
464     if (!postParseChecks(parseContext))
465     {
466         return nullptr;
467     }
468 
469     setASTMetadata(parseContext);
470 
471     if (!checkShaderVersion(&parseContext))
472     {
473         return nullptr;
474     }
475 
476     TIntermBlock *root = parseContext.getTreeRoot();
477     if (!checkAndSimplifyAST(root, parseContext, compileOptions))
478     {
479         return nullptr;
480     }
481 
482     return root;
483 }
484 
checkShaderVersion(TParseContext * parseContext)485 bool TCompiler::checkShaderVersion(TParseContext *parseContext)
486 {
487     if (GetMaxShaderVersionForSpec(mShaderSpec) < mShaderVersion)
488     {
489         mDiagnostics.globalError("unsupported shader version");
490         return false;
491     }
492 
493     ASSERT(parseContext);
494     switch (mShaderType)
495     {
496         case GL_COMPUTE_SHADER:
497             if (mShaderVersion < 310)
498             {
499                 mDiagnostics.globalError("Compute shader is not supported in this shader version.");
500                 return false;
501             }
502             break;
503 
504         case GL_GEOMETRY_SHADER_EXT:
505             if (mShaderVersion < 310)
506             {
507                 mDiagnostics.globalError(
508                     "Geometry shader is not supported in this shader version.");
509                 return false;
510             }
511             else if (mShaderVersion == 310)
512             {
513                 if (!parseContext->checkCanUseOneOfExtensions(
514                         sh::TSourceLoc(),
515                         std::array<TExtension, 2u>{
516                             {TExtension::EXT_geometry_shader, TExtension::OES_geometry_shader}}))
517                 {
518                     return false;
519                 }
520             }
521             break;
522 
523         case GL_TESS_CONTROL_SHADER_EXT:
524         case GL_TESS_EVALUATION_SHADER_EXT:
525             if (mShaderVersion < 310)
526             {
527                 mDiagnostics.globalError(
528                     "Tessellation shaders are not supported in this shader version.");
529                 return false;
530             }
531             else if (mShaderVersion == 310)
532             {
533                 if (!parseContext->checkCanUseExtension(sh::TSourceLoc(),
534                                                         TExtension::EXT_tessellation_shader))
535                 {
536                     return false;
537                 }
538             }
539             break;
540 
541         default:
542             break;
543     }
544 
545     return true;
546 }
547 
setASTMetadata(const TParseContext & parseContext)548 void TCompiler::setASTMetadata(const TParseContext &parseContext)
549 {
550     mShaderVersion = parseContext.getShaderVersion();
551 
552     mPragma = parseContext.pragma();
553     mSymbolTable.setGlobalInvariant(mPragma.stdgl.invariantAll);
554 
555     mEarlyFragmentTestsSpecified = parseContext.isEarlyFragmentTestsSpecified();
556 
557     mComputeShaderLocalSizeDeclared = parseContext.isComputeShaderLocalSizeDeclared();
558     mComputeShaderLocalSize         = parseContext.getComputeShaderLocalSize();
559 
560     mNumViews = parseContext.getNumViews();
561 
562     mHasAnyPreciseType = parseContext.hasAnyPreciseType();
563 
564     if (mShaderType == GL_FRAGMENT_SHADER)
565     {
566         mAdvancedBlendEquations = parseContext.getAdvancedBlendEquations();
567     }
568     if (mShaderType == GL_GEOMETRY_SHADER_EXT)
569     {
570         mGeometryShaderInputPrimitiveType  = parseContext.getGeometryShaderInputPrimitiveType();
571         mGeometryShaderOutputPrimitiveType = parseContext.getGeometryShaderOutputPrimitiveType();
572         mGeometryShaderMaxVertices         = parseContext.getGeometryShaderMaxVertices();
573         mGeometryShaderInvocations         = parseContext.getGeometryShaderInvocations();
574     }
575     if (mShaderType == GL_TESS_CONTROL_SHADER_EXT)
576     {
577         mTessControlShaderOutputVertices = parseContext.getTessControlShaderOutputVertices();
578     }
579     if (mShaderType == GL_TESS_EVALUATION_SHADER_EXT)
580     {
581         mTessEvaluationShaderInputPrimitiveType =
582             parseContext.getTessEvaluationShaderInputPrimitiveType();
583         mTessEvaluationShaderInputVertexSpacingType =
584             parseContext.getTessEvaluationShaderInputVertexSpacingType();
585         mTessEvaluationShaderInputOrderingType =
586             parseContext.getTessEvaluationShaderInputOrderingType();
587         mTessEvaluationShaderInputPointType = parseContext.getTessEvaluationShaderInputPointType();
588     }
589 }
590 
getSharedMemorySize() const591 unsigned int TCompiler::getSharedMemorySize() const
592 {
593     unsigned int sharedMemSize = 0;
594     for (const sh::ShaderVariable &var : mSharedVariables)
595     {
596         sharedMemSize += var.getExternalSize();
597     }
598 
599     return sharedMemSize;
600 }
601 
validateAST(TIntermNode * root)602 bool TCompiler::validateAST(TIntermNode *root)
603 {
604     if ((mCompileOptions & SH_VALIDATE_AST) != 0)
605     {
606         bool valid = ValidateAST(root, &mDiagnostics, mValidateASTOptions);
607 
608 #if defined(ANGLE_ENABLE_ASSERTS)
609         if (!valid)
610         {
611             OutputTree(root, mInfoSink.info);
612             fprintf(stderr, "AST validation error(s):\n%s\n", mInfoSink.info.c_str());
613         }
614 #endif
615         // In debug, assert validation.  In release, validation errors will be returned back to the
616         // application as internal ANGLE errors.
617         ASSERT(valid);
618 
619         return valid;
620     }
621     return true;
622 }
623 
disableValidateFunctionCall()624 bool TCompiler::disableValidateFunctionCall()
625 {
626     bool wasEnabled                          = mValidateASTOptions.validateFunctionCall;
627     mValidateASTOptions.validateFunctionCall = false;
628     return wasEnabled;
629 }
630 
restoreValidateFunctionCall(bool enable)631 void TCompiler::restoreValidateFunctionCall(bool enable)
632 {
633     ASSERT(!mValidateASTOptions.validateFunctionCall);
634     mValidateASTOptions.validateFunctionCall = enable;
635 }
636 
disableValidateVariableReferences()637 bool TCompiler::disableValidateVariableReferences()
638 {
639     bool wasEnabled                                = mValidateASTOptions.validateVariableReferences;
640     mValidateASTOptions.validateVariableReferences = false;
641     return wasEnabled;
642 }
643 
restoreValidateVariableReferences(bool enable)644 void TCompiler::restoreValidateVariableReferences(bool enable)
645 {
646     ASSERT(!mValidateASTOptions.validateVariableReferences);
647     mValidateASTOptions.validateVariableReferences = enable;
648 }
649 
enableValidateNoMoreTransformations()650 void TCompiler::enableValidateNoMoreTransformations()
651 {
652     mValidateASTOptions.validateNoMoreTransformations = true;
653 }
654 
checkAndSimplifyAST(TIntermBlock * root,const TParseContext & parseContext,ShCompileOptions compileOptions)655 bool TCompiler::checkAndSimplifyAST(TIntermBlock *root,
656                                     const TParseContext &parseContext,
657                                     ShCompileOptions compileOptions)
658 {
659     mValidateASTOptions = {};
660 
661     // Desktop GLSL shaders don't have precision, so don't expect them to be specified.
662     mValidateASTOptions.validatePrecision = !IsDesktopGLSpec(mShaderSpec);
663 
664     if (!validateAST(root))
665     {
666         return false;
667     }
668 
669     // Disallow expressions deemed too complex.
670     if ((compileOptions & SH_LIMIT_EXPRESSION_COMPLEXITY) != 0 && !limitExpressionComplexity(root))
671     {
672         return false;
673     }
674 
675     if (shouldRunLoopAndIndexingValidation(compileOptions) &&
676         !ValidateLimitations(root, mShaderType, &mSymbolTable, &mDiagnostics))
677     {
678         return false;
679     }
680 
681     if (shouldLimitTypeSizes() && !ValidateTypeSizeLimitations(root, &mSymbolTable, &mDiagnostics))
682     {
683         return false;
684     }
685 
686     if (!ValidateFragColorAndFragData(mShaderType, mShaderVersion, mSymbolTable, &mDiagnostics))
687     {
688         return false;
689     }
690 
691     // Fold expressions that could not be folded before validation that was done as a part of
692     // parsing.
693     if (!FoldExpressions(this, root, &mDiagnostics))
694     {
695         return false;
696     }
697     // Folding should only be able to generate warnings.
698     ASSERT(mDiagnostics.numErrors() == 0);
699 
700     // Validate no barrier() after return before prunning it in |PruneNoOps()| below.
701     if (mShaderType == GL_TESS_CONTROL_SHADER && !ValidateBarrierFunctionCall(root, &mDiagnostics))
702     {
703         return false;
704     }
705 
706     // We prune no-ops to work around driver bugs and to keep AST processing and output simple.
707     // The following kinds of no-ops are pruned:
708     //   1. Empty declarations "int;".
709     //   2. Literal statements: "1.0;". The ESSL output doesn't define a default precision
710     //      for float, so float literal statements would end up with no precision which is
711     //      invalid ESSL.
712     //   3. Any unreachable statement after a discard, return, break or continue.
713     // After this empty declarations are not allowed in the AST.
714     if (!PruneNoOps(this, root, &mSymbolTable))
715     {
716         return false;
717     }
718     mValidateASTOptions.validateNoStatementsAfterBranch = true;
719 
720     // We need to generate globals early if we have non constant initializers enabled
721     bool initializeLocalsAndGlobals = (compileOptions & SH_INITIALIZE_UNINITIALIZED_LOCALS) != 0 &&
722                                       !IsOutputHLSL(getOutputType());
723     bool canUseLoopsToInitialize =
724         (compileOptions & SH_DONT_USE_LOOPS_TO_INITIALIZE_VARIABLES) == 0;
725     bool highPrecisionSupported        = isHighPrecisionSupported();
726     bool enableNonConstantInitializers = IsExtensionEnabled(
727         mExtensionBehavior, TExtension::EXT_shader_non_constant_global_initializers);
728     // forceDeferGlobalInitializers is needed for MSL
729     // to convert a non-const global. For example:
730     //
731     //    int someGlobal = 123;
732     //
733     // to
734     //
735     //    int someGlobal;
736     //    void main() {
737     //        someGlobal = 123;
738     //
739     // This is because MSL doesn't allow statically initialized globals.
740     bool forceDeferGlobalInitializers = getOutputType() == SH_MSL_METAL_OUTPUT;
741 
742     if (enableNonConstantInitializers &&
743         !DeferGlobalInitializers(this, root, initializeLocalsAndGlobals, canUseLoopsToInitialize,
744                                  highPrecisionSupported, forceDeferGlobalInitializers,
745                                  &mSymbolTable))
746     {
747         return false;
748     }
749 
750     // Create the function DAG and check there is no recursion
751     if (!initCallDag(root))
752     {
753         return false;
754     }
755 
756     if ((compileOptions & SH_LIMIT_CALL_STACK_DEPTH) != 0 && !checkCallDepth())
757     {
758         return false;
759     }
760 
761     // Checks which functions are used and if "main" exists
762     mFunctionMetadata.clear();
763     mFunctionMetadata.resize(mCallDag.size());
764     if (!tagUsedFunctions())
765     {
766         return false;
767     }
768 
769     if (!pruneUnusedFunctions(root))
770     {
771         return false;
772     }
773 
774     if (IsSpecWithFunctionBodyNewScope(mShaderSpec, mShaderVersion))
775     {
776         if (!ReplaceShadowingVariables(this, root, &mSymbolTable))
777         {
778             return false;
779         }
780     }
781 
782     if (mShaderVersion >= 310 && !ValidateVaryingLocations(root, &mDiagnostics, mShaderType))
783     {
784         return false;
785     }
786 
787     if (mShaderVersion >= 300 && mShaderType == GL_FRAGMENT_SHADER &&
788         !ValidateOutputs(root, getExtensionBehavior(), mResources.MaxDrawBuffers, &mDiagnostics))
789     {
790         return false;
791     }
792 
793     if (parseContext.isExtensionEnabled(TExtension::EXT_clip_cull_distance))
794     {
795         if (!ValidateClipCullDistance(root, &mDiagnostics,
796                                       mResources.MaxCombinedClipAndCullDistances))
797         {
798             return false;
799         }
800     }
801 
802     // Clamping uniform array bounds needs to happen after validateLimitations pass.
803     if ((compileOptions & SH_CLAMP_INDIRECT_ARRAY_BOUNDS) != 0)
804     {
805         if (!ClampIndirectIndices(this, root, &mSymbolTable))
806         {
807             return false;
808         }
809     }
810 
811     if ((compileOptions & SH_INITIALIZE_BUILTINS_FOR_INSTANCED_MULTIVIEW) != 0 &&
812         (parseContext.isExtensionEnabled(TExtension::OVR_multiview2) ||
813          parseContext.isExtensionEnabled(TExtension::OVR_multiview)) &&
814         getShaderType() != GL_COMPUTE_SHADER)
815     {
816         if (!DeclareAndInitBuiltinsForInstancedMultiview(
817                 this, root, mNumViews, mShaderType, compileOptions, mOutputType, &mSymbolTable))
818         {
819             return false;
820         }
821     }
822 
823     // This pass might emit short circuits so keep it before the short circuit unfolding
824     if ((compileOptions & SH_REWRITE_DO_WHILE_LOOPS) != 0)
825     {
826         if (!RewriteDoWhile(this, root, &mSymbolTable))
827         {
828             return false;
829         }
830     }
831 
832     if ((compileOptions & SH_ADD_AND_TRUE_TO_LOOP_CONDITION) != 0)
833     {
834         if (!AddAndTrueToLoopCondition(this, root))
835         {
836             return false;
837         }
838     }
839 
840     if ((compileOptions & SH_UNFOLD_SHORT_CIRCUIT) != 0)
841     {
842         if (!UnfoldShortCircuitAST(this, root))
843         {
844             return false;
845         }
846     }
847 
848     if ((compileOptions & SH_REGENERATE_STRUCT_NAMES) != 0)
849     {
850         if (!RegenerateStructNames(this, root, &mSymbolTable))
851         {
852             return false;
853         }
854     }
855 
856     if (mShaderType == GL_VERTEX_SHADER &&
857         IsExtensionEnabled(mExtensionBehavior, TExtension::ANGLE_multi_draw))
858     {
859         if ((compileOptions & SH_EMULATE_GL_DRAW_ID) != 0)
860         {
861             if (!EmulateGLDrawID(this, root, &mSymbolTable, &mUniforms,
862                                  shouldCollectVariables(compileOptions)))
863             {
864                 return false;
865             }
866         }
867     }
868 
869     if (mShaderType == GL_VERTEX_SHADER &&
870         IsExtensionEnabled(mExtensionBehavior,
871                            TExtension::ANGLE_base_vertex_base_instance_shader_builtin))
872     {
873         if ((compileOptions & SH_EMULATE_GL_BASE_VERTEX_BASE_INSTANCE) != 0)
874         {
875             if (!EmulateGLBaseVertexBaseInstance(
876                     this, root, &mSymbolTable, &mUniforms, shouldCollectVariables(compileOptions),
877                     (compileOptions & SH_ADD_BASE_VERTEX_TO_VERTEX_ID) != 0))
878             {
879                 return false;
880             }
881         }
882     }
883 
884     if (mShaderType == GL_FRAGMENT_SHADER && mShaderVersion == 100 && mResources.EXT_draw_buffers &&
885         mResources.MaxDrawBuffers > 1 &&
886         IsExtensionEnabled(mExtensionBehavior, TExtension::EXT_draw_buffers))
887     {
888         if (!EmulateGLFragColorBroadcast(this, root, mResources.MaxDrawBuffers, &mOutputVariables,
889                                          &mSymbolTable, mShaderVersion))
890         {
891             return false;
892         }
893     }
894 
895     int simplifyScalarized = (compileOptions & SH_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS) != 0
896                                  ? IntermNodePatternMatcher::kScalarizedVecOrMatConstructor
897                                  : 0;
898 
899     // Split multi declarations and remove calls to array length().
900     // Note that SimplifyLoopConditions needs to be run before any other AST transformations
901     // that may need to generate new statements from loop conditions or loop expressions.
902     if (!SimplifyLoopConditions(this, root,
903                                 IntermNodePatternMatcher::kMultiDeclaration |
904                                     IntermNodePatternMatcher::kArrayLengthMethod |
905                                     simplifyScalarized,
906                                 &getSymbolTable()))
907     {
908         return false;
909     }
910 
911     // Note that separate declarations need to be run before other AST transformations that
912     // generate new statements from expressions.
913     if (!SeparateDeclarations(this, root, &getSymbolTable()))
914     {
915         return false;
916     }
917     mValidateASTOptions.validateMultiDeclarations = true;
918 
919     if (!SplitSequenceOperator(this, root,
920                                IntermNodePatternMatcher::kArrayLengthMethod | simplifyScalarized,
921                                &getSymbolTable()))
922     {
923         return false;
924     }
925 
926     if (!RemoveArrayLengthMethod(this, root))
927     {
928         return false;
929     }
930 
931     if (!RemoveUnreferencedVariables(this, root, &mSymbolTable))
932     {
933         return false;
934     }
935 
936     // In case the last case inside a switch statement is a certain type of no-op, GLSL compilers in
937     // drivers may not accept it. In this case we clean up the dead code from the end of switch
938     // statements. This is also required because PruneNoOps or RemoveUnreferencedVariables may have
939     // left switch statements that only contained an empty declaration inside the final case in an
940     // invalid state. Relies on that PruneNoOps and RemoveUnreferencedVariables have already been
941     // run.
942     if (!PruneEmptyCases(this, root))
943     {
944         return false;
945     }
946 
947     // Built-in function emulation needs to happen after validateLimitations pass.
948     GetGlobalPoolAllocator()->lock();
949     initBuiltInFunctionEmulator(&mBuiltInFunctionEmulator, compileOptions);
950     GetGlobalPoolAllocator()->unlock();
951     mBuiltInFunctionEmulator.markBuiltInFunctionsForEmulation(root);
952 
953     if ((compileOptions & SH_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS) != 0)
954     {
955         if (!ScalarizeVecAndMatConstructorArgs(this, root, &mSymbolTable))
956         {
957             return false;
958         }
959     }
960 
961     if ((compileOptions & SH_FORCE_SHADER_PRECISION_HIGHP_TO_MEDIUMP) != 0)
962     {
963         if (!ForceShaderPrecisionToMediump(root, &mSymbolTable, mShaderType))
964         {
965             return false;
966         }
967     }
968 
969     if (shouldCollectVariables(compileOptions))
970     {
971         ASSERT(!mVariablesCollected);
972         CollectVariables(root, &mAttributes, &mOutputVariables, &mUniforms, &mInputVaryings,
973                          &mOutputVaryings, &mSharedVariables, &mUniformBlocks,
974                          &mShaderStorageBlocks, mResources.HashFunction, &mSymbolTable, mShaderType,
975                          mExtensionBehavior, mResources, mTessControlShaderOutputVertices);
976         collectInterfaceBlocks();
977         mVariablesCollected = true;
978         if ((compileOptions & SH_USE_UNUSED_STANDARD_SHARED_BLOCKS) != 0)
979         {
980             if (!useAllMembersInUnusedStandardAndSharedBlocks(root))
981             {
982                 return false;
983             }
984         }
985         if ((compileOptions & SH_ENFORCE_PACKING_RESTRICTIONS) != 0)
986         {
987             int maxUniformVectors = GetMaxUniformVectorsForShaderType(mShaderType, mResources);
988             // Returns true if, after applying the packing rules in the GLSL ES 1.00.17 spec
989             // Appendix A, section 7, the shader does not use too many uniforms.
990             if (!CheckVariablesInPackingLimits(maxUniformVectors, mUniforms))
991             {
992                 mDiagnostics.globalError("too many uniforms");
993                 return false;
994             }
995         }
996         bool needInitializeOutputVariables =
997             (compileOptions & SH_INIT_OUTPUT_VARIABLES) != 0 && mShaderType != GL_COMPUTE_SHADER;
998         needInitializeOutputVariables |=
999             (compileOptions & SH_INIT_FRAGMENT_OUTPUT_VARIABLES) != 0 &&
1000             mShaderType == GL_FRAGMENT_SHADER;
1001         if (needInitializeOutputVariables)
1002         {
1003             if (!initializeOutputVariables(root))
1004             {
1005                 return false;
1006             }
1007         }
1008     }
1009 
1010     // Removing invariant declarations must be done after collecting variables.
1011     // Otherwise, built-in invariant declarations don't apply.
1012     if (RemoveInvariant(mShaderType, mShaderVersion, mOutputType, compileOptions))
1013     {
1014         if (!RemoveInvariantDeclaration(this, root))
1015         {
1016             return false;
1017         }
1018     }
1019 
1020     // gl_Position is always written in compatibility output mode.
1021     // It may have been already initialized among other output variables, in that case we don't
1022     // need to initialize it twice.
1023     if (mShaderType == GL_VERTEX_SHADER && !mGLPositionInitialized &&
1024         ((compileOptions & SH_INIT_GL_POSITION) != 0 ||
1025          mOutputType == SH_GLSL_COMPATIBILITY_OUTPUT))
1026     {
1027         if (!initializeGLPosition(root))
1028         {
1029             return false;
1030         }
1031         mGLPositionInitialized = true;
1032     }
1033 
1034     // DeferGlobalInitializers needs to be run before other AST transformations that generate new
1035     // statements from expressions. But it's fine to run DeferGlobalInitializers after the above
1036     // SplitSequenceOperator and RemoveArrayLengthMethod since they only have an effect on the AST
1037     // on ESSL >= 3.00, and the initializers that need to be deferred can only exist in ESSL < 3.00.
1038     // Exception: if EXT_shader_non_constant_global_initializers is enabled, we must generate global
1039     // initializers before we generate the DAG, since initializers may call functions which must not
1040     // be optimized out
1041     if (!enableNonConstantInitializers &&
1042         !DeferGlobalInitializers(this, root, initializeLocalsAndGlobals, canUseLoopsToInitialize,
1043                                  highPrecisionSupported, forceDeferGlobalInitializers,
1044                                  &mSymbolTable))
1045     {
1046         return false;
1047     }
1048 
1049     if (initializeLocalsAndGlobals)
1050     {
1051         // Initialize uninitialized local variables.
1052         // In some cases initializing can generate extra statements in the parent block, such as
1053         // when initializing nameless structs or initializing arrays in ESSL 1.00. In that case
1054         // we need to first simplify loop conditions. We've already separated declarations
1055         // earlier, which is also required. If we don't follow the Appendix A limitations, loop
1056         // init statements can declare arrays or nameless structs and have multiple
1057         // declarations.
1058 
1059         if (!shouldRunLoopAndIndexingValidation(compileOptions))
1060         {
1061             if (!SimplifyLoopConditions(this, root,
1062                                         IntermNodePatternMatcher::kArrayDeclaration |
1063                                             IntermNodePatternMatcher::kNamelessStructDeclaration,
1064                                         &getSymbolTable()))
1065             {
1066                 return false;
1067             }
1068         }
1069 
1070         if (!InitializeUninitializedLocals(this, root, getShaderVersion(), canUseLoopsToInitialize,
1071                                            highPrecisionSupported, &getSymbolTable()))
1072         {
1073             return false;
1074         }
1075     }
1076 
1077     if (getShaderType() == GL_VERTEX_SHADER && (compileOptions & SH_CLAMP_POINT_SIZE) != 0)
1078     {
1079         if (!ClampPointSize(this, root, mResources.MaxPointSize, &getSymbolTable()))
1080         {
1081             return false;
1082         }
1083     }
1084 
1085     if (getShaderType() == GL_FRAGMENT_SHADER && (compileOptions & SH_CLAMP_FRAG_DEPTH) != 0)
1086     {
1087         if (!ClampFragDepth(this, root, &getSymbolTable()))
1088         {
1089             return false;
1090         }
1091     }
1092 
1093     if ((compileOptions & SH_REWRITE_REPEATED_ASSIGN_TO_SWIZZLED) != 0)
1094     {
1095         if (!sh::RewriteRepeatedAssignToSwizzled(this, root))
1096         {
1097             return false;
1098         }
1099     }
1100 
1101     if ((compileOptions & SH_REMOVE_DYNAMIC_INDEXING_OF_SWIZZLED_VECTOR) != 0)
1102     {
1103         if (!sh::RemoveDynamicIndexingOfSwizzledVector(this, root, &getSymbolTable(), nullptr))
1104         {
1105             return false;
1106         }
1107     }
1108 
1109     mEarlyFragmentTestsOptimized = false;
1110     if ((compileOptions & SH_EARLY_FRAGMENT_TESTS_OPTIMIZATION) != 0)
1111     {
1112         if (mShaderVersion <= 300 && mShaderType == GL_FRAGMENT_SHADER &&
1113             !isEarlyFragmentTestsSpecified())
1114         {
1115             mEarlyFragmentTestsOptimized = CheckEarlyFragmentTestsFeasible(this, root);
1116         }
1117     }
1118 
1119     return true;
1120 }
1121 
postParseChecks(const TParseContext & parseContext)1122 bool TCompiler::postParseChecks(const TParseContext &parseContext)
1123 {
1124     std::stringstream errorMessage;
1125 
1126     if (parseContext.getTreeRoot() == nullptr)
1127     {
1128         errorMessage << "Shader parsing failed (mTreeRoot == nullptr)";
1129     }
1130 
1131     for (TType *type : parseContext.getDeferredArrayTypesToSize())
1132     {
1133         errorMessage << "Unsized global array type: " << type->getBasicString();
1134     }
1135 
1136     if (!errorMessage.str().empty())
1137     {
1138         mDiagnostics.globalError(errorMessage.str().c_str());
1139         return false;
1140     }
1141 
1142     return true;
1143 }
1144 
compile(const char * const shaderStrings[],size_t numStrings,ShCompileOptions compileOptionsIn)1145 bool TCompiler::compile(const char *const shaderStrings[],
1146                         size_t numStrings,
1147                         ShCompileOptions compileOptionsIn)
1148 {
1149 #if defined(ANGLE_ENABLE_FUZZER_CORPUS_OUTPUT)
1150     DumpFuzzerCase(shaderStrings, numStrings, mShaderType, mShaderSpec, mOutputType,
1151                    compileOptionsIn);
1152 #endif  // defined(ANGLE_ENABLE_FUZZER_CORPUS_OUTPUT)
1153 
1154     if (numStrings == 0)
1155         return true;
1156 
1157     ShCompileOptions compileOptions = compileOptionsIn;
1158 
1159     // Apply key workarounds.
1160     if (shouldFlattenPragmaStdglInvariantAll())
1161     {
1162         // This should be harmless to do in all cases, but for the moment, do it only conditionally.
1163         compileOptions |= SH_FLATTEN_PRAGMA_STDGL_INVARIANT_ALL;
1164     }
1165 
1166     TScopedPoolAllocator scopedAlloc(&allocator);
1167     TIntermBlock *root = compileTreeImpl(shaderStrings, numStrings, compileOptions);
1168 
1169     if (root)
1170     {
1171         if ((compileOptions & SH_INTERMEDIATE_TREE) != 0)
1172         {
1173             OutputTree(root, mInfoSink.info);
1174         }
1175 
1176         if ((compileOptions & SH_OBJECT_CODE) != 0)
1177         {
1178             PerformanceDiagnostics perfDiagnostics(&mDiagnostics);
1179             if (!translate(root, compileOptions, &perfDiagnostics))
1180             {
1181                 return false;
1182             }
1183         }
1184 
1185         if (mShaderType == GL_VERTEX_SHADER)
1186         {
1187             bool lookForDrawID =
1188                 IsExtensionEnabled(mExtensionBehavior, TExtension::ANGLE_multi_draw) &&
1189                 (compileOptions & SH_EMULATE_GL_DRAW_ID) != 0;
1190             bool lookForBaseVertexBaseInstance =
1191                 IsExtensionEnabled(mExtensionBehavior,
1192                                    TExtension::ANGLE_base_vertex_base_instance_shader_builtin) &&
1193                 (compileOptions & SH_EMULATE_GL_BASE_VERTEX_BASE_INSTANCE) != 0;
1194 
1195             if (lookForDrawID || lookForBaseVertexBaseInstance)
1196             {
1197                 for (auto &uniform : mUniforms)
1198                 {
1199                     if (lookForDrawID && uniform.name == "angle_DrawID" &&
1200                         uniform.mappedName == "angle_DrawID")
1201                     {
1202                         uniform.name = "gl_DrawID";
1203                     }
1204                     else if (lookForBaseVertexBaseInstance && uniform.name == "angle_BaseVertex" &&
1205                              uniform.mappedName == "angle_BaseVertex")
1206                     {
1207                         uniform.name = "gl_BaseVertex";
1208                     }
1209                     else if (lookForBaseVertexBaseInstance &&
1210                              uniform.name == "angle_BaseInstance" &&
1211                              uniform.mappedName == "angle_BaseInstance")
1212                     {
1213                         uniform.name = "gl_BaseInstance";
1214                     }
1215                 }
1216             }
1217         }
1218 
1219         // The IntermNode tree doesn't need to be deleted here, since the
1220         // memory will be freed in a big chunk by the PoolAllocator.
1221         return true;
1222     }
1223     return false;
1224 }
1225 
initBuiltInSymbolTable(const ShBuiltInResources & resources)1226 bool TCompiler::initBuiltInSymbolTable(const ShBuiltInResources &resources)
1227 {
1228     if (resources.MaxDrawBuffers < 1)
1229     {
1230         return false;
1231     }
1232     if (resources.EXT_blend_func_extended && resources.MaxDualSourceDrawBuffers < 1)
1233     {
1234         return false;
1235     }
1236 
1237     mSymbolTable.initializeBuiltIns(mShaderType, mShaderSpec, resources);
1238 
1239     return true;
1240 }
1241 
setResourceString()1242 void TCompiler::setResourceString()
1243 {
1244     std::ostringstream strstream = sh::InitializeStream<std::ostringstream>();
1245 
1246     // clang-format off
1247     strstream << ":MaxVertexAttribs:" << mResources.MaxVertexAttribs
1248         << ":MaxVertexUniformVectors:" << mResources.MaxVertexUniformVectors
1249         << ":MaxVaryingVectors:" << mResources.MaxVaryingVectors
1250         << ":MaxVertexTextureImageUnits:" << mResources.MaxVertexTextureImageUnits
1251         << ":MaxCombinedTextureImageUnits:" << mResources.MaxCombinedTextureImageUnits
1252         << ":MaxTextureImageUnits:" << mResources.MaxTextureImageUnits
1253         << ":MaxFragmentUniformVectors:" << mResources.MaxFragmentUniformVectors
1254         << ":MaxDrawBuffers:" << mResources.MaxDrawBuffers
1255         << ":OES_standard_derivatives:" << mResources.OES_standard_derivatives
1256         << ":OES_EGL_image_external:" << mResources.OES_EGL_image_external
1257         << ":OES_EGL_image_external_essl3:" << mResources.OES_EGL_image_external_essl3
1258         << ":NV_EGL_stream_consumer_external:" << mResources.NV_EGL_stream_consumer_external
1259         << ":ARB_texture_rectangle:" << mResources.ARB_texture_rectangle
1260         << ":EXT_draw_buffers:" << mResources.EXT_draw_buffers
1261         << ":FragmentPrecisionHigh:" << mResources.FragmentPrecisionHigh
1262         << ":MaxExpressionComplexity:" << mResources.MaxExpressionComplexity
1263         << ":MaxCallStackDepth:" << mResources.MaxCallStackDepth
1264         << ":MaxFunctionParameters:" << mResources.MaxFunctionParameters
1265         << ":EXT_blend_func_extended:" << mResources.EXT_blend_func_extended
1266         << ":EXT_frag_depth:" << mResources.EXT_frag_depth
1267         << ":EXT_primitive_bounding_box:" << mResources.EXT_primitive_bounding_box
1268         << ":OES_primitive_bounding_box:" << mResources.OES_primitive_bounding_box
1269         << ":EXT_shader_texture_lod:" << mResources.EXT_shader_texture_lod
1270         << ":EXT_shader_framebuffer_fetch:" << mResources.EXT_shader_framebuffer_fetch
1271         << ":EXT_shader_framebuffer_fetch_non_coherent:" << mResources.EXT_shader_framebuffer_fetch_non_coherent
1272         << ":NV_shader_framebuffer_fetch:" << mResources.NV_shader_framebuffer_fetch
1273         << ":ARM_shader_framebuffer_fetch:" << mResources.ARM_shader_framebuffer_fetch
1274         << ":OVR_multiview2:" << mResources.OVR_multiview2
1275         << ":OVR_multiview:" << mResources.OVR_multiview
1276         << ":EXT_YUV_target:" << mResources.EXT_YUV_target
1277         << ":EXT_geometry_shader:" << mResources.EXT_geometry_shader
1278         << ":OES_geometry_shader:" << mResources.OES_geometry_shader
1279         << ":OES_shader_io_blocks:" << mResources.OES_shader_io_blocks
1280         << ":EXT_shader_io_blocks:" << mResources.EXT_shader_io_blocks
1281         << ":EXT_gpu_shader5:" << mResources.EXT_gpu_shader5
1282         << ":OES_texture_3D:" << mResources.OES_texture_3D
1283         << ":MaxVertexOutputVectors:" << mResources.MaxVertexOutputVectors
1284         << ":MaxFragmentInputVectors:" << mResources.MaxFragmentInputVectors
1285         << ":MinProgramTexelOffset:" << mResources.MinProgramTexelOffset
1286         << ":MaxProgramTexelOffset:" << mResources.MaxProgramTexelOffset
1287         << ":MaxDualSourceDrawBuffers:" << mResources.MaxDualSourceDrawBuffers
1288         << ":MaxViewsOVR:" << mResources.MaxViewsOVR
1289         << ":NV_draw_buffers:" << mResources.NV_draw_buffers
1290         << ":ANGLE_multi_draw:" << mResources.ANGLE_multi_draw
1291         << ":ANGLE_base_vertex_base_instance_shader_builtin:" << mResources.ANGLE_base_vertex_base_instance_shader_builtin
1292         << ":APPLE_clip_distance:" << mResources.APPLE_clip_distance
1293         << ":OES_texture_cube_map_array:" << mResources.OES_texture_cube_map_array
1294         << ":EXT_texture_cube_map_array:" << mResources.EXT_texture_cube_map_array
1295         << ":EXT_shadow_samplers:" << mResources.EXT_shadow_samplers
1296         << ":OES_shader_multisample_interpolation:" << mResources.OES_shader_multisample_interpolation
1297         << ":OES_shader_image_atomic:" << mResources.OES_shader_image_atomic
1298         << ":EXT_tessellation_shader:" << mResources.EXT_tessellation_shader
1299         << ":OES_texture_buffer:" << mResources.OES_texture_buffer
1300         << ":EXT_texture_buffer:" << mResources.EXT_texture_buffer
1301         << ":OES_sample_variables:" << mResources.OES_sample_variables
1302         << ":EXT_clip_cull_distance:" << mResources.EXT_clip_cull_distance
1303         << ":MinProgramTextureGatherOffset:" << mResources.MinProgramTextureGatherOffset
1304         << ":MaxProgramTextureGatherOffset:" << mResources.MaxProgramTextureGatherOffset
1305         << ":MaxImageUnits:" << mResources.MaxImageUnits
1306         << ":MaxSamples:" << mResources.MaxSamples
1307         << ":MaxVertexImageUniforms:" << mResources.MaxVertexImageUniforms
1308         << ":MaxFragmentImageUniforms:" << mResources.MaxFragmentImageUniforms
1309         << ":MaxComputeImageUniforms:" << mResources.MaxComputeImageUniforms
1310         << ":MaxCombinedImageUniforms:" << mResources.MaxCombinedImageUniforms
1311         << ":MaxCombinedShaderOutputResources:" << mResources.MaxCombinedShaderOutputResources
1312         << ":MaxComputeWorkGroupCountX:" << mResources.MaxComputeWorkGroupCount[0]
1313         << ":MaxComputeWorkGroupCountY:" << mResources.MaxComputeWorkGroupCount[1]
1314         << ":MaxComputeWorkGroupCountZ:" << mResources.MaxComputeWorkGroupCount[2]
1315         << ":MaxComputeWorkGroupSizeX:" << mResources.MaxComputeWorkGroupSize[0]
1316         << ":MaxComputeWorkGroupSizeY:" << mResources.MaxComputeWorkGroupSize[1]
1317         << ":MaxComputeWorkGroupSizeZ:" << mResources.MaxComputeWorkGroupSize[2]
1318         << ":MaxComputeUniformComponents:" << mResources.MaxComputeUniformComponents
1319         << ":MaxComputeTextureImageUnits:" << mResources.MaxComputeTextureImageUnits
1320         << ":MaxComputeAtomicCounters:" << mResources.MaxComputeAtomicCounters
1321         << ":MaxComputeAtomicCounterBuffers:" << mResources.MaxComputeAtomicCounterBuffers
1322         << ":MaxVertexAtomicCounters:" << mResources.MaxVertexAtomicCounters
1323         << ":MaxFragmentAtomicCounters:" << mResources.MaxFragmentAtomicCounters
1324         << ":MaxCombinedAtomicCounters:" << mResources.MaxCombinedAtomicCounters
1325         << ":MaxAtomicCounterBindings:" << mResources.MaxAtomicCounterBindings
1326         << ":MaxVertexAtomicCounterBuffers:" << mResources.MaxVertexAtomicCounterBuffers
1327         << ":MaxFragmentAtomicCounterBuffers:" << mResources.MaxFragmentAtomicCounterBuffers
1328         << ":MaxCombinedAtomicCounterBuffers:" << mResources.MaxCombinedAtomicCounterBuffers
1329         << ":MaxAtomicCounterBufferSize:" << mResources.MaxAtomicCounterBufferSize
1330         << ":MaxGeometryUniformComponents:" << mResources.MaxGeometryUniformComponents
1331         << ":MaxGeometryUniformBlocks:" << mResources.MaxGeometryUniformBlocks
1332         << ":MaxGeometryInputComponents:" << mResources.MaxGeometryInputComponents
1333         << ":MaxGeometryOutputComponents:" << mResources.MaxGeometryOutputComponents
1334         << ":MaxGeometryOutputVertices:" << mResources.MaxGeometryOutputVertices
1335         << ":MaxGeometryTotalOutputComponents:" << mResources.MaxGeometryTotalOutputComponents
1336         << ":MaxGeometryTextureImageUnits:" << mResources.MaxGeometryTextureImageUnits
1337         << ":MaxGeometryAtomicCounterBuffers:" << mResources.MaxGeometryAtomicCounterBuffers
1338         << ":MaxGeometryAtomicCounters:" << mResources.MaxGeometryAtomicCounters
1339         << ":MaxGeometryShaderStorageBlocks:" << mResources.MaxGeometryShaderStorageBlocks
1340         << ":MaxGeometryShaderInvocations:" << mResources.MaxGeometryShaderInvocations
1341         << ":MaxGeometryImageUniforms:" << mResources.MaxGeometryImageUniforms
1342         << ":MaxClipDistances" << mResources.MaxClipDistances
1343         << ":MaxCullDistances" << mResources.MaxCullDistances
1344         << ":MaxCombinedClipAndCullDistances" << mResources.MaxCombinedClipAndCullDistances
1345         << ":MaxTessControlInputComponents:" << mResources.MaxTessControlInputComponents
1346         << ":MaxTessControlOutputComponents:" << mResources.MaxTessControlOutputComponents
1347         << ":MaxTessControlTextureImageUnits:" << mResources.MaxTessControlTextureImageUnits
1348         << ":MaxTessControlUniformComponents:" << mResources.MaxTessControlUniformComponents
1349         << ":MaxTessControlTotalOutputComponents:" << mResources.MaxTessControlTotalOutputComponents
1350         << ":MaxTessControlImageUniforms:" << mResources.MaxTessControlImageUniforms
1351         << ":MaxTessControlAtomicCounters:" << mResources.MaxTessControlAtomicCounters
1352         << ":MaxTessControlAtomicCounterBuffers:" << mResources.MaxTessControlAtomicCounterBuffers
1353         << ":MaxTessPatchComponents:" << mResources.MaxTessPatchComponents
1354         << ":MaxPatchVertices:" << mResources.MaxPatchVertices
1355         << ":MaxTessGenLevel:" << mResources.MaxTessGenLevel
1356         << ":MaxTessEvaluationInputComponents:" << mResources.MaxTessEvaluationInputComponents
1357         << ":MaxTessEvaluationOutputComponents:" << mResources.MaxTessEvaluationOutputComponents
1358         << ":MaxTessEvaluationTextureImageUnits:" << mResources.MaxTessEvaluationTextureImageUnits
1359         << ":MaxTessEvaluationUniformComponents:" << mResources.MaxTessEvaluationUniformComponents
1360         << ":MaxTessEvaluationImageUniforms:" << mResources.MaxTessEvaluationImageUniforms
1361         << ":MaxTessEvaluationAtomicCounters:" << mResources.MaxTessEvaluationAtomicCounters
1362         << ":MaxTessEvaluationAtomicCounterBuffers:" << mResources.MaxTessEvaluationAtomicCounterBuffers;
1363     // clang-format on
1364 
1365     mBuiltInResourcesString = strstream.str();
1366 }
1367 
collectInterfaceBlocks()1368 void TCompiler::collectInterfaceBlocks()
1369 {
1370     ASSERT(mInterfaceBlocks.empty());
1371     mInterfaceBlocks.reserve(mUniformBlocks.size() + mShaderStorageBlocks.size());
1372     mInterfaceBlocks.insert(mInterfaceBlocks.end(), mUniformBlocks.begin(), mUniformBlocks.end());
1373     mInterfaceBlocks.insert(mInterfaceBlocks.end(), mShaderStorageBlocks.begin(),
1374                             mShaderStorageBlocks.end());
1375 }
1376 
clearResults()1377 void TCompiler::clearResults()
1378 {
1379     mInfoSink.info.erase();
1380     mInfoSink.obj.erase();
1381     mInfoSink.debug.erase();
1382     mDiagnostics.resetErrorCount();
1383 
1384     mAttributes.clear();
1385     mOutputVariables.clear();
1386     mUniforms.clear();
1387     mInputVaryings.clear();
1388     mOutputVaryings.clear();
1389     mSharedVariables.clear();
1390     mInterfaceBlocks.clear();
1391     mUniformBlocks.clear();
1392     mShaderStorageBlocks.clear();
1393     mVariablesCollected    = false;
1394     mGLPositionInitialized = false;
1395 
1396     mNumViews = -1;
1397 
1398     mGeometryShaderInputPrimitiveType  = EptUndefined;
1399     mGeometryShaderOutputPrimitiveType = EptUndefined;
1400     mGeometryShaderInvocations         = 0;
1401     mGeometryShaderMaxVertices         = -1;
1402 
1403     mTessControlShaderOutputVertices            = 0;
1404     mTessEvaluationShaderInputPrimitiveType     = EtetUndefined;
1405     mTessEvaluationShaderInputVertexSpacingType = EtetUndefined;
1406     mTessEvaluationShaderInputOrderingType      = EtetUndefined;
1407     mTessEvaluationShaderInputPointType         = EtetUndefined;
1408 
1409     mBuiltInFunctionEmulator.cleanup();
1410 
1411     mNameMap.clear();
1412 
1413     mSourcePath = nullptr;
1414 
1415     mSymbolTable.clearCompilationResults();
1416 }
1417 
initCallDag(TIntermNode * root)1418 bool TCompiler::initCallDag(TIntermNode *root)
1419 {
1420     mCallDag.clear();
1421 
1422     switch (mCallDag.init(root, &mDiagnostics))
1423     {
1424         case CallDAG::INITDAG_SUCCESS:
1425             return true;
1426         case CallDAG::INITDAG_RECURSION:
1427         case CallDAG::INITDAG_UNDEFINED:
1428             // Error message has already been written out.
1429             ASSERT(mDiagnostics.numErrors() > 0);
1430             return false;
1431     }
1432 
1433     UNREACHABLE();
1434     return true;
1435 }
1436 
checkCallDepth()1437 bool TCompiler::checkCallDepth()
1438 {
1439     std::vector<int> depths(mCallDag.size());
1440 
1441     for (size_t i = 0; i < mCallDag.size(); i++)
1442     {
1443         int depth                     = 0;
1444         const CallDAG::Record &record = mCallDag.getRecordFromIndex(i);
1445 
1446         for (int calleeIndex : record.callees)
1447         {
1448             depth = std::max(depth, depths[calleeIndex] + 1);
1449         }
1450 
1451         depths[i] = depth;
1452 
1453         if (depth >= mResources.MaxCallStackDepth)
1454         {
1455             // Trace back the function chain to have a meaningful info log.
1456             std::stringstream errorStream = sh::InitializeStream<std::stringstream>();
1457             errorStream << "Call stack too deep (larger than " << mResources.MaxCallStackDepth
1458                         << ") with the following call chain: "
1459                         << record.node->getFunction()->name();
1460 
1461             int currentFunction = static_cast<int>(i);
1462             int currentDepth    = depth;
1463 
1464             while (currentFunction != -1)
1465             {
1466                 errorStream
1467                     << " -> "
1468                     << mCallDag.getRecordFromIndex(currentFunction).node->getFunction()->name();
1469 
1470                 int nextFunction = -1;
1471                 for (const int &calleeIndex : mCallDag.getRecordFromIndex(currentFunction).callees)
1472                 {
1473                     if (depths[calleeIndex] == currentDepth - 1)
1474                     {
1475                         currentDepth--;
1476                         nextFunction = calleeIndex;
1477                     }
1478                 }
1479 
1480                 currentFunction = nextFunction;
1481             }
1482 
1483             std::string errorStr = errorStream.str();
1484             mDiagnostics.globalError(errorStr.c_str());
1485 
1486             return false;
1487         }
1488     }
1489 
1490     return true;
1491 }
1492 
tagUsedFunctions()1493 bool TCompiler::tagUsedFunctions()
1494 {
1495     // Search from main, starting from the end of the DAG as it usually is the root.
1496     for (size_t i = mCallDag.size(); i-- > 0;)
1497     {
1498         if (mCallDag.getRecordFromIndex(i).node->getFunction()->isMain())
1499         {
1500             internalTagUsedFunction(i);
1501             return true;
1502         }
1503     }
1504 
1505     mDiagnostics.globalError("Missing main()");
1506     return false;
1507 }
1508 
internalTagUsedFunction(size_t index)1509 void TCompiler::internalTagUsedFunction(size_t index)
1510 {
1511     if (mFunctionMetadata[index].used)
1512     {
1513         return;
1514     }
1515 
1516     mFunctionMetadata[index].used = true;
1517 
1518     for (int calleeIndex : mCallDag.getRecordFromIndex(index).callees)
1519     {
1520         internalTagUsedFunction(calleeIndex);
1521     }
1522 }
1523 
pruneUnusedFunctions(TIntermBlock * root)1524 bool TCompiler::pruneUnusedFunctions(TIntermBlock *root)
1525 {
1526     TIntermSequence *sequence = root->getSequence();
1527 
1528     size_t writeIndex = 0;
1529     for (size_t readIndex = 0; readIndex < sequence->size(); ++readIndex)
1530     {
1531         TIntermNode *node = sequence->at(readIndex);
1532 
1533         // Keep anything that's not unused.
1534         const TFunction *function = nullptr;
1535         const bool shouldPrune =
1536             IsTopLevelNodeUnusedFunction(mCallDag, mFunctionMetadata, node, &function);
1537         if (!shouldPrune)
1538         {
1539             (*sequence)[writeIndex++] = node;
1540             continue;
1541         }
1542 
1543         // If a function is unused, it may have a struct declaration in its return value which
1544         // shouldn't be pruned.  In that case, replace the function definition with the struct
1545         // definition.
1546         ASSERT(function != nullptr);
1547         const TType &returnType = function->getReturnType();
1548         if (!returnType.isStructSpecifier())
1549         {
1550             continue;
1551         }
1552 
1553         TVariable *structVariable =
1554             new TVariable(&mSymbolTable, kEmptyImmutableString, &returnType, SymbolType::Empty);
1555         TIntermSymbol *structSymbol           = new TIntermSymbol(structVariable);
1556         TIntermDeclaration *structDeclaration = new TIntermDeclaration;
1557         structDeclaration->appendDeclarator(structSymbol);
1558 
1559         structSymbol->setLine(node->getLine());
1560         structDeclaration->setLine(node->getLine());
1561 
1562         (*sequence)[writeIndex++] = structDeclaration;
1563     }
1564 
1565     sequence->resize(writeIndex);
1566 
1567     return validateAST(root);
1568 }
1569 
limitExpressionComplexity(TIntermBlock * root)1570 bool TCompiler::limitExpressionComplexity(TIntermBlock *root)
1571 {
1572     if (!IsASTDepthBelowLimit(root, mResources.MaxExpressionComplexity))
1573     {
1574         mDiagnostics.globalError("Expression too complex.");
1575         return false;
1576     }
1577 
1578     if (!ValidateMaxParameters(root, mResources.MaxFunctionParameters))
1579     {
1580         mDiagnostics.globalError("Function has too many parameters.");
1581         return false;
1582     }
1583 
1584     return true;
1585 }
1586 
shouldCollectVariables(ShCompileOptions compileOptions)1587 bool TCompiler::shouldCollectVariables(ShCompileOptions compileOptions)
1588 {
1589     return (compileOptions & SH_VARIABLES) != 0;
1590 }
1591 
wereVariablesCollected() const1592 bool TCompiler::wereVariablesCollected() const
1593 {
1594     return mVariablesCollected;
1595 }
1596 
initializeGLPosition(TIntermBlock * root)1597 bool TCompiler::initializeGLPosition(TIntermBlock *root)
1598 {
1599     sh::ShaderVariable var(GL_FLOAT_VEC4);
1600     var.name = "gl_Position";
1601     return InitializeVariables(this, root, {var}, &mSymbolTable, mShaderVersion, mExtensionBehavior,
1602                                false, false);
1603 }
1604 
useAllMembersInUnusedStandardAndSharedBlocks(TIntermBlock * root)1605 bool TCompiler::useAllMembersInUnusedStandardAndSharedBlocks(TIntermBlock *root)
1606 {
1607     sh::InterfaceBlockList list;
1608 
1609     for (const sh::InterfaceBlock &block : mUniformBlocks)
1610     {
1611         if (!block.staticUse &&
1612             (block.layout == sh::BLOCKLAYOUT_STD140 || block.layout == sh::BLOCKLAYOUT_SHARED))
1613         {
1614             list.push_back(block);
1615         }
1616     }
1617 
1618     return sh::UseInterfaceBlockFields(this, root, list, mSymbolTable);
1619 }
1620 
initializeOutputVariables(TIntermBlock * root)1621 bool TCompiler::initializeOutputVariables(TIntermBlock *root)
1622 {
1623     InitVariableList list;
1624     list.reserve(mOutputVaryings.size());
1625     if (mShaderType == GL_VERTEX_SHADER || mShaderType == GL_GEOMETRY_SHADER_EXT)
1626     {
1627         for (const sh::ShaderVariable &var : mOutputVaryings)
1628         {
1629             list.push_back(var);
1630             if (var.name == "gl_Position")
1631             {
1632                 ASSERT(!mGLPositionInitialized);
1633                 mGLPositionInitialized = true;
1634             }
1635         }
1636     }
1637     else
1638     {
1639         ASSERT(mShaderType == GL_FRAGMENT_SHADER);
1640         for (const sh::ShaderVariable &var : mOutputVariables)
1641         {
1642             // in-out variables represent the context of the framebuffer
1643             // when the draw call starts, so they have to be considered
1644             // as already initialized.
1645             if (!var.isFragmentInOut)
1646             {
1647                 list.push_back(var);
1648             }
1649         }
1650     }
1651     return InitializeVariables(this, root, list, &mSymbolTable, mShaderVersion, mExtensionBehavior,
1652                                false, false);
1653 }
1654 
getExtensionBehavior() const1655 const TExtensionBehavior &TCompiler::getExtensionBehavior() const
1656 {
1657     return mExtensionBehavior;
1658 }
1659 
getSourcePath() const1660 const char *TCompiler::getSourcePath() const
1661 {
1662     return mSourcePath;
1663 }
1664 
getResources() const1665 const ShBuiltInResources &TCompiler::getResources() const
1666 {
1667     return mResources;
1668 }
1669 
getBuiltInFunctionEmulator() const1670 const BuiltInFunctionEmulator &TCompiler::getBuiltInFunctionEmulator() const
1671 {
1672     return mBuiltInFunctionEmulator;
1673 }
1674 
isVaryingDefined(const char * varyingName)1675 bool TCompiler::isVaryingDefined(const char *varyingName)
1676 {
1677     ASSERT(mVariablesCollected);
1678     for (size_t ii = 0; ii < mInputVaryings.size(); ++ii)
1679     {
1680         if (mInputVaryings[ii].name == varyingName)
1681         {
1682             return true;
1683         }
1684     }
1685     for (size_t ii = 0; ii < mOutputVaryings.size(); ++ii)
1686     {
1687         if (mOutputVaryings[ii].name == varyingName)
1688         {
1689             return true;
1690         }
1691     }
1692 
1693     return false;
1694 }
1695 
1696 }  // namespace sh
1697