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