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