Path: blob/main_old/src/compiler/translator/Compiler.cpp
1693 views
//1// Copyright 2002 The ANGLE Project Authors. All rights reserved.2// Use of this source code is governed by a BSD-style license that can be3// found in the LICENSE file.4//56#include "compiler/translator/Compiler.h"78#include <sstream>910#include "angle_gl.h"11#include "common/utilities.h"12#include "compiler/translator/CallDAG.h"13#include "compiler/translator/CollectVariables.h"14#include "compiler/translator/Initialize.h"15#include "compiler/translator/IsASTDepthBelowLimit.h"16#include "compiler/translator/OutputTree.h"17#include "compiler/translator/ParseContext.h"18#include "compiler/translator/ValidateBarrierFunctionCall.h"19#include "compiler/translator/ValidateClipCullDistance.h"20#include "compiler/translator/ValidateLimitations.h"21#include "compiler/translator/ValidateMaxParameters.h"22#include "compiler/translator/ValidateOutputs.h"23#include "compiler/translator/ValidateTypeSizeLimitations.h"24#include "compiler/translator/ValidateVaryingLocations.h"25#include "compiler/translator/VariablePacker.h"26#include "compiler/translator/tree_ops/ClampIndirectIndices.h"27#include "compiler/translator/tree_ops/ClampPointSize.h"28#include "compiler/translator/tree_ops/DeclareAndInitBuiltinsForInstancedMultiview.h"29#include "compiler/translator/tree_ops/DeferGlobalInitializers.h"30#include "compiler/translator/tree_ops/EmulateGLFragColorBroadcast.h"31#include "compiler/translator/tree_ops/EmulateMultiDrawShaderBuiltins.h"32#include "compiler/translator/tree_ops/FoldExpressions.h"33#include "compiler/translator/tree_ops/ForcePrecisionQualifier.h"34#include "compiler/translator/tree_ops/InitializeVariables.h"35#include "compiler/translator/tree_ops/PruneEmptyCases.h"36#include "compiler/translator/tree_ops/PruneNoOps.h"37#include "compiler/translator/tree_ops/RemoveArrayLengthMethod.h"38#include "compiler/translator/tree_ops/RemoveDynamicIndexing.h"39#include "compiler/translator/tree_ops/RemoveInvariantDeclaration.h"40#include "compiler/translator/tree_ops/RemoveUnreferencedVariables.h"41#include "compiler/translator/tree_ops/ScalarizeVecAndMatConstructorArgs.h"42#include "compiler/translator/tree_ops/SeparateDeclarations.h"43#include "compiler/translator/tree_ops/SimplifyLoopConditions.h"44#include "compiler/translator/tree_ops/SplitSequenceOperator.h"45#include "compiler/translator/tree_ops/apple/AddAndTrueToLoopCondition.h"46#include "compiler/translator/tree_ops/apple/RewriteDoWhile.h"47#include "compiler/translator/tree_ops/apple/UnfoldShortCircuitAST.h"48#include "compiler/translator/tree_ops/gl/ClampFragDepth.h"49#include "compiler/translator/tree_ops/gl/RegenerateStructNames.h"50#include "compiler/translator/tree_ops/gl/RewriteRepeatedAssignToSwizzled.h"51#include "compiler/translator/tree_ops/gl/UseInterfaceBlockFields.h"52#include "compiler/translator/tree_ops/vulkan/EarlyFragmentTestsOptimization.h"53#include "compiler/translator/tree_util/BuiltIn.h"54#include "compiler/translator/tree_util/IntermNodePatternMatcher.h"55#include "compiler/translator/tree_util/ReplaceShadowingVariables.h"56#include "compiler/translator/util.h"5758namespace sh59{6061namespace62{6364#if defined(ANGLE_ENABLE_FUZZER_CORPUS_OUTPUT)65void DumpFuzzerCase(char const *const *shaderStrings,66size_t numStrings,67uint32_t type,68uint32_t spec,69uint32_t output,70uint64_t options)71{72static int fileIndex = 0;7374std::ostringstream o = sh::InitializeStream<std::ostringstream>();75o << "corpus/" << fileIndex++ << ".sample";76std::string s = o.str();7778// Must match the input format of the fuzzer79FILE *f = fopen(s.c_str(), "w");80fwrite(&type, sizeof(type), 1, f);81fwrite(&spec, sizeof(spec), 1, f);82fwrite(&output, sizeof(output), 1, f);83fwrite(&options, sizeof(options), 1, f);8485char zero[128 - 20] = {0};86fwrite(&zero, 128 - 20, 1, f);8788for (size_t i = 0; i < numStrings; i++)89{90fwrite(shaderStrings[i], sizeof(char), strlen(shaderStrings[i]), f);91}92fwrite(&zero, 1, 1, f);9394fclose(f);95}96#endif // defined(ANGLE_ENABLE_FUZZER_CORPUS_OUTPUT)97} // anonymous namespace9899bool IsGLSL130OrNewer(ShShaderOutput output)100{101return (output == SH_GLSL_130_OUTPUT || output == SH_GLSL_140_OUTPUT ||102output == SH_GLSL_150_CORE_OUTPUT || output == SH_GLSL_330_CORE_OUTPUT ||103output == SH_GLSL_400_CORE_OUTPUT || output == SH_GLSL_410_CORE_OUTPUT ||104output == SH_GLSL_420_CORE_OUTPUT || output == SH_GLSL_430_CORE_OUTPUT ||105output == SH_GLSL_440_CORE_OUTPUT || output == SH_GLSL_450_CORE_OUTPUT);106}107108bool IsGLSL420OrNewer(ShShaderOutput output)109{110return (output == SH_GLSL_420_CORE_OUTPUT || output == SH_GLSL_430_CORE_OUTPUT ||111output == SH_GLSL_440_CORE_OUTPUT || output == SH_GLSL_450_CORE_OUTPUT);112}113114bool IsGLSL410OrOlder(ShShaderOutput output)115{116return (output == SH_GLSL_130_OUTPUT || output == SH_GLSL_140_OUTPUT ||117output == SH_GLSL_150_CORE_OUTPUT || output == SH_GLSL_330_CORE_OUTPUT ||118output == SH_GLSL_400_CORE_OUTPUT || output == SH_GLSL_410_CORE_OUTPUT);119}120121bool RemoveInvariant(sh::GLenum shaderType,122int shaderVersion,123ShShaderOutput outputType,124ShCompileOptions compileOptions)125{126if (shaderType == GL_FRAGMENT_SHADER && IsGLSL420OrNewer(outputType))127return true;128129if ((compileOptions & SH_REMOVE_INVARIANT_AND_CENTROID_FOR_ESSL3) != 0 &&130shaderVersion >= 300 && shaderType == GL_VERTEX_SHADER)131return true;132133return false;134}135136size_t GetGlobalMaxTokenSize(ShShaderSpec spec)137{138// WebGL defines a max token length of 256, while ES2 leaves max token139// size undefined. ES3 defines a max size of 1024 characters.140switch (spec)141{142case SH_WEBGL_SPEC:143return 256;144default:145return 1024;146}147}148149int GetMaxUniformVectorsForShaderType(GLenum shaderType, const ShBuiltInResources &resources)150{151switch (shaderType)152{153case GL_VERTEX_SHADER:154return resources.MaxVertexUniformVectors;155case GL_FRAGMENT_SHADER:156return resources.MaxFragmentUniformVectors;157158// TODO ([email protected]): check if we need finer-grained component counting159case GL_COMPUTE_SHADER:160return resources.MaxComputeUniformComponents / 4;161case GL_GEOMETRY_SHADER_EXT:162return resources.MaxGeometryUniformComponents / 4;163default:164UNREACHABLE();165return -1;166}167}168169namespace170{171172class TScopedPoolAllocator173{174public:175TScopedPoolAllocator(angle::PoolAllocator *allocator) : mAllocator(allocator)176{177mAllocator->push();178SetGlobalPoolAllocator(mAllocator);179}180~TScopedPoolAllocator()181{182SetGlobalPoolAllocator(nullptr);183mAllocator->pop();184}185186private:187angle::PoolAllocator *mAllocator;188};189190class TScopedSymbolTableLevel191{192public:193TScopedSymbolTableLevel(TSymbolTable *table) : mTable(table)194{195ASSERT(mTable->isEmpty());196mTable->push();197}198~TScopedSymbolTableLevel()199{200while (!mTable->isEmpty())201mTable->pop();202}203204private:205TSymbolTable *mTable;206};207208int GetMaxShaderVersionForSpec(ShShaderSpec spec)209{210switch (spec)211{212case SH_GLES2_SPEC:213case SH_WEBGL_SPEC:214return 100;215case SH_GLES3_SPEC:216case SH_WEBGL2_SPEC:217return 300;218case SH_GLES3_1_SPEC:219case SH_WEBGL3_SPEC:220return 310;221case SH_GLES3_2_SPEC:222return 320;223case SH_GL_CORE_SPEC:224case SH_GL_COMPATIBILITY_SPEC:225return 460;226default:227UNREACHABLE();228return 0;229}230}231232bool ValidateFragColorAndFragData(GLenum shaderType,233int shaderVersion,234const TSymbolTable &symbolTable,235TDiagnostics *diagnostics)236{237if (shaderVersion > 100 || shaderType != GL_FRAGMENT_SHADER)238{239return true;240}241242bool usesFragColor = false;243bool usesFragData = false;244// This validation is a bit stricter than the spec - it's only an error to write to245// both FragData and FragColor. But because it's better not to have reads from undefined246// variables, we always return an error if they are both referenced, rather than only if they247// are written.248if (symbolTable.isStaticallyUsed(*BuiltInVariable::gl_FragColor()) ||249symbolTable.isStaticallyUsed(*BuiltInVariable::gl_SecondaryFragColorEXT()))250{251usesFragColor = true;252}253// Extension variables may not always be initialized (saves some time at symbol table init).254bool secondaryFragDataUsed =255symbolTable.gl_SecondaryFragDataEXT() != nullptr &&256symbolTable.isStaticallyUsed(*symbolTable.gl_SecondaryFragDataEXT());257if (symbolTable.isStaticallyUsed(*symbolTable.gl_FragData()) || secondaryFragDataUsed)258{259usesFragData = true;260}261if (usesFragColor && usesFragData)262{263const char *errorMessage = "cannot use both gl_FragData and gl_FragColor";264if (symbolTable.isStaticallyUsed(*BuiltInVariable::gl_SecondaryFragColorEXT()) ||265secondaryFragDataUsed)266{267errorMessage =268"cannot use both output variable sets (gl_FragData, gl_SecondaryFragDataEXT)"269" and (gl_FragColor, gl_SecondaryFragColorEXT)";270}271diagnostics->globalError(errorMessage);272return false;273}274return true;275}276277} // namespace278279TShHandleBase::TShHandleBase()280{281allocator.push();282SetGlobalPoolAllocator(&allocator);283}284285TShHandleBase::~TShHandleBase()286{287SetGlobalPoolAllocator(nullptr);288allocator.popAll();289}290291TCompiler::TCompiler(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output)292: mVariablesCollected(false),293mGLPositionInitialized(false),294mShaderType(type),295mShaderSpec(spec),296mOutputType(output),297mBuiltInFunctionEmulator(),298mDiagnostics(mInfoSink.info),299mSourcePath(nullptr),300mComputeShaderLocalSizeDeclared(false),301mComputeShaderLocalSize(1),302mGeometryShaderMaxVertices(-1),303mGeometryShaderInvocations(0),304mGeometryShaderInputPrimitiveType(EptUndefined),305mGeometryShaderOutputPrimitiveType(EptUndefined),306mTessControlShaderOutputVertices(0),307mTessEvaluationShaderInputPrimitiveType(EtetUndefined),308mTessEvaluationShaderInputVertexSpacingType(EtetUndefined),309mTessEvaluationShaderInputOrderingType(EtetUndefined),310mTessEvaluationShaderInputPointType(EtetUndefined),311mHasAnyPreciseType(false),312mCompileOptions(0)313{}314315TCompiler::~TCompiler() {}316317bool TCompiler::isHighPrecisionSupported() const318{319return mShaderVersion > 100 || mShaderType != GL_FRAGMENT_SHADER ||320mResources.FragmentPrecisionHigh == 1;321}322323bool TCompiler::shouldRunLoopAndIndexingValidation(ShCompileOptions compileOptions) const324{325// If compiling an ESSL 1.00 shader for WebGL, or if its been requested through the API,326// validate loop and indexing as well (to verify that the shader only uses minimal functionality327// of ESSL 1.00 as in Appendix A of the spec).328return (IsWebGLBasedSpec(mShaderSpec) && mShaderVersion == 100) ||329(compileOptions & SH_VALIDATE_LOOP_INDEXING) != 0;330}331332bool TCompiler::shouldLimitTypeSizes() const333{334// WebGL shaders limit the size of variables' types in shaders,335// including arrays, structs and interface blocks.336return IsWebGLBasedSpec(mShaderSpec);337}338339bool TCompiler::Init(const ShBuiltInResources &resources)340{341SetGlobalPoolAllocator(&allocator);342343// Generate built-in symbol table.344if (!initBuiltInSymbolTable(resources))345return false;346347mResources = resources;348setResourceString();349350InitExtensionBehavior(resources, mExtensionBehavior);351return true;352}353354TIntermBlock *TCompiler::compileTreeForTesting(const char *const shaderStrings[],355size_t numStrings,356ShCompileOptions compileOptions)357{358return compileTreeImpl(shaderStrings, numStrings, compileOptions);359}360361TIntermBlock *TCompiler::compileTreeImpl(const char *const shaderStrings[],362size_t numStrings,363const ShCompileOptions compileOptions)364{365// Remember the compile options for helper functions such as validateAST.366mCompileOptions = compileOptions;367368clearResults();369370ASSERT(numStrings > 0);371ASSERT(GetGlobalPoolAllocator());372373// Reset the extension behavior for each compilation unit.374ResetExtensionBehavior(mResources, mExtensionBehavior, compileOptions);375376// If gl_DrawID is not supported, remove it from the available extensions377// Currently we only allow emulation of gl_DrawID378const bool glDrawIDSupported = (compileOptions & SH_EMULATE_GL_DRAW_ID) != 0;379if (!glDrawIDSupported)380{381auto it = mExtensionBehavior.find(TExtension::ANGLE_multi_draw);382if (it != mExtensionBehavior.end())383{384mExtensionBehavior.erase(it);385}386}387388const bool glBaseVertexBaseInstanceSupported =389(compileOptions & SH_EMULATE_GL_BASE_VERTEX_BASE_INSTANCE) != 0;390if (!glBaseVertexBaseInstanceSupported)391{392auto it = mExtensionBehavior.find(TExtension::ANGLE_base_vertex_base_instance);393if (it != mExtensionBehavior.end())394{395mExtensionBehavior.erase(it);396}397}398399// First string is path of source file if flag is set. The actual source follows.400size_t firstSource = 0;401if ((compileOptions & SH_SOURCE_PATH) != 0)402{403mSourcePath = shaderStrings[0];404++firstSource;405}406407TParseContext parseContext(mSymbolTable, mExtensionBehavior, mShaderType, mShaderSpec,408compileOptions, !IsDesktopGLSpec(mShaderSpec), &mDiagnostics,409getResources(), getOutputType());410411parseContext.setFragmentPrecisionHighOnESSL1(mResources.FragmentPrecisionHigh == 1);412413// We preserve symbols at the built-in level from compile-to-compile.414// Start pushing the user-defined symbols at global level.415TScopedSymbolTableLevel globalLevel(&mSymbolTable);416ASSERT(mSymbolTable.atGlobalLevel());417418// Parse shader.419if (PaParseStrings(numStrings - firstSource, &shaderStrings[firstSource], nullptr,420&parseContext) != 0)421{422return nullptr;423}424425if (parseContext.getTreeRoot() == nullptr)426{427return nullptr;428}429430setASTMetadata(parseContext);431432if (!checkShaderVersion(&parseContext))433{434return nullptr;435}436437TIntermBlock *root = parseContext.getTreeRoot();438if (!checkAndSimplifyAST(root, parseContext, compileOptions))439{440return nullptr;441}442443return root;444}445446bool TCompiler::checkShaderVersion(TParseContext *parseContext)447{448if (GetMaxShaderVersionForSpec(mShaderSpec) < mShaderVersion)449{450mDiagnostics.globalError("unsupported shader version");451return false;452}453454ASSERT(parseContext);455switch (mShaderType)456{457case GL_COMPUTE_SHADER:458if (mShaderVersion < 310)459{460mDiagnostics.globalError("Compute shader is not supported in this shader version.");461return false;462}463break;464465case GL_GEOMETRY_SHADER_EXT:466if (mShaderVersion < 310)467{468mDiagnostics.globalError(469"Geometry shader is not supported in this shader version.");470return false;471}472else if (mShaderVersion == 310)473{474if (!parseContext->checkCanUseOneOfExtensions(475sh::TSourceLoc(),476std::array<TExtension, 2u>{477{TExtension::EXT_geometry_shader, TExtension::OES_geometry_shader}}))478{479return false;480}481}482break;483484case GL_TESS_CONTROL_SHADER_EXT:485case GL_TESS_EVALUATION_SHADER_EXT:486if (mShaderVersion < 310)487{488mDiagnostics.globalError(489"Tessellation shaders are not supported in this shader version.");490return false;491}492else if (mShaderVersion == 310)493{494if (!parseContext->checkCanUseExtension(sh::TSourceLoc(),495TExtension::EXT_tessellation_shader))496{497return false;498}499}500break;501502default:503break;504}505506return true;507}508509void TCompiler::setASTMetadata(const TParseContext &parseContext)510{511mShaderVersion = parseContext.getShaderVersion();512513mPragma = parseContext.pragma();514mSymbolTable.setGlobalInvariant(mPragma.stdgl.invariantAll);515516mEarlyFragmentTestsSpecified = parseContext.isEarlyFragmentTestsSpecified();517518mComputeShaderLocalSizeDeclared = parseContext.isComputeShaderLocalSizeDeclared();519mComputeShaderLocalSize = parseContext.getComputeShaderLocalSize();520521mNumViews = parseContext.getNumViews();522523mHasAnyPreciseType = parseContext.hasAnyPreciseType();524525if (mShaderType == GL_GEOMETRY_SHADER_EXT)526{527mGeometryShaderInputPrimitiveType = parseContext.getGeometryShaderInputPrimitiveType();528mGeometryShaderOutputPrimitiveType = parseContext.getGeometryShaderOutputPrimitiveType();529mGeometryShaderMaxVertices = parseContext.getGeometryShaderMaxVertices();530mGeometryShaderInvocations = parseContext.getGeometryShaderInvocations();531}532if (mShaderType == GL_TESS_CONTROL_SHADER_EXT)533{534mTessControlShaderOutputVertices = parseContext.getTessControlShaderOutputVertices();535}536if (mShaderType == GL_TESS_EVALUATION_SHADER_EXT)537{538mTessEvaluationShaderInputPrimitiveType =539parseContext.getTessEvaluationShaderInputPrimitiveType();540mTessEvaluationShaderInputVertexSpacingType =541parseContext.getTessEvaluationShaderInputVertexSpacingType();542mTessEvaluationShaderInputOrderingType =543parseContext.getTessEvaluationShaderInputOrderingType();544mTessEvaluationShaderInputPointType = parseContext.getTessEvaluationShaderInputPointType();545}546}547548unsigned int TCompiler::getSharedMemorySize() const549{550unsigned int sharedMemSize = 0;551for (const sh::ShaderVariable &var : mSharedVariables)552{553sharedMemSize += var.getExternalSize();554}555556return sharedMemSize;557}558559bool TCompiler::validateAST(TIntermNode *root)560{561if ((mCompileOptions & SH_VALIDATE_AST) != 0)562{563bool valid = ValidateAST(root, &mDiagnostics, mValidateASTOptions);564565#if defined(ANGLE_ENABLE_ASSERTS)566if (!valid)567{568OutputTree(root, mInfoSink.info);569fprintf(stderr, "AST validation error(s):\n%s\n", mInfoSink.info.c_str());570}571#endif572// In debug, assert validation. In release, validation errors will be returned back to the573// application as internal ANGLE errors.574ASSERT(valid);575576return valid;577}578return true;579}580581bool TCompiler::disableValidateFunctionCall()582{583bool wasEnabled = mValidateASTOptions.validateFunctionCall;584mValidateASTOptions.validateFunctionCall = false;585return wasEnabled;586}587588void TCompiler::restoreValidateFunctionCall(bool enable)589{590ASSERT(!mValidateASTOptions.validateFunctionCall);591mValidateASTOptions.validateFunctionCall = enable;592}593594bool TCompiler::disableValidateVariableReferences()595{596bool wasEnabled = mValidateASTOptions.validateVariableReferences;597mValidateASTOptions.validateVariableReferences = false;598return wasEnabled;599}600601void TCompiler::restoreValidateVariableReferences(bool enable)602{603ASSERT(!mValidateASTOptions.validateVariableReferences);604mValidateASTOptions.validateVariableReferences = enable;605}606607void TCompiler::enableValidateNoMoreTransformations()608{609mValidateASTOptions.validateNoMoreTransformations = true;610}611612bool TCompiler::checkAndSimplifyAST(TIntermBlock *root,613const TParseContext &parseContext,614ShCompileOptions compileOptions)615{616mValidateASTOptions = {};617618// Desktop GLSL shaders don't have precision, so don't expect them to be specified.619mValidateASTOptions.validatePrecision = !IsDesktopGLSpec(mShaderSpec);620621if (!validateAST(root))622{623return false;624}625626// Disallow expressions deemed too complex.627if ((compileOptions & SH_LIMIT_EXPRESSION_COMPLEXITY) != 0 && !limitExpressionComplexity(root))628{629return false;630}631632if (shouldRunLoopAndIndexingValidation(compileOptions) &&633!ValidateLimitations(root, mShaderType, &mSymbolTable, &mDiagnostics))634{635return false;636}637638if (shouldLimitTypeSizes() && !ValidateTypeSizeLimitations(root, &mSymbolTable, &mDiagnostics))639{640return false;641}642643if (!ValidateFragColorAndFragData(mShaderType, mShaderVersion, mSymbolTable, &mDiagnostics))644{645return false;646}647648// Fold expressions that could not be folded before validation that was done as a part of649// parsing.650if (!FoldExpressions(this, root, &mDiagnostics))651{652return false;653}654// Folding should only be able to generate warnings.655ASSERT(mDiagnostics.numErrors() == 0);656657// Validate no barrier() after return before prunning it in |PruneNoOps()| below.658if (mShaderType == GL_TESS_CONTROL_SHADER && !ValidateBarrierFunctionCall(root, &mDiagnostics))659{660return false;661}662663// We prune no-ops to work around driver bugs and to keep AST processing and output simple.664// The following kinds of no-ops are pruned:665// 1. Empty declarations "int;".666// 2. Literal statements: "1.0;". The ESSL output doesn't define a default precision667// for float, so float literal statements would end up with no precision which is668// invalid ESSL.669// 3. Any unreachable statement after a discard, return, break or continue.670// After this empty declarations are not allowed in the AST.671if (!PruneNoOps(this, root, &mSymbolTable))672{673return false;674}675676// We need to generate globals early if we have non constant initializers enabled677bool initializeLocalsAndGlobals = (compileOptions & SH_INITIALIZE_UNINITIALIZED_LOCALS) != 0 &&678!IsOutputHLSL(getOutputType());679bool canUseLoopsToInitialize =680(compileOptions & SH_DONT_USE_LOOPS_TO_INITIALIZE_VARIABLES) == 0;681bool highPrecisionSupported = isHighPrecisionSupported();682bool enableNonConstantInitializers = IsExtensionEnabled(683mExtensionBehavior, TExtension::EXT_shader_non_constant_global_initializers);684// forceDeferGlobalInitializers is needed for MSL685// to convert a non-const global. For example:686//687// int someGlobal = 123;688//689// to690//691// int someGlobal;692// void main() {693// someGlobal = 123;694//695// This is because MSL doesn't allow statically initialized globals.696bool forceDeferGlobalInitializers = getOutputType() == SH_MSL_METAL_OUTPUT;697698if (enableNonConstantInitializers &&699!DeferGlobalInitializers(this, root, initializeLocalsAndGlobals, canUseLoopsToInitialize,700highPrecisionSupported, forceDeferGlobalInitializers,701&mSymbolTable))702{703return false;704}705706// Create the function DAG and check there is no recursion707if (!initCallDag(root))708{709return false;710}711712if ((compileOptions & SH_LIMIT_CALL_STACK_DEPTH) != 0 && !checkCallDepth())713{714return false;715}716717// Checks which functions are used and if "main" exists718mFunctionMetadata.clear();719mFunctionMetadata.resize(mCallDag.size());720if (!tagUsedFunctions())721{722return false;723}724725pruneUnusedFunctions(root);726if (IsSpecWithFunctionBodyNewScope(mShaderSpec, mShaderVersion))727{728if (!ReplaceShadowingVariables(this, root, &mSymbolTable))729{730return false;731}732}733734if (mShaderVersion >= 310 && !ValidateVaryingLocations(root, &mDiagnostics, mShaderType))735{736return false;737}738739if (mShaderVersion >= 300 && mShaderType == GL_FRAGMENT_SHADER &&740!ValidateOutputs(root, getExtensionBehavior(), mResources.MaxDrawBuffers, &mDiagnostics))741{742return false;743}744745if (parseContext.isExtensionEnabled(TExtension::EXT_clip_cull_distance))746{747if (!ValidateClipCullDistance(root, &mDiagnostics,748mResources.MaxCombinedClipAndCullDistances))749{750return false;751}752}753754// Clamping uniform array bounds needs to happen after validateLimitations pass.755if ((compileOptions & SH_CLAMP_INDIRECT_ARRAY_BOUNDS) != 0)756{757if (!ClampIndirectIndices(this, root, &mSymbolTable))758{759return false;760}761}762763if ((compileOptions & SH_INITIALIZE_BUILTINS_FOR_INSTANCED_MULTIVIEW) != 0 &&764(parseContext.isExtensionEnabled(TExtension::OVR_multiview2) ||765parseContext.isExtensionEnabled(TExtension::OVR_multiview)) &&766getShaderType() != GL_COMPUTE_SHADER)767{768if (!DeclareAndInitBuiltinsForInstancedMultiview(769this, root, mNumViews, mShaderType, compileOptions, mOutputType, &mSymbolTable))770{771return false;772}773}774775// This pass might emit short circuits so keep it before the short circuit unfolding776if ((compileOptions & SH_REWRITE_DO_WHILE_LOOPS) != 0)777{778if (!RewriteDoWhile(this, root, &mSymbolTable))779{780return false;781}782}783784if ((compileOptions & SH_ADD_AND_TRUE_TO_LOOP_CONDITION) != 0)785{786if (!AddAndTrueToLoopCondition(this, root))787{788return false;789}790}791792if ((compileOptions & SH_UNFOLD_SHORT_CIRCUIT) != 0)793{794if (!UnfoldShortCircuitAST(this, root))795{796return false;797}798}799800if ((compileOptions & SH_REGENERATE_STRUCT_NAMES) != 0)801{802if (!RegenerateStructNames(this, root, &mSymbolTable))803{804return false;805}806}807808if (mShaderType == GL_VERTEX_SHADER &&809IsExtensionEnabled(mExtensionBehavior, TExtension::ANGLE_multi_draw))810{811if ((compileOptions & SH_EMULATE_GL_DRAW_ID) != 0)812{813if (!EmulateGLDrawID(this, root, &mSymbolTable, &mUniforms,814shouldCollectVariables(compileOptions)))815{816return false;817}818}819}820821if (mShaderType == GL_VERTEX_SHADER &&822IsExtensionEnabled(mExtensionBehavior, TExtension::ANGLE_base_vertex_base_instance))823{824if ((compileOptions & SH_EMULATE_GL_BASE_VERTEX_BASE_INSTANCE) != 0)825{826if (!EmulateGLBaseVertexBaseInstance(827this, root, &mSymbolTable, &mUniforms, shouldCollectVariables(compileOptions),828(compileOptions & SH_ADD_BASE_VERTEX_TO_VERTEX_ID) != 0))829{830return false;831}832}833}834835if (mShaderType == GL_FRAGMENT_SHADER && mShaderVersion == 100 && mResources.EXT_draw_buffers &&836mResources.MaxDrawBuffers > 1 &&837IsExtensionEnabled(mExtensionBehavior, TExtension::EXT_draw_buffers))838{839if (!EmulateGLFragColorBroadcast(this, root, mResources.MaxDrawBuffers, &mOutputVariables,840&mSymbolTable, mShaderVersion))841{842return false;843}844}845846int simplifyScalarized = (compileOptions & SH_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS) != 0847? IntermNodePatternMatcher::kScalarizedVecOrMatConstructor848: 0;849850// Split multi declarations and remove calls to array length().851// Note that SimplifyLoopConditions needs to be run before any other AST transformations852// that may need to generate new statements from loop conditions or loop expressions.853if (!SimplifyLoopConditions(this, root,854IntermNodePatternMatcher::kMultiDeclaration |855IntermNodePatternMatcher::kArrayLengthMethod |856simplifyScalarized,857&getSymbolTable()))858{859return false;860}861862// Note that separate declarations need to be run before other AST transformations that863// generate new statements from expressions.864if (!SeparateDeclarations(this, root, &getSymbolTable()))865{866return false;867}868mValidateASTOptions.validateMultiDeclarations = true;869870if (!SplitSequenceOperator(this, root,871IntermNodePatternMatcher::kArrayLengthMethod | simplifyScalarized,872&getSymbolTable()))873{874return false;875}876877if (!RemoveArrayLengthMethod(this, root))878{879return false;880}881882if (!RemoveUnreferencedVariables(this, root, &mSymbolTable))883{884return false;885}886887// In case the last case inside a switch statement is a certain type of no-op, GLSL compilers in888// drivers may not accept it. In this case we clean up the dead code from the end of switch889// statements. This is also required because PruneNoOps or RemoveUnreferencedVariables may have890// left switch statements that only contained an empty declaration inside the final case in an891// invalid state. Relies on that PruneNoOps and RemoveUnreferencedVariables have already been892// run.893if (!PruneEmptyCases(this, root))894{895return false;896}897898// Built-in function emulation needs to happen after validateLimitations pass.899// TODO(jmadill): Remove global pool allocator.900GetGlobalPoolAllocator()->lock();901initBuiltInFunctionEmulator(&mBuiltInFunctionEmulator, compileOptions);902GetGlobalPoolAllocator()->unlock();903mBuiltInFunctionEmulator.markBuiltInFunctionsForEmulation(root);904905if ((compileOptions & SH_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS) != 0)906{907if (!ScalarizeVecAndMatConstructorArgs(this, root, &mSymbolTable))908{909return false;910}911}912913if ((compileOptions & SH_FORCE_SHADER_PRECISION_HIGHP_TO_MEDIUMP) != 0)914{915if (!ForceShaderPrecisionToMediump(root, &mSymbolTable, mShaderType))916{917return false;918}919}920921if (shouldCollectVariables(compileOptions))922{923ASSERT(!mVariablesCollected);924CollectVariables(root, &mAttributes, &mOutputVariables, &mUniforms, &mInputVaryings,925&mOutputVaryings, &mSharedVariables, &mUniformBlocks,926&mShaderStorageBlocks, mResources.HashFunction, &mSymbolTable, mShaderType,927mExtensionBehavior, mResources, mTessControlShaderOutputVertices);928collectInterfaceBlocks();929mVariablesCollected = true;930if ((compileOptions & SH_USE_UNUSED_STANDARD_SHARED_BLOCKS) != 0)931{932if (!useAllMembersInUnusedStandardAndSharedBlocks(root))933{934return false;935}936}937if ((compileOptions & SH_ENFORCE_PACKING_RESTRICTIONS) != 0)938{939int maxUniformVectors = GetMaxUniformVectorsForShaderType(mShaderType, mResources);940// Returns true if, after applying the packing rules in the GLSL ES 1.00.17 spec941// Appendix A, section 7, the shader does not use too many uniforms.942if (!CheckVariablesInPackingLimits(maxUniformVectors, mUniforms))943{944mDiagnostics.globalError("too many uniforms");945return false;946}947}948bool needInitializeOutputVariables =949(compileOptions & SH_INIT_OUTPUT_VARIABLES) != 0 && mShaderType != GL_COMPUTE_SHADER;950needInitializeOutputVariables |=951(compileOptions & SH_INIT_FRAGMENT_OUTPUT_VARIABLES) != 0 &&952mShaderType == GL_FRAGMENT_SHADER;953if (needInitializeOutputVariables)954{955if (!initializeOutputVariables(root))956{957return false;958}959}960}961962// Removing invariant declarations must be done after collecting variables.963// Otherwise, built-in invariant declarations don't apply.964if (RemoveInvariant(mShaderType, mShaderVersion, mOutputType, compileOptions))965{966if (!RemoveInvariantDeclaration(this, root))967{968return false;969}970}971972// gl_Position is always written in compatibility output mode.973// It may have been already initialized among other output variables, in that case we don't974// need to initialize it twice.975if (mShaderType == GL_VERTEX_SHADER && !mGLPositionInitialized &&976((compileOptions & SH_INIT_GL_POSITION) != 0 ||977mOutputType == SH_GLSL_COMPATIBILITY_OUTPUT))978{979if (!initializeGLPosition(root))980{981return false;982}983mGLPositionInitialized = true;984}985986// DeferGlobalInitializers needs to be run before other AST transformations that generate new987// statements from expressions. But it's fine to run DeferGlobalInitializers after the above988// SplitSequenceOperator and RemoveArrayLengthMethod since they only have an effect on the AST989// on ESSL >= 3.00, and the initializers that need to be deferred can only exist in ESSL < 3.00.990// Exception: if EXT_shader_non_constant_global_initializers is enabled, we must generate global991// initializers before we generate the DAG, since initializers may call functions which must not992// be optimized out993if (!enableNonConstantInitializers &&994!DeferGlobalInitializers(this, root, initializeLocalsAndGlobals, canUseLoopsToInitialize,995highPrecisionSupported, forceDeferGlobalInitializers,996&mSymbolTable))997{998return false;999}10001001if (initializeLocalsAndGlobals)1002{1003// Initialize uninitialized local variables.1004// In some cases initializing can generate extra statements in the parent block, such as1005// when initializing nameless structs or initializing arrays in ESSL 1.00. In that case1006// we need to first simplify loop conditions. We've already separated declarations1007// earlier, which is also required. If we don't follow the Appendix A limitations, loop1008// init statements can declare arrays or nameless structs and have multiple1009// declarations.10101011if (!shouldRunLoopAndIndexingValidation(compileOptions))1012{1013if (!SimplifyLoopConditions(this, root,1014IntermNodePatternMatcher::kArrayDeclaration |1015IntermNodePatternMatcher::kNamelessStructDeclaration,1016&getSymbolTable()))1017{1018return false;1019}1020}10211022if (!InitializeUninitializedLocals(this, root, getShaderVersion(), canUseLoopsToInitialize,1023highPrecisionSupported, &getSymbolTable()))1024{1025return false;1026}1027}10281029if (getShaderType() == GL_VERTEX_SHADER && (compileOptions & SH_CLAMP_POINT_SIZE) != 0)1030{1031if (!ClampPointSize(this, root, mResources.MaxPointSize, &getSymbolTable()))1032{1033return false;1034}1035}10361037if (getShaderType() == GL_FRAGMENT_SHADER && (compileOptions & SH_CLAMP_FRAG_DEPTH) != 0)1038{1039if (!ClampFragDepth(this, root, &getSymbolTable()))1040{1041return false;1042}1043}10441045if ((compileOptions & SH_REWRITE_REPEATED_ASSIGN_TO_SWIZZLED) != 0)1046{1047if (!sh::RewriteRepeatedAssignToSwizzled(this, root))1048{1049return false;1050}1051}10521053if ((compileOptions & SH_REMOVE_DYNAMIC_INDEXING_OF_SWIZZLED_VECTOR) != 0)1054{1055if (!sh::RemoveDynamicIndexingOfSwizzledVector(this, root, &getSymbolTable(), nullptr))1056{1057return false;1058}1059}10601061mEarlyFragmentTestsOptimized = false;1062if ((compileOptions & SH_EARLY_FRAGMENT_TESTS_OPTIMIZATION) != 0)1063{1064if (mShaderVersion <= 300 && mShaderType == GL_FRAGMENT_SHADER &&1065!isEarlyFragmentTestsSpecified())1066{1067mEarlyFragmentTestsOptimized = CheckEarlyFragmentTestsFeasible(this, root);1068}1069}10701071return true;1072}10731074bool TCompiler::compile(const char *const shaderStrings[],1075size_t numStrings,1076ShCompileOptions compileOptionsIn)1077{1078#if defined(ANGLE_ENABLE_FUZZER_CORPUS_OUTPUT)1079DumpFuzzerCase(shaderStrings, numStrings, mShaderType, mShaderSpec, mOutputType,1080compileOptionsIn);1081#endif // defined(ANGLE_ENABLE_FUZZER_CORPUS_OUTPUT)10821083if (numStrings == 0)1084return true;10851086ShCompileOptions compileOptions = compileOptionsIn;10871088// Apply key workarounds.1089if (shouldFlattenPragmaStdglInvariantAll())1090{1091// This should be harmless to do in all cases, but for the moment, do it only conditionally.1092compileOptions |= SH_FLATTEN_PRAGMA_STDGL_INVARIANT_ALL;1093}10941095TScopedPoolAllocator scopedAlloc(&allocator);1096TIntermBlock *root = compileTreeImpl(shaderStrings, numStrings, compileOptions);10971098if (root)1099{1100if ((compileOptions & SH_INTERMEDIATE_TREE) != 0)1101{1102OutputTree(root, mInfoSink.info);1103}11041105if ((compileOptions & SH_OBJECT_CODE) != 0)1106{1107PerformanceDiagnostics perfDiagnostics(&mDiagnostics);1108if (!translate(root, compileOptions, &perfDiagnostics))1109{1110return false;1111}1112}11131114if (mShaderType == GL_VERTEX_SHADER)1115{1116bool lookForDrawID =1117IsExtensionEnabled(mExtensionBehavior, TExtension::ANGLE_multi_draw) &&1118(compileOptions & SH_EMULATE_GL_DRAW_ID) != 0;1119bool lookForBaseVertexBaseInstance =1120IsExtensionEnabled(mExtensionBehavior,1121TExtension::ANGLE_base_vertex_base_instance) &&1122(compileOptions & SH_EMULATE_GL_BASE_VERTEX_BASE_INSTANCE) != 0;11231124if (lookForDrawID || lookForBaseVertexBaseInstance)1125{1126for (auto &uniform : mUniforms)1127{1128if (lookForDrawID && uniform.name == "angle_DrawID" &&1129uniform.mappedName == "angle_DrawID")1130{1131uniform.name = "gl_DrawID";1132}1133else if (lookForBaseVertexBaseInstance && uniform.name == "angle_BaseVertex" &&1134uniform.mappedName == "angle_BaseVertex")1135{1136uniform.name = "gl_BaseVertex";1137}1138else if (lookForBaseVertexBaseInstance &&1139uniform.name == "angle_BaseInstance" &&1140uniform.mappedName == "angle_BaseInstance")1141{1142uniform.name = "gl_BaseInstance";1143}1144}1145}1146}11471148// The IntermNode tree doesn't need to be deleted here, since the1149// memory will be freed in a big chunk by the PoolAllocator.1150return true;1151}1152return false;1153}11541155bool TCompiler::initBuiltInSymbolTable(const ShBuiltInResources &resources)1156{1157if (resources.MaxDrawBuffers < 1)1158{1159return false;1160}1161if (resources.EXT_blend_func_extended && resources.MaxDualSourceDrawBuffers < 1)1162{1163return false;1164}11651166mSymbolTable.initializeBuiltIns(mShaderType, mShaderSpec, resources);11671168return true;1169}11701171void TCompiler::setResourceString()1172{1173std::ostringstream strstream = sh::InitializeStream<std::ostringstream>();11741175// clang-format off1176strstream << ":MaxVertexAttribs:" << mResources.MaxVertexAttribs1177<< ":MaxVertexUniformVectors:" << mResources.MaxVertexUniformVectors1178<< ":MaxVaryingVectors:" << mResources.MaxVaryingVectors1179<< ":MaxVertexTextureImageUnits:" << mResources.MaxVertexTextureImageUnits1180<< ":MaxCombinedTextureImageUnits:" << mResources.MaxCombinedTextureImageUnits1181<< ":MaxTextureImageUnits:" << mResources.MaxTextureImageUnits1182<< ":MaxFragmentUniformVectors:" << mResources.MaxFragmentUniformVectors1183<< ":MaxDrawBuffers:" << mResources.MaxDrawBuffers1184<< ":OES_standard_derivatives:" << mResources.OES_standard_derivatives1185<< ":OES_EGL_image_external:" << mResources.OES_EGL_image_external1186<< ":OES_EGL_image_external_essl3:" << mResources.OES_EGL_image_external_essl31187<< ":NV_EGL_stream_consumer_external:" << mResources.NV_EGL_stream_consumer_external1188<< ":ARB_texture_rectangle:" << mResources.ARB_texture_rectangle1189<< ":EXT_draw_buffers:" << mResources.EXT_draw_buffers1190<< ":FragmentPrecisionHigh:" << mResources.FragmentPrecisionHigh1191<< ":MaxExpressionComplexity:" << mResources.MaxExpressionComplexity1192<< ":MaxCallStackDepth:" << mResources.MaxCallStackDepth1193<< ":MaxFunctionParameters:" << mResources.MaxFunctionParameters1194<< ":EXT_blend_func_extended:" << mResources.EXT_blend_func_extended1195<< ":EXT_frag_depth:" << mResources.EXT_frag_depth1196<< ":EXT_primitive_bounding_box:" << mResources.EXT_primitive_bounding_box1197<< ":EXT_shader_texture_lod:" << mResources.EXT_shader_texture_lod1198<< ":EXT_shader_framebuffer_fetch:" << mResources.EXT_shader_framebuffer_fetch1199<< ":EXT_shader_framebuffer_fetch_non_coherent:" << mResources.EXT_shader_framebuffer_fetch_non_coherent1200<< ":NV_shader_framebuffer_fetch:" << mResources.NV_shader_framebuffer_fetch1201<< ":ARM_shader_framebuffer_fetch:" << mResources.ARM_shader_framebuffer_fetch1202<< ":OVR_multiview2:" << mResources.OVR_multiview21203<< ":OVR_multiview:" << mResources.OVR_multiview1204<< ":EXT_YUV_target:" << mResources.EXT_YUV_target1205<< ":EXT_geometry_shader:" << mResources.EXT_geometry_shader1206<< ":OES_geometry_shader:" << mResources.OES_geometry_shader1207<< ":OES_shader_io_blocks:" << mResources.OES_shader_io_blocks1208<< ":EXT_shader_io_blocks:" << mResources.EXT_shader_io_blocks1209<< ":EXT_gpu_shader5:" << mResources.EXT_gpu_shader51210<< ":OES_texture_3D:" << mResources.OES_texture_3D1211<< ":MaxVertexOutputVectors:" << mResources.MaxVertexOutputVectors1212<< ":MaxFragmentInputVectors:" << mResources.MaxFragmentInputVectors1213<< ":MinProgramTexelOffset:" << mResources.MinProgramTexelOffset1214<< ":MaxProgramTexelOffset:" << mResources.MaxProgramTexelOffset1215<< ":MaxDualSourceDrawBuffers:" << mResources.MaxDualSourceDrawBuffers1216<< ":MaxViewsOVR:" << mResources.MaxViewsOVR1217<< ":NV_draw_buffers:" << mResources.NV_draw_buffers1218<< ":ANGLE_multi_draw:" << mResources.ANGLE_multi_draw1219<< ":ANGLE_base_vertex_base_instance:" << mResources.ANGLE_base_vertex_base_instance1220<< ":APPLE_clip_distance:" << mResources.APPLE_clip_distance1221<< ":OES_texture_cube_map_array:" << mResources.OES_texture_cube_map_array1222<< ":EXT_texture_cube_map_array:" << mResources.EXT_texture_cube_map_array1223<< ":EXT_shadow_samplers:" << mResources.EXT_shadow_samplers1224<< ":OES_shader_multisample_interpolation:" << mResources.OES_shader_multisample_interpolation1225<< ":OES_shader_image_atomic:" << mResources.OES_shader_image_atomic1226<< ":EXT_tessellation_shader:" << mResources.EXT_tessellation_shader1227<< ":OES_texture_buffer:" << mResources.OES_texture_buffer1228<< ":EXT_texture_buffer:" << mResources.EXT_texture_buffer1229<< ":OES_sample_variables:" << mResources.OES_sample_variables1230<< ":EXT_clip_cull_distance:" << mResources.EXT_clip_cull_distance1231<< ":MinProgramTextureGatherOffset:" << mResources.MinProgramTextureGatherOffset1232<< ":MaxProgramTextureGatherOffset:" << mResources.MaxProgramTextureGatherOffset1233<< ":MaxImageUnits:" << mResources.MaxImageUnits1234<< ":MaxSamples:" << mResources.MaxSamples1235<< ":MaxVertexImageUniforms:" << mResources.MaxVertexImageUniforms1236<< ":MaxFragmentImageUniforms:" << mResources.MaxFragmentImageUniforms1237<< ":MaxComputeImageUniforms:" << mResources.MaxComputeImageUniforms1238<< ":MaxCombinedImageUniforms:" << mResources.MaxCombinedImageUniforms1239<< ":MaxCombinedShaderOutputResources:" << mResources.MaxCombinedShaderOutputResources1240<< ":MaxComputeWorkGroupCountX:" << mResources.MaxComputeWorkGroupCount[0]1241<< ":MaxComputeWorkGroupCountY:" << mResources.MaxComputeWorkGroupCount[1]1242<< ":MaxComputeWorkGroupCountZ:" << mResources.MaxComputeWorkGroupCount[2]1243<< ":MaxComputeWorkGroupSizeX:" << mResources.MaxComputeWorkGroupSize[0]1244<< ":MaxComputeWorkGroupSizeY:" << mResources.MaxComputeWorkGroupSize[1]1245<< ":MaxComputeWorkGroupSizeZ:" << mResources.MaxComputeWorkGroupSize[2]1246<< ":MaxComputeUniformComponents:" << mResources.MaxComputeUniformComponents1247<< ":MaxComputeTextureImageUnits:" << mResources.MaxComputeTextureImageUnits1248<< ":MaxComputeAtomicCounters:" << mResources.MaxComputeAtomicCounters1249<< ":MaxComputeAtomicCounterBuffers:" << mResources.MaxComputeAtomicCounterBuffers1250<< ":MaxVertexAtomicCounters:" << mResources.MaxVertexAtomicCounters1251<< ":MaxFragmentAtomicCounters:" << mResources.MaxFragmentAtomicCounters1252<< ":MaxCombinedAtomicCounters:" << mResources.MaxCombinedAtomicCounters1253<< ":MaxAtomicCounterBindings:" << mResources.MaxAtomicCounterBindings1254<< ":MaxVertexAtomicCounterBuffers:" << mResources.MaxVertexAtomicCounterBuffers1255<< ":MaxFragmentAtomicCounterBuffers:" << mResources.MaxFragmentAtomicCounterBuffers1256<< ":MaxCombinedAtomicCounterBuffers:" << mResources.MaxCombinedAtomicCounterBuffers1257<< ":MaxAtomicCounterBufferSize:" << mResources.MaxAtomicCounterBufferSize1258<< ":MaxGeometryUniformComponents:" << mResources.MaxGeometryUniformComponents1259<< ":MaxGeometryUniformBlocks:" << mResources.MaxGeometryUniformBlocks1260<< ":MaxGeometryInputComponents:" << mResources.MaxGeometryInputComponents1261<< ":MaxGeometryOutputComponents:" << mResources.MaxGeometryOutputComponents1262<< ":MaxGeometryOutputVertices:" << mResources.MaxGeometryOutputVertices1263<< ":MaxGeometryTotalOutputComponents:" << mResources.MaxGeometryTotalOutputComponents1264<< ":MaxGeometryTextureImageUnits:" << mResources.MaxGeometryTextureImageUnits1265<< ":MaxGeometryAtomicCounterBuffers:" << mResources.MaxGeometryAtomicCounterBuffers1266<< ":MaxGeometryAtomicCounters:" << mResources.MaxGeometryAtomicCounters1267<< ":MaxGeometryShaderStorageBlocks:" << mResources.MaxGeometryShaderStorageBlocks1268<< ":MaxGeometryShaderInvocations:" << mResources.MaxGeometryShaderInvocations1269<< ":MaxGeometryImageUniforms:" << mResources.MaxGeometryImageUniforms1270<< ":MaxClipDistances" << mResources.MaxClipDistances1271<< ":MaxCullDistances" << mResources.MaxCullDistances1272<< ":MaxCombinedClipAndCullDistances" << mResources.MaxCombinedClipAndCullDistances1273<< ":MaxTessControlInputComponents:" << mResources.MaxTessControlInputComponents1274<< ":MaxTessControlOutputComponents:" << mResources.MaxTessControlOutputComponents1275<< ":MaxTessControlTextureImageUnits:" << mResources.MaxTessControlTextureImageUnits1276<< ":MaxTessControlUniformComponents:" << mResources.MaxTessControlUniformComponents1277<< ":MaxTessControlTotalOutputComponents:" << mResources.MaxTessControlTotalOutputComponents1278<< ":MaxTessControlImageUniforms:" << mResources.MaxTessControlImageUniforms1279<< ":MaxTessControlAtomicCounters:" << mResources.MaxTessControlAtomicCounters1280<< ":MaxTessControlAtomicCounterBuffers:" << mResources.MaxTessControlAtomicCounterBuffers1281<< ":MaxTessPatchComponents:" << mResources.MaxTessPatchComponents1282<< ":MaxPatchVertices:" << mResources.MaxPatchVertices1283<< ":MaxTessGenLevel:" << mResources.MaxTessGenLevel1284<< ":MaxTessEvaluationInputComponents:" << mResources.MaxTessEvaluationInputComponents1285<< ":MaxTessEvaluationOutputComponents:" << mResources.MaxTessEvaluationOutputComponents1286<< ":MaxTessEvaluationTextureImageUnits:" << mResources.MaxTessEvaluationTextureImageUnits1287<< ":MaxTessEvaluationUniformComponents:" << mResources.MaxTessEvaluationUniformComponents1288<< ":MaxTessEvaluationImageUniforms:" << mResources.MaxTessEvaluationImageUniforms1289<< ":MaxTessEvaluationAtomicCounters:" << mResources.MaxTessEvaluationAtomicCounters1290<< ":MaxTessEvaluationAtomicCounterBuffers:" << mResources.MaxTessEvaluationAtomicCounterBuffers;1291// clang-format on12921293mBuiltInResourcesString = strstream.str();1294}12951296void TCompiler::collectInterfaceBlocks()1297{1298ASSERT(mInterfaceBlocks.empty());1299mInterfaceBlocks.reserve(mUniformBlocks.size() + mShaderStorageBlocks.size());1300mInterfaceBlocks.insert(mInterfaceBlocks.end(), mUniformBlocks.begin(), mUniformBlocks.end());1301mInterfaceBlocks.insert(mInterfaceBlocks.end(), mShaderStorageBlocks.begin(),1302mShaderStorageBlocks.end());1303}13041305void TCompiler::clearResults()1306{1307mInfoSink.info.erase();1308mInfoSink.obj.erase();1309mInfoSink.debug.erase();1310mDiagnostics.resetErrorCount();13111312mAttributes.clear();1313mOutputVariables.clear();1314mUniforms.clear();1315mInputVaryings.clear();1316mOutputVaryings.clear();1317mSharedVariables.clear();1318mInterfaceBlocks.clear();1319mUniformBlocks.clear();1320mShaderStorageBlocks.clear();1321mVariablesCollected = false;1322mGLPositionInitialized = false;13231324mNumViews = -1;13251326mGeometryShaderInputPrimitiveType = EptUndefined;1327mGeometryShaderOutputPrimitiveType = EptUndefined;1328mGeometryShaderInvocations = 0;1329mGeometryShaderMaxVertices = -1;13301331mTessControlShaderOutputVertices = 0;1332mTessEvaluationShaderInputPrimitiveType = EtetUndefined;1333mTessEvaluationShaderInputVertexSpacingType = EtetUndefined;1334mTessEvaluationShaderInputOrderingType = EtetUndefined;1335mTessEvaluationShaderInputPointType = EtetUndefined;13361337mBuiltInFunctionEmulator.cleanup();13381339mNameMap.clear();13401341mSourcePath = nullptr;13421343mSymbolTable.clearCompilationResults();1344}13451346bool TCompiler::initCallDag(TIntermNode *root)1347{1348mCallDag.clear();13491350switch (mCallDag.init(root, &mDiagnostics))1351{1352case CallDAG::INITDAG_SUCCESS:1353return true;1354case CallDAG::INITDAG_RECURSION:1355case CallDAG::INITDAG_UNDEFINED:1356// Error message has already been written out.1357ASSERT(mDiagnostics.numErrors() > 0);1358return false;1359}13601361UNREACHABLE();1362return true;1363}13641365bool TCompiler::checkCallDepth()1366{1367std::vector<int> depths(mCallDag.size());13681369for (size_t i = 0; i < mCallDag.size(); i++)1370{1371int depth = 0;1372const CallDAG::Record &record = mCallDag.getRecordFromIndex(i);13731374for (int calleeIndex : record.callees)1375{1376depth = std::max(depth, depths[calleeIndex] + 1);1377}13781379depths[i] = depth;13801381if (depth >= mResources.MaxCallStackDepth)1382{1383// Trace back the function chain to have a meaningful info log.1384std::stringstream errorStream = sh::InitializeStream<std::stringstream>();1385errorStream << "Call stack too deep (larger than " << mResources.MaxCallStackDepth1386<< ") with the following call chain: "1387<< record.node->getFunction()->name();13881389int currentFunction = static_cast<int>(i);1390int currentDepth = depth;13911392while (currentFunction != -1)1393{1394errorStream1395<< " -> "1396<< mCallDag.getRecordFromIndex(currentFunction).node->getFunction()->name();13971398int nextFunction = -1;1399for (const int &calleeIndex : mCallDag.getRecordFromIndex(currentFunction).callees)1400{1401if (depths[calleeIndex] == currentDepth - 1)1402{1403currentDepth--;1404nextFunction = calleeIndex;1405}1406}14071408currentFunction = nextFunction;1409}14101411std::string errorStr = errorStream.str();1412mDiagnostics.globalError(errorStr.c_str());14131414return false;1415}1416}14171418return true;1419}14201421bool TCompiler::tagUsedFunctions()1422{1423// Search from main, starting from the end of the DAG as it usually is the root.1424for (size_t i = mCallDag.size(); i-- > 0;)1425{1426if (mCallDag.getRecordFromIndex(i).node->getFunction()->isMain())1427{1428internalTagUsedFunction(i);1429return true;1430}1431}14321433mDiagnostics.globalError("Missing main()");1434return false;1435}14361437void TCompiler::internalTagUsedFunction(size_t index)1438{1439if (mFunctionMetadata[index].used)1440{1441return;1442}14431444mFunctionMetadata[index].used = true;14451446for (int calleeIndex : mCallDag.getRecordFromIndex(index).callees)1447{1448internalTagUsedFunction(calleeIndex);1449}1450}14511452// A predicate for the stl that returns if a top-level node is unused1453class TCompiler::UnusedPredicate1454{1455public:1456UnusedPredicate(const CallDAG *callDag, const std::vector<FunctionMetadata> *metadatas)1457: mCallDag(callDag), mMetadatas(metadatas)1458{}14591460bool operator()(TIntermNode *node)1461{1462const TIntermFunctionPrototype *asFunctionPrototype = node->getAsFunctionPrototypeNode();1463const TIntermFunctionDefinition *asFunctionDefinition = node->getAsFunctionDefinition();14641465const TFunction *func = nullptr;14661467if (asFunctionDefinition)1468{1469func = asFunctionDefinition->getFunction();1470}1471else if (asFunctionPrototype)1472{1473func = asFunctionPrototype->getFunction();1474}1475if (func == nullptr)1476{1477return false;1478}14791480size_t callDagIndex = mCallDag->findIndex(func->uniqueId());1481if (callDagIndex == CallDAG::InvalidIndex)1482{1483// This happens only for unimplemented prototypes which are thus unused1484ASSERT(asFunctionPrototype);1485return true;1486}14871488ASSERT(callDagIndex < mMetadatas->size());1489return !(*mMetadatas)[callDagIndex].used;1490}14911492private:1493const CallDAG *mCallDag;1494const std::vector<FunctionMetadata> *mMetadatas;1495};14961497void TCompiler::pruneUnusedFunctions(TIntermBlock *root)1498{1499UnusedPredicate isUnused(&mCallDag, &mFunctionMetadata);1500TIntermSequence *sequence = root->getSequence();15011502if (!sequence->empty())1503{1504sequence->erase(std::remove_if(sequence->begin(), sequence->end(), isUnused),1505sequence->end());1506}1507}15081509bool TCompiler::limitExpressionComplexity(TIntermBlock *root)1510{1511if (!IsASTDepthBelowLimit(root, mResources.MaxExpressionComplexity))1512{1513mDiagnostics.globalError("Expression too complex.");1514return false;1515}15161517if (!ValidateMaxParameters(root, mResources.MaxFunctionParameters))1518{1519mDiagnostics.globalError("Function has too many parameters.");1520return false;1521}15221523return true;1524}15251526bool TCompiler::shouldCollectVariables(ShCompileOptions compileOptions)1527{1528return (compileOptions & SH_VARIABLES) != 0;1529}15301531bool TCompiler::wereVariablesCollected() const1532{1533return mVariablesCollected;1534}15351536bool TCompiler::initializeGLPosition(TIntermBlock *root)1537{1538sh::ShaderVariable var(GL_FLOAT_VEC4);1539var.name = "gl_Position";1540return InitializeVariables(this, root, {var}, &mSymbolTable, mShaderVersion, mExtensionBehavior,1541false, false);1542}15431544bool TCompiler::useAllMembersInUnusedStandardAndSharedBlocks(TIntermBlock *root)1545{1546sh::InterfaceBlockList list;15471548for (const sh::InterfaceBlock &block : mUniformBlocks)1549{1550if (!block.staticUse &&1551(block.layout == sh::BLOCKLAYOUT_STD140 || block.layout == sh::BLOCKLAYOUT_SHARED))1552{1553list.push_back(block);1554}1555}15561557return sh::UseInterfaceBlockFields(this, root, list, mSymbolTable);1558}15591560bool TCompiler::initializeOutputVariables(TIntermBlock *root)1561{1562InitVariableList list;1563list.reserve(mOutputVaryings.size());1564if (mShaderType == GL_VERTEX_SHADER || mShaderType == GL_GEOMETRY_SHADER_EXT)1565{1566for (const sh::ShaderVariable &var : mOutputVaryings)1567{1568list.push_back(var);1569if (var.name == "gl_Position")1570{1571ASSERT(!mGLPositionInitialized);1572mGLPositionInitialized = true;1573}1574}1575}1576else1577{1578ASSERT(mShaderType == GL_FRAGMENT_SHADER);1579for (const sh::ShaderVariable &var : mOutputVariables)1580{1581list.push_back(var);1582}1583}1584return InitializeVariables(this, root, list, &mSymbolTable, mShaderVersion, mExtensionBehavior,1585false, false);1586}15871588const TExtensionBehavior &TCompiler::getExtensionBehavior() const1589{1590return mExtensionBehavior;1591}15921593const char *TCompiler::getSourcePath() const1594{1595return mSourcePath;1596}15971598const ShBuiltInResources &TCompiler::getResources() const1599{1600return mResources;1601}16021603const BuiltInFunctionEmulator &TCompiler::getBuiltInFunctionEmulator() const1604{1605return mBuiltInFunctionEmulator;1606}16071608bool TCompiler::isVaryingDefined(const char *varyingName)1609{1610ASSERT(mVariablesCollected);1611for (size_t ii = 0; ii < mInputVaryings.size(); ++ii)1612{1613if (mInputVaryings[ii].name == varyingName)1614{1615return true;1616}1617}1618for (size_t ii = 0; ii < mOutputVaryings.size(); ++ii)1619{1620if (mOutputVaryings[ii].name == varyingName)1621{1622return true;1623}1624}16251626return false;1627}16281629} // namespace sh163016311632