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