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