blob: 74eb7bbaa531cd9540d40f51b742c8309e79fe43 [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"
Olli Etuaho983460e2018-05-02 17:57:39 +030041#include "compiler/translator/tree_ops/RewriteRepeatedAssignToSwizzled.h"
Olli Etuahoa07b4212018-03-22 16:13:13 +020042#include "compiler/translator/tree_ops/ScalarizeVecAndMatConstructorArgs.h"
43#include "compiler/translator/tree_ops/SeparateDeclarations.h"
44#include "compiler/translator/tree_ops/SimplifyLoopConditions.h"
45#include "compiler/translator/tree_ops/SplitSequenceOperator.h"
46#include "compiler/translator/tree_ops/UnfoldShortCircuitAST.h"
47#include "compiler/translator/tree_ops/UseInterfaceBlockFields.h"
48#include "compiler/translator/tree_ops/VectorizeVectorScalarArithmetic.h"
Olli Etuaho59c5b892018-04-03 11:44:50 +030049#include "compiler/translator/tree_util/BuiltIn_autogen.h"
Olli Etuahoc26214d2018-03-16 10:43:11 +020050#include "compiler/translator/tree_util/IntermNodePatternMatcher.h"
Olli Etuahob5601eb2017-11-15 18:08:04 +020051#include "compiler/translator/util.h"
shannon.woods@transgaming.comda1ed362013-01-25 21:54:57 +000052#include "third_party/compiler/ArrayBoundsClamper.h"
Corentin Wallez28b65282016-06-16 07:24:50 -070053
Jamie Madillacb4b812016-11-07 13:50:29 -050054namespace sh
55{
56
Corentin Wallez28b65282016-06-16 07:24:50 -070057namespace
58{
59
60#if defined(ANGLE_ENABLE_FUZZER_CORPUS_OUTPUT)
61void DumpFuzzerCase(char const *const *shaderStrings,
62 size_t numStrings,
63 uint32_t type,
64 uint32_t spec,
65 uint32_t output,
66 uint64_t options)
67{
68 static int fileIndex = 0;
69
70 std::ostringstream o;
71 o << "corpus/" << fileIndex++ << ".sample";
72 std::string s = o.str();
73
74 // Must match the input format of the fuzzer
75 FILE *f = fopen(s.c_str(), "w");
76 fwrite(&type, sizeof(type), 1, f);
77 fwrite(&spec, sizeof(spec), 1, f);
78 fwrite(&output, sizeof(output), 1, f);
79 fwrite(&options, sizeof(options), 1, f);
80
81 char zero[128 - 20] = {0};
82 fwrite(&zero, 128 - 20, 1, f);
83
84 for (size_t i = 0; i < numStrings; i++)
85 {
86 fwrite(shaderStrings[i], sizeof(char), strlen(shaderStrings[i]), f);
87 }
88 fwrite(&zero, 1, 1, f);
89
90 fclose(f);
91}
92#endif // defined(ANGLE_ENABLE_FUZZER_CORPUS_OUTPUT)
93} // anonymous namespace
94
Jamie Madill5508f392014-02-20 13:31:36 -050095bool IsWebGLBasedSpec(ShShaderSpec spec)
maxvujovic@gmail.com430f5e02012-06-08 17:47:59 +000096{
Qiankun Miaoc2c5fc42016-08-31 15:24:22 +080097 return (spec == SH_WEBGL_SPEC || spec == SH_WEBGL2_SPEC || spec == SH_WEBGL3_SPEC);
maxvujovic@gmail.com430f5e02012-06-08 17:47:59 +000098}
99
Qingqing Dengad0d0792015-04-08 14:25:06 -0700100bool IsGLSL130OrNewer(ShShaderOutput output)
101{
Jamie Madillacb4b812016-11-07 13:50:29 -0500102 return (output == SH_GLSL_130_OUTPUT || output == SH_GLSL_140_OUTPUT ||
103 output == SH_GLSL_150_CORE_OUTPUT || output == SH_GLSL_330_CORE_OUTPUT ||
104 output == SH_GLSL_400_CORE_OUTPUT || output == SH_GLSL_410_CORE_OUTPUT ||
105 output == SH_GLSL_420_CORE_OUTPUT || output == SH_GLSL_430_CORE_OUTPUT ||
106 output == SH_GLSL_440_CORE_OUTPUT || output == SH_GLSL_450_CORE_OUTPUT);
Qingqing Dengad0d0792015-04-08 14:25:06 -0700107}
108
Qiankun Miao705a9192016-08-29 10:05:27 +0800109bool IsGLSL420OrNewer(ShShaderOutput output)
110{
Jamie Madillacb4b812016-11-07 13:50:29 -0500111 return (output == SH_GLSL_420_CORE_OUTPUT || output == SH_GLSL_430_CORE_OUTPUT ||
112 output == SH_GLSL_440_CORE_OUTPUT || output == SH_GLSL_450_CORE_OUTPUT);
Qiankun Miao705a9192016-08-29 10:05:27 +0800113}
114
Zhenyao Mob7bf7422016-11-08 14:44:05 -0800115bool IsGLSL410OrOlder(ShShaderOutput output)
116{
117 return (output == SH_GLSL_130_OUTPUT || output == SH_GLSL_140_OUTPUT ||
118 output == SH_GLSL_150_CORE_OUTPUT || output == SH_GLSL_330_CORE_OUTPUT ||
119 output == SH_GLSL_400_CORE_OUTPUT || output == SH_GLSL_410_CORE_OUTPUT);
120}
121
Qiankun Miao89dd8f32016-11-09 12:59:30 +0000122bool RemoveInvariant(sh::GLenum shaderType,
123 int shaderVersion,
124 ShShaderOutput outputType,
125 ShCompileOptions compileOptions)
126{
127 if ((compileOptions & SH_DONT_REMOVE_INVARIANT_FOR_FRAGMENT_INPUT) == 0 &&
128 shaderType == GL_FRAGMENT_SHADER && IsGLSL420OrNewer(outputType))
129 return true;
130
131 if ((compileOptions & SH_REMOVE_INVARIANT_AND_CENTROID_FOR_ESSL3) != 0 &&
Qiankun Miao41f9f672016-11-16 17:04:36 +0800132 shaderVersion >= 300 && shaderType == GL_VERTEX_SHADER)
Qiankun Miao89dd8f32016-11-09 12:59:30 +0000133 return true;
134
135 return false;
136}
137
Zhenyao Mo7faf1a12014-04-25 18:03:56 -0700138size_t GetGlobalMaxTokenSize(ShShaderSpec spec)
Jamie Madill88f6e942014-02-19 10:27:53 -0500139{
He Yunchao29ab9ff2015-08-06 16:58:30 +0800140 // WebGL defines a max token length of 256, while ES2 leaves max token
Jamie Madill88f6e942014-02-19 10:27:53 -0500141 // size undefined. ES3 defines a max size of 1024 characters.
Zhenyao Modb9b40b2014-10-29 15:00:04 -0700142 switch (spec)
Jamie Madill88f6e942014-02-19 10:27:53 -0500143 {
Jamie Madillacb4b812016-11-07 13:50:29 -0500144 case SH_WEBGL_SPEC:
145 return 256;
146 default:
147 return 1024;
Jamie Madill88f6e942014-02-19 10:27:53 -0500148 }
149}
150
Shao77891c02017-06-23 16:30:17 +0800151int GetMaxUniformVectorsForShaderType(GLenum shaderType, const ShBuiltInResources &resources)
152{
153 switch (shaderType)
154 {
155 case GL_VERTEX_SHADER:
156 return resources.MaxVertexUniformVectors;
157 case GL_FRAGMENT_SHADER:
158 return resources.MaxFragmentUniformVectors;
Shaob5cc1192017-07-06 10:47:20 +0800159
160 // TODO (jiawei.shao@intel.com): check if we need finer-grained component counting
Shao77891c02017-06-23 16:30:17 +0800161 case GL_COMPUTE_SHADER:
Shao77891c02017-06-23 16:30:17 +0800162 return resources.MaxComputeUniformComponents / 4;
Jiawei Shaobd924af2017-11-16 15:28:04 +0800163 case GL_GEOMETRY_SHADER_EXT:
Shaob5cc1192017-07-06 10:47:20 +0800164 return resources.MaxGeometryUniformComponents / 4;
Shao77891c02017-06-23 16:30:17 +0800165 default:
Shaob5cc1192017-07-06 10:47:20 +0800166 UNREACHABLE();
Shao77891c02017-06-23 16:30:17 +0800167 return -1;
168 }
169}
170
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500171namespace
172{
Zhenyao Modb9b40b2014-10-29 15:00:04 -0700173
Zhenyao Mo4a667fe2014-02-11 12:35:01 -0800174class TScopedPoolAllocator
175{
176 public:
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500177 TScopedPoolAllocator(TPoolAllocator *allocator) : mAllocator(allocator)
Zhenyao Mo4a667fe2014-02-11 12:35:01 -0800178 {
Alok Priyadarshibc3f1ac2013-09-23 14:57:02 -0400179 mAllocator->push();
alokp@chromium.orgbafcbaa2010-11-23 19:07:43 +0000180 SetGlobalPoolAllocator(mAllocator);
181 }
Zhenyao Mo4a667fe2014-02-11 12:35:01 -0800182 ~TScopedPoolAllocator()
183 {
Yunchao Hef81ce4a2017-04-24 10:49:17 +0800184 SetGlobalPoolAllocator(nullptr);
Alok Priyadarshibc3f1ac2013-09-23 14:57:02 -0400185 mAllocator->pop();
alokp@chromium.orgbafcbaa2010-11-23 19:07:43 +0000186 }
187
Zhenyao Mo4a667fe2014-02-11 12:35:01 -0800188 private:
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500189 TPoolAllocator *mAllocator;
Alok Priyadarshibc3f1ac2013-09-23 14:57:02 -0400190};
191
Zhenyao Mo4a667fe2014-02-11 12:35:01 -0800192class TScopedSymbolTableLevel
193{
194 public:
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500195 TScopedSymbolTableLevel(TSymbolTable *table) : mTable(table)
Zhenyao Mo4a667fe2014-02-11 12:35:01 -0800196 {
Olli Etuaho437664b2018-02-28 15:38:14 +0200197 ASSERT(mTable->isEmpty());
Alok Priyadarshibc3f1ac2013-09-23 14:57:02 -0400198 mTable->push();
199 }
Zhenyao Mo4a667fe2014-02-11 12:35:01 -0800200 ~TScopedSymbolTableLevel()
201 {
Olli Etuaho437664b2018-02-28 15:38:14 +0200202 while (!mTable->isEmpty())
Alok Priyadarshibc3f1ac2013-09-23 14:57:02 -0400203 mTable->pop();
204 }
205
Zhenyao Mo4a667fe2014-02-11 12:35:01 -0800206 private:
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500207 TSymbolTable *mTable;
alokp@chromium.orgbafcbaa2010-11-23 19:07:43 +0000208};
Zhenyao Modb9b40b2014-10-29 15:00:04 -0700209
210int MapSpecToShaderVersion(ShShaderSpec spec)
211{
212 switch (spec)
213 {
Jamie Madillacb4b812016-11-07 13:50:29 -0500214 case SH_GLES2_SPEC:
215 case SH_WEBGL_SPEC:
216 return 100;
217 case SH_GLES3_SPEC:
218 case SH_WEBGL2_SPEC:
219 return 300;
220 case SH_GLES3_1_SPEC:
221 case SH_WEBGL3_SPEC:
222 return 310;
223 default:
224 UNREACHABLE();
225 return 0;
Zhenyao Modb9b40b2014-10-29 15:00:04 -0700226 }
227}
228
Olli Etuaho59c5b892018-04-03 11:44:50 +0300229bool ValidateFragColorAndFragData(GLenum shaderType,
230 int shaderVersion,
231 const TSymbolTable &symbolTable,
232 TDiagnostics *diagnostics)
233{
234 if (shaderVersion > 100 || shaderType != GL_FRAGMENT_SHADER)
235 {
236 return true;
237 }
238
239 bool usesFragColor = false;
240 bool usesFragData = false;
241 // This validation is a bit stricter than the spec - it's only an error to write to
242 // both FragData and FragColor. But because it's better not to have reads from undefined
243 // variables, we always return an error if they are both referenced, rather than only if they
244 // are written.
245 if (symbolTable.isStaticallyUsed(*BuiltInVariable::gl_FragColor()) ||
246 symbolTable.isStaticallyUsed(*BuiltInVariable::gl_SecondaryFragColorEXT()))
247 {
248 usesFragColor = true;
249 }
250 // Extension variables may not always be initialized (saves some time at symbol table init).
251 bool secondaryFragDataUsed =
252 symbolTable.gl_SecondaryFragDataEXT() != nullptr &&
253 symbolTable.isStaticallyUsed(*symbolTable.gl_SecondaryFragDataEXT());
254 if (symbolTable.isStaticallyUsed(*symbolTable.gl_FragData()) || secondaryFragDataUsed)
255 {
256 usesFragData = true;
257 }
258 if (usesFragColor && usesFragData)
259 {
260 const char *errorMessage = "cannot use both gl_FragData and gl_FragColor";
261 if (symbolTable.isStaticallyUsed(*BuiltInVariable::gl_SecondaryFragColorEXT()) ||
262 secondaryFragDataUsed)
263 {
264 errorMessage =
265 "cannot use both output variable sets (gl_FragData, gl_SecondaryFragDataEXT)"
266 " and (gl_FragColor, gl_SecondaryFragColorEXT)";
267 }
268 diagnostics->globalError(errorMessage);
269 return false;
270 }
271 return true;
272}
273
alokp@chromium.orgbafcbaa2010-11-23 19:07:43 +0000274} // namespace
275
Zhenyao Mo4a667fe2014-02-11 12:35:01 -0800276TShHandleBase::TShHandleBase()
277{
alokp@chromium.orgbafcbaa2010-11-23 19:07:43 +0000278 allocator.push();
279 SetGlobalPoolAllocator(&allocator);
280}
281
Zhenyao Mo4a667fe2014-02-11 12:35:01 -0800282TShHandleBase::~TShHandleBase()
283{
Yunchao Hef81ce4a2017-04-24 10:49:17 +0800284 SetGlobalPoolAllocator(nullptr);
alokp@chromium.orgbafcbaa2010-11-23 19:07:43 +0000285 allocator.popAll();
286}
287
Jamie Madill183bde52014-07-02 15:31:19 -0400288TCompiler::TCompiler(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output)
Kenneth Russellbccc65d2016-07-19 16:48:43 -0700289 : variablesCollected(false),
Olli Etuahob12040c2017-06-27 14:20:45 +0300290 mGLPositionInitialized(false),
Kenneth Russellbccc65d2016-07-19 16:48:43 -0700291 shaderType(type),
zmo@google.comf420c422011-09-12 18:27:59 +0000292 shaderSpec(spec),
Jamie Madill68fe74a2014-05-27 12:56:01 -0400293 outputType(output),
Jamie Madilleb1a0102013-07-08 13:31:38 -0400294 maxUniformVectors(0),
295 maxExpressionComplexity(0),
296 maxCallStackDepth(0),
Olli Etuaho19d1dc92016-03-08 17:18:46 +0200297 maxFunctionParameters(0),
shannon.woods%transgaming.com@gtempaccount.comcbb6b6a2013-04-13 03:27:47 +0000298 fragmentPrecisionHigh(false),
shannon.woods@transgaming.com1d432bb2013-01-25 21:57:28 +0000299 clampingStrategy(SH_CLAMP_WITH_CLAMP_INTRINSIC),
Olli Etuaho8efc5ad2015-03-03 17:21:10 +0200300 builtInFunctionEmulator(),
Olli Etuaho77ba4082016-12-16 12:01:18 +0000301 mDiagnostics(infoSink.info),
Yunchao Hef81ce4a2017-04-24 10:49:17 +0800302 mSourcePath(nullptr),
Shaob5cc1192017-07-06 10:47:20 +0800303 mComputeShaderLocalSizeDeclared(false),
Jamie Madill2f294c92017-11-20 14:47:26 -0500304 mComputeShaderLocalSize(1),
Shaob5cc1192017-07-06 10:47:20 +0800305 mGeometryShaderMaxVertices(-1),
306 mGeometryShaderInvocations(0),
307 mGeometryShaderInputPrimitiveType(EptUndefined),
308 mGeometryShaderOutputPrimitiveType(EptUndefined)
alokp@chromium.org4888ceb2010-10-01 21:13:12 +0000309{
310}
311
312TCompiler::~TCompiler()
313{
314}
315
Qiankun Miao7ebb97f2016-09-08 18:01:50 +0800316bool TCompiler::shouldRunLoopAndIndexingValidation(ShCompileOptions compileOptions) const
Olli Etuaho5d91dda2015-06-18 15:47:46 +0300317{
318 // If compiling an ESSL 1.00 shader for WebGL, or if its been requested through the API,
319 // validate loop and indexing as well (to verify that the shader only uses minimal functionality
320 // of ESSL 1.00 as in Appendix A of the spec).
321 return (IsWebGLBasedSpec(shaderSpec) && shaderVersion == 100) ||
322 (compileOptions & SH_VALIDATE_LOOP_INDEXING);
323}
324
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500325bool TCompiler::Init(const ShBuiltInResources &resources)
alokp@chromium.org07620a52010-09-23 17:53:56 +0000326{
Shao77891c02017-06-23 16:30:17 +0800327 shaderVersion = 100;
328
329 maxUniformVectors = GetMaxUniformVectorsForShaderType(shaderType, resources);
330
Jamie Madilleb1a0102013-07-08 13:31:38 -0400331 maxExpressionComplexity = resources.MaxExpressionComplexity;
Olli Etuaho19d1dc92016-03-08 17:18:46 +0200332 maxCallStackDepth = resources.MaxCallStackDepth;
333 maxFunctionParameters = resources.MaxFunctionParameters;
Alok Priyadarshibc3f1ac2013-09-23 14:57:02 -0400334
335 SetGlobalPoolAllocator(&allocator);
alokp@chromium.orgbafcbaa2010-11-23 19:07:43 +0000336
alokp@chromium.org07620a52010-09-23 17:53:56 +0000337 // Generate built-in symbol table.
338 if (!InitBuiltInSymbolTable(resources))
339 return false;
alokp@chromium.org07620a52010-09-23 17:53:56 +0000340 InitExtensionBehavior(resources, extensionBehavior);
shannon.woods%transgaming.com@gtempaccount.comcbb6b6a2013-04-13 03:27:47 +0000341 fragmentPrecisionHigh = resources.FragmentPrecisionHigh == 1;
alokp@chromium.orgbafcbaa2010-11-23 19:07:43 +0000342
shannon.woods@transgaming.com1d432bb2013-01-25 21:57:28 +0000343 arrayBoundsClamper.SetClampingStrategy(resources.ArrayIndexClampingStrategy);
344 clampingStrategy = resources.ArrayIndexClampingStrategy;
345
daniel@transgaming.comc23f4612012-11-28 19:42:57 +0000346 hashFunction = resources.HashFunction;
347
alokp@chromium.org07620a52010-09-23 17:53:56 +0000348 return true;
349}
350
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100351TIntermBlock *TCompiler::compileTreeForTesting(const char *const shaderStrings[],
352 size_t numStrings,
353 ShCompileOptions compileOptions)
alokp@chromium.org07620a52010-09-23 17:53:56 +0000354{
Olli Etuahoa3a5cc62015-02-13 13:12:22 +0200355 return compileTreeImpl(shaderStrings, numStrings, compileOptions);
356}
357
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100358TIntermBlock *TCompiler::compileTreeImpl(const char *const shaderStrings[],
359 size_t numStrings,
360 const ShCompileOptions compileOptions)
Olli Etuahoa3a5cc62015-02-13 13:12:22 +0200361{
alokp@chromium.org07620a52010-09-23 17:53:56 +0000362 clearResults();
363
Olli Etuahoa3a5cc62015-02-13 13:12:22 +0200364 ASSERT(numStrings > 0);
365 ASSERT(GetGlobalPoolAllocator());
alokp@chromium.org07620a52010-09-23 17:53:56 +0000366
David Yen0fbd1282015-02-02 14:46:09 -0800367 // Reset the extension behavior for each compilation unit.
368 ResetExtensionBehavior(extensionBehavior);
369
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +0000370 // First string is path of source file if flag is set. The actual source follows.
shannon.woods@transgaming.comd64b3da2013-02-28 23:19:26 +0000371 size_t firstSource = 0;
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +0000372 if (compileOptions & SH_SOURCE_PATH)
373 {
Olli Etuahoa3a5cc62015-02-13 13:12:22 +0200374 mSourcePath = shaderStrings[0];
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +0000375 ++firstSource;
376 }
377
Olli Etuahof119a262016-08-19 15:54:22 +0300378 TParseContext parseContext(symbolTable, extensionBehavior, shaderType, shaderSpec,
Olli Etuaho77ba4082016-12-16 12:01:18 +0000379 compileOptions, true, &mDiagnostics, getResources());
Olli Etuaho853dc1a2014-11-06 17:25:48 +0200380
Olli Etuahoa6996682015-10-12 14:32:30 +0300381 parseContext.setFragmentPrecisionHighOnESSL1(fragmentPrecisionHigh);
alokp@chromium.org07620a52010-09-23 17:53:56 +0000382
383 // We preserve symbols at the built-in level from compile-to-compile.
384 // Start pushing the user-defined symbols at global level.
Olli Etuahoe5fe7aa2018-01-29 12:06:11 +0200385 TScopedSymbolTableLevel globalLevel(&symbolTable);
386 ASSERT(symbolTable.atGlobalLevel());
alokp@chromium.org07620a52010-09-23 17:53:56 +0000387
388 // Parse shader.
Olli Etuahod10cf692017-11-02 11:06:14 +0200389 if (PaParseStrings(numStrings - firstSource, &shaderStrings[firstSource], nullptr,
390 &parseContext) != 0)
391 {
392 return nullptr;
393 }
shannon.woods%transgaming.com@gtempaccount.com0bbed382013-04-13 03:38:07 +0000394
Olli Etuahod10cf692017-11-02 11:06:14 +0200395 if (parseContext.getTreeRoot() == nullptr)
396 {
397 return nullptr;
398 }
399
400 setASTMetadata(parseContext);
401
Jiawei Shaoe41df652018-02-09 14:31:39 +0800402 if (!checkShaderVersion(&parseContext))
Zhenyao Modb9b40b2014-10-29 15:00:04 -0700403 {
Olli Etuahod10cf692017-11-02 11:06:14 +0200404 return nullptr;
Zhenyao Modb9b40b2014-10-29 15:00:04 -0700405 }
shannon.woods%transgaming.com@gtempaccount.com0bbed382013-04-13 03:38:07 +0000406
Olli Etuahod10cf692017-11-02 11:06:14 +0200407 TIntermBlock *root = parseContext.getTreeRoot();
408 if (!checkAndSimplifyAST(root, parseContext, compileOptions))
Zhenyao Mo4a667fe2014-02-11 12:35:01 -0800409 {
Olli Etuahod10cf692017-11-02 11:06:14 +0200410 return nullptr;
411 }
Zhenyao Mo94ac7b72014-10-15 18:22:08 -0700412
Olli Etuahod10cf692017-11-02 11:06:14 +0200413 return root;
414}
Martin Radev802abe02016-08-04 17:48:32 +0300415
Jiawei Shaoe41df652018-02-09 14:31:39 +0800416bool TCompiler::checkShaderVersion(TParseContext *parseContext)
417{
418 if (MapSpecToShaderVersion(shaderSpec) < shaderVersion)
419 {
420 mDiagnostics.globalError("unsupported shader version");
421 return false;
422 }
423
424 ASSERT(parseContext);
425 switch (shaderType)
426 {
427 case GL_COMPUTE_SHADER:
428 if (shaderVersion < 310)
429 {
430 mDiagnostics.globalError("Compute shader is not supported in this shader version.");
431 return false;
432 }
433 break;
434
435 case GL_GEOMETRY_SHADER_EXT:
436 if (shaderVersion < 310)
437 {
438 mDiagnostics.globalError(
439 "Geometry shader is not supported in this shader version.");
440 return false;
441 }
442 else
443 {
444 ASSERT(shaderVersion == 310);
445 if (!parseContext->checkCanUseExtension(sh::TSourceLoc(),
446 TExtension::EXT_geometry_shader))
447 {
448 return false;
449 }
450 }
451 break;
452
453 default:
454 break;
455 }
456
457 return true;
458}
459
Olli Etuahod10cf692017-11-02 11:06:14 +0200460void TCompiler::setASTMetadata(const TParseContext &parseContext)
461{
462 shaderVersion = parseContext.getShaderVersion();
Olli Etuaho09b04a22016-12-15 13:30:26 +0000463
Olli Etuahod10cf692017-11-02 11:06:14 +0200464 mPragma = parseContext.pragma();
465 symbolTable.setGlobalInvariant(mPragma.stdgl.invariantAll);
alokp@chromium.orgb59a7782010-11-24 18:38:33 +0000466
Olli Etuahod10cf692017-11-02 11:06:14 +0200467 mComputeShaderLocalSizeDeclared = parseContext.isComputeShaderLocalSizeDeclared();
468 mComputeShaderLocalSize = parseContext.getComputeShaderLocalSize();
Olli Etuahoa6996682015-10-12 14:32:30 +0300469
Olli Etuahod10cf692017-11-02 11:06:14 +0200470 mNumViews = parseContext.getNumViews();
471
472 // Highp might have been auto-enabled based on shader version
473 fragmentPrecisionHigh = parseContext.getFragmentPrecisionHigh();
474
Jiawei Shaobd924af2017-11-16 15:28:04 +0800475 if (shaderType == GL_GEOMETRY_SHADER_EXT)
Olli Etuahod10cf692017-11-02 11:06:14 +0200476 {
477 mGeometryShaderInputPrimitiveType = parseContext.getGeometryShaderInputPrimitiveType();
478 mGeometryShaderOutputPrimitiveType = parseContext.getGeometryShaderOutputPrimitiveType();
479 mGeometryShaderMaxVertices = parseContext.getGeometryShaderMaxVertices();
480 mGeometryShaderInvocations = parseContext.getGeometryShaderInvocations();
481 }
482}
483
484bool TCompiler::checkAndSimplifyAST(TIntermBlock *root,
485 const TParseContext &parseContext,
486 ShCompileOptions compileOptions)
487{
488 // Disallow expressions deemed too complex.
489 if ((compileOptions & SH_LIMIT_EXPRESSION_COMPLEXITY) && !limitExpressionComplexity(root))
490 {
491 return false;
492 }
493
Olli Etuaho765924f2018-01-04 12:48:36 +0200494 if (shouldRunLoopAndIndexingValidation(compileOptions) &&
Olli Etuaho68981eb2018-01-23 17:46:12 +0200495 !ValidateLimitations(root, shaderType, &symbolTable, &mDiagnostics))
Olli Etuaho765924f2018-01-04 12:48:36 +0200496 {
497 return false;
498 }
499
Olli Etuaho59c5b892018-04-03 11:44:50 +0300500 if (!ValidateFragColorAndFragData(shaderType, shaderVersion, symbolTable, &mDiagnostics))
501 {
502 return false;
503 }
504
Olli Etuaho765924f2018-01-04 12:48:36 +0200505 // Fold expressions that could not be folded before validation that was done as a part of
506 // parsing.
507 FoldExpressions(root, &mDiagnostics);
508 // Folding should only be able to generate warnings.
509 ASSERT(mDiagnostics.numErrors() == 0);
510
Olli Etuahod10cf692017-11-02 11:06:14 +0200511 // We prune no-ops to work around driver bugs and to keep AST processing and output simple.
512 // The following kinds of no-ops are pruned:
513 // 1. Empty declarations "int;".
514 // 2. Literal statements: "1.0;". The ESSL output doesn't define a default precision
515 // for float, so float literal statements would end up with no precision which is
516 // invalid ESSL.
517 // After this empty declarations are not allowed in the AST.
Olli Etuahob38dfde2018-01-04 15:49:03 +0200518 PruneNoOps(root, &symbolTable);
Olli Etuahod10cf692017-11-02 11:06:14 +0200519
Olli Etuahod10cf692017-11-02 11:06:14 +0200520 // Create the function DAG and check there is no recursion
521 if (!initCallDag(root))
522 {
523 return false;
524 }
525
526 if ((compileOptions & SH_LIMIT_CALL_STACK_DEPTH) && !checkCallDepth())
527 {
528 return false;
529 }
530
531 // Checks which functions are used and if "main" exists
532 functionMetadata.clear();
533 functionMetadata.resize(mCallDag.size());
534 if (!tagUsedFunctions())
535 {
536 return false;
537 }
538
539 if (!(compileOptions & SH_DONT_PRUNE_UNUSED_FUNCTIONS))
540 {
541 pruneUnusedFunctions(root);
542 }
543
544 if (shaderVersion >= 310 && !ValidateVaryingLocations(root, &mDiagnostics, shaderType))
545 {
546 return false;
547 }
548
549 if (shaderVersion >= 300 && shaderType == GL_FRAGMENT_SHADER &&
550 !ValidateOutputs(root, getExtensionBehavior(), compileResources.MaxDrawBuffers,
551 &mDiagnostics))
552 {
553 return false;
554 }
555
Olli Etuahod10cf692017-11-02 11:06:14 +0200556 // Fail compilation if precision emulation not supported.
557 if (getResources().WEBGL_debug_shader_precision && getPragma().debugShaderPrecision &&
558 !EmulatePrecision::SupportedInLanguage(outputType))
559 {
560 mDiagnostics.globalError("Precision emulation not supported for this output type.");
561 return false;
562 }
563
Olli Etuahod10cf692017-11-02 11:06:14 +0200564 // Clamping uniform array bounds needs to happen after validateLimitations pass.
565 if (compileOptions & SH_CLAMP_INDIRECT_ARRAY_BOUNDS)
566 {
567 arrayBoundsClamper.MarkIndirectArrayBoundsForClamping(root);
568 }
569
570 if ((compileOptions & SH_INITIALIZE_BUILTINS_FOR_INSTANCED_MULTIVIEW) &&
571 parseContext.isExtensionEnabled(TExtension::OVR_multiview) &&
572 getShaderType() != GL_COMPUTE_SHADER)
573 {
574 DeclareAndInitBuiltinsForInstancedMultiview(root, mNumViews, shaderType, compileOptions,
575 outputType, &symbolTable);
576 }
577
578 // This pass might emit short circuits so keep it before the short circuit unfolding
579 if (compileOptions & SH_REWRITE_DO_WHILE_LOOPS)
580 RewriteDoWhile(root, &symbolTable);
581
582 if (compileOptions & SH_ADD_AND_TRUE_TO_LOOP_CONDITION)
Olli Etuaho1776fd02018-01-31 11:46:52 +0200583 AddAndTrueToLoopCondition(root);
Olli Etuahod10cf692017-11-02 11:06:14 +0200584
585 if (compileOptions & SH_UNFOLD_SHORT_CIRCUIT)
586 {
Olli Etuaho1776fd02018-01-31 11:46:52 +0200587 UnfoldShortCircuitAST(root);
Olli Etuahod10cf692017-11-02 11:06:14 +0200588 }
589
590 if (compileOptions & SH_REMOVE_POW_WITH_CONSTANT_EXPONENT)
591 {
Olli Etuaho5fec7ab2018-04-04 11:58:33 +0300592 RemovePow(root, &symbolTable);
Olli Etuahod10cf692017-11-02 11:06:14 +0200593 }
594
Olli Etuahod10cf692017-11-02 11:06:14 +0200595 if (compileOptions & SH_REGENERATE_STRUCT_NAMES)
596 {
Olli Etuaho9d4d7f02017-12-07 17:11:41 +0100597 RegenerateStructNames gen(&symbolTable);
Olli Etuahod10cf692017-11-02 11:06:14 +0200598 root->traverse(&gen);
599 }
600
601 if (shaderType == GL_FRAGMENT_SHADER && shaderVersion == 100 &&
602 compileResources.EXT_draw_buffers && compileResources.MaxDrawBuffers > 1 &&
603 IsExtensionEnabled(extensionBehavior, TExtension::EXT_draw_buffers))
604 {
605 EmulateGLFragColorBroadcast(root, compileResources.MaxDrawBuffers, &outputVariables,
606 &symbolTable, shaderVersion);
607 }
608
Olli Etuahoae04e1e2017-11-27 16:00:39 +0200609 int simplifyScalarized = (compileOptions & SH_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS)
610 ? IntermNodePatternMatcher::kScalarizedVecOrMatConstructor
611 : 0;
612
Olli Etuahod10cf692017-11-02 11:06:14 +0200613 // Split multi declarations and remove calls to array length().
614 // Note that SimplifyLoopConditions needs to be run before any other AST transformations
615 // that may need to generate new statements from loop conditions or loop expressions.
Olli Etuahoae04e1e2017-11-27 16:00:39 +0200616 SimplifyLoopConditions(root,
617 IntermNodePatternMatcher::kMultiDeclaration |
618 IntermNodePatternMatcher::kArrayLengthMethod | simplifyScalarized,
Olli Etuaho68981eb2018-01-23 17:46:12 +0200619 &getSymbolTable());
Olli Etuahod10cf692017-11-02 11:06:14 +0200620
621 // Note that separate declarations need to be run before other AST transformations that
622 // generate new statements from expressions.
623 SeparateDeclarations(root);
624
Olli Etuahoae04e1e2017-11-27 16:00:39 +0200625 SplitSequenceOperator(root, IntermNodePatternMatcher::kArrayLengthMethod | simplifyScalarized,
Olli Etuaho68981eb2018-01-23 17:46:12 +0200626 &getSymbolTable());
Olli Etuahod10cf692017-11-02 11:06:14 +0200627
628 RemoveArrayLengthMethod(root);
629
Olli Etuaho3d70ca92017-11-10 16:53:26 +0200630 RemoveUnreferencedVariables(root, &symbolTable);
631
Olli Etuaho41217992018-03-15 11:15:33 +0200632 // In case the last case inside a switch statement is a certain type of no-op, GLSL compilers in
633 // drivers may not accept it. In this case we clean up the dead code from the end of switch
634 // statements. This is also required because PruneNoOps or RemoveUnreferencedVariables may have
635 // left switch statements that only contained an empty declaration inside the final case in an
636 // invalid state. Relies on that PruneNoOps and RemoveUnreferencedVariables have already been
637 // run.
Olli Etuaho0b0dcbc2018-03-14 11:33:22 +0200638 PruneEmptyCases(root);
639
Olli Etuaho3d70ca92017-11-10 16:53:26 +0200640 // Built-in function emulation needs to happen after validateLimitations pass.
641 // TODO(jmadill): Remove global pool allocator.
642 GetGlobalPoolAllocator()->lock();
643 initBuiltInFunctionEmulator(&builtInFunctionEmulator, compileOptions);
644 GetGlobalPoolAllocator()->unlock();
645 builtInFunctionEmulator.markBuiltInFunctionsForEmulation(root);
646
647 if (compileOptions & SH_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS)
648 {
649 ScalarizeVecAndMatConstructorArgs(root, shaderType, fragmentPrecisionHigh, &symbolTable);
650 }
651
652 if (shouldCollectVariables(compileOptions))
653 {
654 ASSERT(!variablesCollected);
655 CollectVariables(root, &attributes, &outputVariables, &uniforms, &inputVaryings,
656 &outputVaryings, &uniformBlocks, &shaderStorageBlocks, &inBlocks,
Olli Etuaho822a84b2018-03-23 12:30:18 +0200657 hashFunction, &symbolTable, shaderType, extensionBehavior);
Olli Etuaho3d70ca92017-11-10 16:53:26 +0200658 collectInterfaceBlocks();
659 variablesCollected = true;
660 if (compileOptions & SH_USE_UNUSED_STANDARD_SHARED_BLOCKS)
661 {
662 useAllMembersInUnusedStandardAndSharedBlocks(root);
663 }
664 if (compileOptions & SH_ENFORCE_PACKING_RESTRICTIONS)
665 {
666 // Returns true if, after applying the packing rules in the GLSL ES 1.00.17 spec
667 // Appendix A, section 7, the shader does not use too many uniforms.
668 if (!CheckVariablesInPackingLimits(maxUniformVectors, uniforms))
669 {
670 mDiagnostics.globalError("too many uniforms");
671 return false;
672 }
673 }
674 if (compileOptions & SH_INIT_OUTPUT_VARIABLES)
675 {
676 initializeOutputVariables(root);
677 }
678 }
679
680 // Removing invariant declarations must be done after collecting variables.
681 // Otherwise, built-in invariant declarations don't apply.
682 if (RemoveInvariant(shaderType, shaderVersion, outputType, compileOptions))
683 {
684 RemoveInvariantDeclaration(root);
685 }
686
687 // gl_Position is always written in compatibility output mode.
688 // It may have been already initialized among other output variables, in that case we don't
689 // need to initialize it twice.
690 if (shaderType == GL_VERTEX_SHADER && !mGLPositionInitialized &&
691 ((compileOptions & SH_INIT_GL_POSITION) || (outputType == SH_GLSL_COMPATIBILITY_OUTPUT)))
692 {
693 initializeGLPosition(root);
694 mGLPositionInitialized = true;
695 }
696
Olli Etuahob5601eb2017-11-15 18:08:04 +0200697 // DeferGlobalInitializers needs to be run before other AST transformations that generate new
698 // statements from expressions. But it's fine to run DeferGlobalInitializers after the above
699 // SplitSequenceOperator and RemoveArrayLengthMethod since they only have an effect on the AST
700 // on ESSL >= 3.00, and the initializers that need to be deferred can only exist in ESSL < 3.00.
701 bool initializeLocalsAndGlobals =
702 (compileOptions & SH_INITIALIZE_UNINITIALIZED_LOCALS) && !IsOutputHLSL(getOutputType());
Olli Etuaho2c7f34c2017-10-09 17:18:02 +0300703 bool canUseLoopsToInitialize = !(compileOptions & SH_DONT_USE_LOOPS_TO_INITIALIZE_VARIABLES);
Olli Etuaho87cc90d2017-12-12 15:28:06 +0200704 bool highPrecisionSupported =
705 shaderType != GL_FRAGMENT_SHADER || compileResources.FragmentPrecisionHigh;
706 DeferGlobalInitializers(root, initializeLocalsAndGlobals, canUseLoopsToInitialize,
707 highPrecisionSupported, &symbolTable);
Olli Etuaho2c7f34c2017-10-09 17:18:02 +0300708
Olli Etuahob5601eb2017-11-15 18:08:04 +0200709 if (initializeLocalsAndGlobals)
Olli Etuahod10cf692017-11-02 11:06:14 +0200710 {
711 // Initialize uninitialized local variables.
712 // In some cases initializing can generate extra statements in the parent block, such as
713 // when initializing nameless structs or initializing arrays in ESSL 1.00. In that case
714 // we need to first simplify loop conditions. We've already separated declarations
715 // earlier, which is also required. If we don't follow the Appendix A limitations, loop
716 // init statements can declare arrays or nameless structs and have multiple
717 // declarations.
718
719 if (!shouldRunLoopAndIndexingValidation(compileOptions))
720 {
721 SimplifyLoopConditions(root,
722 IntermNodePatternMatcher::kArrayDeclaration |
723 IntermNodePatternMatcher::kNamelessStructDeclaration,
Olli Etuaho68981eb2018-01-23 17:46:12 +0200724 &getSymbolTable());
Olli Etuahod10cf692017-11-02 11:06:14 +0200725 }
Olli Etuaho661fc482017-10-16 12:17:05 +0300726
Olli Etuaho2c7f34c2017-10-09 17:18:02 +0300727 InitializeUninitializedLocals(root, getShaderVersion(), canUseLoopsToInitialize,
Olli Etuaho87cc90d2017-12-12 15:28:06 +0200728 highPrecisionSupported, &getSymbolTable());
Olli Etuahod10cf692017-11-02 11:06:14 +0200729 }
730
731 if (getShaderType() == GL_VERTEX_SHADER && (compileOptions & SH_CLAMP_POINT_SIZE))
732 {
733 ClampPointSize(root, compileResources.MaxPointSize, &getSymbolTable());
734 }
735
Olli Etuaho0690e1a2017-12-21 20:51:38 +0200736 if (getShaderType() == GL_FRAGMENT_SHADER && (compileOptions & SH_CLAMP_FRAG_DEPTH))
737 {
738 ClampFragDepth(root, &getSymbolTable());
739 }
740
Olli Etuaho983460e2018-05-02 17:57:39 +0300741 if (compileOptions & SH_REWRITE_REPEATED_ASSIGN_TO_SWIZZLED)
742 {
743 sh::RewriteRepeatedAssignToSwizzled(root);
744 }
745
Olli Etuaho661fc482017-10-16 12:17:05 +0300746 if (compileOptions & SH_REWRITE_VECTOR_SCALAR_ARITHMETIC)
747 {
748 VectorizeVectorScalarArithmetic(root, &getSymbolTable());
749 }
750
Olli Etuahod10cf692017-11-02 11:06:14 +0200751 return true;
Olli Etuahoa3a5cc62015-02-13 13:12:22 +0200752}
753
Qiankun Miao7ebb97f2016-09-08 18:01:50 +0800754bool TCompiler::compile(const char *const shaderStrings[],
755 size_t numStrings,
756 ShCompileOptions compileOptionsIn)
Olli Etuahoa3a5cc62015-02-13 13:12:22 +0200757{
Corentin Wallez28b65282016-06-16 07:24:50 -0700758#if defined(ANGLE_ENABLE_FUZZER_CORPUS_OUTPUT)
759 DumpFuzzerCase(shaderStrings, numStrings, shaderType, shaderSpec, outputType, compileOptionsIn);
760#endif // defined(ANGLE_ENABLE_FUZZER_CORPUS_OUTPUT)
761
Olli Etuahoa3a5cc62015-02-13 13:12:22 +0200762 if (numStrings == 0)
763 return true;
764
Qiankun Miao7ebb97f2016-09-08 18:01:50 +0800765 ShCompileOptions compileOptions = compileOptionsIn;
Kenneth Russellbccc65d2016-07-19 16:48:43 -0700766
767 // Apply key workarounds.
768 if (shouldFlattenPragmaStdglInvariantAll())
769 {
770 // This should be harmless to do in all cases, but for the moment, do it only conditionally.
771 compileOptions |= SH_FLATTEN_PRAGMA_STDGL_INVARIANT_ALL;
772 }
773
Olli Etuahoa3a5cc62015-02-13 13:12:22 +0200774 TScopedPoolAllocator scopedAlloc(&allocator);
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100775 TIntermBlock *root = compileTreeImpl(shaderStrings, numStrings, compileOptions);
Olli Etuahoa3a5cc62015-02-13 13:12:22 +0200776
777 if (root)
778 {
779 if (compileOptions & SH_INTERMEDIATE_TREE)
Olli Etuahocccf2b02017-07-05 14:50:54 +0300780 OutputTree(root, infoSink.info);
Olli Etuahoa3a5cc62015-02-13 13:12:22 +0200781
782 if (compileOptions & SH_OBJECT_CODE)
Olli Etuaho89a69a02017-10-23 12:20:45 +0300783 {
784 PerformanceDiagnostics perfDiagnostics(&mDiagnostics);
785 translate(root, compileOptions, &perfDiagnostics);
786 }
Olli Etuahoa3a5cc62015-02-13 13:12:22 +0200787
788 // The IntermNode tree doesn't need to be deleted here, since the
789 // memory will be freed in a big chunk by the PoolAllocator.
790 return true;
791 }
792 return false;
alokp@chromium.org07620a52010-09-23 17:53:56 +0000793}
794
Nicolas Capens49a88872013-06-20 09:54:03 -0400795bool TCompiler::InitBuiltInSymbolTable(const ShBuiltInResources &resources)
alokp@chromium.org07620a52010-09-23 17:53:56 +0000796{
Olli Etuaho28cb0362016-11-22 15:42:37 +0000797 if (resources.MaxDrawBuffers < 1)
798 {
799 return false;
800 }
801 if (resources.EXT_blend_func_extended && resources.MaxDualSourceDrawBuffers < 1)
802 {
803 return false;
804 }
805
shannon.woods%transgaming.com@gtempaccount.com18b4c4b2013-04-13 03:31:40 +0000806 compileResources = resources;
Shannon Woods2d76e5f2014-05-16 17:46:41 -0400807 setResourceString();
shannonwoods@chromium.org2ac0be92013-05-30 00:02:27 +0000808
Olli Etuaho29bda812018-01-26 17:37:36 +0200809 symbolTable.initializeBuiltIns(shaderType, shaderSpec, resources);
Olli Etuaho5d69db12017-11-24 16:51:15 +0200810
Nicolas Capens49a88872013-06-20 09:54:03 -0400811 return true;
alokp@chromium.org07620a52010-09-23 17:53:56 +0000812}
813
Shannon Woods2d76e5f2014-05-16 17:46:41 -0400814void TCompiler::setResourceString()
815{
816 std::ostringstream strstream;
Geoff Langb66a9092016-05-16 15:59:14 -0400817
818 // clang-format off
Shannon Woods2d76e5f2014-05-16 17:46:41 -0400819 strstream << ":MaxVertexAttribs:" << compileResources.MaxVertexAttribs
Jamie Madillacb4b812016-11-07 13:50:29 -0500820 << ":MaxVertexUniformVectors:" << compileResources.MaxVertexUniformVectors
821 << ":MaxVaryingVectors:" << compileResources.MaxVaryingVectors
822 << ":MaxVertexTextureImageUnits:" << compileResources.MaxVertexTextureImageUnits
823 << ":MaxCombinedTextureImageUnits:" << compileResources.MaxCombinedTextureImageUnits
824 << ":MaxTextureImageUnits:" << compileResources.MaxTextureImageUnits
825 << ":MaxFragmentUniformVectors:" << compileResources.MaxFragmentUniformVectors
826 << ":MaxDrawBuffers:" << compileResources.MaxDrawBuffers
827 << ":OES_standard_derivatives:" << compileResources.OES_standard_derivatives
828 << ":OES_EGL_image_external:" << compileResources.OES_EGL_image_external
829 << ":OES_EGL_image_external_essl3:" << compileResources.OES_EGL_image_external_essl3
830 << ":NV_EGL_stream_consumer_external:" << compileResources.NV_EGL_stream_consumer_external
831 << ":ARB_texture_rectangle:" << compileResources.ARB_texture_rectangle
832 << ":EXT_draw_buffers:" << compileResources.EXT_draw_buffers
833 << ":FragmentPrecisionHigh:" << compileResources.FragmentPrecisionHigh
834 << ":MaxExpressionComplexity:" << compileResources.MaxExpressionComplexity
835 << ":MaxCallStackDepth:" << compileResources.MaxCallStackDepth
836 << ":MaxFunctionParameters:" << compileResources.MaxFunctionParameters
837 << ":EXT_blend_func_extended:" << compileResources.EXT_blend_func_extended
838 << ":EXT_frag_depth:" << compileResources.EXT_frag_depth
839 << ":EXT_shader_texture_lod:" << compileResources.EXT_shader_texture_lod
840 << ":EXT_shader_framebuffer_fetch:" << compileResources.EXT_shader_framebuffer_fetch
841 << ":NV_shader_framebuffer_fetch:" << compileResources.NV_shader_framebuffer_fetch
842 << ":ARM_shader_framebuffer_fetch:" << compileResources.ARM_shader_framebuffer_fetch
Martin Radev318f9aa2017-05-17 17:47:28 +0300843 << ":OVR_multiview:" << compileResources.OVR_multiview
Andrei Volykhina5527072017-03-22 16:46:30 +0300844 << ":EXT_YUV_target:" << compileResources.EXT_YUV_target
Jiawei Shaobd924af2017-11-16 15:28:04 +0800845 << ":EXT_geometry_shader:" << compileResources.EXT_geometry_shader
Jamie Madillacb4b812016-11-07 13:50:29 -0500846 << ":MaxVertexOutputVectors:" << compileResources.MaxVertexOutputVectors
847 << ":MaxFragmentInputVectors:" << compileResources.MaxFragmentInputVectors
848 << ":MinProgramTexelOffset:" << compileResources.MinProgramTexelOffset
849 << ":MaxProgramTexelOffset:" << compileResources.MaxProgramTexelOffset
850 << ":MaxDualSourceDrawBuffers:" << compileResources.MaxDualSourceDrawBuffers
Martin Radev318f9aa2017-05-17 17:47:28 +0300851 << ":MaxViewsOVR:" << compileResources.MaxViewsOVR
Jamie Madillacb4b812016-11-07 13:50:29 -0500852 << ":NV_draw_buffers:" << compileResources.NV_draw_buffers
853 << ":WEBGL_debug_shader_precision:" << compileResources.WEBGL_debug_shader_precision
Martin Radev84aa2dc2017-09-11 15:51:02 +0300854 << ":MinProgramTextureGatherOffset:" << compileResources.MinProgramTextureGatherOffset
855 << ":MaxProgramTextureGatherOffset:" << compileResources.MaxProgramTextureGatherOffset
Jamie Madillacb4b812016-11-07 13:50:29 -0500856 << ":MaxImageUnits:" << compileResources.MaxImageUnits
857 << ":MaxVertexImageUniforms:" << compileResources.MaxVertexImageUniforms
858 << ":MaxFragmentImageUniforms:" << compileResources.MaxFragmentImageUniforms
859 << ":MaxComputeImageUniforms:" << compileResources.MaxComputeImageUniforms
860 << ":MaxCombinedImageUniforms:" << compileResources.MaxCombinedImageUniforms
861 << ":MaxCombinedShaderOutputResources:" << compileResources.MaxCombinedShaderOutputResources
862 << ":MaxComputeWorkGroupCountX:" << compileResources.MaxComputeWorkGroupCount[0]
863 << ":MaxComputeWorkGroupCountY:" << compileResources.MaxComputeWorkGroupCount[1]
864 << ":MaxComputeWorkGroupCountZ:" << compileResources.MaxComputeWorkGroupCount[2]
865 << ":MaxComputeWorkGroupSizeX:" << compileResources.MaxComputeWorkGroupSize[0]
866 << ":MaxComputeWorkGroupSizeY:" << compileResources.MaxComputeWorkGroupSize[1]
867 << ":MaxComputeWorkGroupSizeZ:" << compileResources.MaxComputeWorkGroupSize[2]
868 << ":MaxComputeUniformComponents:" << compileResources.MaxComputeUniformComponents
869 << ":MaxComputeTextureImageUnits:" << compileResources.MaxComputeTextureImageUnits
870 << ":MaxComputeAtomicCounters:" << compileResources.MaxComputeAtomicCounters
871 << ":MaxComputeAtomicCounterBuffers:" << compileResources.MaxComputeAtomicCounterBuffers
872 << ":MaxVertexAtomicCounters:" << compileResources.MaxVertexAtomicCounters
873 << ":MaxFragmentAtomicCounters:" << compileResources.MaxFragmentAtomicCounters
874 << ":MaxCombinedAtomicCounters:" << compileResources.MaxCombinedAtomicCounters
875 << ":MaxAtomicCounterBindings:" << compileResources.MaxAtomicCounterBindings
876 << ":MaxVertexAtomicCounterBuffers:" << compileResources.MaxVertexAtomicCounterBuffers
877 << ":MaxFragmentAtomicCounterBuffers:" << compileResources.MaxFragmentAtomicCounterBuffers
878 << ":MaxCombinedAtomicCounterBuffers:" << compileResources.MaxCombinedAtomicCounterBuffers
Shaob5cc1192017-07-06 10:47:20 +0800879 << ":MaxAtomicCounterBufferSize:" << compileResources.MaxAtomicCounterBufferSize
Shaob5cc1192017-07-06 10:47:20 +0800880 << ":MaxGeometryUniformComponents:" << compileResources.MaxGeometryUniformComponents
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800881 << ":MaxGeometryUniformBlocks:" << compileResources.MaxGeometryUniformBlocks
882 << ":MaxGeometryInputComponents:" << compileResources.MaxGeometryInputComponents
883 << ":MaxGeometryOutputComponents:" << compileResources.MaxGeometryOutputComponents
884 << ":MaxGeometryOutputVertices:" << compileResources.MaxGeometryOutputVertices
885 << ":MaxGeometryTotalOutputComponents:" << compileResources.MaxGeometryTotalOutputComponents
886 << ":MaxGeometryTextureImageUnits:" << compileResources.MaxGeometryTextureImageUnits
887 << ":MaxGeometryAtomicCounterBuffers:" << compileResources.MaxGeometryAtomicCounterBuffers
888 << ":MaxGeometryAtomicCounters:" << compileResources.MaxGeometryAtomicCounters
889 << ":MaxGeometryShaderStorageBlocks:" << compileResources.MaxGeometryShaderStorageBlocks
890 << ":MaxGeometryShaderInvocations:" << compileResources.MaxGeometryShaderInvocations
891 << ":MaxGeometryImageUniforms:" << compileResources.MaxGeometryImageUniforms;
Geoff Langb66a9092016-05-16 15:59:14 -0400892 // clang-format on
Shannon Woods2d76e5f2014-05-16 17:46:41 -0400893
894 builtInResourcesString = strstream.str();
895}
896
Jiajia Qin9b11ea42017-07-11 16:50:08 +0800897void TCompiler::collectInterfaceBlocks()
898{
899 ASSERT(interfaceBlocks.empty());
Jiawei Shaod8105a02017-08-08 09:54:36 +0800900 interfaceBlocks.reserve(uniformBlocks.size() + shaderStorageBlocks.size() + inBlocks.size());
Jiajia Qin9b11ea42017-07-11 16:50:08 +0800901 interfaceBlocks.insert(interfaceBlocks.end(), uniformBlocks.begin(), uniformBlocks.end());
902 interfaceBlocks.insert(interfaceBlocks.end(), shaderStorageBlocks.begin(),
903 shaderStorageBlocks.end());
Jiawei Shaod8105a02017-08-08 09:54:36 +0800904 interfaceBlocks.insert(interfaceBlocks.end(), inBlocks.begin(), inBlocks.end());
Jiajia Qin9b11ea42017-07-11 16:50:08 +0800905}
906
alokp@chromium.org07620a52010-09-23 17:53:56 +0000907void TCompiler::clearResults()
908{
daniel@transgaming.com4167cc92013-01-11 04:11:53 +0000909 arrayBoundsClamper.Cleanup();
alokp@chromium.org07620a52010-09-23 17:53:56 +0000910 infoSink.info.erase();
911 infoSink.obj.erase();
912 infoSink.debug.erase();
Olli Etuaho77ba4082016-12-16 12:01:18 +0000913 mDiagnostics.resetErrorCount();
alokp@chromium.org07620a52010-09-23 17:53:56 +0000914
Jamie Madilled27c722014-07-02 15:31:23 -0400915 attributes.clear();
916 outputVariables.clear();
alokp@chromium.org07620a52010-09-23 17:53:56 +0000917 uniforms.clear();
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800918 inputVaryings.clear();
919 outputVaryings.clear();
Jamie Madilled27c722014-07-02 15:31:23 -0400920 interfaceBlocks.clear();
Jiajia Qin9b11ea42017-07-11 16:50:08 +0800921 uniformBlocks.clear();
922 shaderStorageBlocks.clear();
Jiawei Shaod8105a02017-08-08 09:54:36 +0800923 inBlocks.clear();
Kenneth Russellbccc65d2016-07-19 16:48:43 -0700924 variablesCollected = false;
Olli Etuahob12040c2017-06-27 14:20:45 +0300925 mGLPositionInitialized = false;
zmo@google.coma3b4ab42011-09-16 00:53:26 +0000926
Olli Etuaho09b04a22016-12-15 13:30:26 +0000927 mNumViews = -1;
928
Shaob5cc1192017-07-06 10:47:20 +0800929 mGeometryShaderInputPrimitiveType = EptUndefined;
930 mGeometryShaderOutputPrimitiveType = EptUndefined;
931 mGeometryShaderInvocations = 0;
932 mGeometryShaderMaxVertices = -1;
933
Olli Etuahodfa75e82017-01-23 09:43:06 -0800934 builtInFunctionEmulator.cleanup();
daniel@transgaming.com0aa3b5a2012-11-28 19:43:24 +0000935
936 nameMap.clear();
Olli Etuahoa3a5cc62015-02-13 13:12:22 +0200937
Yunchao Hed7297bf2017-04-19 15:27:10 +0800938 mSourcePath = nullptr;
Olli Etuaho5d69db12017-11-24 16:51:15 +0200939
940 symbolTable.clearCompilationResults();
alokp@chromium.org07620a52010-09-23 17:53:56 +0000941}
942
Corentin Wallez71d147f2015-02-11 11:15:24 -0800943bool TCompiler::initCallDag(TIntermNode *root)
zmo@google.comb1762df2011-07-30 02:04:23 +0000944{
Corentin Wallez71d147f2015-02-11 11:15:24 -0800945 mCallDag.clear();
946
Olli Etuaho77ba4082016-12-16 12:01:18 +0000947 switch (mCallDag.init(root, &mDiagnostics))
Zhenyao Mo4a667fe2014-02-11 12:35:01 -0800948 {
Jamie Madillacb4b812016-11-07 13:50:29 -0500949 case CallDAG::INITDAG_SUCCESS:
950 return true;
951 case CallDAG::INITDAG_RECURSION:
Jamie Madillacb4b812016-11-07 13:50:29 -0500952 case CallDAG::INITDAG_UNDEFINED:
Olli Etuaho77ba4082016-12-16 12:01:18 +0000953 // Error message has already been written out.
954 ASSERT(mDiagnostics.numErrors() > 0);
Jamie Madillacb4b812016-11-07 13:50:29 -0500955 return false;
Corentin Wallez71d147f2015-02-11 11:15:24 -0800956 }
957
958 UNREACHABLE();
959 return true;
960}
961
962bool TCompiler::checkCallDepth()
963{
964 std::vector<int> depths(mCallDag.size());
965
966 for (size_t i = 0; i < mCallDag.size(); i++)
967 {
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500968 int depth = 0;
Corentin Wallez71d147f2015-02-11 11:15:24 -0800969 auto &record = mCallDag.getRecordFromIndex(i);
970
971 for (auto &calleeIndex : record.callees)
972 {
973 depth = std::max(depth, depths[calleeIndex] + 1);
974 }
975
976 depths[i] = depth;
977
978 if (depth >= maxCallStackDepth)
979 {
980 // Trace back the function chain to have a meaningful info log.
Olli Etuaho77ba4082016-12-16 12:01:18 +0000981 std::stringstream errorStream;
982 errorStream << "Call stack too deep (larger than " << maxCallStackDepth
Olli Etuahoc33f1e82017-12-29 16:55:29 +0200983 << ") with the following call chain: "
984 << record.node->getFunction()->name();
Corentin Wallez71d147f2015-02-11 11:15:24 -0800985
Cooper Partin4d61f7e2015-08-12 10:56:50 -0700986 int currentFunction = static_cast<int>(i);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500987 int currentDepth = depth;
Corentin Wallez71d147f2015-02-11 11:15:24 -0800988
989 while (currentFunction != -1)
990 {
Olli Etuahoc33f1e82017-12-29 16:55:29 +0200991 errorStream
992 << " -> "
993 << mCallDag.getRecordFromIndex(currentFunction).node->getFunction()->name();
Corentin Wallez71d147f2015-02-11 11:15:24 -0800994
995 int nextFunction = -1;
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500996 for (auto &calleeIndex : mCallDag.getRecordFromIndex(currentFunction).callees)
Corentin Wallez71d147f2015-02-11 11:15:24 -0800997 {
998 if (depths[calleeIndex] == currentDepth - 1)
999 {
1000 currentDepth--;
1001 nextFunction = calleeIndex;
1002 }
1003 }
1004
1005 currentFunction = nextFunction;
1006 }
1007
Olli Etuaho77ba4082016-12-16 12:01:18 +00001008 std::string errorStr = errorStream.str();
1009 mDiagnostics.globalError(errorStr.c_str());
1010
Corentin Wallez71d147f2015-02-11 11:15:24 -08001011 return false;
1012 }
1013 }
1014
1015 return true;
1016}
1017
1018bool TCompiler::tagUsedFunctions()
1019{
1020 // Search from main, starting from the end of the DAG as it usually is the root.
Cooper Partin4d61f7e2015-08-12 10:56:50 -07001021 for (size_t i = mCallDag.size(); i-- > 0;)
Corentin Wallez71d147f2015-02-11 11:15:24 -08001022 {
Olli Etuahoc33f1e82017-12-29 16:55:29 +02001023 if (mCallDag.getRecordFromIndex(i).node->getFunction()->isMain())
Corentin Wallez71d147f2015-02-11 11:15:24 -08001024 {
1025 internalTagUsedFunction(i);
1026 return true;
1027 }
1028 }
1029
Olli Etuaho77ba4082016-12-16 12:01:18 +00001030 mDiagnostics.globalError("Missing main()");
Corentin Wallez71d147f2015-02-11 11:15:24 -08001031 return false;
1032}
1033
1034void TCompiler::internalTagUsedFunction(size_t index)
1035{
1036 if (functionMetadata[index].used)
1037 {
1038 return;
1039 }
1040
1041 functionMetadata[index].used = true;
1042
1043 for (int calleeIndex : mCallDag.getRecordFromIndex(index).callees)
1044 {
1045 internalTagUsedFunction(calleeIndex);
zmo@google.comb1762df2011-07-30 02:04:23 +00001046 }
1047}
1048
Corentin Walleza094a8a2015-04-07 11:53:06 -07001049// A predicate for the stl that returns if a top-level node is unused
1050class TCompiler::UnusedPredicate
1051{
1052 public:
1053 UnusedPredicate(const CallDAG *callDag, const std::vector<FunctionMetadata> *metadatas)
Jamie Madillacb4b812016-11-07 13:50:29 -05001054 : mCallDag(callDag), mMetadatas(metadatas)
Corentin Walleza094a8a2015-04-07 11:53:06 -07001055 {
1056 }
1057
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001058 bool operator()(TIntermNode *node)
Corentin Walleza094a8a2015-04-07 11:53:06 -07001059 {
Olli Etuaho16c745a2017-01-16 17:02:27 +00001060 const TIntermFunctionPrototype *asFunctionPrototype = node->getAsFunctionPrototypeNode();
1061 const TIntermFunctionDefinition *asFunctionDefinition = node->getAsFunctionDefinition();
Corentin Walleza094a8a2015-04-07 11:53:06 -07001062
Olli Etuahobeb6dc72017-12-14 16:03:03 +02001063 const TFunction *func = nullptr;
Olli Etuaho336b1472016-10-05 16:37:55 +01001064
Olli Etuaho16c745a2017-01-16 17:02:27 +00001065 if (asFunctionDefinition)
Olli Etuaho336b1472016-10-05 16:37:55 +01001066 {
Olli Etuahobeb6dc72017-12-14 16:03:03 +02001067 func = asFunctionDefinition->getFunction();
Olli Etuaho336b1472016-10-05 16:37:55 +01001068 }
Olli Etuaho16c745a2017-01-16 17:02:27 +00001069 else if (asFunctionPrototype)
Olli Etuaho336b1472016-10-05 16:37:55 +01001070 {
Olli Etuahobeb6dc72017-12-14 16:03:03 +02001071 func = asFunctionPrototype->getFunction();
Olli Etuaho336b1472016-10-05 16:37:55 +01001072 }
Olli Etuahobeb6dc72017-12-14 16:03:03 +02001073 if (func == nullptr)
Corentin Walleza094a8a2015-04-07 11:53:06 -07001074 {
1075 return false;
1076 }
1077
Olli Etuahobeb6dc72017-12-14 16:03:03 +02001078 size_t callDagIndex = mCallDag->findIndex(func->uniqueId());
Corentin Walleza094a8a2015-04-07 11:53:06 -07001079 if (callDagIndex == CallDAG::InvalidIndex)
1080 {
1081 // This happens only for unimplemented prototypes which are thus unused
Olli Etuaho16c745a2017-01-16 17:02:27 +00001082 ASSERT(asFunctionPrototype);
Corentin Walleza094a8a2015-04-07 11:53:06 -07001083 return true;
1084 }
1085
1086 ASSERT(callDagIndex < mMetadatas->size());
1087 return !(*mMetadatas)[callDagIndex].used;
1088 }
1089
1090 private:
1091 const CallDAG *mCallDag;
1092 const std::vector<FunctionMetadata> *mMetadatas;
1093};
1094
Olli Etuahod10cf692017-11-02 11:06:14 +02001095void TCompiler::pruneUnusedFunctions(TIntermBlock *root)
Corentin Walleza094a8a2015-04-07 11:53:06 -07001096{
Corentin Walleza094a8a2015-04-07 11:53:06 -07001097 UnusedPredicate isUnused(&mCallDag, &functionMetadata);
Olli Etuaho6d40bbd2016-09-30 13:49:38 +01001098 TIntermSequence *sequence = root->getSequence();
Corentin Wallezb081e782015-07-20 05:40:04 -07001099
1100 if (!sequence->empty())
1101 {
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001102 sequence->erase(std::remove_if(sequence->begin(), sequence->end(), isUnused),
1103 sequence->end());
Corentin Wallezb081e782015-07-20 05:40:04 -07001104 }
Corentin Walleza094a8a2015-04-07 11:53:06 -07001105}
1106
Olli Etuahob4279202017-05-18 15:08:24 +03001107bool TCompiler::limitExpressionComplexity(TIntermBlock *root)
Jamie Madilleb1a0102013-07-08 13:31:38 -04001108{
Olli Etuahocccf2b02017-07-05 14:50:54 +03001109 if (!IsASTDepthBelowLimit(root, maxExpressionComplexity))
Jamie Madill6654bc92014-03-26 14:01:57 -04001110 {
Olli Etuaho77ba4082016-12-16 12:01:18 +00001111 mDiagnostics.globalError("Expression too complex.");
Jamie Madill6654bc92014-03-26 14:01:57 -04001112 return false;
1113 }
1114
Olli Etuahob4279202017-05-18 15:08:24 +03001115 if (!ValidateMaxParameters(root, maxFunctionParameters))
Olli Etuaho19d1dc92016-03-08 17:18:46 +02001116 {
Olli Etuaho77ba4082016-12-16 12:01:18 +00001117 mDiagnostics.globalError("Function has too many parameters.");
Olli Etuaho19d1dc92016-03-08 17:18:46 +02001118 return false;
1119 }
1120
Jamie Madilleb1a0102013-07-08 13:31:38 -04001121 return true;
1122}
1123
Corentin Wallez1df16022016-10-27 08:16:56 -04001124bool TCompiler::shouldCollectVariables(ShCompileOptions compileOptions)
1125{
1126 return (compileOptions & SH_VARIABLES) != 0;
1127}
1128
1129bool TCompiler::wereVariablesCollected() const
1130{
1131 return variablesCollected;
1132}
1133
Olli Etuaho9cbc07c2017-05-10 18:22:01 +03001134void TCompiler::initializeGLPosition(TIntermBlock *root)
Zhenyao Mo4a667fe2014-02-11 12:35:01 -08001135{
Zhenyao Mo72111912016-07-20 17:45:56 -07001136 InitVariableList list;
Olli Etuahoe7c28572017-10-23 16:29:33 +03001137 sh::ShaderVariable var(GL_FLOAT_VEC4);
Zhenyao Mo72111912016-07-20 17:45:56 -07001138 var.name = "gl_Position";
1139 list.push_back(var);
Olli Etuaho87cc90d2017-12-12 15:28:06 +02001140 InitializeVariables(root, list, &symbolTable, shaderVersion, extensionBehavior, false, false);
Zhenyao Mo4a667fe2014-02-11 12:35:01 -08001141}
1142
Olli Etuaho9cbc07c2017-05-10 18:22:01 +03001143void TCompiler::useAllMembersInUnusedStandardAndSharedBlocks(TIntermBlock *root)
Qin Jiajia7835b522016-10-08 11:20:17 +08001144{
1145 sh::InterfaceBlockList list;
1146
Jiajia Qin9b11ea42017-07-11 16:50:08 +08001147 for (auto block : uniformBlocks)
Qin Jiajia7835b522016-10-08 11:20:17 +08001148 {
1149 if (!block.staticUse &&
Qin Jiajiaca68d982017-09-18 16:41:56 +08001150 (block.layout == sh::BLOCKLAYOUT_STD140 || block.layout == sh::BLOCKLAYOUT_SHARED))
Qin Jiajia7835b522016-10-08 11:20:17 +08001151 {
1152 list.push_back(block);
1153 }
1154 }
1155
Zhenyao Mod7490962016-11-09 15:49:51 -08001156 sh::UseInterfaceBlockFields(root, list, symbolTable);
Qin Jiajia7835b522016-10-08 11:20:17 +08001157}
1158
Olli Etuaho9cbc07c2017-05-10 18:22:01 +03001159void TCompiler::initializeOutputVariables(TIntermBlock *root)
Zhenyao Mo4a667fe2014-02-11 12:35:01 -08001160{
Zhenyao Mo72111912016-07-20 17:45:56 -07001161 InitVariableList list;
Jiawei Shaobd924af2017-11-16 15:28:04 +08001162 if (shaderType == GL_VERTEX_SHADER || shaderType == GL_GEOMETRY_SHADER_EXT)
Zhenyao Mo4a667fe2014-02-11 12:35:01 -08001163 {
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +08001164 for (auto var : outputVaryings)
Zhenyao Mo4a667fe2014-02-11 12:35:01 -08001165 {
Zhenyao Mof9312682016-07-22 12:51:31 -07001166 list.push_back(var);
Olli Etuahob12040c2017-06-27 14:20:45 +03001167 if (var.name == "gl_Position")
1168 {
1169 ASSERT(!mGLPositionInitialized);
1170 mGLPositionInitialized = true;
1171 }
Zhenyao Mo4a667fe2014-02-11 12:35:01 -08001172 }
Zhenyao Mo4a667fe2014-02-11 12:35:01 -08001173 }
Zhenyao Mo72111912016-07-20 17:45:56 -07001174 else
1175 {
1176 ASSERT(shaderType == GL_FRAGMENT_SHADER);
1177 for (auto var : outputVariables)
1178 {
1179 list.push_back(var);
1180 }
1181 }
Olli Etuaho87cc90d2017-12-12 15:28:06 +02001182 InitializeVariables(root, list, &symbolTable, shaderVersion, extensionBehavior, false, false);
Zhenyao Mo4a667fe2014-02-11 12:35:01 -08001183}
1184
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001185const TExtensionBehavior &TCompiler::getExtensionBehavior() const
zmo@google.com5601ea02011-06-10 18:23:25 +00001186{
1187 return extensionBehavior;
1188}
zmo@google.com32e97312011-08-24 01:03:11 +00001189
Olli Etuahoa3a5cc62015-02-13 13:12:22 +02001190const char *TCompiler::getSourcePath() const
1191{
1192 return mSourcePath;
1193}
1194
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001195const ShBuiltInResources &TCompiler::getResources() const
shannon.woods%transgaming.com@gtempaccount.com18b4c4b2013-04-13 03:31:40 +00001196{
1197 return compileResources;
1198}
1199
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001200const ArrayBoundsClamper &TCompiler::getArrayBoundsClamper() const
daniel@transgaming.com4167cc92013-01-11 04:11:53 +00001201{
1202 return arrayBoundsClamper;
1203}
1204
shannon.woods@transgaming.com1d432bb2013-01-25 21:57:28 +00001205ShArrayIndexClampingStrategy TCompiler::getArrayIndexClampingStrategy() const
1206{
1207 return clampingStrategy;
1208}
1209
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001210const BuiltInFunctionEmulator &TCompiler::getBuiltInFunctionEmulator() const
shannon.woods@transgaming.com1d432bb2013-01-25 21:57:28 +00001211{
1212 return builtInFunctionEmulator;
1213}
Zhenyao Mo94ac7b72014-10-15 18:22:08 -07001214
Qiankun Miao7ebb97f2016-09-08 18:01:50 +08001215void TCompiler::writePragma(ShCompileOptions compileOptions)
Zhenyao Mo94ac7b72014-10-15 18:22:08 -07001216{
Kenneth Russellbccc65d2016-07-19 16:48:43 -07001217 if (!(compileOptions & SH_FLATTEN_PRAGMA_STDGL_INVARIANT_ALL))
1218 {
1219 TInfoSinkBase &sink = infoSink.obj;
1220 if (mPragma.stdgl.invariantAll)
1221 sink << "#pragma STDGL invariant(all)\n";
1222 }
1223}
1224
1225bool TCompiler::isVaryingDefined(const char *varyingName)
1226{
1227 ASSERT(variablesCollected);
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +08001228 for (size_t ii = 0; ii < inputVaryings.size(); ++ii)
Kenneth Russellbccc65d2016-07-19 16:48:43 -07001229 {
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +08001230 if (inputVaryings[ii].name == varyingName)
1231 {
1232 return true;
1233 }
1234 }
1235 for (size_t ii = 0; ii < outputVaryings.size(); ++ii)
1236 {
1237 if (outputVaryings[ii].name == varyingName)
Kenneth Russellbccc65d2016-07-19 16:48:43 -07001238 {
1239 return true;
1240 }
1241 }
1242
1243 return false;
Zhenyao Mo94ac7b72014-10-15 18:22:08 -07001244}
Jamie Madillacb4b812016-11-07 13:50:29 -05001245
1246} // namespace sh