blob: 946d1e589583494ac3a7300d5ab1e6a8e8a42a07 [file] [log] [blame]
alokp@chromium.org07620a52010-09-23 17:53:56 +00001//
Jamie Madill88f6e942014-02-19 10:27:53 -05002// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved.
alokp@chromium.org07620a52010-09-23 17:53:56 +00003// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
Corentin Wallez8b28a8b2016-09-15 19:47:56 -04007#include "compiler/translator/Compiler.h"
8
9#include <sstream>
10
11#include "angle_gl.h"
12#include "common/utilities.h"
Corentin Wallez71d147f2015-02-11 11:15:24 -080013#include "compiler/translator/CallDAG.h"
Olli Etuaho78ed6cd2017-08-09 16:19:00 +030014#include "compiler/translator/CollectVariables.h"
Geoff Lang17732822013-08-29 13:46:49 -040015#include "compiler/translator/Initialize.h"
Olli Etuahocccf2b02017-07-05 14:50:54 +030016#include "compiler/translator/IsASTDepthBelowLimit.h"
17#include "compiler/translator/OutputTree.h"
Jamie Madill6b9cb252013-10-17 10:45:47 -040018#include "compiler/translator/ParseContext.h"
Geoff Lang17732822013-08-29 13:46:49 -040019#include "compiler/translator/ValidateLimitations.h"
Olli Etuaho19d1dc92016-03-08 17:18:46 +020020#include "compiler/translator/ValidateMaxParameters.h"
Geoff Lang17732822013-08-29 13:46:49 -040021#include "compiler/translator/ValidateOutputs.h"
Jiawei Shao4cc89e22017-08-31 14:25:54 +080022#include "compiler/translator/ValidateVaryingLocations.h"
Geoff Lang17732822013-08-29 13:46:49 -040023#include "compiler/translator/VariablePacker.h"
Olli Etuahoa07b4212018-03-22 16:13:13 +020024#include "compiler/translator/tree_ops/AddAndTrueToLoopCondition.h"
25#include "compiler/translator/tree_ops/ClampFragDepth.h"
26#include "compiler/translator/tree_ops/ClampPointSize.h"
27#include "compiler/translator/tree_ops/DeclareAndInitBuiltinsForInstancedMultiview.h"
28#include "compiler/translator/tree_ops/DeferGlobalInitializers.h"
29#include "compiler/translator/tree_ops/EmulateGLFragColorBroadcast.h"
30#include "compiler/translator/tree_ops/EmulatePrecision.h"
31#include "compiler/translator/tree_ops/FoldExpressions.h"
32#include "compiler/translator/tree_ops/InitializeVariables.h"
33#include "compiler/translator/tree_ops/PruneEmptyCases.h"
34#include "compiler/translator/tree_ops/PruneNoOps.h"
35#include "compiler/translator/tree_ops/RegenerateStructNames.h"
36#include "compiler/translator/tree_ops/RemoveArrayLengthMethod.h"
37#include "compiler/translator/tree_ops/RemoveInvariantDeclaration.h"
38#include "compiler/translator/tree_ops/RemovePow.h"
39#include "compiler/translator/tree_ops/RemoveUnreferencedVariables.h"
40#include "compiler/translator/tree_ops/RewriteDoWhile.h"
41#include "compiler/translator/tree_ops/ScalarizeVecAndMatConstructorArgs.h"
42#include "compiler/translator/tree_ops/SeparateDeclarations.h"
43#include "compiler/translator/tree_ops/SimplifyLoopConditions.h"
44#include "compiler/translator/tree_ops/SplitSequenceOperator.h"
45#include "compiler/translator/tree_ops/UnfoldShortCircuitAST.h"
46#include "compiler/translator/tree_ops/UseInterfaceBlockFields.h"
47#include "compiler/translator/tree_ops/VectorizeVectorScalarArithmetic.h"
Olli Etuaho59c5b892018-04-03 11:44:50 +030048#include "compiler/translator/tree_util/BuiltIn_autogen.h"
Olli Etuahoc26214d2018-03-16 10:43:11 +020049#include "compiler/translator/tree_util/IntermNodePatternMatcher.h"
Olli Etuahob5601eb2017-11-15 18:08:04 +020050#include "compiler/translator/util.h"
shannon.woods@transgaming.comda1ed362013-01-25 21:54:57 +000051#include "third_party/compiler/ArrayBoundsClamper.h"
Corentin Wallez28b65282016-06-16 07:24:50 -070052
Jamie Madillacb4b812016-11-07 13:50:29 -050053namespace sh
54{
55
Corentin Wallez28b65282016-06-16 07:24:50 -070056namespace
57{
58
59#if defined(ANGLE_ENABLE_FUZZER_CORPUS_OUTPUT)
60void DumpFuzzerCase(char const *const *shaderStrings,
61 size_t numStrings,
62 uint32_t type,
63 uint32_t spec,
64 uint32_t output,
65 uint64_t options)
66{
67 static int fileIndex = 0;
68
69 std::ostringstream o;
70 o << "corpus/" << fileIndex++ << ".sample";
71 std::string s = o.str();
72
73 // Must match the input format of the fuzzer
74 FILE *f = fopen(s.c_str(), "w");
75 fwrite(&type, sizeof(type), 1, f);
76 fwrite(&spec, sizeof(spec), 1, f);
77 fwrite(&output, sizeof(output), 1, f);
78 fwrite(&options, sizeof(options), 1, f);
79
80 char zero[128 - 20] = {0};
81 fwrite(&zero, 128 - 20, 1, f);
82
83 for (size_t i = 0; i < numStrings; i++)
84 {
85 fwrite(shaderStrings[i], sizeof(char), strlen(shaderStrings[i]), f);
86 }
87 fwrite(&zero, 1, 1, f);
88
89 fclose(f);
90}
91#endif // defined(ANGLE_ENABLE_FUZZER_CORPUS_OUTPUT)
92} // anonymous namespace
93
Jamie Madill5508f392014-02-20 13:31:36 -050094bool IsWebGLBasedSpec(ShShaderSpec spec)
maxvujovic@gmail.com430f5e02012-06-08 17:47:59 +000095{
Qiankun Miaoc2c5fc42016-08-31 15:24:22 +080096 return (spec == SH_WEBGL_SPEC || spec == SH_WEBGL2_SPEC || spec == SH_WEBGL3_SPEC);
maxvujovic@gmail.com430f5e02012-06-08 17:47:59 +000097}
98
Qingqing Dengad0d0792015-04-08 14:25:06 -070099bool IsGLSL130OrNewer(ShShaderOutput output)
100{
Jamie Madillacb4b812016-11-07 13:50:29 -0500101 return (output == SH_GLSL_130_OUTPUT || output == SH_GLSL_140_OUTPUT ||
102 output == SH_GLSL_150_CORE_OUTPUT || output == SH_GLSL_330_CORE_OUTPUT ||
103 output == SH_GLSL_400_CORE_OUTPUT || output == SH_GLSL_410_CORE_OUTPUT ||
104 output == SH_GLSL_420_CORE_OUTPUT || output == SH_GLSL_430_CORE_OUTPUT ||
105 output == SH_GLSL_440_CORE_OUTPUT || output == SH_GLSL_450_CORE_OUTPUT);
Qingqing Dengad0d0792015-04-08 14:25:06 -0700106}
107
Qiankun Miao705a9192016-08-29 10:05:27 +0800108bool IsGLSL420OrNewer(ShShaderOutput output)
109{
Jamie Madillacb4b812016-11-07 13:50:29 -0500110 return (output == SH_GLSL_420_CORE_OUTPUT || output == SH_GLSL_430_CORE_OUTPUT ||
111 output == SH_GLSL_440_CORE_OUTPUT || output == SH_GLSL_450_CORE_OUTPUT);
Qiankun Miao705a9192016-08-29 10:05:27 +0800112}
113
Zhenyao Mob7bf7422016-11-08 14:44:05 -0800114bool IsGLSL410OrOlder(ShShaderOutput output)
115{
116 return (output == SH_GLSL_130_OUTPUT || output == SH_GLSL_140_OUTPUT ||
117 output == SH_GLSL_150_CORE_OUTPUT || output == SH_GLSL_330_CORE_OUTPUT ||
118 output == SH_GLSL_400_CORE_OUTPUT || output == SH_GLSL_410_CORE_OUTPUT);
119}
120
Qiankun Miao89dd8f32016-11-09 12:59:30 +0000121bool RemoveInvariant(sh::GLenum shaderType,
122 int shaderVersion,
123 ShShaderOutput outputType,
124 ShCompileOptions compileOptions)
125{
126 if ((compileOptions & SH_DONT_REMOVE_INVARIANT_FOR_FRAGMENT_INPUT) == 0 &&
127 shaderType == GL_FRAGMENT_SHADER && IsGLSL420OrNewer(outputType))
128 return true;
129
130 if ((compileOptions & SH_REMOVE_INVARIANT_AND_CENTROID_FOR_ESSL3) != 0 &&
Qiankun Miao41f9f672016-11-16 17:04:36 +0800131 shaderVersion >= 300 && shaderType == GL_VERTEX_SHADER)
Qiankun Miao89dd8f32016-11-09 12:59:30 +0000132 return true;
133
134 return false;
135}
136
Zhenyao Mo7faf1a12014-04-25 18:03:56 -0700137size_t GetGlobalMaxTokenSize(ShShaderSpec spec)
Jamie Madill88f6e942014-02-19 10:27:53 -0500138{
He Yunchao29ab9ff2015-08-06 16:58:30 +0800139 // WebGL defines a max token length of 256, while ES2 leaves max token
Jamie Madill88f6e942014-02-19 10:27:53 -0500140 // size undefined. ES3 defines a max size of 1024 characters.
Zhenyao Modb9b40b2014-10-29 15:00:04 -0700141 switch (spec)
Jamie Madill88f6e942014-02-19 10:27:53 -0500142 {
Jamie Madillacb4b812016-11-07 13:50:29 -0500143 case SH_WEBGL_SPEC:
144 return 256;
145 default:
146 return 1024;
Jamie Madill88f6e942014-02-19 10:27:53 -0500147 }
148}
149
Shao77891c02017-06-23 16:30:17 +0800150int GetMaxUniformVectorsForShaderType(GLenum shaderType, const ShBuiltInResources &resources)
151{
152 switch (shaderType)
153 {
154 case GL_VERTEX_SHADER:
155 return resources.MaxVertexUniformVectors;
156 case GL_FRAGMENT_SHADER:
157 return resources.MaxFragmentUniformVectors;
Shaob5cc1192017-07-06 10:47:20 +0800158
159 // TODO (jiawei.shao@intel.com): check if we need finer-grained component counting
Shao77891c02017-06-23 16:30:17 +0800160 case GL_COMPUTE_SHADER:
Shao77891c02017-06-23 16:30:17 +0800161 return resources.MaxComputeUniformComponents / 4;
Jiawei Shaobd924af2017-11-16 15:28:04 +0800162 case GL_GEOMETRY_SHADER_EXT:
Shaob5cc1192017-07-06 10:47:20 +0800163 return resources.MaxGeometryUniformComponents / 4;
Shao77891c02017-06-23 16:30:17 +0800164 default:
Shaob5cc1192017-07-06 10:47:20 +0800165 UNREACHABLE();
Shao77891c02017-06-23 16:30:17 +0800166 return -1;
167 }
168}
169
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500170namespace
171{
Zhenyao Modb9b40b2014-10-29 15:00:04 -0700172
Zhenyao Mo4a667fe2014-02-11 12:35:01 -0800173class TScopedPoolAllocator
174{
175 public:
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500176 TScopedPoolAllocator(TPoolAllocator *allocator) : mAllocator(allocator)
Zhenyao Mo4a667fe2014-02-11 12:35:01 -0800177 {
Alok Priyadarshibc3f1ac2013-09-23 14:57:02 -0400178 mAllocator->push();
alokp@chromium.orgbafcbaa2010-11-23 19:07:43 +0000179 SetGlobalPoolAllocator(mAllocator);
180 }
Zhenyao Mo4a667fe2014-02-11 12:35:01 -0800181 ~TScopedPoolAllocator()
182 {
Yunchao Hef81ce4a2017-04-24 10:49:17 +0800183 SetGlobalPoolAllocator(nullptr);
Alok Priyadarshibc3f1ac2013-09-23 14:57:02 -0400184 mAllocator->pop();
alokp@chromium.orgbafcbaa2010-11-23 19:07:43 +0000185 }
186
Zhenyao Mo4a667fe2014-02-11 12:35:01 -0800187 private:
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500188 TPoolAllocator *mAllocator;
Alok Priyadarshibc3f1ac2013-09-23 14:57:02 -0400189};
190
Zhenyao Mo4a667fe2014-02-11 12:35:01 -0800191class TScopedSymbolTableLevel
192{
193 public:
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500194 TScopedSymbolTableLevel(TSymbolTable *table) : mTable(table)
Zhenyao Mo4a667fe2014-02-11 12:35:01 -0800195 {
Olli Etuaho437664b2018-02-28 15:38:14 +0200196 ASSERT(mTable->isEmpty());
Alok Priyadarshibc3f1ac2013-09-23 14:57:02 -0400197 mTable->push();
198 }
Zhenyao Mo4a667fe2014-02-11 12:35:01 -0800199 ~TScopedSymbolTableLevel()
200 {
Olli Etuaho437664b2018-02-28 15:38:14 +0200201 while (!mTable->isEmpty())
Alok Priyadarshibc3f1ac2013-09-23 14:57:02 -0400202 mTable->pop();
203 }
204
Zhenyao Mo4a667fe2014-02-11 12:35:01 -0800205 private:
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500206 TSymbolTable *mTable;
alokp@chromium.orgbafcbaa2010-11-23 19:07:43 +0000207};
Zhenyao Modb9b40b2014-10-29 15:00:04 -0700208
209int MapSpecToShaderVersion(ShShaderSpec spec)
210{
211 switch (spec)
212 {
Jamie Madillacb4b812016-11-07 13:50:29 -0500213 case SH_GLES2_SPEC:
214 case SH_WEBGL_SPEC:
215 return 100;
216 case SH_GLES3_SPEC:
217 case SH_WEBGL2_SPEC:
218 return 300;
219 case SH_GLES3_1_SPEC:
220 case SH_WEBGL3_SPEC:
221 return 310;
222 default:
223 UNREACHABLE();
224 return 0;
Zhenyao Modb9b40b2014-10-29 15:00:04 -0700225 }
226}
227
Olli Etuaho59c5b892018-04-03 11:44:50 +0300228bool ValidateFragColorAndFragData(GLenum shaderType,
229 int shaderVersion,
230 const TSymbolTable &symbolTable,
231 TDiagnostics *diagnostics)
232{
233 if (shaderVersion > 100 || shaderType != GL_FRAGMENT_SHADER)
234 {
235 return true;
236 }
237
238 bool usesFragColor = false;
239 bool usesFragData = false;
240 // This validation is a bit stricter than the spec - it's only an error to write to
241 // both FragData and FragColor. But because it's better not to have reads from undefined
242 // variables, we always return an error if they are both referenced, rather than only if they
243 // are written.
244 if (symbolTable.isStaticallyUsed(*BuiltInVariable::gl_FragColor()) ||
245 symbolTable.isStaticallyUsed(*BuiltInVariable::gl_SecondaryFragColorEXT()))
246 {
247 usesFragColor = true;
248 }
249 // Extension variables may not always be initialized (saves some time at symbol table init).
250 bool secondaryFragDataUsed =
251 symbolTable.gl_SecondaryFragDataEXT() != nullptr &&
252 symbolTable.isStaticallyUsed(*symbolTable.gl_SecondaryFragDataEXT());
253 if (symbolTable.isStaticallyUsed(*symbolTable.gl_FragData()) || secondaryFragDataUsed)
254 {
255 usesFragData = true;
256 }
257 if (usesFragColor && usesFragData)
258 {
259 const char *errorMessage = "cannot use both gl_FragData and gl_FragColor";
260 if (symbolTable.isStaticallyUsed(*BuiltInVariable::gl_SecondaryFragColorEXT()) ||
261 secondaryFragDataUsed)
262 {
263 errorMessage =
264 "cannot use both output variable sets (gl_FragData, gl_SecondaryFragDataEXT)"
265 " and (gl_FragColor, gl_SecondaryFragColorEXT)";
266 }
267 diagnostics->globalError(errorMessage);
268 return false;
269 }
270 return true;
271}
272
alokp@chromium.orgbafcbaa2010-11-23 19:07:43 +0000273} // namespace
274
Zhenyao Mo4a667fe2014-02-11 12:35:01 -0800275TShHandleBase::TShHandleBase()
276{
alokp@chromium.orgbafcbaa2010-11-23 19:07:43 +0000277 allocator.push();
278 SetGlobalPoolAllocator(&allocator);
279}
280
Zhenyao Mo4a667fe2014-02-11 12:35:01 -0800281TShHandleBase::~TShHandleBase()
282{
Yunchao Hef81ce4a2017-04-24 10:49:17 +0800283 SetGlobalPoolAllocator(nullptr);
alokp@chromium.orgbafcbaa2010-11-23 19:07:43 +0000284 allocator.popAll();
285}
286
Jamie Madill183bde52014-07-02 15:31:19 -0400287TCompiler::TCompiler(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output)
Kenneth Russellbccc65d2016-07-19 16:48:43 -0700288 : variablesCollected(false),
Olli Etuahob12040c2017-06-27 14:20:45 +0300289 mGLPositionInitialized(false),
Kenneth Russellbccc65d2016-07-19 16:48:43 -0700290 shaderType(type),
zmo@google.comf420c422011-09-12 18:27:59 +0000291 shaderSpec(spec),
Jamie Madill68fe74a2014-05-27 12:56:01 -0400292 outputType(output),
Jamie Madilleb1a0102013-07-08 13:31:38 -0400293 maxUniformVectors(0),
294 maxExpressionComplexity(0),
295 maxCallStackDepth(0),
Olli Etuaho19d1dc92016-03-08 17:18:46 +0200296 maxFunctionParameters(0),
shannon.woods%transgaming.com@gtempaccount.comcbb6b6a2013-04-13 03:27:47 +0000297 fragmentPrecisionHigh(false),
shannon.woods@transgaming.com1d432bb2013-01-25 21:57:28 +0000298 clampingStrategy(SH_CLAMP_WITH_CLAMP_INTRINSIC),
Olli Etuaho8efc5ad2015-03-03 17:21:10 +0200299 builtInFunctionEmulator(),
Olli Etuaho77ba4082016-12-16 12:01:18 +0000300 mDiagnostics(infoSink.info),
Yunchao Hef81ce4a2017-04-24 10:49:17 +0800301 mSourcePath(nullptr),
Shaob5cc1192017-07-06 10:47:20 +0800302 mComputeShaderLocalSizeDeclared(false),
Jamie Madill2f294c92017-11-20 14:47:26 -0500303 mComputeShaderLocalSize(1),
Shaob5cc1192017-07-06 10:47:20 +0800304 mGeometryShaderMaxVertices(-1),
305 mGeometryShaderInvocations(0),
306 mGeometryShaderInputPrimitiveType(EptUndefined),
307 mGeometryShaderOutputPrimitiveType(EptUndefined)
alokp@chromium.org4888ceb2010-10-01 21:13:12 +0000308{
309}
310
311TCompiler::~TCompiler()
312{
313}
314
Qiankun Miao7ebb97f2016-09-08 18:01:50 +0800315bool TCompiler::shouldRunLoopAndIndexingValidation(ShCompileOptions compileOptions) const
Olli Etuaho5d91dda2015-06-18 15:47:46 +0300316{
317 // If compiling an ESSL 1.00 shader for WebGL, or if its been requested through the API,
318 // validate loop and indexing as well (to verify that the shader only uses minimal functionality
319 // of ESSL 1.00 as in Appendix A of the spec).
320 return (IsWebGLBasedSpec(shaderSpec) && shaderVersion == 100) ||
321 (compileOptions & SH_VALIDATE_LOOP_INDEXING);
322}
323
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500324bool TCompiler::Init(const ShBuiltInResources &resources)
alokp@chromium.org07620a52010-09-23 17:53:56 +0000325{
Shao77891c02017-06-23 16:30:17 +0800326 shaderVersion = 100;
327
328 maxUniformVectors = GetMaxUniformVectorsForShaderType(shaderType, resources);
329
Jamie Madilleb1a0102013-07-08 13:31:38 -0400330 maxExpressionComplexity = resources.MaxExpressionComplexity;
Olli Etuaho19d1dc92016-03-08 17:18:46 +0200331 maxCallStackDepth = resources.MaxCallStackDepth;
332 maxFunctionParameters = resources.MaxFunctionParameters;
Alok Priyadarshibc3f1ac2013-09-23 14:57:02 -0400333
334 SetGlobalPoolAllocator(&allocator);
alokp@chromium.orgbafcbaa2010-11-23 19:07:43 +0000335
alokp@chromium.org07620a52010-09-23 17:53:56 +0000336 // Generate built-in symbol table.
337 if (!InitBuiltInSymbolTable(resources))
338 return false;
alokp@chromium.org07620a52010-09-23 17:53:56 +0000339 InitExtensionBehavior(resources, extensionBehavior);
shannon.woods%transgaming.com@gtempaccount.comcbb6b6a2013-04-13 03:27:47 +0000340 fragmentPrecisionHigh = resources.FragmentPrecisionHigh == 1;
alokp@chromium.orgbafcbaa2010-11-23 19:07:43 +0000341
shannon.woods@transgaming.com1d432bb2013-01-25 21:57:28 +0000342 arrayBoundsClamper.SetClampingStrategy(resources.ArrayIndexClampingStrategy);
343 clampingStrategy = resources.ArrayIndexClampingStrategy;
344
daniel@transgaming.comc23f4612012-11-28 19:42:57 +0000345 hashFunction = resources.HashFunction;
346
alokp@chromium.org07620a52010-09-23 17:53:56 +0000347 return true;
348}
349
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100350TIntermBlock *TCompiler::compileTreeForTesting(const char *const shaderStrings[],
351 size_t numStrings,
352 ShCompileOptions compileOptions)
alokp@chromium.org07620a52010-09-23 17:53:56 +0000353{
Olli Etuahoa3a5cc62015-02-13 13:12:22 +0200354 return compileTreeImpl(shaderStrings, numStrings, compileOptions);
355}
356
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100357TIntermBlock *TCompiler::compileTreeImpl(const char *const shaderStrings[],
358 size_t numStrings,
359 const ShCompileOptions compileOptions)
Olli Etuahoa3a5cc62015-02-13 13:12:22 +0200360{
alokp@chromium.org07620a52010-09-23 17:53:56 +0000361 clearResults();
362
Olli Etuahoa3a5cc62015-02-13 13:12:22 +0200363 ASSERT(numStrings > 0);
364 ASSERT(GetGlobalPoolAllocator());
alokp@chromium.org07620a52010-09-23 17:53:56 +0000365
David Yen0fbd1282015-02-02 14:46:09 -0800366 // Reset the extension behavior for each compilation unit.
367 ResetExtensionBehavior(extensionBehavior);
368
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +0000369 // First string is path of source file if flag is set. The actual source follows.
shannon.woods@transgaming.comd64b3da2013-02-28 23:19:26 +0000370 size_t firstSource = 0;
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +0000371 if (compileOptions & SH_SOURCE_PATH)
372 {
Olli Etuahoa3a5cc62015-02-13 13:12:22 +0200373 mSourcePath = shaderStrings[0];
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +0000374 ++firstSource;
375 }
376
Olli Etuahof119a262016-08-19 15:54:22 +0300377 TParseContext parseContext(symbolTable, extensionBehavior, shaderType, shaderSpec,
Olli Etuaho77ba4082016-12-16 12:01:18 +0000378 compileOptions, true, &mDiagnostics, getResources());
Olli Etuaho853dc1a2014-11-06 17:25:48 +0200379
Olli Etuahoa6996682015-10-12 14:32:30 +0300380 parseContext.setFragmentPrecisionHighOnESSL1(fragmentPrecisionHigh);
alokp@chromium.org07620a52010-09-23 17:53:56 +0000381
382 // We preserve symbols at the built-in level from compile-to-compile.
383 // Start pushing the user-defined symbols at global level.
Olli Etuahoe5fe7aa2018-01-29 12:06:11 +0200384 TScopedSymbolTableLevel globalLevel(&symbolTable);
385 ASSERT(symbolTable.atGlobalLevel());
alokp@chromium.org07620a52010-09-23 17:53:56 +0000386
387 // Parse shader.
Olli Etuahod10cf692017-11-02 11:06:14 +0200388 if (PaParseStrings(numStrings - firstSource, &shaderStrings[firstSource], nullptr,
389 &parseContext) != 0)
390 {
391 return nullptr;
392 }
shannon.woods%transgaming.com@gtempaccount.com0bbed382013-04-13 03:38:07 +0000393
Olli Etuahod10cf692017-11-02 11:06:14 +0200394 if (parseContext.getTreeRoot() == nullptr)
395 {
396 return nullptr;
397 }
398
399 setASTMetadata(parseContext);
400
Jiawei Shaoe41df652018-02-09 14:31:39 +0800401 if (!checkShaderVersion(&parseContext))
Zhenyao Modb9b40b2014-10-29 15:00:04 -0700402 {
Olli Etuahod10cf692017-11-02 11:06:14 +0200403 return nullptr;
Zhenyao Modb9b40b2014-10-29 15:00:04 -0700404 }
shannon.woods%transgaming.com@gtempaccount.com0bbed382013-04-13 03:38:07 +0000405
Olli Etuahod10cf692017-11-02 11:06:14 +0200406 TIntermBlock *root = parseContext.getTreeRoot();
407 if (!checkAndSimplifyAST(root, parseContext, compileOptions))
Zhenyao Mo4a667fe2014-02-11 12:35:01 -0800408 {
Olli Etuahod10cf692017-11-02 11:06:14 +0200409 return nullptr;
410 }
Zhenyao Mo94ac7b72014-10-15 18:22:08 -0700411
Olli Etuahod10cf692017-11-02 11:06:14 +0200412 return root;
413}
Martin Radev802abe02016-08-04 17:48:32 +0300414
Jiawei Shaoe41df652018-02-09 14:31:39 +0800415bool TCompiler::checkShaderVersion(TParseContext *parseContext)
416{
417 if (MapSpecToShaderVersion(shaderSpec) < shaderVersion)
418 {
419 mDiagnostics.globalError("unsupported shader version");
420 return false;
421 }
422
423 ASSERT(parseContext);
424 switch (shaderType)
425 {
426 case GL_COMPUTE_SHADER:
427 if (shaderVersion < 310)
428 {
429 mDiagnostics.globalError("Compute shader is not supported in this shader version.");
430 return false;
431 }
432 break;
433
434 case GL_GEOMETRY_SHADER_EXT:
435 if (shaderVersion < 310)
436 {
437 mDiagnostics.globalError(
438 "Geometry shader is not supported in this shader version.");
439 return false;
440 }
441 else
442 {
443 ASSERT(shaderVersion == 310);
444 if (!parseContext->checkCanUseExtension(sh::TSourceLoc(),
445 TExtension::EXT_geometry_shader))
446 {
447 return false;
448 }
449 }
450 break;
451
452 default:
453 break;
454 }
455
456 return true;
457}
458
Olli Etuahod10cf692017-11-02 11:06:14 +0200459void TCompiler::setASTMetadata(const TParseContext &parseContext)
460{
461 shaderVersion = parseContext.getShaderVersion();
Olli Etuaho09b04a22016-12-15 13:30:26 +0000462
Olli Etuahod10cf692017-11-02 11:06:14 +0200463 mPragma = parseContext.pragma();
464 symbolTable.setGlobalInvariant(mPragma.stdgl.invariantAll);
alokp@chromium.orgb59a7782010-11-24 18:38:33 +0000465
Olli Etuahod10cf692017-11-02 11:06:14 +0200466 mComputeShaderLocalSizeDeclared = parseContext.isComputeShaderLocalSizeDeclared();
467 mComputeShaderLocalSize = parseContext.getComputeShaderLocalSize();
Olli Etuahoa6996682015-10-12 14:32:30 +0300468
Olli Etuahod10cf692017-11-02 11:06:14 +0200469 mNumViews = parseContext.getNumViews();
470
471 // Highp might have been auto-enabled based on shader version
472 fragmentPrecisionHigh = parseContext.getFragmentPrecisionHigh();
473
Jiawei Shaobd924af2017-11-16 15:28:04 +0800474 if (shaderType == GL_GEOMETRY_SHADER_EXT)
Olli Etuahod10cf692017-11-02 11:06:14 +0200475 {
476 mGeometryShaderInputPrimitiveType = parseContext.getGeometryShaderInputPrimitiveType();
477 mGeometryShaderOutputPrimitiveType = parseContext.getGeometryShaderOutputPrimitiveType();
478 mGeometryShaderMaxVertices = parseContext.getGeometryShaderMaxVertices();
479 mGeometryShaderInvocations = parseContext.getGeometryShaderInvocations();
480 }
481}
482
483bool TCompiler::checkAndSimplifyAST(TIntermBlock *root,
484 const TParseContext &parseContext,
485 ShCompileOptions compileOptions)
486{
487 // Disallow expressions deemed too complex.
488 if ((compileOptions & SH_LIMIT_EXPRESSION_COMPLEXITY) && !limitExpressionComplexity(root))
489 {
490 return false;
491 }
492
Olli Etuaho765924f2018-01-04 12:48:36 +0200493 if (shouldRunLoopAndIndexingValidation(compileOptions) &&
Olli Etuaho68981eb2018-01-23 17:46:12 +0200494 !ValidateLimitations(root, shaderType, &symbolTable, &mDiagnostics))
Olli Etuaho765924f2018-01-04 12:48:36 +0200495 {
496 return false;
497 }
498
Olli Etuaho59c5b892018-04-03 11:44:50 +0300499 if (!ValidateFragColorAndFragData(shaderType, shaderVersion, symbolTable, &mDiagnostics))
500 {
501 return false;
502 }
503
Olli Etuaho765924f2018-01-04 12:48:36 +0200504 // Fold expressions that could not be folded before validation that was done as a part of
505 // parsing.
506 FoldExpressions(root, &mDiagnostics);
507 // Folding should only be able to generate warnings.
508 ASSERT(mDiagnostics.numErrors() == 0);
509
Olli Etuahod10cf692017-11-02 11:06:14 +0200510 // We prune no-ops to work around driver bugs and to keep AST processing and output simple.
511 // The following kinds of no-ops are pruned:
512 // 1. Empty declarations "int;".
513 // 2. Literal statements: "1.0;". The ESSL output doesn't define a default precision
514 // for float, so float literal statements would end up with no precision which is
515 // invalid ESSL.
516 // After this empty declarations are not allowed in the AST.
Olli Etuahob38dfde2018-01-04 15:49:03 +0200517 PruneNoOps(root, &symbolTable);
Olli Etuahod10cf692017-11-02 11:06:14 +0200518
Olli Etuahod10cf692017-11-02 11:06:14 +0200519 // Create the function DAG and check there is no recursion
520 if (!initCallDag(root))
521 {
522 return false;
523 }
524
525 if ((compileOptions & SH_LIMIT_CALL_STACK_DEPTH) && !checkCallDepth())
526 {
527 return false;
528 }
529
530 // Checks which functions are used and if "main" exists
531 functionMetadata.clear();
532 functionMetadata.resize(mCallDag.size());
533 if (!tagUsedFunctions())
534 {
535 return false;
536 }
537
538 if (!(compileOptions & SH_DONT_PRUNE_UNUSED_FUNCTIONS))
539 {
540 pruneUnusedFunctions(root);
541 }
542
543 if (shaderVersion >= 310 && !ValidateVaryingLocations(root, &mDiagnostics, shaderType))
544 {
545 return false;
546 }
547
548 if (shaderVersion >= 300 && shaderType == GL_FRAGMENT_SHADER &&
549 !ValidateOutputs(root, getExtensionBehavior(), compileResources.MaxDrawBuffers,
550 &mDiagnostics))
551 {
552 return false;
553 }
554
Olli Etuahod10cf692017-11-02 11:06:14 +0200555 // Fail compilation if precision emulation not supported.
556 if (getResources().WEBGL_debug_shader_precision && getPragma().debugShaderPrecision &&
557 !EmulatePrecision::SupportedInLanguage(outputType))
558 {
559 mDiagnostics.globalError("Precision emulation not supported for this output type.");
560 return false;
561 }
562
Olli Etuahod10cf692017-11-02 11:06:14 +0200563 // Clamping uniform array bounds needs to happen after validateLimitations pass.
564 if (compileOptions & SH_CLAMP_INDIRECT_ARRAY_BOUNDS)
565 {
566 arrayBoundsClamper.MarkIndirectArrayBoundsForClamping(root);
567 }
568
569 if ((compileOptions & SH_INITIALIZE_BUILTINS_FOR_INSTANCED_MULTIVIEW) &&
570 parseContext.isExtensionEnabled(TExtension::OVR_multiview) &&
571 getShaderType() != GL_COMPUTE_SHADER)
572 {
573 DeclareAndInitBuiltinsForInstancedMultiview(root, mNumViews, shaderType, compileOptions,
574 outputType, &symbolTable);
575 }
576
577 // This pass might emit short circuits so keep it before the short circuit unfolding
578 if (compileOptions & SH_REWRITE_DO_WHILE_LOOPS)
579 RewriteDoWhile(root, &symbolTable);
580
581 if (compileOptions & SH_ADD_AND_TRUE_TO_LOOP_CONDITION)
Olli Etuaho1776fd02018-01-31 11:46:52 +0200582 AddAndTrueToLoopCondition(root);
Olli Etuahod10cf692017-11-02 11:06:14 +0200583
584 if (compileOptions & SH_UNFOLD_SHORT_CIRCUIT)
585 {
Olli Etuaho1776fd02018-01-31 11:46:52 +0200586 UnfoldShortCircuitAST(root);
Olli Etuahod10cf692017-11-02 11:06:14 +0200587 }
588
589 if (compileOptions & SH_REMOVE_POW_WITH_CONSTANT_EXPONENT)
590 {
591 RemovePow(root);
592 }
593
Olli Etuahod10cf692017-11-02 11:06:14 +0200594 if (compileOptions & SH_REGENERATE_STRUCT_NAMES)
595 {
Olli Etuaho9d4d7f02017-12-07 17:11:41 +0100596 RegenerateStructNames gen(&symbolTable);
Olli Etuahod10cf692017-11-02 11:06:14 +0200597 root->traverse(&gen);
598 }
599
600 if (shaderType == GL_FRAGMENT_SHADER && shaderVersion == 100 &&
601 compileResources.EXT_draw_buffers && compileResources.MaxDrawBuffers > 1 &&
602 IsExtensionEnabled(extensionBehavior, TExtension::EXT_draw_buffers))
603 {
604 EmulateGLFragColorBroadcast(root, compileResources.MaxDrawBuffers, &outputVariables,
605 &symbolTable, shaderVersion);
606 }
607
Olli Etuahoae04e1e2017-11-27 16:00:39 +0200608 int simplifyScalarized = (compileOptions & SH_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS)
609 ? IntermNodePatternMatcher::kScalarizedVecOrMatConstructor
610 : 0;
611
Olli Etuahod10cf692017-11-02 11:06:14 +0200612 // Split multi declarations and remove calls to array length().
613 // Note that SimplifyLoopConditions needs to be run before any other AST transformations
614 // that may need to generate new statements from loop conditions or loop expressions.
Olli Etuahoae04e1e2017-11-27 16:00:39 +0200615 SimplifyLoopConditions(root,
616 IntermNodePatternMatcher::kMultiDeclaration |
617 IntermNodePatternMatcher::kArrayLengthMethod | simplifyScalarized,
Olli Etuaho68981eb2018-01-23 17:46:12 +0200618 &getSymbolTable());
Olli Etuahod10cf692017-11-02 11:06:14 +0200619
620 // Note that separate declarations need to be run before other AST transformations that
621 // generate new statements from expressions.
622 SeparateDeclarations(root);
623
Olli Etuahoae04e1e2017-11-27 16:00:39 +0200624 SplitSequenceOperator(root, IntermNodePatternMatcher::kArrayLengthMethod | simplifyScalarized,
Olli Etuaho68981eb2018-01-23 17:46:12 +0200625 &getSymbolTable());
Olli Etuahod10cf692017-11-02 11:06:14 +0200626
627 RemoveArrayLengthMethod(root);
628
Olli Etuaho3d70ca92017-11-10 16:53:26 +0200629 RemoveUnreferencedVariables(root, &symbolTable);
630
Olli Etuaho41217992018-03-15 11:15:33 +0200631 // In case the last case inside a switch statement is a certain type of no-op, GLSL compilers in
632 // drivers may not accept it. In this case we clean up the dead code from the end of switch
633 // statements. This is also required because PruneNoOps or RemoveUnreferencedVariables may have
634 // left switch statements that only contained an empty declaration inside the final case in an
635 // invalid state. Relies on that PruneNoOps and RemoveUnreferencedVariables have already been
636 // run.
Olli Etuaho0b0dcbc2018-03-14 11:33:22 +0200637 PruneEmptyCases(root);
638
Olli Etuaho3d70ca92017-11-10 16:53:26 +0200639 // Built-in function emulation needs to happen after validateLimitations pass.
640 // TODO(jmadill): Remove global pool allocator.
641 GetGlobalPoolAllocator()->lock();
642 initBuiltInFunctionEmulator(&builtInFunctionEmulator, compileOptions);
643 GetGlobalPoolAllocator()->unlock();
644 builtInFunctionEmulator.markBuiltInFunctionsForEmulation(root);
645
646 if (compileOptions & SH_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS)
647 {
648 ScalarizeVecAndMatConstructorArgs(root, shaderType, fragmentPrecisionHigh, &symbolTable);
649 }
650
651 if (shouldCollectVariables(compileOptions))
652 {
653 ASSERT(!variablesCollected);
654 CollectVariables(root, &attributes, &outputVariables, &uniforms, &inputVaryings,
655 &outputVaryings, &uniformBlocks, &shaderStorageBlocks, &inBlocks,
Olli Etuaho822a84b2018-03-23 12:30:18 +0200656 hashFunction, &symbolTable, shaderType, extensionBehavior);
Olli Etuaho3d70ca92017-11-10 16:53:26 +0200657 collectInterfaceBlocks();
658 variablesCollected = true;
659 if (compileOptions & SH_USE_UNUSED_STANDARD_SHARED_BLOCKS)
660 {
661 useAllMembersInUnusedStandardAndSharedBlocks(root);
662 }
663 if (compileOptions & SH_ENFORCE_PACKING_RESTRICTIONS)
664 {
665 // Returns true if, after applying the packing rules in the GLSL ES 1.00.17 spec
666 // Appendix A, section 7, the shader does not use too many uniforms.
667 if (!CheckVariablesInPackingLimits(maxUniformVectors, uniforms))
668 {
669 mDiagnostics.globalError("too many uniforms");
670 return false;
671 }
672 }
673 if (compileOptions & SH_INIT_OUTPUT_VARIABLES)
674 {
675 initializeOutputVariables(root);
676 }
677 }
678
679 // Removing invariant declarations must be done after collecting variables.
680 // Otherwise, built-in invariant declarations don't apply.
681 if (RemoveInvariant(shaderType, shaderVersion, outputType, compileOptions))
682 {
683 RemoveInvariantDeclaration(root);
684 }
685
686 // gl_Position is always written in compatibility output mode.
687 // It may have been already initialized among other output variables, in that case we don't
688 // need to initialize it twice.
689 if (shaderType == GL_VERTEX_SHADER && !mGLPositionInitialized &&
690 ((compileOptions & SH_INIT_GL_POSITION) || (outputType == SH_GLSL_COMPATIBILITY_OUTPUT)))
691 {
692 initializeGLPosition(root);
693 mGLPositionInitialized = true;
694 }
695
Olli Etuahob5601eb2017-11-15 18:08:04 +0200696 // DeferGlobalInitializers needs to be run before other AST transformations that generate new
697 // statements from expressions. But it's fine to run DeferGlobalInitializers after the above
698 // SplitSequenceOperator and RemoveArrayLengthMethod since they only have an effect on the AST
699 // on ESSL >= 3.00, and the initializers that need to be deferred can only exist in ESSL < 3.00.
700 bool initializeLocalsAndGlobals =
701 (compileOptions & SH_INITIALIZE_UNINITIALIZED_LOCALS) && !IsOutputHLSL(getOutputType());
Olli Etuaho2c7f34c2017-10-09 17:18:02 +0300702 bool canUseLoopsToInitialize = !(compileOptions & SH_DONT_USE_LOOPS_TO_INITIALIZE_VARIABLES);
Olli Etuaho87cc90d2017-12-12 15:28:06 +0200703 bool highPrecisionSupported =
704 shaderType != GL_FRAGMENT_SHADER || compileResources.FragmentPrecisionHigh;
705 DeferGlobalInitializers(root, initializeLocalsAndGlobals, canUseLoopsToInitialize,
706 highPrecisionSupported, &symbolTable);
Olli Etuaho2c7f34c2017-10-09 17:18:02 +0300707
Olli Etuahob5601eb2017-11-15 18:08:04 +0200708 if (initializeLocalsAndGlobals)
Olli Etuahod10cf692017-11-02 11:06:14 +0200709 {
710 // Initialize uninitialized local variables.
711 // In some cases initializing can generate extra statements in the parent block, such as
712 // when initializing nameless structs or initializing arrays in ESSL 1.00. In that case
713 // we need to first simplify loop conditions. We've already separated declarations
714 // earlier, which is also required. If we don't follow the Appendix A limitations, loop
715 // init statements can declare arrays or nameless structs and have multiple
716 // declarations.
717
718 if (!shouldRunLoopAndIndexingValidation(compileOptions))
719 {
720 SimplifyLoopConditions(root,
721 IntermNodePatternMatcher::kArrayDeclaration |
722 IntermNodePatternMatcher::kNamelessStructDeclaration,
Olli Etuaho68981eb2018-01-23 17:46:12 +0200723 &getSymbolTable());
Olli Etuahod10cf692017-11-02 11:06:14 +0200724 }
Olli Etuaho661fc482017-10-16 12:17:05 +0300725
Olli Etuaho2c7f34c2017-10-09 17:18:02 +0300726 InitializeUninitializedLocals(root, getShaderVersion(), canUseLoopsToInitialize,
Olli Etuaho87cc90d2017-12-12 15:28:06 +0200727 highPrecisionSupported, &getSymbolTable());
Olli Etuahod10cf692017-11-02 11:06:14 +0200728 }
729
730 if (getShaderType() == GL_VERTEX_SHADER && (compileOptions & SH_CLAMP_POINT_SIZE))
731 {
732 ClampPointSize(root, compileResources.MaxPointSize, &getSymbolTable());
733 }
734
Olli Etuaho0690e1a2017-12-21 20:51:38 +0200735 if (getShaderType() == GL_FRAGMENT_SHADER && (compileOptions & SH_CLAMP_FRAG_DEPTH))
736 {
737 ClampFragDepth(root, &getSymbolTable());
738 }
739
Olli Etuaho661fc482017-10-16 12:17:05 +0300740 if (compileOptions & SH_REWRITE_VECTOR_SCALAR_ARITHMETIC)
741 {
742 VectorizeVectorScalarArithmetic(root, &getSymbolTable());
743 }
744
Olli Etuahod10cf692017-11-02 11:06:14 +0200745 return true;
Olli Etuahoa3a5cc62015-02-13 13:12:22 +0200746}
747
Qiankun Miao7ebb97f2016-09-08 18:01:50 +0800748bool TCompiler::compile(const char *const shaderStrings[],
749 size_t numStrings,
750 ShCompileOptions compileOptionsIn)
Olli Etuahoa3a5cc62015-02-13 13:12:22 +0200751{
Corentin Wallez28b65282016-06-16 07:24:50 -0700752#if defined(ANGLE_ENABLE_FUZZER_CORPUS_OUTPUT)
753 DumpFuzzerCase(shaderStrings, numStrings, shaderType, shaderSpec, outputType, compileOptionsIn);
754#endif // defined(ANGLE_ENABLE_FUZZER_CORPUS_OUTPUT)
755
Olli Etuahoa3a5cc62015-02-13 13:12:22 +0200756 if (numStrings == 0)
757 return true;
758
Qiankun Miao7ebb97f2016-09-08 18:01:50 +0800759 ShCompileOptions compileOptions = compileOptionsIn;
Kenneth Russellbccc65d2016-07-19 16:48:43 -0700760
761 // Apply key workarounds.
762 if (shouldFlattenPragmaStdglInvariantAll())
763 {
764 // This should be harmless to do in all cases, but for the moment, do it only conditionally.
765 compileOptions |= SH_FLATTEN_PRAGMA_STDGL_INVARIANT_ALL;
766 }
767
Olli Etuahoa3a5cc62015-02-13 13:12:22 +0200768 TScopedPoolAllocator scopedAlloc(&allocator);
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100769 TIntermBlock *root = compileTreeImpl(shaderStrings, numStrings, compileOptions);
Olli Etuahoa3a5cc62015-02-13 13:12:22 +0200770
771 if (root)
772 {
773 if (compileOptions & SH_INTERMEDIATE_TREE)
Olli Etuahocccf2b02017-07-05 14:50:54 +0300774 OutputTree(root, infoSink.info);
Olli Etuahoa3a5cc62015-02-13 13:12:22 +0200775
776 if (compileOptions & SH_OBJECT_CODE)
Olli Etuaho89a69a02017-10-23 12:20:45 +0300777 {
778 PerformanceDiagnostics perfDiagnostics(&mDiagnostics);
779 translate(root, compileOptions, &perfDiagnostics);
780 }
Olli Etuahoa3a5cc62015-02-13 13:12:22 +0200781
782 // The IntermNode tree doesn't need to be deleted here, since the
783 // memory will be freed in a big chunk by the PoolAllocator.
784 return true;
785 }
786 return false;
alokp@chromium.org07620a52010-09-23 17:53:56 +0000787}
788
Nicolas Capens49a88872013-06-20 09:54:03 -0400789bool TCompiler::InitBuiltInSymbolTable(const ShBuiltInResources &resources)
alokp@chromium.org07620a52010-09-23 17:53:56 +0000790{
Olli Etuaho28cb0362016-11-22 15:42:37 +0000791 if (resources.MaxDrawBuffers < 1)
792 {
793 return false;
794 }
795 if (resources.EXT_blend_func_extended && resources.MaxDualSourceDrawBuffers < 1)
796 {
797 return false;
798 }
799
shannon.woods%transgaming.com@gtempaccount.com18b4c4b2013-04-13 03:31:40 +0000800 compileResources = resources;
Shannon Woods2d76e5f2014-05-16 17:46:41 -0400801 setResourceString();
shannonwoods@chromium.org2ac0be92013-05-30 00:02:27 +0000802
Olli Etuaho29bda812018-01-26 17:37:36 +0200803 symbolTable.initializeBuiltIns(shaderType, shaderSpec, resources);
Olli Etuaho5d69db12017-11-24 16:51:15 +0200804
Nicolas Capens49a88872013-06-20 09:54:03 -0400805 return true;
alokp@chromium.org07620a52010-09-23 17:53:56 +0000806}
807
Shannon Woods2d76e5f2014-05-16 17:46:41 -0400808void TCompiler::setResourceString()
809{
810 std::ostringstream strstream;
Geoff Langb66a9092016-05-16 15:59:14 -0400811
812 // clang-format off
Shannon Woods2d76e5f2014-05-16 17:46:41 -0400813 strstream << ":MaxVertexAttribs:" << compileResources.MaxVertexAttribs
Jamie Madillacb4b812016-11-07 13:50:29 -0500814 << ":MaxVertexUniformVectors:" << compileResources.MaxVertexUniformVectors
815 << ":MaxVaryingVectors:" << compileResources.MaxVaryingVectors
816 << ":MaxVertexTextureImageUnits:" << compileResources.MaxVertexTextureImageUnits
817 << ":MaxCombinedTextureImageUnits:" << compileResources.MaxCombinedTextureImageUnits
818 << ":MaxTextureImageUnits:" << compileResources.MaxTextureImageUnits
819 << ":MaxFragmentUniformVectors:" << compileResources.MaxFragmentUniformVectors
820 << ":MaxDrawBuffers:" << compileResources.MaxDrawBuffers
821 << ":OES_standard_derivatives:" << compileResources.OES_standard_derivatives
822 << ":OES_EGL_image_external:" << compileResources.OES_EGL_image_external
823 << ":OES_EGL_image_external_essl3:" << compileResources.OES_EGL_image_external_essl3
824 << ":NV_EGL_stream_consumer_external:" << compileResources.NV_EGL_stream_consumer_external
825 << ":ARB_texture_rectangle:" << compileResources.ARB_texture_rectangle
826 << ":EXT_draw_buffers:" << compileResources.EXT_draw_buffers
827 << ":FragmentPrecisionHigh:" << compileResources.FragmentPrecisionHigh
828 << ":MaxExpressionComplexity:" << compileResources.MaxExpressionComplexity
829 << ":MaxCallStackDepth:" << compileResources.MaxCallStackDepth
830 << ":MaxFunctionParameters:" << compileResources.MaxFunctionParameters
831 << ":EXT_blend_func_extended:" << compileResources.EXT_blend_func_extended
832 << ":EXT_frag_depth:" << compileResources.EXT_frag_depth
833 << ":EXT_shader_texture_lod:" << compileResources.EXT_shader_texture_lod
834 << ":EXT_shader_framebuffer_fetch:" << compileResources.EXT_shader_framebuffer_fetch
835 << ":NV_shader_framebuffer_fetch:" << compileResources.NV_shader_framebuffer_fetch
836 << ":ARM_shader_framebuffer_fetch:" << compileResources.ARM_shader_framebuffer_fetch
Martin Radev318f9aa2017-05-17 17:47:28 +0300837 << ":OVR_multiview:" << compileResources.OVR_multiview
Andrei Volykhina5527072017-03-22 16:46:30 +0300838 << ":EXT_YUV_target:" << compileResources.EXT_YUV_target
Jiawei Shaobd924af2017-11-16 15:28:04 +0800839 << ":EXT_geometry_shader:" << compileResources.EXT_geometry_shader
Jamie Madillacb4b812016-11-07 13:50:29 -0500840 << ":MaxVertexOutputVectors:" << compileResources.MaxVertexOutputVectors
841 << ":MaxFragmentInputVectors:" << compileResources.MaxFragmentInputVectors
842 << ":MinProgramTexelOffset:" << compileResources.MinProgramTexelOffset
843 << ":MaxProgramTexelOffset:" << compileResources.MaxProgramTexelOffset
844 << ":MaxDualSourceDrawBuffers:" << compileResources.MaxDualSourceDrawBuffers
Martin Radev318f9aa2017-05-17 17:47:28 +0300845 << ":MaxViewsOVR:" << compileResources.MaxViewsOVR
Jamie Madillacb4b812016-11-07 13:50:29 -0500846 << ":NV_draw_buffers:" << compileResources.NV_draw_buffers
847 << ":WEBGL_debug_shader_precision:" << compileResources.WEBGL_debug_shader_precision
Martin Radev84aa2dc2017-09-11 15:51:02 +0300848 << ":MinProgramTextureGatherOffset:" << compileResources.MinProgramTextureGatherOffset
849 << ":MaxProgramTextureGatherOffset:" << compileResources.MaxProgramTextureGatherOffset
Jamie Madillacb4b812016-11-07 13:50:29 -0500850 << ":MaxImageUnits:" << compileResources.MaxImageUnits
851 << ":MaxVertexImageUniforms:" << compileResources.MaxVertexImageUniforms
852 << ":MaxFragmentImageUniforms:" << compileResources.MaxFragmentImageUniforms
853 << ":MaxComputeImageUniforms:" << compileResources.MaxComputeImageUniforms
854 << ":MaxCombinedImageUniforms:" << compileResources.MaxCombinedImageUniforms
855 << ":MaxCombinedShaderOutputResources:" << compileResources.MaxCombinedShaderOutputResources
856 << ":MaxComputeWorkGroupCountX:" << compileResources.MaxComputeWorkGroupCount[0]
857 << ":MaxComputeWorkGroupCountY:" << compileResources.MaxComputeWorkGroupCount[1]
858 << ":MaxComputeWorkGroupCountZ:" << compileResources.MaxComputeWorkGroupCount[2]
859 << ":MaxComputeWorkGroupSizeX:" << compileResources.MaxComputeWorkGroupSize[0]
860 << ":MaxComputeWorkGroupSizeY:" << compileResources.MaxComputeWorkGroupSize[1]
861 << ":MaxComputeWorkGroupSizeZ:" << compileResources.MaxComputeWorkGroupSize[2]
862 << ":MaxComputeUniformComponents:" << compileResources.MaxComputeUniformComponents
863 << ":MaxComputeTextureImageUnits:" << compileResources.MaxComputeTextureImageUnits
864 << ":MaxComputeAtomicCounters:" << compileResources.MaxComputeAtomicCounters
865 << ":MaxComputeAtomicCounterBuffers:" << compileResources.MaxComputeAtomicCounterBuffers
866 << ":MaxVertexAtomicCounters:" << compileResources.MaxVertexAtomicCounters
867 << ":MaxFragmentAtomicCounters:" << compileResources.MaxFragmentAtomicCounters
868 << ":MaxCombinedAtomicCounters:" << compileResources.MaxCombinedAtomicCounters
869 << ":MaxAtomicCounterBindings:" << compileResources.MaxAtomicCounterBindings
870 << ":MaxVertexAtomicCounterBuffers:" << compileResources.MaxVertexAtomicCounterBuffers
871 << ":MaxFragmentAtomicCounterBuffers:" << compileResources.MaxFragmentAtomicCounterBuffers
872 << ":MaxCombinedAtomicCounterBuffers:" << compileResources.MaxCombinedAtomicCounterBuffers
Shaob5cc1192017-07-06 10:47:20 +0800873 << ":MaxAtomicCounterBufferSize:" << compileResources.MaxAtomicCounterBufferSize
Shaob5cc1192017-07-06 10:47:20 +0800874 << ":MaxGeometryUniformComponents:" << compileResources.MaxGeometryUniformComponents
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800875 << ":MaxGeometryUniformBlocks:" << compileResources.MaxGeometryUniformBlocks
876 << ":MaxGeometryInputComponents:" << compileResources.MaxGeometryInputComponents
877 << ":MaxGeometryOutputComponents:" << compileResources.MaxGeometryOutputComponents
878 << ":MaxGeometryOutputVertices:" << compileResources.MaxGeometryOutputVertices
879 << ":MaxGeometryTotalOutputComponents:" << compileResources.MaxGeometryTotalOutputComponents
880 << ":MaxGeometryTextureImageUnits:" << compileResources.MaxGeometryTextureImageUnits
881 << ":MaxGeometryAtomicCounterBuffers:" << compileResources.MaxGeometryAtomicCounterBuffers
882 << ":MaxGeometryAtomicCounters:" << compileResources.MaxGeometryAtomicCounters
883 << ":MaxGeometryShaderStorageBlocks:" << compileResources.MaxGeometryShaderStorageBlocks
884 << ":MaxGeometryShaderInvocations:" << compileResources.MaxGeometryShaderInvocations
885 << ":MaxGeometryImageUniforms:" << compileResources.MaxGeometryImageUniforms;
Geoff Langb66a9092016-05-16 15:59:14 -0400886 // clang-format on
Shannon Woods2d76e5f2014-05-16 17:46:41 -0400887
888 builtInResourcesString = strstream.str();
889}
890
Jiajia Qin9b11ea42017-07-11 16:50:08 +0800891void TCompiler::collectInterfaceBlocks()
892{
893 ASSERT(interfaceBlocks.empty());
Jiawei Shaod8105a02017-08-08 09:54:36 +0800894 interfaceBlocks.reserve(uniformBlocks.size() + shaderStorageBlocks.size() + inBlocks.size());
Jiajia Qin9b11ea42017-07-11 16:50:08 +0800895 interfaceBlocks.insert(interfaceBlocks.end(), uniformBlocks.begin(), uniformBlocks.end());
896 interfaceBlocks.insert(interfaceBlocks.end(), shaderStorageBlocks.begin(),
897 shaderStorageBlocks.end());
Jiawei Shaod8105a02017-08-08 09:54:36 +0800898 interfaceBlocks.insert(interfaceBlocks.end(), inBlocks.begin(), inBlocks.end());
Jiajia Qin9b11ea42017-07-11 16:50:08 +0800899}
900
alokp@chromium.org07620a52010-09-23 17:53:56 +0000901void TCompiler::clearResults()
902{
daniel@transgaming.com4167cc92013-01-11 04:11:53 +0000903 arrayBoundsClamper.Cleanup();
alokp@chromium.org07620a52010-09-23 17:53:56 +0000904 infoSink.info.erase();
905 infoSink.obj.erase();
906 infoSink.debug.erase();
Olli Etuaho77ba4082016-12-16 12:01:18 +0000907 mDiagnostics.resetErrorCount();
alokp@chromium.org07620a52010-09-23 17:53:56 +0000908
Jamie Madilled27c722014-07-02 15:31:23 -0400909 attributes.clear();
910 outputVariables.clear();
alokp@chromium.org07620a52010-09-23 17:53:56 +0000911 uniforms.clear();
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800912 inputVaryings.clear();
913 outputVaryings.clear();
Jamie Madilled27c722014-07-02 15:31:23 -0400914 interfaceBlocks.clear();
Jiajia Qin9b11ea42017-07-11 16:50:08 +0800915 uniformBlocks.clear();
916 shaderStorageBlocks.clear();
Jiawei Shaod8105a02017-08-08 09:54:36 +0800917 inBlocks.clear();
Kenneth Russellbccc65d2016-07-19 16:48:43 -0700918 variablesCollected = false;
Olli Etuahob12040c2017-06-27 14:20:45 +0300919 mGLPositionInitialized = false;
zmo@google.coma3b4ab42011-09-16 00:53:26 +0000920
Olli Etuaho09b04a22016-12-15 13:30:26 +0000921 mNumViews = -1;
922
Shaob5cc1192017-07-06 10:47:20 +0800923 mGeometryShaderInputPrimitiveType = EptUndefined;
924 mGeometryShaderOutputPrimitiveType = EptUndefined;
925 mGeometryShaderInvocations = 0;
926 mGeometryShaderMaxVertices = -1;
927
Olli Etuahodfa75e82017-01-23 09:43:06 -0800928 builtInFunctionEmulator.cleanup();
daniel@transgaming.com0aa3b5a2012-11-28 19:43:24 +0000929
930 nameMap.clear();
Olli Etuahoa3a5cc62015-02-13 13:12:22 +0200931
Yunchao Hed7297bf2017-04-19 15:27:10 +0800932 mSourcePath = nullptr;
Olli Etuaho5d69db12017-11-24 16:51:15 +0200933
934 symbolTable.clearCompilationResults();
alokp@chromium.org07620a52010-09-23 17:53:56 +0000935}
936
Corentin Wallez71d147f2015-02-11 11:15:24 -0800937bool TCompiler::initCallDag(TIntermNode *root)
zmo@google.comb1762df2011-07-30 02:04:23 +0000938{
Corentin Wallez71d147f2015-02-11 11:15:24 -0800939 mCallDag.clear();
940
Olli Etuaho77ba4082016-12-16 12:01:18 +0000941 switch (mCallDag.init(root, &mDiagnostics))
Zhenyao Mo4a667fe2014-02-11 12:35:01 -0800942 {
Jamie Madillacb4b812016-11-07 13:50:29 -0500943 case CallDAG::INITDAG_SUCCESS:
944 return true;
945 case CallDAG::INITDAG_RECURSION:
Jamie Madillacb4b812016-11-07 13:50:29 -0500946 case CallDAG::INITDAG_UNDEFINED:
Olli Etuaho77ba4082016-12-16 12:01:18 +0000947 // Error message has already been written out.
948 ASSERT(mDiagnostics.numErrors() > 0);
Jamie Madillacb4b812016-11-07 13:50:29 -0500949 return false;
Corentin Wallez71d147f2015-02-11 11:15:24 -0800950 }
951
952 UNREACHABLE();
953 return true;
954}
955
956bool TCompiler::checkCallDepth()
957{
958 std::vector<int> depths(mCallDag.size());
959
960 for (size_t i = 0; i < mCallDag.size(); i++)
961 {
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500962 int depth = 0;
Corentin Wallez71d147f2015-02-11 11:15:24 -0800963 auto &record = mCallDag.getRecordFromIndex(i);
964
965 for (auto &calleeIndex : record.callees)
966 {
967 depth = std::max(depth, depths[calleeIndex] + 1);
968 }
969
970 depths[i] = depth;
971
972 if (depth >= maxCallStackDepth)
973 {
974 // Trace back the function chain to have a meaningful info log.
Olli Etuaho77ba4082016-12-16 12:01:18 +0000975 std::stringstream errorStream;
976 errorStream << "Call stack too deep (larger than " << maxCallStackDepth
Olli Etuahoc33f1e82017-12-29 16:55:29 +0200977 << ") with the following call chain: "
978 << record.node->getFunction()->name();
Corentin Wallez71d147f2015-02-11 11:15:24 -0800979
Cooper Partin4d61f7e2015-08-12 10:56:50 -0700980 int currentFunction = static_cast<int>(i);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500981 int currentDepth = depth;
Corentin Wallez71d147f2015-02-11 11:15:24 -0800982
983 while (currentFunction != -1)
984 {
Olli Etuahoc33f1e82017-12-29 16:55:29 +0200985 errorStream
986 << " -> "
987 << mCallDag.getRecordFromIndex(currentFunction).node->getFunction()->name();
Corentin Wallez71d147f2015-02-11 11:15:24 -0800988
989 int nextFunction = -1;
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500990 for (auto &calleeIndex : mCallDag.getRecordFromIndex(currentFunction).callees)
Corentin Wallez71d147f2015-02-11 11:15:24 -0800991 {
992 if (depths[calleeIndex] == currentDepth - 1)
993 {
994 currentDepth--;
995 nextFunction = calleeIndex;
996 }
997 }
998
999 currentFunction = nextFunction;
1000 }
1001
Olli Etuaho77ba4082016-12-16 12:01:18 +00001002 std::string errorStr = errorStream.str();
1003 mDiagnostics.globalError(errorStr.c_str());
1004
Corentin Wallez71d147f2015-02-11 11:15:24 -08001005 return false;
1006 }
1007 }
1008
1009 return true;
1010}
1011
1012bool TCompiler::tagUsedFunctions()
1013{
1014 // Search from main, starting from the end of the DAG as it usually is the root.
Cooper Partin4d61f7e2015-08-12 10:56:50 -07001015 for (size_t i = mCallDag.size(); i-- > 0;)
Corentin Wallez71d147f2015-02-11 11:15:24 -08001016 {
Olli Etuahoc33f1e82017-12-29 16:55:29 +02001017 if (mCallDag.getRecordFromIndex(i).node->getFunction()->isMain())
Corentin Wallez71d147f2015-02-11 11:15:24 -08001018 {
1019 internalTagUsedFunction(i);
1020 return true;
1021 }
1022 }
1023
Olli Etuaho77ba4082016-12-16 12:01:18 +00001024 mDiagnostics.globalError("Missing main()");
Corentin Wallez71d147f2015-02-11 11:15:24 -08001025 return false;
1026}
1027
1028void TCompiler::internalTagUsedFunction(size_t index)
1029{
1030 if (functionMetadata[index].used)
1031 {
1032 return;
1033 }
1034
1035 functionMetadata[index].used = true;
1036
1037 for (int calleeIndex : mCallDag.getRecordFromIndex(index).callees)
1038 {
1039 internalTagUsedFunction(calleeIndex);
zmo@google.comb1762df2011-07-30 02:04:23 +00001040 }
1041}
1042
Corentin Walleza094a8a2015-04-07 11:53:06 -07001043// A predicate for the stl that returns if a top-level node is unused
1044class TCompiler::UnusedPredicate
1045{
1046 public:
1047 UnusedPredicate(const CallDAG *callDag, const std::vector<FunctionMetadata> *metadatas)
Jamie Madillacb4b812016-11-07 13:50:29 -05001048 : mCallDag(callDag), mMetadatas(metadatas)
Corentin Walleza094a8a2015-04-07 11:53:06 -07001049 {
1050 }
1051
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001052 bool operator()(TIntermNode *node)
Corentin Walleza094a8a2015-04-07 11:53:06 -07001053 {
Olli Etuaho16c745a2017-01-16 17:02:27 +00001054 const TIntermFunctionPrototype *asFunctionPrototype = node->getAsFunctionPrototypeNode();
1055 const TIntermFunctionDefinition *asFunctionDefinition = node->getAsFunctionDefinition();
Corentin Walleza094a8a2015-04-07 11:53:06 -07001056
Olli Etuahobeb6dc72017-12-14 16:03:03 +02001057 const TFunction *func = nullptr;
Olli Etuaho336b1472016-10-05 16:37:55 +01001058
Olli Etuaho16c745a2017-01-16 17:02:27 +00001059 if (asFunctionDefinition)
Olli Etuaho336b1472016-10-05 16:37:55 +01001060 {
Olli Etuahobeb6dc72017-12-14 16:03:03 +02001061 func = asFunctionDefinition->getFunction();
Olli Etuaho336b1472016-10-05 16:37:55 +01001062 }
Olli Etuaho16c745a2017-01-16 17:02:27 +00001063 else if (asFunctionPrototype)
Olli Etuaho336b1472016-10-05 16:37:55 +01001064 {
Olli Etuahobeb6dc72017-12-14 16:03:03 +02001065 func = asFunctionPrototype->getFunction();
Olli Etuaho336b1472016-10-05 16:37:55 +01001066 }
Olli Etuahobeb6dc72017-12-14 16:03:03 +02001067 if (func == nullptr)
Corentin Walleza094a8a2015-04-07 11:53:06 -07001068 {
1069 return false;
1070 }
1071
Olli Etuahobeb6dc72017-12-14 16:03:03 +02001072 size_t callDagIndex = mCallDag->findIndex(func->uniqueId());
Corentin Walleza094a8a2015-04-07 11:53:06 -07001073 if (callDagIndex == CallDAG::InvalidIndex)
1074 {
1075 // This happens only for unimplemented prototypes which are thus unused
Olli Etuaho16c745a2017-01-16 17:02:27 +00001076 ASSERT(asFunctionPrototype);
Corentin Walleza094a8a2015-04-07 11:53:06 -07001077 return true;
1078 }
1079
1080 ASSERT(callDagIndex < mMetadatas->size());
1081 return !(*mMetadatas)[callDagIndex].used;
1082 }
1083
1084 private:
1085 const CallDAG *mCallDag;
1086 const std::vector<FunctionMetadata> *mMetadatas;
1087};
1088
Olli Etuahod10cf692017-11-02 11:06:14 +02001089void TCompiler::pruneUnusedFunctions(TIntermBlock *root)
Corentin Walleza094a8a2015-04-07 11:53:06 -07001090{
Corentin Walleza094a8a2015-04-07 11:53:06 -07001091 UnusedPredicate isUnused(&mCallDag, &functionMetadata);
Olli Etuaho6d40bbd2016-09-30 13:49:38 +01001092 TIntermSequence *sequence = root->getSequence();
Corentin Wallezb081e782015-07-20 05:40:04 -07001093
1094 if (!sequence->empty())
1095 {
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001096 sequence->erase(std::remove_if(sequence->begin(), sequence->end(), isUnused),
1097 sequence->end());
Corentin Wallezb081e782015-07-20 05:40:04 -07001098 }
Corentin Walleza094a8a2015-04-07 11:53:06 -07001099}
1100
Olli Etuahob4279202017-05-18 15:08:24 +03001101bool TCompiler::limitExpressionComplexity(TIntermBlock *root)
Jamie Madilleb1a0102013-07-08 13:31:38 -04001102{
Olli Etuahocccf2b02017-07-05 14:50:54 +03001103 if (!IsASTDepthBelowLimit(root, maxExpressionComplexity))
Jamie Madill6654bc92014-03-26 14:01:57 -04001104 {
Olli Etuaho77ba4082016-12-16 12:01:18 +00001105 mDiagnostics.globalError("Expression too complex.");
Jamie Madill6654bc92014-03-26 14:01:57 -04001106 return false;
1107 }
1108
Olli Etuahob4279202017-05-18 15:08:24 +03001109 if (!ValidateMaxParameters(root, maxFunctionParameters))
Olli Etuaho19d1dc92016-03-08 17:18:46 +02001110 {
Olli Etuaho77ba4082016-12-16 12:01:18 +00001111 mDiagnostics.globalError("Function has too many parameters.");
Olli Etuaho19d1dc92016-03-08 17:18:46 +02001112 return false;
1113 }
1114
Jamie Madilleb1a0102013-07-08 13:31:38 -04001115 return true;
1116}
1117
Corentin Wallez1df16022016-10-27 08:16:56 -04001118bool TCompiler::shouldCollectVariables(ShCompileOptions compileOptions)
1119{
1120 return (compileOptions & SH_VARIABLES) != 0;
1121}
1122
1123bool TCompiler::wereVariablesCollected() const
1124{
1125 return variablesCollected;
1126}
1127
Olli Etuaho9cbc07c2017-05-10 18:22:01 +03001128void TCompiler::initializeGLPosition(TIntermBlock *root)
Zhenyao Mo4a667fe2014-02-11 12:35:01 -08001129{
Zhenyao Mo72111912016-07-20 17:45:56 -07001130 InitVariableList list;
Olli Etuahoe7c28572017-10-23 16:29:33 +03001131 sh::ShaderVariable var(GL_FLOAT_VEC4);
Zhenyao Mo72111912016-07-20 17:45:56 -07001132 var.name = "gl_Position";
1133 list.push_back(var);
Olli Etuaho87cc90d2017-12-12 15:28:06 +02001134 InitializeVariables(root, list, &symbolTable, shaderVersion, extensionBehavior, false, false);
Zhenyao Mo4a667fe2014-02-11 12:35:01 -08001135}
1136
Olli Etuaho9cbc07c2017-05-10 18:22:01 +03001137void TCompiler::useAllMembersInUnusedStandardAndSharedBlocks(TIntermBlock *root)
Qin Jiajia7835b522016-10-08 11:20:17 +08001138{
1139 sh::InterfaceBlockList list;
1140
Jiajia Qin9b11ea42017-07-11 16:50:08 +08001141 for (auto block : uniformBlocks)
Qin Jiajia7835b522016-10-08 11:20:17 +08001142 {
1143 if (!block.staticUse &&
Qin Jiajiaca68d982017-09-18 16:41:56 +08001144 (block.layout == sh::BLOCKLAYOUT_STD140 || block.layout == sh::BLOCKLAYOUT_SHARED))
Qin Jiajia7835b522016-10-08 11:20:17 +08001145 {
1146 list.push_back(block);
1147 }
1148 }
1149
Zhenyao Mod7490962016-11-09 15:49:51 -08001150 sh::UseInterfaceBlockFields(root, list, symbolTable);
Qin Jiajia7835b522016-10-08 11:20:17 +08001151}
1152
Olli Etuaho9cbc07c2017-05-10 18:22:01 +03001153void TCompiler::initializeOutputVariables(TIntermBlock *root)
Zhenyao Mo4a667fe2014-02-11 12:35:01 -08001154{
Zhenyao Mo72111912016-07-20 17:45:56 -07001155 InitVariableList list;
Jiawei Shaobd924af2017-11-16 15:28:04 +08001156 if (shaderType == GL_VERTEX_SHADER || shaderType == GL_GEOMETRY_SHADER_EXT)
Zhenyao Mo4a667fe2014-02-11 12:35:01 -08001157 {
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +08001158 for (auto var : outputVaryings)
Zhenyao Mo4a667fe2014-02-11 12:35:01 -08001159 {
Zhenyao Mof9312682016-07-22 12:51:31 -07001160 list.push_back(var);
Olli Etuahob12040c2017-06-27 14:20:45 +03001161 if (var.name == "gl_Position")
1162 {
1163 ASSERT(!mGLPositionInitialized);
1164 mGLPositionInitialized = true;
1165 }
Zhenyao Mo4a667fe2014-02-11 12:35:01 -08001166 }
Zhenyao Mo4a667fe2014-02-11 12:35:01 -08001167 }
Zhenyao Mo72111912016-07-20 17:45:56 -07001168 else
1169 {
1170 ASSERT(shaderType == GL_FRAGMENT_SHADER);
1171 for (auto var : outputVariables)
1172 {
1173 list.push_back(var);
1174 }
1175 }
Olli Etuaho87cc90d2017-12-12 15:28:06 +02001176 InitializeVariables(root, list, &symbolTable, shaderVersion, extensionBehavior, false, false);
Zhenyao Mo4a667fe2014-02-11 12:35:01 -08001177}
1178
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001179const TExtensionBehavior &TCompiler::getExtensionBehavior() const
zmo@google.com5601ea02011-06-10 18:23:25 +00001180{
1181 return extensionBehavior;
1182}
zmo@google.com32e97312011-08-24 01:03:11 +00001183
Olli Etuahoa3a5cc62015-02-13 13:12:22 +02001184const char *TCompiler::getSourcePath() const
1185{
1186 return mSourcePath;
1187}
1188
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001189const ShBuiltInResources &TCompiler::getResources() const
shannon.woods%transgaming.com@gtempaccount.com18b4c4b2013-04-13 03:31:40 +00001190{
1191 return compileResources;
1192}
1193
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001194const ArrayBoundsClamper &TCompiler::getArrayBoundsClamper() const
daniel@transgaming.com4167cc92013-01-11 04:11:53 +00001195{
1196 return arrayBoundsClamper;
1197}
1198
shannon.woods@transgaming.com1d432bb2013-01-25 21:57:28 +00001199ShArrayIndexClampingStrategy TCompiler::getArrayIndexClampingStrategy() const
1200{
1201 return clampingStrategy;
1202}
1203
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001204const BuiltInFunctionEmulator &TCompiler::getBuiltInFunctionEmulator() const
shannon.woods@transgaming.com1d432bb2013-01-25 21:57:28 +00001205{
1206 return builtInFunctionEmulator;
1207}
Zhenyao Mo94ac7b72014-10-15 18:22:08 -07001208
Qiankun Miao7ebb97f2016-09-08 18:01:50 +08001209void TCompiler::writePragma(ShCompileOptions compileOptions)
Zhenyao Mo94ac7b72014-10-15 18:22:08 -07001210{
Kenneth Russellbccc65d2016-07-19 16:48:43 -07001211 if (!(compileOptions & SH_FLATTEN_PRAGMA_STDGL_INVARIANT_ALL))
1212 {
1213 TInfoSinkBase &sink = infoSink.obj;
1214 if (mPragma.stdgl.invariantAll)
1215 sink << "#pragma STDGL invariant(all)\n";
1216 }
1217}
1218
1219bool TCompiler::isVaryingDefined(const char *varyingName)
1220{
1221 ASSERT(variablesCollected);
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +08001222 for (size_t ii = 0; ii < inputVaryings.size(); ++ii)
Kenneth Russellbccc65d2016-07-19 16:48:43 -07001223 {
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +08001224 if (inputVaryings[ii].name == varyingName)
1225 {
1226 return true;
1227 }
1228 }
1229 for (size_t ii = 0; ii < outputVaryings.size(); ++ii)
1230 {
1231 if (outputVaryings[ii].name == varyingName)
Kenneth Russellbccc65d2016-07-19 16:48:43 -07001232 {
1233 return true;
1234 }
1235 }
1236
1237 return false;
Zhenyao Mo94ac7b72014-10-15 18:22:08 -07001238}
Jamie Madillacb4b812016-11-07 13:50:29 -05001239
1240} // namespace sh