summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/angle/src/compiler/translator/Compiler.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/3rdparty/angle/src/compiler/translator/Compiler.cpp')
-rw-r--r--src/3rdparty/angle/src/compiler/translator/Compiler.cpp1169
1 files changed, 0 insertions, 1169 deletions
diff --git a/src/3rdparty/angle/src/compiler/translator/Compiler.cpp b/src/3rdparty/angle/src/compiler/translator/Compiler.cpp
deleted file mode 100644
index 2f411cb58c..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/Compiler.cpp
+++ /dev/null
@@ -1,1169 +0,0 @@
-//
-// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#include "compiler/translator/Compiler.h"
-
-#include <sstream>
-
-#include "angle_gl.h"
-#include "common/utilities.h"
-#include "compiler/translator/AddAndTrueToLoopCondition.h"
-#include "compiler/translator/Cache.h"
-#include "compiler/translator/CallDAG.h"
-#include "compiler/translator/ClampPointSize.h"
-#include "compiler/translator/CollectVariables.h"
-#include "compiler/translator/DeclareAndInitBuiltinsForInstancedMultiview.h"
-#include "compiler/translator/DeferGlobalInitializers.h"
-#include "compiler/translator/EmulateGLFragColorBroadcast.h"
-#include "compiler/translator/EmulatePrecision.h"
-#include "compiler/translator/Initialize.h"
-#include "compiler/translator/InitializeVariables.h"
-#include "compiler/translator/IntermNodePatternMatcher.h"
-#include "compiler/translator/IsASTDepthBelowLimit.h"
-#include "compiler/translator/OutputTree.h"
-#include "compiler/translator/ParseContext.h"
-#include "compiler/translator/PruneNoOps.h"
-#include "compiler/translator/RegenerateStructNames.h"
-#include "compiler/translator/RemoveArrayLengthMethod.h"
-#include "compiler/translator/RemoveEmptySwitchStatements.h"
-#include "compiler/translator/RemoveInvariantDeclaration.h"
-#include "compiler/translator/RemoveNoOpCasesFromEndOfSwitchStatements.h"
-#include "compiler/translator/RemovePow.h"
-#include "compiler/translator/RemoveUnreferencedVariables.h"
-#include "compiler/translator/RewriteDoWhile.h"
-#include "compiler/translator/ScalarizeVecAndMatConstructorArgs.h"
-#include "compiler/translator/SeparateDeclarations.h"
-#include "compiler/translator/SimplifyLoopConditions.h"
-#include "compiler/translator/SplitSequenceOperator.h"
-#include "compiler/translator/UnfoldShortCircuitAST.h"
-#include "compiler/translator/UseInterfaceBlockFields.h"
-#include "compiler/translator/ValidateLimitations.h"
-#include "compiler/translator/ValidateMaxParameters.h"
-#include "compiler/translator/ValidateOutputs.h"
-#include "compiler/translator/ValidateVaryingLocations.h"
-#include "compiler/translator/VariablePacker.h"
-#include "compiler/translator/VectorizeVectorScalarArithmetic.h"
-#include "compiler/translator/util.h"
-#include "third_party/compiler/ArrayBoundsClamper.h"
-
-namespace sh
-{
-
-namespace
-{
-
-#if defined(ANGLE_ENABLE_FUZZER_CORPUS_OUTPUT)
-void DumpFuzzerCase(char const *const *shaderStrings,
- size_t numStrings,
- uint32_t type,
- uint32_t spec,
- uint32_t output,
- uint64_t options)
-{
- static int fileIndex = 0;
-
- std::ostringstream o;
- o << "corpus/" << fileIndex++ << ".sample";
- std::string s = o.str();
-
- // Must match the input format of the fuzzer
- FILE *f = fopen(s.c_str(), "w");
- fwrite(&type, sizeof(type), 1, f);
- fwrite(&spec, sizeof(spec), 1, f);
- fwrite(&output, sizeof(output), 1, f);
- fwrite(&options, sizeof(options), 1, f);
-
- char zero[128 - 20] = {0};
- fwrite(&zero, 128 - 20, 1, f);
-
- for (size_t i = 0; i < numStrings; i++)
- {
- fwrite(shaderStrings[i], sizeof(char), strlen(shaderStrings[i]), f);
- }
- fwrite(&zero, 1, 1, f);
-
- fclose(f);
-}
-#endif // defined(ANGLE_ENABLE_FUZZER_CORPUS_OUTPUT)
-} // anonymous namespace
-
-bool IsWebGLBasedSpec(ShShaderSpec spec)
-{
- return (spec == SH_WEBGL_SPEC || spec == SH_WEBGL2_SPEC || spec == SH_WEBGL3_SPEC);
-}
-
-bool IsGLSL130OrNewer(ShShaderOutput output)
-{
- return (output == SH_GLSL_130_OUTPUT || output == SH_GLSL_140_OUTPUT ||
- output == SH_GLSL_150_CORE_OUTPUT || output == SH_GLSL_330_CORE_OUTPUT ||
- output == SH_GLSL_400_CORE_OUTPUT || output == SH_GLSL_410_CORE_OUTPUT ||
- output == SH_GLSL_420_CORE_OUTPUT || output == SH_GLSL_430_CORE_OUTPUT ||
- output == SH_GLSL_440_CORE_OUTPUT || output == SH_GLSL_450_CORE_OUTPUT);
-}
-
-bool IsGLSL420OrNewer(ShShaderOutput output)
-{
- return (output == SH_GLSL_420_CORE_OUTPUT || output == SH_GLSL_430_CORE_OUTPUT ||
- output == SH_GLSL_440_CORE_OUTPUT || output == SH_GLSL_450_CORE_OUTPUT);
-}
-
-bool IsGLSL410OrOlder(ShShaderOutput output)
-{
- return (output == SH_GLSL_130_OUTPUT || output == SH_GLSL_140_OUTPUT ||
- output == SH_GLSL_150_CORE_OUTPUT || output == SH_GLSL_330_CORE_OUTPUT ||
- output == SH_GLSL_400_CORE_OUTPUT || output == SH_GLSL_410_CORE_OUTPUT);
-}
-
-bool RemoveInvariant(sh::GLenum shaderType,
- int shaderVersion,
- ShShaderOutput outputType,
- ShCompileOptions compileOptions)
-{
- if ((compileOptions & SH_DONT_REMOVE_INVARIANT_FOR_FRAGMENT_INPUT) == 0 &&
- shaderType == GL_FRAGMENT_SHADER && IsGLSL420OrNewer(outputType))
- return true;
-
- if ((compileOptions & SH_REMOVE_INVARIANT_AND_CENTROID_FOR_ESSL3) != 0 &&
- shaderVersion >= 300 && shaderType == GL_VERTEX_SHADER)
- return true;
-
- return false;
-}
-
-size_t GetGlobalMaxTokenSize(ShShaderSpec spec)
-{
- // WebGL defines a max token length of 256, while ES2 leaves max token
- // size undefined. ES3 defines a max size of 1024 characters.
- switch (spec)
- {
- case SH_WEBGL_SPEC:
- return 256;
- default:
- return 1024;
- }
-}
-
-int GetMaxUniformVectorsForShaderType(GLenum shaderType, const ShBuiltInResources &resources)
-{
- switch (shaderType)
- {
- case GL_VERTEX_SHADER:
- return resources.MaxVertexUniformVectors;
- case GL_FRAGMENT_SHADER:
- return resources.MaxFragmentUniformVectors;
-
- // TODO (jiawei.shao@intel.com): check if we need finer-grained component counting
- case GL_COMPUTE_SHADER:
- return resources.MaxComputeUniformComponents / 4;
- case GL_GEOMETRY_SHADER_OES:
- return resources.MaxGeometryUniformComponents / 4;
- default:
- UNREACHABLE();
- return -1;
- }
-}
-
-namespace
-{
-
-class TScopedPoolAllocator
-{
- public:
- TScopedPoolAllocator(TPoolAllocator *allocator) : mAllocator(allocator)
- {
- mAllocator->push();
- SetGlobalPoolAllocator(mAllocator);
- }
- ~TScopedPoolAllocator()
- {
- SetGlobalPoolAllocator(nullptr);
- mAllocator->pop();
- }
-
- private:
- TPoolAllocator *mAllocator;
-};
-
-class TScopedSymbolTableLevel
-{
- public:
- TScopedSymbolTableLevel(TSymbolTable *table) : mTable(table)
- {
- ASSERT(mTable->atBuiltInLevel());
- mTable->push();
- }
- ~TScopedSymbolTableLevel()
- {
- while (!mTable->atBuiltInLevel())
- mTable->pop();
- }
-
- private:
- TSymbolTable *mTable;
-};
-
-int MapSpecToShaderVersion(ShShaderSpec spec)
-{
- switch (spec)
- {
- case SH_GLES2_SPEC:
- case SH_WEBGL_SPEC:
- return 100;
- case SH_GLES3_SPEC:
- case SH_WEBGL2_SPEC:
- return 300;
- case SH_GLES3_1_SPEC:
- case SH_WEBGL3_SPEC:
- return 310;
- default:
- UNREACHABLE();
- return 0;
- }
-}
-
-} // namespace
-
-TShHandleBase::TShHandleBase()
-{
- allocator.push();
- SetGlobalPoolAllocator(&allocator);
-}
-
-TShHandleBase::~TShHandleBase()
-{
- SetGlobalPoolAllocator(nullptr);
- allocator.popAll();
-}
-
-TCompiler::TCompiler(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output)
- : variablesCollected(false),
- mGLPositionInitialized(false),
- shaderType(type),
- shaderSpec(spec),
- outputType(output),
- maxUniformVectors(0),
- maxExpressionComplexity(0),
- maxCallStackDepth(0),
- maxFunctionParameters(0),
- fragmentPrecisionHigh(false),
- clampingStrategy(SH_CLAMP_WITH_CLAMP_INTRINSIC),
- builtInFunctionEmulator(),
- mDiagnostics(infoSink.info),
- mSourcePath(nullptr),
- mComputeShaderLocalSizeDeclared(false),
- mComputeShaderLocalSize(1),
- mGeometryShaderMaxVertices(-1),
- mGeometryShaderInvocations(0),
- mGeometryShaderInputPrimitiveType(EptUndefined),
- mGeometryShaderOutputPrimitiveType(EptUndefined)
-{
-}
-
-TCompiler::~TCompiler()
-{
-}
-
-bool TCompiler::shouldRunLoopAndIndexingValidation(ShCompileOptions compileOptions) const
-{
- // If compiling an ESSL 1.00 shader for WebGL, or if its been requested through the API,
- // validate loop and indexing as well (to verify that the shader only uses minimal functionality
- // of ESSL 1.00 as in Appendix A of the spec).
- return (IsWebGLBasedSpec(shaderSpec) && shaderVersion == 100) ||
- (compileOptions & SH_VALIDATE_LOOP_INDEXING);
-}
-
-bool TCompiler::Init(const ShBuiltInResources &resources)
-{
- shaderVersion = 100;
-
- maxUniformVectors = GetMaxUniformVectorsForShaderType(shaderType, resources);
-
- maxExpressionComplexity = resources.MaxExpressionComplexity;
- maxCallStackDepth = resources.MaxCallStackDepth;
- maxFunctionParameters = resources.MaxFunctionParameters;
-
- SetGlobalPoolAllocator(&allocator);
-
- // Generate built-in symbol table.
- if (!InitBuiltInSymbolTable(resources))
- return false;
- InitExtensionBehavior(resources, extensionBehavior);
- fragmentPrecisionHigh = resources.FragmentPrecisionHigh == 1;
-
- arrayBoundsClamper.SetClampingStrategy(resources.ArrayIndexClampingStrategy);
- clampingStrategy = resources.ArrayIndexClampingStrategy;
-
- hashFunction = resources.HashFunction;
-
- return true;
-}
-
-TIntermBlock *TCompiler::compileTreeForTesting(const char *const shaderStrings[],
- size_t numStrings,
- ShCompileOptions compileOptions)
-{
- return compileTreeImpl(shaderStrings, numStrings, compileOptions);
-}
-
-TIntermBlock *TCompiler::compileTreeImpl(const char *const shaderStrings[],
- size_t numStrings,
- const ShCompileOptions compileOptions)
-{
- clearResults();
-
- ASSERT(numStrings > 0);
- ASSERT(GetGlobalPoolAllocator());
-
- // Reset the extension behavior for each compilation unit.
- ResetExtensionBehavior(extensionBehavior);
-
- // First string is path of source file if flag is set. The actual source follows.
- size_t firstSource = 0;
- if (compileOptions & SH_SOURCE_PATH)
- {
- mSourcePath = shaderStrings[0];
- ++firstSource;
- }
-
- TParseContext parseContext(symbolTable, extensionBehavior, shaderType, shaderSpec,
- compileOptions, true, &mDiagnostics, getResources());
-
- parseContext.setFragmentPrecisionHighOnESSL1(fragmentPrecisionHigh);
-
- // We preserve symbols at the built-in level from compile-to-compile.
- // Start pushing the user-defined symbols at global level.
- TScopedSymbolTableLevel scopedSymbolLevel(&symbolTable);
-
- // Parse shader.
- if (PaParseStrings(numStrings - firstSource, &shaderStrings[firstSource], nullptr,
- &parseContext) != 0)
- {
- return nullptr;
- }
-
- if (parseContext.getTreeRoot() == nullptr)
- {
- return nullptr;
- }
-
- setASTMetadata(parseContext);
-
- if (MapSpecToShaderVersion(shaderSpec) < shaderVersion)
- {
- mDiagnostics.globalError("unsupported shader version");
- return nullptr;
- }
-
- TIntermBlock *root = parseContext.getTreeRoot();
- if (!checkAndSimplifyAST(root, parseContext, compileOptions))
- {
- return nullptr;
- }
-
- return root;
-}
-
-void TCompiler::setASTMetadata(const TParseContext &parseContext)
-{
- shaderVersion = parseContext.getShaderVersion();
-
- mPragma = parseContext.pragma();
- symbolTable.setGlobalInvariant(mPragma.stdgl.invariantAll);
-
- mComputeShaderLocalSizeDeclared = parseContext.isComputeShaderLocalSizeDeclared();
- mComputeShaderLocalSize = parseContext.getComputeShaderLocalSize();
-
- mNumViews = parseContext.getNumViews();
-
- // Highp might have been auto-enabled based on shader version
- fragmentPrecisionHigh = parseContext.getFragmentPrecisionHigh();
-
- if (shaderType == GL_GEOMETRY_SHADER_OES)
- {
- mGeometryShaderInputPrimitiveType = parseContext.getGeometryShaderInputPrimitiveType();
- mGeometryShaderOutputPrimitiveType = parseContext.getGeometryShaderOutputPrimitiveType();
- mGeometryShaderMaxVertices = parseContext.getGeometryShaderMaxVertices();
- mGeometryShaderInvocations = parseContext.getGeometryShaderInvocations();
- }
-}
-
-bool TCompiler::checkAndSimplifyAST(TIntermBlock *root,
- const TParseContext &parseContext,
- ShCompileOptions compileOptions)
-{
- // Disallow expressions deemed too complex.
- if ((compileOptions & SH_LIMIT_EXPRESSION_COMPLEXITY) && !limitExpressionComplexity(root))
- {
- return false;
- }
-
- // We prune no-ops to work around driver bugs and to keep AST processing and output simple.
- // The following kinds of no-ops are pruned:
- // 1. Empty declarations "int;".
- // 2. Literal statements: "1.0;". The ESSL output doesn't define a default precision
- // for float, so float literal statements would end up with no precision which is
- // invalid ESSL.
- // After this empty declarations are not allowed in the AST.
- PruneNoOps(root);
-
- // In case the last case inside a switch statement is a certain type of no-op, GLSL
- // compilers in drivers may not accept it. In this case we clean up the dead code from the
- // end of switch statements. This is also required because PruneNoOps may have left switch
- // statements that only contained an empty declaration inside the final case in an invalid
- // state. Relies on that PruneNoOps has already been run.
- RemoveNoOpCasesFromEndOfSwitchStatements(root, &symbolTable);
-
- // Remove empty switch statements - this makes output simpler.
- RemoveEmptySwitchStatements(root);
-
- // Create the function DAG and check there is no recursion
- if (!initCallDag(root))
- {
- return false;
- }
-
- if ((compileOptions & SH_LIMIT_CALL_STACK_DEPTH) && !checkCallDepth())
- {
- return false;
- }
-
- // Checks which functions are used and if "main" exists
- functionMetadata.clear();
- functionMetadata.resize(mCallDag.size());
- if (!tagUsedFunctions())
- {
- return false;
- }
-
- if (!(compileOptions & SH_DONT_PRUNE_UNUSED_FUNCTIONS))
- {
- pruneUnusedFunctions(root);
- }
-
- if (shaderVersion >= 310 && !ValidateVaryingLocations(root, &mDiagnostics, shaderType))
- {
- return false;
- }
-
- if (shaderVersion >= 300 && shaderType == GL_FRAGMENT_SHADER &&
- !ValidateOutputs(root, getExtensionBehavior(), compileResources.MaxDrawBuffers,
- &mDiagnostics))
- {
- return false;
- }
-
- if (shouldRunLoopAndIndexingValidation(compileOptions) &&
- !ValidateLimitations(root, shaderType, &symbolTable, shaderVersion, &mDiagnostics))
- {
- return false;
- }
-
- // Fail compilation if precision emulation not supported.
- if (getResources().WEBGL_debug_shader_precision && getPragma().debugShaderPrecision &&
- !EmulatePrecision::SupportedInLanguage(outputType))
- {
- mDiagnostics.globalError("Precision emulation not supported for this output type.");
- return false;
- }
-
- // Clamping uniform array bounds needs to happen after validateLimitations pass.
- if (compileOptions & SH_CLAMP_INDIRECT_ARRAY_BOUNDS)
- {
- arrayBoundsClamper.MarkIndirectArrayBoundsForClamping(root);
- }
-
- if ((compileOptions & SH_INITIALIZE_BUILTINS_FOR_INSTANCED_MULTIVIEW) &&
- parseContext.isExtensionEnabled(TExtension::OVR_multiview) &&
- getShaderType() != GL_COMPUTE_SHADER)
- {
- DeclareAndInitBuiltinsForInstancedMultiview(root, mNumViews, shaderType, compileOptions,
- outputType, &symbolTable);
- }
-
- // This pass might emit short circuits so keep it before the short circuit unfolding
- if (compileOptions & SH_REWRITE_DO_WHILE_LOOPS)
- RewriteDoWhile(root, &symbolTable);
-
- if (compileOptions & SH_ADD_AND_TRUE_TO_LOOP_CONDITION)
- sh::AddAndTrueToLoopCondition(root);
-
- if (compileOptions & SH_UNFOLD_SHORT_CIRCUIT)
- {
- UnfoldShortCircuitAST unfoldShortCircuit;
- root->traverse(&unfoldShortCircuit);
- unfoldShortCircuit.updateTree();
- }
-
- if (compileOptions & SH_REMOVE_POW_WITH_CONSTANT_EXPONENT)
- {
- RemovePow(root);
- }
-
- if (compileOptions & SH_REGENERATE_STRUCT_NAMES)
- {
- RegenerateStructNames gen(&symbolTable, shaderVersion);
- root->traverse(&gen);
- }
-
- if (shaderType == GL_FRAGMENT_SHADER && shaderVersion == 100 &&
- compileResources.EXT_draw_buffers && compileResources.MaxDrawBuffers > 1 &&
- IsExtensionEnabled(extensionBehavior, TExtension::EXT_draw_buffers))
- {
- EmulateGLFragColorBroadcast(root, compileResources.MaxDrawBuffers, &outputVariables,
- &symbolTable, shaderVersion);
- }
-
- // Split multi declarations and remove calls to array length().
- // Note that SimplifyLoopConditions needs to be run before any other AST transformations
- // that may need to generate new statements from loop conditions or loop expressions.
- SimplifyLoopConditions(
- root,
- IntermNodePatternMatcher::kMultiDeclaration | IntermNodePatternMatcher::kArrayLengthMethod,
- &getSymbolTable(), getShaderVersion());
-
- // Note that separate declarations need to be run before other AST transformations that
- // generate new statements from expressions.
- SeparateDeclarations(root);
-
- SplitSequenceOperator(root, IntermNodePatternMatcher::kArrayLengthMethod, &getSymbolTable(),
- getShaderVersion());
-
- RemoveArrayLengthMethod(root);
-
- RemoveUnreferencedVariables(root, &symbolTable);
-
- // Built-in function emulation needs to happen after validateLimitations pass.
- // TODO(jmadill): Remove global pool allocator.
- GetGlobalPoolAllocator()->lock();
- initBuiltInFunctionEmulator(&builtInFunctionEmulator, compileOptions);
- GetGlobalPoolAllocator()->unlock();
- builtInFunctionEmulator.markBuiltInFunctionsForEmulation(root);
-
- if (compileOptions & SH_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS)
- {
- ScalarizeVecAndMatConstructorArgs(root, shaderType, fragmentPrecisionHigh, &symbolTable);
- }
-
- if (shouldCollectVariables(compileOptions))
- {
- ASSERT(!variablesCollected);
- CollectVariables(root, &attributes, &outputVariables, &uniforms, &inputVaryings,
- &outputVaryings, &uniformBlocks, &shaderStorageBlocks, &inBlocks,
- hashFunction, &symbolTable, shaderVersion, shaderType, extensionBehavior);
- collectInterfaceBlocks();
- variablesCollected = true;
- if (compileOptions & SH_USE_UNUSED_STANDARD_SHARED_BLOCKS)
- {
- useAllMembersInUnusedStandardAndSharedBlocks(root);
- }
- if (compileOptions & SH_ENFORCE_PACKING_RESTRICTIONS)
- {
- // Returns true if, after applying the packing rules in the GLSL ES 1.00.17 spec
- // Appendix A, section 7, the shader does not use too many uniforms.
- if (!CheckVariablesInPackingLimits(maxUniformVectors, uniforms))
- {
- mDiagnostics.globalError("too many uniforms");
- return false;
- }
- }
- if (compileOptions & SH_INIT_OUTPUT_VARIABLES)
- {
- initializeOutputVariables(root);
- }
- }
-
- // Removing invariant declarations must be done after collecting variables.
- // Otherwise, built-in invariant declarations don't apply.
- if (RemoveInvariant(shaderType, shaderVersion, outputType, compileOptions))
- {
- RemoveInvariantDeclaration(root);
- }
-
- // gl_Position is always written in compatibility output mode.
- // It may have been already initialized among other output variables, in that case we don't
- // need to initialize it twice.
- if (shaderType == GL_VERTEX_SHADER && !mGLPositionInitialized &&
- ((compileOptions & SH_INIT_GL_POSITION) || (outputType == SH_GLSL_COMPATIBILITY_OUTPUT)))
- {
- initializeGLPosition(root);
- mGLPositionInitialized = true;
- }
-
- // DeferGlobalInitializers needs to be run before other AST transformations that generate new
- // statements from expressions. But it's fine to run DeferGlobalInitializers after the above
- // SplitSequenceOperator and RemoveArrayLengthMethod since they only have an effect on the AST
- // on ESSL >= 3.00, and the initializers that need to be deferred can only exist in ESSL < 3.00.
- bool initializeLocalsAndGlobals =
- (compileOptions & SH_INITIALIZE_UNINITIALIZED_LOCALS) && !IsOutputHLSL(getOutputType());
- bool canUseLoopsToInitialize = !(compileOptions & SH_DONT_USE_LOOPS_TO_INITIALIZE_VARIABLES);
- DeferGlobalInitializers(root, initializeLocalsAndGlobals, canUseLoopsToInitialize, &symbolTable);
-
- if (initializeLocalsAndGlobals)
- {
- // Initialize uninitialized local variables.
- // In some cases initializing can generate extra statements in the parent block, such as
- // when initializing nameless structs or initializing arrays in ESSL 1.00. In that case
- // we need to first simplify loop conditions. We've already separated declarations
- // earlier, which is also required. If we don't follow the Appendix A limitations, loop
- // init statements can declare arrays or nameless structs and have multiple
- // declarations.
-
- if (!shouldRunLoopAndIndexingValidation(compileOptions))
- {
- SimplifyLoopConditions(root,
- IntermNodePatternMatcher::kArrayDeclaration |
- IntermNodePatternMatcher::kNamelessStructDeclaration,
- &getSymbolTable(), getShaderVersion());
- }
-
- InitializeUninitializedLocals(root, getShaderVersion(), canUseLoopsToInitialize,
- &getSymbolTable());
- }
-
- if (getShaderType() == GL_VERTEX_SHADER && (compileOptions & SH_CLAMP_POINT_SIZE))
- {
- ClampPointSize(root, compileResources.MaxPointSize, &getSymbolTable());
- }
-
- if (compileOptions & SH_REWRITE_VECTOR_SCALAR_ARITHMETIC)
- {
- VectorizeVectorScalarArithmetic(root, &getSymbolTable());
- }
-
- return true;
-}
-
-bool TCompiler::compile(const char *const shaderStrings[],
- size_t numStrings,
- ShCompileOptions compileOptionsIn)
-{
-#if defined(ANGLE_ENABLE_FUZZER_CORPUS_OUTPUT)
- DumpFuzzerCase(shaderStrings, numStrings, shaderType, shaderSpec, outputType, compileOptionsIn);
-#endif // defined(ANGLE_ENABLE_FUZZER_CORPUS_OUTPUT)
-
- if (numStrings == 0)
- return true;
-
- ShCompileOptions compileOptions = compileOptionsIn;
-
- // Apply key workarounds.
- if (shouldFlattenPragmaStdglInvariantAll())
- {
- // This should be harmless to do in all cases, but for the moment, do it only conditionally.
- compileOptions |= SH_FLATTEN_PRAGMA_STDGL_INVARIANT_ALL;
- }
-
- TScopedPoolAllocator scopedAlloc(&allocator);
- TIntermBlock *root = compileTreeImpl(shaderStrings, numStrings, compileOptions);
-
- if (root)
- {
- if (compileOptions & SH_INTERMEDIATE_TREE)
- OutputTree(root, infoSink.info);
-
- if (compileOptions & SH_OBJECT_CODE)
- {
- PerformanceDiagnostics perfDiagnostics(&mDiagnostics);
- translate(root, compileOptions, &perfDiagnostics);
- }
-
- // The IntermNode tree doesn't need to be deleted here, since the
- // memory will be freed in a big chunk by the PoolAllocator.
- return true;
- }
- return false;
-}
-
-bool TCompiler::InitBuiltInSymbolTable(const ShBuiltInResources &resources)
-{
- if (resources.MaxDrawBuffers < 1)
- {
- return false;
- }
- if (resources.EXT_blend_func_extended && resources.MaxDualSourceDrawBuffers < 1)
- {
- return false;
- }
-
- compileResources = resources;
- setResourceString();
-
- ASSERT(symbolTable.isEmpty());
- symbolTable.push(); // COMMON_BUILTINS
- symbolTable.push(); // ESSL1_BUILTINS
- symbolTable.push(); // ESSL3_BUILTINS
- symbolTable.push(); // ESSL3_1_BUILTINS
- symbolTable.push(); // GLSL_BUILTINS
-
- switch (shaderType)
- {
- case GL_FRAGMENT_SHADER:
- symbolTable.setDefaultPrecision(EbtInt, EbpMedium);
- break;
- case GL_VERTEX_SHADER:
- case GL_COMPUTE_SHADER:
- case GL_GEOMETRY_SHADER_OES:
- symbolTable.setDefaultPrecision(EbtInt, EbpHigh);
- symbolTable.setDefaultPrecision(EbtFloat, EbpHigh);
- break;
- default:
- UNREACHABLE();
- }
- // Set defaults for sampler types that have default precision, even those that are
- // only available if an extension exists.
- // New sampler types in ESSL3 don't have default precision. ESSL1 types do.
- initSamplerDefaultPrecision(EbtSampler2D);
- initSamplerDefaultPrecision(EbtSamplerCube);
- // SamplerExternalOES is specified in the extension to have default precision.
- initSamplerDefaultPrecision(EbtSamplerExternalOES);
- // SamplerExternal2DY2YEXT is specified in the extension to have default precision.
- initSamplerDefaultPrecision(EbtSamplerExternal2DY2YEXT);
- // It isn't specified whether Sampler2DRect has default precision.
- initSamplerDefaultPrecision(EbtSampler2DRect);
-
- symbolTable.setDefaultPrecision(EbtAtomicCounter, EbpHigh);
-
- InsertBuiltInFunctions(shaderType, shaderSpec, resources, symbolTable);
-
- IdentifyBuiltIns(shaderType, shaderSpec, resources, symbolTable);
-
- return true;
-}
-
-void TCompiler::initSamplerDefaultPrecision(TBasicType samplerType)
-{
- ASSERT(samplerType > EbtGuardSamplerBegin && samplerType < EbtGuardSamplerEnd);
- symbolTable.setDefaultPrecision(samplerType, EbpLow);
-}
-
-void TCompiler::setResourceString()
-{
- std::ostringstream strstream;
-
- // clang-format off
- strstream << ":MaxVertexAttribs:" << compileResources.MaxVertexAttribs
- << ":MaxVertexUniformVectors:" << compileResources.MaxVertexUniformVectors
- << ":MaxVaryingVectors:" << compileResources.MaxVaryingVectors
- << ":MaxVertexTextureImageUnits:" << compileResources.MaxVertexTextureImageUnits
- << ":MaxCombinedTextureImageUnits:" << compileResources.MaxCombinedTextureImageUnits
- << ":MaxTextureImageUnits:" << compileResources.MaxTextureImageUnits
- << ":MaxFragmentUniformVectors:" << compileResources.MaxFragmentUniformVectors
- << ":MaxDrawBuffers:" << compileResources.MaxDrawBuffers
- << ":OES_standard_derivatives:" << compileResources.OES_standard_derivatives
- << ":OES_EGL_image_external:" << compileResources.OES_EGL_image_external
- << ":OES_EGL_image_external_essl3:" << compileResources.OES_EGL_image_external_essl3
- << ":NV_EGL_stream_consumer_external:" << compileResources.NV_EGL_stream_consumer_external
- << ":ARB_texture_rectangle:" << compileResources.ARB_texture_rectangle
- << ":EXT_draw_buffers:" << compileResources.EXT_draw_buffers
- << ":FragmentPrecisionHigh:" << compileResources.FragmentPrecisionHigh
- << ":MaxExpressionComplexity:" << compileResources.MaxExpressionComplexity
- << ":MaxCallStackDepth:" << compileResources.MaxCallStackDepth
- << ":MaxFunctionParameters:" << compileResources.MaxFunctionParameters
- << ":EXT_blend_func_extended:" << compileResources.EXT_blend_func_extended
- << ":EXT_frag_depth:" << compileResources.EXT_frag_depth
- << ":EXT_shader_texture_lod:" << compileResources.EXT_shader_texture_lod
- << ":EXT_shader_framebuffer_fetch:" << compileResources.EXT_shader_framebuffer_fetch
- << ":NV_shader_framebuffer_fetch:" << compileResources.NV_shader_framebuffer_fetch
- << ":ARM_shader_framebuffer_fetch:" << compileResources.ARM_shader_framebuffer_fetch
- << ":OVR_multiview:" << compileResources.OVR_multiview
- << ":EXT_YUV_target:" << compileResources.EXT_YUV_target
- << ":OES_geometry_shader:" << compileResources.OES_geometry_shader
- << ":MaxVertexOutputVectors:" << compileResources.MaxVertexOutputVectors
- << ":MaxFragmentInputVectors:" << compileResources.MaxFragmentInputVectors
- << ":MinProgramTexelOffset:" << compileResources.MinProgramTexelOffset
- << ":MaxProgramTexelOffset:" << compileResources.MaxProgramTexelOffset
- << ":MaxDualSourceDrawBuffers:" << compileResources.MaxDualSourceDrawBuffers
- << ":MaxViewsOVR:" << compileResources.MaxViewsOVR
- << ":NV_draw_buffers:" << compileResources.NV_draw_buffers
- << ":WEBGL_debug_shader_precision:" << compileResources.WEBGL_debug_shader_precision
- << ":MinProgramTextureGatherOffset:" << compileResources.MinProgramTextureGatherOffset
- << ":MaxProgramTextureGatherOffset:" << compileResources.MaxProgramTextureGatherOffset
- << ":MaxImageUnits:" << compileResources.MaxImageUnits
- << ":MaxVertexImageUniforms:" << compileResources.MaxVertexImageUniforms
- << ":MaxFragmentImageUniforms:" << compileResources.MaxFragmentImageUniforms
- << ":MaxComputeImageUniforms:" << compileResources.MaxComputeImageUniforms
- << ":MaxCombinedImageUniforms:" << compileResources.MaxCombinedImageUniforms
- << ":MaxCombinedShaderOutputResources:" << compileResources.MaxCombinedShaderOutputResources
- << ":MaxComputeWorkGroupCountX:" << compileResources.MaxComputeWorkGroupCount[0]
- << ":MaxComputeWorkGroupCountY:" << compileResources.MaxComputeWorkGroupCount[1]
- << ":MaxComputeWorkGroupCountZ:" << compileResources.MaxComputeWorkGroupCount[2]
- << ":MaxComputeWorkGroupSizeX:" << compileResources.MaxComputeWorkGroupSize[0]
- << ":MaxComputeWorkGroupSizeY:" << compileResources.MaxComputeWorkGroupSize[1]
- << ":MaxComputeWorkGroupSizeZ:" << compileResources.MaxComputeWorkGroupSize[2]
- << ":MaxComputeUniformComponents:" << compileResources.MaxComputeUniformComponents
- << ":MaxComputeTextureImageUnits:" << compileResources.MaxComputeTextureImageUnits
- << ":MaxComputeAtomicCounters:" << compileResources.MaxComputeAtomicCounters
- << ":MaxComputeAtomicCounterBuffers:" << compileResources.MaxComputeAtomicCounterBuffers
- << ":MaxVertexAtomicCounters:" << compileResources.MaxVertexAtomicCounters
- << ":MaxFragmentAtomicCounters:" << compileResources.MaxFragmentAtomicCounters
- << ":MaxCombinedAtomicCounters:" << compileResources.MaxCombinedAtomicCounters
- << ":MaxAtomicCounterBindings:" << compileResources.MaxAtomicCounterBindings
- << ":MaxVertexAtomicCounterBuffers:" << compileResources.MaxVertexAtomicCounterBuffers
- << ":MaxFragmentAtomicCounterBuffers:" << compileResources.MaxFragmentAtomicCounterBuffers
- << ":MaxCombinedAtomicCounterBuffers:" << compileResources.MaxCombinedAtomicCounterBuffers
- << ":MaxAtomicCounterBufferSize:" << compileResources.MaxAtomicCounterBufferSize
- << ":MaxGeometryUniformComponents:" << compileResources.MaxGeometryUniformComponents
- << ":MaxGeometryUniformBlocks:" << compileResources.MaxGeometryUniformBlocks
- << ":MaxGeometryInputComponents:" << compileResources.MaxGeometryInputComponents
- << ":MaxGeometryOutputComponents:" << compileResources.MaxGeometryOutputComponents
- << ":MaxGeometryOutputVertices:" << compileResources.MaxGeometryOutputVertices
- << ":MaxGeometryTotalOutputComponents:" << compileResources.MaxGeometryTotalOutputComponents
- << ":MaxGeometryTextureImageUnits:" << compileResources.MaxGeometryTextureImageUnits
- << ":MaxGeometryAtomicCounterBuffers:" << compileResources.MaxGeometryAtomicCounterBuffers
- << ":MaxGeometryAtomicCounters:" << compileResources.MaxGeometryAtomicCounters
- << ":MaxGeometryShaderStorageBlocks:" << compileResources.MaxGeometryShaderStorageBlocks
- << ":MaxGeometryShaderInvocations:" << compileResources.MaxGeometryShaderInvocations
- << ":MaxGeometryImageUniforms:" << compileResources.MaxGeometryImageUniforms;
- // clang-format on
-
- builtInResourcesString = strstream.str();
-}
-
-void TCompiler::collectInterfaceBlocks()
-{
- ASSERT(interfaceBlocks.empty());
- interfaceBlocks.reserve(uniformBlocks.size() + shaderStorageBlocks.size() + inBlocks.size());
- interfaceBlocks.insert(interfaceBlocks.end(), uniformBlocks.begin(), uniformBlocks.end());
- interfaceBlocks.insert(interfaceBlocks.end(), shaderStorageBlocks.begin(),
- shaderStorageBlocks.end());
- interfaceBlocks.insert(interfaceBlocks.end(), inBlocks.begin(), inBlocks.end());
-}
-
-void TCompiler::clearResults()
-{
- arrayBoundsClamper.Cleanup();
- infoSink.info.erase();
- infoSink.obj.erase();
- infoSink.debug.erase();
- mDiagnostics.resetErrorCount();
-
- attributes.clear();
- outputVariables.clear();
- uniforms.clear();
- inputVaryings.clear();
- outputVaryings.clear();
- interfaceBlocks.clear();
- uniformBlocks.clear();
- shaderStorageBlocks.clear();
- inBlocks.clear();
- variablesCollected = false;
- mGLPositionInitialized = false;
-
- mNumViews = -1;
-
- mGeometryShaderInputPrimitiveType = EptUndefined;
- mGeometryShaderOutputPrimitiveType = EptUndefined;
- mGeometryShaderInvocations = 0;
- mGeometryShaderMaxVertices = -1;
-
- builtInFunctionEmulator.cleanup();
-
- nameMap.clear();
-
- mSourcePath = nullptr;
-}
-
-bool TCompiler::initCallDag(TIntermNode *root)
-{
- mCallDag.clear();
-
- switch (mCallDag.init(root, &mDiagnostics))
- {
- case CallDAG::INITDAG_SUCCESS:
- return true;
- case CallDAG::INITDAG_RECURSION:
- case CallDAG::INITDAG_UNDEFINED:
- // Error message has already been written out.
- ASSERT(mDiagnostics.numErrors() > 0);
- return false;
- }
-
- UNREACHABLE();
- return true;
-}
-
-bool TCompiler::checkCallDepth()
-{
- std::vector<int> depths(mCallDag.size());
-
- for (size_t i = 0; i < mCallDag.size(); i++)
- {
- int depth = 0;
- auto &record = mCallDag.getRecordFromIndex(i);
-
- for (auto &calleeIndex : record.callees)
- {
- depth = std::max(depth, depths[calleeIndex] + 1);
- }
-
- depths[i] = depth;
-
- if (depth >= maxCallStackDepth)
- {
- // Trace back the function chain to have a meaningful info log.
- std::stringstream errorStream;
- errorStream << "Call stack too deep (larger than " << maxCallStackDepth
- << ") with the following call chain: " << record.name;
-
- int currentFunction = static_cast<int>(i);
- int currentDepth = depth;
-
- while (currentFunction != -1)
- {
- errorStream << " -> " << mCallDag.getRecordFromIndex(currentFunction).name;
-
- int nextFunction = -1;
- for (auto &calleeIndex : mCallDag.getRecordFromIndex(currentFunction).callees)
- {
- if (depths[calleeIndex] == currentDepth - 1)
- {
- currentDepth--;
- nextFunction = calleeIndex;
- }
- }
-
- currentFunction = nextFunction;
- }
-
- std::string errorStr = errorStream.str();
- mDiagnostics.globalError(errorStr.c_str());
-
- return false;
- }
- }
-
- return true;
-}
-
-bool TCompiler::tagUsedFunctions()
-{
- // Search from main, starting from the end of the DAG as it usually is the root.
- for (size_t i = mCallDag.size(); i-- > 0;)
- {
- if (mCallDag.getRecordFromIndex(i).name == "main")
- {
- internalTagUsedFunction(i);
- return true;
- }
- }
-
- mDiagnostics.globalError("Missing main()");
- return false;
-}
-
-void TCompiler::internalTagUsedFunction(size_t index)
-{
- if (functionMetadata[index].used)
- {
- return;
- }
-
- functionMetadata[index].used = true;
-
- for (int calleeIndex : mCallDag.getRecordFromIndex(index).callees)
- {
- internalTagUsedFunction(calleeIndex);
- }
-}
-
-// A predicate for the stl that returns if a top-level node is unused
-class TCompiler::UnusedPredicate
-{
- public:
- UnusedPredicate(const CallDAG *callDag, const std::vector<FunctionMetadata> *metadatas)
- : mCallDag(callDag), mMetadatas(metadatas)
- {
- }
-
- bool operator()(TIntermNode *node)
- {
- const TIntermFunctionPrototype *asFunctionPrototype = node->getAsFunctionPrototypeNode();
- const TIntermFunctionDefinition *asFunctionDefinition = node->getAsFunctionDefinition();
-
- const TFunctionSymbolInfo *functionInfo = nullptr;
-
- if (asFunctionDefinition)
- {
- functionInfo = asFunctionDefinition->getFunctionSymbolInfo();
- }
- else if (asFunctionPrototype)
- {
- functionInfo = asFunctionPrototype->getFunctionSymbolInfo();
- }
- if (functionInfo == nullptr)
- {
- return false;
- }
-
- size_t callDagIndex = mCallDag->findIndex(functionInfo);
- if (callDagIndex == CallDAG::InvalidIndex)
- {
- // This happens only for unimplemented prototypes which are thus unused
- ASSERT(asFunctionPrototype);
- return true;
- }
-
- ASSERT(callDagIndex < mMetadatas->size());
- return !(*mMetadatas)[callDagIndex].used;
- }
-
- private:
- const CallDAG *mCallDag;
- const std::vector<FunctionMetadata> *mMetadatas;
-};
-
-void TCompiler::pruneUnusedFunctions(TIntermBlock *root)
-{
- UnusedPredicate isUnused(&mCallDag, &functionMetadata);
- TIntermSequence *sequence = root->getSequence();
-
- if (!sequence->empty())
- {
- sequence->erase(std::remove_if(sequence->begin(), sequence->end(), isUnused),
- sequence->end());
- }
-}
-
-bool TCompiler::limitExpressionComplexity(TIntermBlock *root)
-{
- if (!IsASTDepthBelowLimit(root, maxExpressionComplexity))
- {
- mDiagnostics.globalError("Expression too complex.");
- return false;
- }
-
- if (!ValidateMaxParameters(root, maxFunctionParameters))
- {
- mDiagnostics.globalError("Function has too many parameters.");
- return false;
- }
-
- return true;
-}
-
-bool TCompiler::shouldCollectVariables(ShCompileOptions compileOptions)
-{
- return (compileOptions & SH_VARIABLES) != 0;
-}
-
-bool TCompiler::wereVariablesCollected() const
-{
- return variablesCollected;
-}
-
-void TCompiler::initializeGLPosition(TIntermBlock *root)
-{
- InitVariableList list;
- sh::ShaderVariable var(GL_FLOAT_VEC4);
- var.name = "gl_Position";
- list.push_back(var);
- InitializeVariables(root, list, &symbolTable, shaderVersion, extensionBehavior, false);
-}
-
-void TCompiler::useAllMembersInUnusedStandardAndSharedBlocks(TIntermBlock *root)
-{
- sh::InterfaceBlockList list;
-
- for (auto block : uniformBlocks)
- {
- if (!block.staticUse &&
- (block.layout == sh::BLOCKLAYOUT_STD140 || block.layout == sh::BLOCKLAYOUT_SHARED))
- {
- list.push_back(block);
- }
- }
-
- sh::UseInterfaceBlockFields(root, list, symbolTable);
-}
-
-void TCompiler::initializeOutputVariables(TIntermBlock *root)
-{
- InitVariableList list;
- if (shaderType == GL_VERTEX_SHADER || shaderType == GL_GEOMETRY_SHADER_OES)
- {
- for (auto var : outputVaryings)
- {
- list.push_back(var);
- if (var.name == "gl_Position")
- {
- ASSERT(!mGLPositionInitialized);
- mGLPositionInitialized = true;
- }
- }
- }
- else
- {
- ASSERT(shaderType == GL_FRAGMENT_SHADER);
- for (auto var : outputVariables)
- {
- list.push_back(var);
- }
- }
- InitializeVariables(root, list, &symbolTable, shaderVersion, extensionBehavior, false);
-}
-
-const TExtensionBehavior &TCompiler::getExtensionBehavior() const
-{
- return extensionBehavior;
-}
-
-const char *TCompiler::getSourcePath() const
-{
- return mSourcePath;
-}
-
-const ShBuiltInResources &TCompiler::getResources() const
-{
- return compileResources;
-}
-
-const ArrayBoundsClamper &TCompiler::getArrayBoundsClamper() const
-{
- return arrayBoundsClamper;
-}
-
-ShArrayIndexClampingStrategy TCompiler::getArrayIndexClampingStrategy() const
-{
- return clampingStrategy;
-}
-
-const BuiltInFunctionEmulator &TCompiler::getBuiltInFunctionEmulator() const
-{
- return builtInFunctionEmulator;
-}
-
-void TCompiler::writePragma(ShCompileOptions compileOptions)
-{
- if (!(compileOptions & SH_FLATTEN_PRAGMA_STDGL_INVARIANT_ALL))
- {
- TInfoSinkBase &sink = infoSink.obj;
- if (mPragma.stdgl.invariantAll)
- sink << "#pragma STDGL invariant(all)\n";
- }
-}
-
-bool TCompiler::isVaryingDefined(const char *varyingName)
-{
- ASSERT(variablesCollected);
- for (size_t ii = 0; ii < inputVaryings.size(); ++ii)
- {
- if (inputVaryings[ii].name == varyingName)
- {
- return true;
- }
- }
- for (size_t ii = 0; ii < outputVaryings.size(); ++ii)
- {
- if (outputVaryings[ii].name == varyingName)
- {
- return true;
- }
- }
-
- return false;
-}
-
-} // namespace sh