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