blob: 665c1d7559ff3c8726923843cb0702b146d56000 [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
Qingqing Dengad0d0792015-04-08 14:25:06 -070095bool IsGLSL130OrNewer(ShShaderOutput output)
96{
Jamie Madillacb4b812016-11-07 13:50:29 -050097 return (output == SH_GLSL_130_OUTPUT || output == SH_GLSL_140_OUTPUT ||
98 output == SH_GLSL_150_CORE_OUTPUT || output == SH_GLSL_330_CORE_OUTPUT ||
99 output == SH_GLSL_400_CORE_OUTPUT || output == SH_GLSL_410_CORE_OUTPUT ||
100 output == SH_GLSL_420_CORE_OUTPUT || output == SH_GLSL_430_CORE_OUTPUT ||
101 output == SH_GLSL_440_CORE_OUTPUT || output == SH_GLSL_450_CORE_OUTPUT);
Qingqing Dengad0d0792015-04-08 14:25:06 -0700102}
103
Qiankun Miao705a9192016-08-29 10:05:27 +0800104bool IsGLSL420OrNewer(ShShaderOutput output)
105{
Jamie Madillacb4b812016-11-07 13:50:29 -0500106 return (output == SH_GLSL_420_CORE_OUTPUT || output == SH_GLSL_430_CORE_OUTPUT ||
107 output == SH_GLSL_440_CORE_OUTPUT || output == SH_GLSL_450_CORE_OUTPUT);
Qiankun Miao705a9192016-08-29 10:05:27 +0800108}
109
Zhenyao Mob7bf7422016-11-08 14:44:05 -0800110bool IsGLSL410OrOlder(ShShaderOutput output)
111{
112 return (output == SH_GLSL_130_OUTPUT || output == SH_GLSL_140_OUTPUT ||
113 output == SH_GLSL_150_CORE_OUTPUT || output == SH_GLSL_330_CORE_OUTPUT ||
114 output == SH_GLSL_400_CORE_OUTPUT || output == SH_GLSL_410_CORE_OUTPUT);
115}
116
Qiankun Miao89dd8f32016-11-09 12:59:30 +0000117bool RemoveInvariant(sh::GLenum shaderType,
118 int shaderVersion,
119 ShShaderOutput outputType,
120 ShCompileOptions compileOptions)
121{
122 if ((compileOptions & SH_DONT_REMOVE_INVARIANT_FOR_FRAGMENT_INPUT) == 0 &&
123 shaderType == GL_FRAGMENT_SHADER && IsGLSL420OrNewer(outputType))
124 return true;
125
126 if ((compileOptions & SH_REMOVE_INVARIANT_AND_CENTROID_FOR_ESSL3) != 0 &&
Qiankun Miao41f9f672016-11-16 17:04:36 +0800127 shaderVersion >= 300 && shaderType == GL_VERTEX_SHADER)
Qiankun Miao89dd8f32016-11-09 12:59:30 +0000128 return true;
129
130 return false;
131}
132
Zhenyao Mo7faf1a12014-04-25 18:03:56 -0700133size_t GetGlobalMaxTokenSize(ShShaderSpec spec)
Jamie Madill88f6e942014-02-19 10:27:53 -0500134{
He Yunchao29ab9ff2015-08-06 16:58:30 +0800135 // WebGL defines a max token length of 256, while ES2 leaves max token
Jamie Madill88f6e942014-02-19 10:27:53 -0500136 // size undefined. ES3 defines a max size of 1024 characters.
Zhenyao Modb9b40b2014-10-29 15:00:04 -0700137 switch (spec)
Jamie Madill88f6e942014-02-19 10:27:53 -0500138 {
Jamie Madillacb4b812016-11-07 13:50:29 -0500139 case SH_WEBGL_SPEC:
140 return 256;
141 default:
142 return 1024;
Jamie Madill88f6e942014-02-19 10:27:53 -0500143 }
144}
145
Shao77891c02017-06-23 16:30:17 +0800146int GetMaxUniformVectorsForShaderType(GLenum shaderType, const ShBuiltInResources &resources)
147{
148 switch (shaderType)
149 {
150 case GL_VERTEX_SHADER:
151 return resources.MaxVertexUniformVectors;
152 case GL_FRAGMENT_SHADER:
153 return resources.MaxFragmentUniformVectors;
Shaob5cc1192017-07-06 10:47:20 +0800154
155 // TODO (jiawei.shao@intel.com): check if we need finer-grained component counting
Shao77891c02017-06-23 16:30:17 +0800156 case GL_COMPUTE_SHADER:
Shao77891c02017-06-23 16:30:17 +0800157 return resources.MaxComputeUniformComponents / 4;
Jiawei Shaobd924af2017-11-16 15:28:04 +0800158 case GL_GEOMETRY_SHADER_EXT:
Shaob5cc1192017-07-06 10:47:20 +0800159 return resources.MaxGeometryUniformComponents / 4;
Shao77891c02017-06-23 16:30:17 +0800160 default:
Shaob5cc1192017-07-06 10:47:20 +0800161 UNREACHABLE();
Shao77891c02017-06-23 16:30:17 +0800162 return -1;
163 }
164}
165
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500166namespace
167{
Zhenyao Modb9b40b2014-10-29 15:00:04 -0700168
Zhenyao Mo4a667fe2014-02-11 12:35:01 -0800169class TScopedPoolAllocator
170{
171 public:
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500172 TScopedPoolAllocator(TPoolAllocator *allocator) : mAllocator(allocator)
Zhenyao Mo4a667fe2014-02-11 12:35:01 -0800173 {
Alok Priyadarshibc3f1ac2013-09-23 14:57:02 -0400174 mAllocator->push();
alokp@chromium.orgbafcbaa2010-11-23 19:07:43 +0000175 SetGlobalPoolAllocator(mAllocator);
176 }
Zhenyao Mo4a667fe2014-02-11 12:35:01 -0800177 ~TScopedPoolAllocator()
178 {
Yunchao Hef81ce4a2017-04-24 10:49:17 +0800179 SetGlobalPoolAllocator(nullptr);
Alok Priyadarshibc3f1ac2013-09-23 14:57:02 -0400180 mAllocator->pop();
alokp@chromium.orgbafcbaa2010-11-23 19:07:43 +0000181 }
182
Zhenyao Mo4a667fe2014-02-11 12:35:01 -0800183 private:
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500184 TPoolAllocator *mAllocator;
Alok Priyadarshibc3f1ac2013-09-23 14:57:02 -0400185};
186
Zhenyao Mo4a667fe2014-02-11 12:35:01 -0800187class TScopedSymbolTableLevel
188{
189 public:
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500190 TScopedSymbolTableLevel(TSymbolTable *table) : mTable(table)
Zhenyao Mo4a667fe2014-02-11 12:35:01 -0800191 {
Olli Etuaho437664b2018-02-28 15:38:14 +0200192 ASSERT(mTable->isEmpty());
Alok Priyadarshibc3f1ac2013-09-23 14:57:02 -0400193 mTable->push();
194 }
Zhenyao Mo4a667fe2014-02-11 12:35:01 -0800195 ~TScopedSymbolTableLevel()
196 {
Olli Etuaho437664b2018-02-28 15:38:14 +0200197 while (!mTable->isEmpty())
Alok Priyadarshibc3f1ac2013-09-23 14:57:02 -0400198 mTable->pop();
199 }
200
Zhenyao Mo4a667fe2014-02-11 12:35:01 -0800201 private:
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500202 TSymbolTable *mTable;
alokp@chromium.orgbafcbaa2010-11-23 19:07:43 +0000203};
Zhenyao Modb9b40b2014-10-29 15:00:04 -0700204
205int MapSpecToShaderVersion(ShShaderSpec spec)
206{
207 switch (spec)
208 {
Jamie Madillacb4b812016-11-07 13:50:29 -0500209 case SH_GLES2_SPEC:
210 case SH_WEBGL_SPEC:
211 return 100;
212 case SH_GLES3_SPEC:
213 case SH_WEBGL2_SPEC:
214 return 300;
215 case SH_GLES3_1_SPEC:
216 case SH_WEBGL3_SPEC:
217 return 310;
218 default:
219 UNREACHABLE();
220 return 0;
Zhenyao Modb9b40b2014-10-29 15:00:04 -0700221 }
222}
223
Olli Etuaho59c5b892018-04-03 11:44:50 +0300224bool ValidateFragColorAndFragData(GLenum shaderType,
225 int shaderVersion,
226 const TSymbolTable &symbolTable,
227 TDiagnostics *diagnostics)
228{
229 if (shaderVersion > 100 || shaderType != GL_FRAGMENT_SHADER)
230 {
231 return true;
232 }
233
234 bool usesFragColor = false;
235 bool usesFragData = false;
236 // This validation is a bit stricter than the spec - it's only an error to write to
237 // both FragData and FragColor. But because it's better not to have reads from undefined
238 // variables, we always return an error if they are both referenced, rather than only if they
239 // are written.
240 if (symbolTable.isStaticallyUsed(*BuiltInVariable::gl_FragColor()) ||
241 symbolTable.isStaticallyUsed(*BuiltInVariable::gl_SecondaryFragColorEXT()))
242 {
243 usesFragColor = true;
244 }
245 // Extension variables may not always be initialized (saves some time at symbol table init).
246 bool secondaryFragDataUsed =
247 symbolTable.gl_SecondaryFragDataEXT() != nullptr &&
248 symbolTable.isStaticallyUsed(*symbolTable.gl_SecondaryFragDataEXT());
249 if (symbolTable.isStaticallyUsed(*symbolTable.gl_FragData()) || secondaryFragDataUsed)
250 {
251 usesFragData = true;
252 }
253 if (usesFragColor && usesFragData)
254 {
255 const char *errorMessage = "cannot use both gl_FragData and gl_FragColor";
256 if (symbolTable.isStaticallyUsed(*BuiltInVariable::gl_SecondaryFragColorEXT()) ||
257 secondaryFragDataUsed)
258 {
259 errorMessage =
260 "cannot use both output variable sets (gl_FragData, gl_SecondaryFragDataEXT)"
261 " and (gl_FragColor, gl_SecondaryFragColorEXT)";
262 }
263 diagnostics->globalError(errorMessage);
264 return false;
265 }
266 return true;
267}
268
alokp@chromium.orgbafcbaa2010-11-23 19:07:43 +0000269} // namespace
270
Zhenyao Mo4a667fe2014-02-11 12:35:01 -0800271TShHandleBase::TShHandleBase()
272{
alokp@chromium.orgbafcbaa2010-11-23 19:07:43 +0000273 allocator.push();
274 SetGlobalPoolAllocator(&allocator);
275}
276
Zhenyao Mo4a667fe2014-02-11 12:35:01 -0800277TShHandleBase::~TShHandleBase()
278{
Yunchao Hef81ce4a2017-04-24 10:49:17 +0800279 SetGlobalPoolAllocator(nullptr);
alokp@chromium.orgbafcbaa2010-11-23 19:07:43 +0000280 allocator.popAll();
281}
282
Jamie Madill183bde52014-07-02 15:31:19 -0400283TCompiler::TCompiler(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output)
Kenneth Russellbccc65d2016-07-19 16:48:43 -0700284 : variablesCollected(false),
Olli Etuahob12040c2017-06-27 14:20:45 +0300285 mGLPositionInitialized(false),
Kenneth Russellbccc65d2016-07-19 16:48:43 -0700286 shaderType(type),
zmo@google.comf420c422011-09-12 18:27:59 +0000287 shaderSpec(spec),
Jamie Madill68fe74a2014-05-27 12:56:01 -0400288 outputType(output),
Jamie Madilleb1a0102013-07-08 13:31:38 -0400289 maxUniformVectors(0),
290 maxExpressionComplexity(0),
291 maxCallStackDepth(0),
Olli Etuaho19d1dc92016-03-08 17:18:46 +0200292 maxFunctionParameters(0),
shannon.woods%transgaming.com@gtempaccount.comcbb6b6a2013-04-13 03:27:47 +0000293 fragmentPrecisionHigh(false),
shannon.woods@transgaming.com1d432bb2013-01-25 21:57:28 +0000294 clampingStrategy(SH_CLAMP_WITH_CLAMP_INTRINSIC),
Olli Etuaho8efc5ad2015-03-03 17:21:10 +0200295 builtInFunctionEmulator(),
Olli Etuaho77ba4082016-12-16 12:01:18 +0000296 mDiagnostics(infoSink.info),
Yunchao Hef81ce4a2017-04-24 10:49:17 +0800297 mSourcePath(nullptr),
Shaob5cc1192017-07-06 10:47:20 +0800298 mComputeShaderLocalSizeDeclared(false),
Jamie Madill2f294c92017-11-20 14:47:26 -0500299 mComputeShaderLocalSize(1),
Shaob5cc1192017-07-06 10:47:20 +0800300 mGeometryShaderMaxVertices(-1),
301 mGeometryShaderInvocations(0),
302 mGeometryShaderInputPrimitiveType(EptUndefined),
303 mGeometryShaderOutputPrimitiveType(EptUndefined)
alokp@chromium.org4888ceb2010-10-01 21:13:12 +0000304{
305}
306
307TCompiler::~TCompiler()
308{
309}
310
Qiankun Miao7ebb97f2016-09-08 18:01:50 +0800311bool TCompiler::shouldRunLoopAndIndexingValidation(ShCompileOptions compileOptions) const
Olli Etuaho5d91dda2015-06-18 15:47:46 +0300312{
313 // If compiling an ESSL 1.00 shader for WebGL, or if its been requested through the API,
314 // validate loop and indexing as well (to verify that the shader only uses minimal functionality
315 // of ESSL 1.00 as in Appendix A of the spec).
316 return (IsWebGLBasedSpec(shaderSpec) && shaderVersion == 100) ||
317 (compileOptions & SH_VALIDATE_LOOP_INDEXING);
318}
319
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500320bool TCompiler::Init(const ShBuiltInResources &resources)
alokp@chromium.org07620a52010-09-23 17:53:56 +0000321{
Shao77891c02017-06-23 16:30:17 +0800322 shaderVersion = 100;
323
324 maxUniformVectors = GetMaxUniformVectorsForShaderType(shaderType, resources);
325
Jamie Madilleb1a0102013-07-08 13:31:38 -0400326 maxExpressionComplexity = resources.MaxExpressionComplexity;
Olli Etuaho19d1dc92016-03-08 17:18:46 +0200327 maxCallStackDepth = resources.MaxCallStackDepth;
328 maxFunctionParameters = resources.MaxFunctionParameters;
Alok Priyadarshibc3f1ac2013-09-23 14:57:02 -0400329
330 SetGlobalPoolAllocator(&allocator);
alokp@chromium.orgbafcbaa2010-11-23 19:07:43 +0000331
alokp@chromium.org07620a52010-09-23 17:53:56 +0000332 // Generate built-in symbol table.
333 if (!InitBuiltInSymbolTable(resources))
334 return false;
alokp@chromium.org07620a52010-09-23 17:53:56 +0000335 InitExtensionBehavior(resources, extensionBehavior);
shannon.woods%transgaming.com@gtempaccount.comcbb6b6a2013-04-13 03:27:47 +0000336 fragmentPrecisionHigh = resources.FragmentPrecisionHigh == 1;
alokp@chromium.orgbafcbaa2010-11-23 19:07:43 +0000337
shannon.woods@transgaming.com1d432bb2013-01-25 21:57:28 +0000338 arrayBoundsClamper.SetClampingStrategy(resources.ArrayIndexClampingStrategy);
339 clampingStrategy = resources.ArrayIndexClampingStrategy;
340
daniel@transgaming.comc23f4612012-11-28 19:42:57 +0000341 hashFunction = resources.HashFunction;
342
alokp@chromium.org07620a52010-09-23 17:53:56 +0000343 return true;
344}
345
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100346TIntermBlock *TCompiler::compileTreeForTesting(const char *const shaderStrings[],
347 size_t numStrings,
348 ShCompileOptions compileOptions)
alokp@chromium.org07620a52010-09-23 17:53:56 +0000349{
Olli Etuahoa3a5cc62015-02-13 13:12:22 +0200350 return compileTreeImpl(shaderStrings, numStrings, compileOptions);
351}
352
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100353TIntermBlock *TCompiler::compileTreeImpl(const char *const shaderStrings[],
354 size_t numStrings,
355 const ShCompileOptions compileOptions)
Olli Etuahoa3a5cc62015-02-13 13:12:22 +0200356{
alokp@chromium.org07620a52010-09-23 17:53:56 +0000357 clearResults();
358
Olli Etuahoa3a5cc62015-02-13 13:12:22 +0200359 ASSERT(numStrings > 0);
360 ASSERT(GetGlobalPoolAllocator());
alokp@chromium.org07620a52010-09-23 17:53:56 +0000361
David Yen0fbd1282015-02-02 14:46:09 -0800362 // Reset the extension behavior for each compilation unit.
363 ResetExtensionBehavior(extensionBehavior);
364
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +0000365 // First string is path of source file if flag is set. The actual source follows.
shannon.woods@transgaming.comd64b3da2013-02-28 23:19:26 +0000366 size_t firstSource = 0;
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +0000367 if (compileOptions & SH_SOURCE_PATH)
368 {
Olli Etuahoa3a5cc62015-02-13 13:12:22 +0200369 mSourcePath = shaderStrings[0];
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +0000370 ++firstSource;
371 }
372
Olli Etuahof119a262016-08-19 15:54:22 +0300373 TParseContext parseContext(symbolTable, extensionBehavior, shaderType, shaderSpec,
Olli Etuaho77ba4082016-12-16 12:01:18 +0000374 compileOptions, true, &mDiagnostics, getResources());
Olli Etuaho853dc1a2014-11-06 17:25:48 +0200375
Olli Etuahoa6996682015-10-12 14:32:30 +0300376 parseContext.setFragmentPrecisionHighOnESSL1(fragmentPrecisionHigh);
alokp@chromium.org07620a52010-09-23 17:53:56 +0000377
378 // We preserve symbols at the built-in level from compile-to-compile.
379 // Start pushing the user-defined symbols at global level.
Olli Etuahoe5fe7aa2018-01-29 12:06:11 +0200380 TScopedSymbolTableLevel globalLevel(&symbolTable);
381 ASSERT(symbolTable.atGlobalLevel());
alokp@chromium.org07620a52010-09-23 17:53:56 +0000382
383 // Parse shader.
Olli Etuahod10cf692017-11-02 11:06:14 +0200384 if (PaParseStrings(numStrings - firstSource, &shaderStrings[firstSource], nullptr,
385 &parseContext) != 0)
386 {
387 return nullptr;
388 }
shannon.woods%transgaming.com@gtempaccount.com0bbed382013-04-13 03:38:07 +0000389
Olli Etuahod10cf692017-11-02 11:06:14 +0200390 if (parseContext.getTreeRoot() == nullptr)
391 {
392 return nullptr;
393 }
394
395 setASTMetadata(parseContext);
396
Jiawei Shaoe41df652018-02-09 14:31:39 +0800397 if (!checkShaderVersion(&parseContext))
Zhenyao Modb9b40b2014-10-29 15:00:04 -0700398 {
Olli Etuahod10cf692017-11-02 11:06:14 +0200399 return nullptr;
Zhenyao Modb9b40b2014-10-29 15:00:04 -0700400 }
shannon.woods%transgaming.com@gtempaccount.com0bbed382013-04-13 03:38:07 +0000401
Olli Etuahod10cf692017-11-02 11:06:14 +0200402 TIntermBlock *root = parseContext.getTreeRoot();
403 if (!checkAndSimplifyAST(root, parseContext, compileOptions))
Zhenyao Mo4a667fe2014-02-11 12:35:01 -0800404 {
Olli Etuahod10cf692017-11-02 11:06:14 +0200405 return nullptr;
406 }
Zhenyao Mo94ac7b72014-10-15 18:22:08 -0700407
Olli Etuahod10cf692017-11-02 11:06:14 +0200408 return root;
409}
Martin Radev802abe02016-08-04 17:48:32 +0300410
Jiawei Shaoe41df652018-02-09 14:31:39 +0800411bool TCompiler::checkShaderVersion(TParseContext *parseContext)
412{
413 if (MapSpecToShaderVersion(shaderSpec) < shaderVersion)
414 {
415 mDiagnostics.globalError("unsupported shader version");
416 return false;
417 }
418
419 ASSERT(parseContext);
420 switch (shaderType)
421 {
422 case GL_COMPUTE_SHADER:
423 if (shaderVersion < 310)
424 {
425 mDiagnostics.globalError("Compute shader is not supported in this shader version.");
426 return false;
427 }
428 break;
429
430 case GL_GEOMETRY_SHADER_EXT:
431 if (shaderVersion < 310)
432 {
433 mDiagnostics.globalError(
434 "Geometry shader is not supported in this shader version.");
435 return false;
436 }
437 else
438 {
439 ASSERT(shaderVersion == 310);
440 if (!parseContext->checkCanUseExtension(sh::TSourceLoc(),
441 TExtension::EXT_geometry_shader))
442 {
443 return false;
444 }
445 }
446 break;
447
448 default:
449 break;
450 }
451
452 return true;
453}
454
Olli Etuahod10cf692017-11-02 11:06:14 +0200455void TCompiler::setASTMetadata(const TParseContext &parseContext)
456{
457 shaderVersion = parseContext.getShaderVersion();
Olli Etuaho09b04a22016-12-15 13:30:26 +0000458
Olli Etuahod10cf692017-11-02 11:06:14 +0200459 mPragma = parseContext.pragma();
460 symbolTable.setGlobalInvariant(mPragma.stdgl.invariantAll);
alokp@chromium.orgb59a7782010-11-24 18:38:33 +0000461
Olli Etuahod10cf692017-11-02 11:06:14 +0200462 mComputeShaderLocalSizeDeclared = parseContext.isComputeShaderLocalSizeDeclared();
463 mComputeShaderLocalSize = parseContext.getComputeShaderLocalSize();
Olli Etuahoa6996682015-10-12 14:32:30 +0300464
Olli Etuahod10cf692017-11-02 11:06:14 +0200465 mNumViews = parseContext.getNumViews();
466
467 // Highp might have been auto-enabled based on shader version
468 fragmentPrecisionHigh = parseContext.getFragmentPrecisionHigh();
469
Jiawei Shaobd924af2017-11-16 15:28:04 +0800470 if (shaderType == GL_GEOMETRY_SHADER_EXT)
Olli Etuahod10cf692017-11-02 11:06:14 +0200471 {
472 mGeometryShaderInputPrimitiveType = parseContext.getGeometryShaderInputPrimitiveType();
473 mGeometryShaderOutputPrimitiveType = parseContext.getGeometryShaderOutputPrimitiveType();
474 mGeometryShaderMaxVertices = parseContext.getGeometryShaderMaxVertices();
475 mGeometryShaderInvocations = parseContext.getGeometryShaderInvocations();
476 }
477}
478
479bool TCompiler::checkAndSimplifyAST(TIntermBlock *root,
480 const TParseContext &parseContext,
481 ShCompileOptions compileOptions)
482{
483 // Disallow expressions deemed too complex.
484 if ((compileOptions & SH_LIMIT_EXPRESSION_COMPLEXITY) && !limitExpressionComplexity(root))
485 {
486 return false;
487 }
488
Olli Etuaho765924f2018-01-04 12:48:36 +0200489 if (shouldRunLoopAndIndexingValidation(compileOptions) &&
Olli Etuaho68981eb2018-01-23 17:46:12 +0200490 !ValidateLimitations(root, shaderType, &symbolTable, &mDiagnostics))
Olli Etuaho765924f2018-01-04 12:48:36 +0200491 {
492 return false;
493 }
494
Olli Etuaho59c5b892018-04-03 11:44:50 +0300495 if (!ValidateFragColorAndFragData(shaderType, shaderVersion, symbolTable, &mDiagnostics))
496 {
497 return false;
498 }
499
Olli Etuaho765924f2018-01-04 12:48:36 +0200500 // Fold expressions that could not be folded before validation that was done as a part of
501 // parsing.
502 FoldExpressions(root, &mDiagnostics);
503 // Folding should only be able to generate warnings.
504 ASSERT(mDiagnostics.numErrors() == 0);
505
Olli Etuahod10cf692017-11-02 11:06:14 +0200506 // We prune no-ops to work around driver bugs and to keep AST processing and output simple.
507 // The following kinds of no-ops are pruned:
508 // 1. Empty declarations "int;".
509 // 2. Literal statements: "1.0;". The ESSL output doesn't define a default precision
510 // for float, so float literal statements would end up with no precision which is
511 // invalid ESSL.
512 // After this empty declarations are not allowed in the AST.
Olli Etuahob38dfde2018-01-04 15:49:03 +0200513 PruneNoOps(root, &symbolTable);
Olli Etuahod10cf692017-11-02 11:06:14 +0200514
Olli Etuahod10cf692017-11-02 11:06:14 +0200515 // Create the function DAG and check there is no recursion
516 if (!initCallDag(root))
517 {
518 return false;
519 }
520
521 if ((compileOptions & SH_LIMIT_CALL_STACK_DEPTH) && !checkCallDepth())
522 {
523 return false;
524 }
525
526 // Checks which functions are used and if "main" exists
527 functionMetadata.clear();
528 functionMetadata.resize(mCallDag.size());
529 if (!tagUsedFunctions())
530 {
531 return false;
532 }
533
534 if (!(compileOptions & SH_DONT_PRUNE_UNUSED_FUNCTIONS))
535 {
536 pruneUnusedFunctions(root);
537 }
538
539 if (shaderVersion >= 310 && !ValidateVaryingLocations(root, &mDiagnostics, shaderType))
540 {
541 return false;
542 }
543
544 if (shaderVersion >= 300 && shaderType == GL_FRAGMENT_SHADER &&
545 !ValidateOutputs(root, getExtensionBehavior(), compileResources.MaxDrawBuffers,
546 &mDiagnostics))
547 {
548 return false;
549 }
550
Olli Etuahod10cf692017-11-02 11:06:14 +0200551 // Fail compilation if precision emulation not supported.
552 if (getResources().WEBGL_debug_shader_precision && getPragma().debugShaderPrecision &&
553 !EmulatePrecision::SupportedInLanguage(outputType))
554 {
555 mDiagnostics.globalError("Precision emulation not supported for this output type.");
556 return false;
557 }
558
Olli Etuahod10cf692017-11-02 11:06:14 +0200559 // Clamping uniform array bounds needs to happen after validateLimitations pass.
560 if (compileOptions & SH_CLAMP_INDIRECT_ARRAY_BOUNDS)
561 {
562 arrayBoundsClamper.MarkIndirectArrayBoundsForClamping(root);
563 }
564
565 if ((compileOptions & SH_INITIALIZE_BUILTINS_FOR_INSTANCED_MULTIVIEW) &&
566 parseContext.isExtensionEnabled(TExtension::OVR_multiview) &&
567 getShaderType() != GL_COMPUTE_SHADER)
568 {
569 DeclareAndInitBuiltinsForInstancedMultiview(root, mNumViews, shaderType, compileOptions,
570 outputType, &symbolTable);
571 }
572
573 // This pass might emit short circuits so keep it before the short circuit unfolding
574 if (compileOptions & SH_REWRITE_DO_WHILE_LOOPS)
575 RewriteDoWhile(root, &symbolTable);
576
577 if (compileOptions & SH_ADD_AND_TRUE_TO_LOOP_CONDITION)
Olli Etuaho1776fd02018-01-31 11:46:52 +0200578 AddAndTrueToLoopCondition(root);
Olli Etuahod10cf692017-11-02 11:06:14 +0200579
580 if (compileOptions & SH_UNFOLD_SHORT_CIRCUIT)
581 {
Olli Etuaho1776fd02018-01-31 11:46:52 +0200582 UnfoldShortCircuitAST(root);
Olli Etuahod10cf692017-11-02 11:06:14 +0200583 }
584
585 if (compileOptions & SH_REMOVE_POW_WITH_CONSTANT_EXPONENT)
586 {
Olli Etuaho5fec7ab2018-04-04 11:58:33 +0300587 RemovePow(root, &symbolTable);
Olli Etuahod10cf692017-11-02 11:06:14 +0200588 }
589
Olli Etuahod10cf692017-11-02 11:06:14 +0200590 if (compileOptions & SH_REGENERATE_STRUCT_NAMES)
591 {
Olli Etuaho9d4d7f02017-12-07 17:11:41 +0100592 RegenerateStructNames gen(&symbolTable);
Olli Etuahod10cf692017-11-02 11:06:14 +0200593 root->traverse(&gen);
594 }
595
596 if (shaderType == GL_FRAGMENT_SHADER && shaderVersion == 100 &&
597 compileResources.EXT_draw_buffers && compileResources.MaxDrawBuffers > 1 &&
598 IsExtensionEnabled(extensionBehavior, TExtension::EXT_draw_buffers))
599 {
600 EmulateGLFragColorBroadcast(root, compileResources.MaxDrawBuffers, &outputVariables,
601 &symbolTable, shaderVersion);
602 }
603
Olli Etuahoae04e1e2017-11-27 16:00:39 +0200604 int simplifyScalarized = (compileOptions & SH_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS)
605 ? IntermNodePatternMatcher::kScalarizedVecOrMatConstructor
606 : 0;
607
Olli Etuahod10cf692017-11-02 11:06:14 +0200608 // Split multi declarations and remove calls to array length().
609 // Note that SimplifyLoopConditions needs to be run before any other AST transformations
610 // that may need to generate new statements from loop conditions or loop expressions.
Olli Etuahoae04e1e2017-11-27 16:00:39 +0200611 SimplifyLoopConditions(root,
612 IntermNodePatternMatcher::kMultiDeclaration |
613 IntermNodePatternMatcher::kArrayLengthMethod | simplifyScalarized,
Olli Etuaho68981eb2018-01-23 17:46:12 +0200614 &getSymbolTable());
Olli Etuahod10cf692017-11-02 11:06:14 +0200615
616 // Note that separate declarations need to be run before other AST transformations that
617 // generate new statements from expressions.
618 SeparateDeclarations(root);
619
Olli Etuahoae04e1e2017-11-27 16:00:39 +0200620 SplitSequenceOperator(root, IntermNodePatternMatcher::kArrayLengthMethod | simplifyScalarized,
Olli Etuaho68981eb2018-01-23 17:46:12 +0200621 &getSymbolTable());
Olli Etuahod10cf692017-11-02 11:06:14 +0200622
623 RemoveArrayLengthMethod(root);
624
Olli Etuaho3d70ca92017-11-10 16:53:26 +0200625 RemoveUnreferencedVariables(root, &symbolTable);
626
Olli Etuaho41217992018-03-15 11:15:33 +0200627 // In case the last case inside a switch statement is a certain type of no-op, GLSL compilers in
628 // drivers may not accept it. In this case we clean up the dead code from the end of switch
629 // statements. This is also required because PruneNoOps or RemoveUnreferencedVariables may have
630 // left switch statements that only contained an empty declaration inside the final case in an
631 // invalid state. Relies on that PruneNoOps and RemoveUnreferencedVariables have already been
632 // run.
Olli Etuaho0b0dcbc2018-03-14 11:33:22 +0200633 PruneEmptyCases(root);
634
Olli Etuaho3d70ca92017-11-10 16:53:26 +0200635 // Built-in function emulation needs to happen after validateLimitations pass.
636 // TODO(jmadill): Remove global pool allocator.
637 GetGlobalPoolAllocator()->lock();
638 initBuiltInFunctionEmulator(&builtInFunctionEmulator, compileOptions);
639 GetGlobalPoolAllocator()->unlock();
640 builtInFunctionEmulator.markBuiltInFunctionsForEmulation(root);
641
642 if (compileOptions & SH_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS)
643 {
644 ScalarizeVecAndMatConstructorArgs(root, shaderType, fragmentPrecisionHigh, &symbolTable);
645 }
646
647 if (shouldCollectVariables(compileOptions))
648 {
649 ASSERT(!variablesCollected);
650 CollectVariables(root, &attributes, &outputVariables, &uniforms, &inputVaryings,
651 &outputVaryings, &uniformBlocks, &shaderStorageBlocks, &inBlocks,
Olli Etuaho822a84b2018-03-23 12:30:18 +0200652 hashFunction, &symbolTable, shaderType, extensionBehavior);
Olli Etuaho3d70ca92017-11-10 16:53:26 +0200653 collectInterfaceBlocks();
654 variablesCollected = true;
655 if (compileOptions & SH_USE_UNUSED_STANDARD_SHARED_BLOCKS)
656 {
657 useAllMembersInUnusedStandardAndSharedBlocks(root);
658 }
659 if (compileOptions & SH_ENFORCE_PACKING_RESTRICTIONS)
660 {
661 // Returns true if, after applying the packing rules in the GLSL ES 1.00.17 spec
662 // Appendix A, section 7, the shader does not use too many uniforms.
663 if (!CheckVariablesInPackingLimits(maxUniformVectors, uniforms))
664 {
665 mDiagnostics.globalError("too many uniforms");
666 return false;
667 }
668 }
Qin Jiajia017bda42018-09-14 18:11:50 +0800669 if ((compileOptions & SH_INIT_OUTPUT_VARIABLES) && (shaderType != GL_COMPUTE_SHADER))
Olli Etuaho3d70ca92017-11-10 16:53:26 +0200670 {
671 initializeOutputVariables(root);
672 }
673 }
674
675 // Removing invariant declarations must be done after collecting variables.
676 // Otherwise, built-in invariant declarations don't apply.
677 if (RemoveInvariant(shaderType, shaderVersion, outputType, compileOptions))
678 {
679 RemoveInvariantDeclaration(root);
680 }
681
682 // gl_Position is always written in compatibility output mode.
683 // It may have been already initialized among other output variables, in that case we don't
684 // need to initialize it twice.
685 if (shaderType == GL_VERTEX_SHADER && !mGLPositionInitialized &&
686 ((compileOptions & SH_INIT_GL_POSITION) || (outputType == SH_GLSL_COMPATIBILITY_OUTPUT)))
687 {
688 initializeGLPosition(root);
689 mGLPositionInitialized = true;
690 }
691
Olli Etuahob5601eb2017-11-15 18:08:04 +0200692 // DeferGlobalInitializers needs to be run before other AST transformations that generate new
693 // statements from expressions. But it's fine to run DeferGlobalInitializers after the above
694 // SplitSequenceOperator and RemoveArrayLengthMethod since they only have an effect on the AST
695 // on ESSL >= 3.00, and the initializers that need to be deferred can only exist in ESSL < 3.00.
696 bool initializeLocalsAndGlobals =
697 (compileOptions & SH_INITIALIZE_UNINITIALIZED_LOCALS) && !IsOutputHLSL(getOutputType());
Olli Etuaho2c7f34c2017-10-09 17:18:02 +0300698 bool canUseLoopsToInitialize = !(compileOptions & SH_DONT_USE_LOOPS_TO_INITIALIZE_VARIABLES);
Olli Etuaho87cc90d2017-12-12 15:28:06 +0200699 bool highPrecisionSupported =
700 shaderType != GL_FRAGMENT_SHADER || compileResources.FragmentPrecisionHigh;
701 DeferGlobalInitializers(root, initializeLocalsAndGlobals, canUseLoopsToInitialize,
702 highPrecisionSupported, &symbolTable);
Olli Etuaho2c7f34c2017-10-09 17:18:02 +0300703
Olli Etuahob5601eb2017-11-15 18:08:04 +0200704 if (initializeLocalsAndGlobals)
Olli Etuahod10cf692017-11-02 11:06:14 +0200705 {
706 // Initialize uninitialized local variables.
707 // In some cases initializing can generate extra statements in the parent block, such as
708 // when initializing nameless structs or initializing arrays in ESSL 1.00. In that case
709 // we need to first simplify loop conditions. We've already separated declarations
710 // earlier, which is also required. If we don't follow the Appendix A limitations, loop
711 // init statements can declare arrays or nameless structs and have multiple
712 // declarations.
713
714 if (!shouldRunLoopAndIndexingValidation(compileOptions))
715 {
716 SimplifyLoopConditions(root,
717 IntermNodePatternMatcher::kArrayDeclaration |
718 IntermNodePatternMatcher::kNamelessStructDeclaration,
Olli Etuaho68981eb2018-01-23 17:46:12 +0200719 &getSymbolTable());
Olli Etuahod10cf692017-11-02 11:06:14 +0200720 }
Olli Etuaho661fc482017-10-16 12:17:05 +0300721
Olli Etuaho2c7f34c2017-10-09 17:18:02 +0300722 InitializeUninitializedLocals(root, getShaderVersion(), canUseLoopsToInitialize,
Olli Etuaho87cc90d2017-12-12 15:28:06 +0200723 highPrecisionSupported, &getSymbolTable());
Olli Etuahod10cf692017-11-02 11:06:14 +0200724 }
725
726 if (getShaderType() == GL_VERTEX_SHADER && (compileOptions & SH_CLAMP_POINT_SIZE))
727 {
728 ClampPointSize(root, compileResources.MaxPointSize, &getSymbolTable());
729 }
730
Olli Etuaho0690e1a2017-12-21 20:51:38 +0200731 if (getShaderType() == GL_FRAGMENT_SHADER && (compileOptions & SH_CLAMP_FRAG_DEPTH))
732 {
733 ClampFragDepth(root, &getSymbolTable());
734 }
735
Olli Etuaho983460e2018-05-02 17:57:39 +0300736 if (compileOptions & SH_REWRITE_REPEATED_ASSIGN_TO_SWIZZLED)
737 {
738 sh::RewriteRepeatedAssignToSwizzled(root);
739 }
740
Olli Etuaho661fc482017-10-16 12:17:05 +0300741 if (compileOptions & SH_REWRITE_VECTOR_SCALAR_ARITHMETIC)
742 {
743 VectorizeVectorScalarArithmetic(root, &getSymbolTable());
744 }
745
Olli Etuahod10cf692017-11-02 11:06:14 +0200746 return true;
Olli Etuahoa3a5cc62015-02-13 13:12:22 +0200747}
748
Qiankun Miao7ebb97f2016-09-08 18:01:50 +0800749bool TCompiler::compile(const char *const shaderStrings[],
750 size_t numStrings,
751 ShCompileOptions compileOptionsIn)
Olli Etuahoa3a5cc62015-02-13 13:12:22 +0200752{
Corentin Wallez28b65282016-06-16 07:24:50 -0700753#if defined(ANGLE_ENABLE_FUZZER_CORPUS_OUTPUT)
754 DumpFuzzerCase(shaderStrings, numStrings, shaderType, shaderSpec, outputType, compileOptionsIn);
755#endif // defined(ANGLE_ENABLE_FUZZER_CORPUS_OUTPUT)
756
Olli Etuahoa3a5cc62015-02-13 13:12:22 +0200757 if (numStrings == 0)
758 return true;
759
Qiankun Miao7ebb97f2016-09-08 18:01:50 +0800760 ShCompileOptions compileOptions = compileOptionsIn;
Kenneth Russellbccc65d2016-07-19 16:48:43 -0700761
762 // Apply key workarounds.
763 if (shouldFlattenPragmaStdglInvariantAll())
764 {
765 // This should be harmless to do in all cases, but for the moment, do it only conditionally.
766 compileOptions |= SH_FLATTEN_PRAGMA_STDGL_INVARIANT_ALL;
767 }
768
Olli Etuahoa3a5cc62015-02-13 13:12:22 +0200769 TScopedPoolAllocator scopedAlloc(&allocator);
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100770 TIntermBlock *root = compileTreeImpl(shaderStrings, numStrings, compileOptions);
Olli Etuahoa3a5cc62015-02-13 13:12:22 +0200771
772 if (root)
773 {
774 if (compileOptions & SH_INTERMEDIATE_TREE)
Olli Etuahocccf2b02017-07-05 14:50:54 +0300775 OutputTree(root, infoSink.info);
Olli Etuahoa3a5cc62015-02-13 13:12:22 +0200776
777 if (compileOptions & SH_OBJECT_CODE)
Olli Etuaho89a69a02017-10-23 12:20:45 +0300778 {
779 PerformanceDiagnostics perfDiagnostics(&mDiagnostics);
780 translate(root, compileOptions, &perfDiagnostics);
781 }
Olli Etuahoa3a5cc62015-02-13 13:12:22 +0200782
783 // The IntermNode tree doesn't need to be deleted here, since the
784 // memory will be freed in a big chunk by the PoolAllocator.
785 return true;
786 }
787 return false;
alokp@chromium.org07620a52010-09-23 17:53:56 +0000788}
789
Nicolas Capens49a88872013-06-20 09:54:03 -0400790bool TCompiler::InitBuiltInSymbolTable(const ShBuiltInResources &resources)
alokp@chromium.org07620a52010-09-23 17:53:56 +0000791{
Olli Etuaho28cb0362016-11-22 15:42:37 +0000792 if (resources.MaxDrawBuffers < 1)
793 {
794 return false;
795 }
796 if (resources.EXT_blend_func_extended && resources.MaxDualSourceDrawBuffers < 1)
797 {
798 return false;
799 }
800
shannon.woods%transgaming.com@gtempaccount.com18b4c4b2013-04-13 03:31:40 +0000801 compileResources = resources;
Shannon Woods2d76e5f2014-05-16 17:46:41 -0400802 setResourceString();
shannonwoods@chromium.org2ac0be92013-05-30 00:02:27 +0000803
Olli Etuaho29bda812018-01-26 17:37:36 +0200804 symbolTable.initializeBuiltIns(shaderType, shaderSpec, resources);
Olli Etuaho5d69db12017-11-24 16:51:15 +0200805
Nicolas Capens49a88872013-06-20 09:54:03 -0400806 return true;
alokp@chromium.org07620a52010-09-23 17:53:56 +0000807}
808
Shannon Woods2d76e5f2014-05-16 17:46:41 -0400809void TCompiler::setResourceString()
810{
811 std::ostringstream strstream;
Geoff Langb66a9092016-05-16 15:59:14 -0400812
813 // clang-format off
Shannon Woods2d76e5f2014-05-16 17:46:41 -0400814 strstream << ":MaxVertexAttribs:" << compileResources.MaxVertexAttribs
Jamie Madillacb4b812016-11-07 13:50:29 -0500815 << ":MaxVertexUniformVectors:" << compileResources.MaxVertexUniformVectors
816 << ":MaxVaryingVectors:" << compileResources.MaxVaryingVectors
817 << ":MaxVertexTextureImageUnits:" << compileResources.MaxVertexTextureImageUnits
818 << ":MaxCombinedTextureImageUnits:" << compileResources.MaxCombinedTextureImageUnits
819 << ":MaxTextureImageUnits:" << compileResources.MaxTextureImageUnits
820 << ":MaxFragmentUniformVectors:" << compileResources.MaxFragmentUniformVectors
821 << ":MaxDrawBuffers:" << compileResources.MaxDrawBuffers
822 << ":OES_standard_derivatives:" << compileResources.OES_standard_derivatives
823 << ":OES_EGL_image_external:" << compileResources.OES_EGL_image_external
824 << ":OES_EGL_image_external_essl3:" << compileResources.OES_EGL_image_external_essl3
825 << ":NV_EGL_stream_consumer_external:" << compileResources.NV_EGL_stream_consumer_external
826 << ":ARB_texture_rectangle:" << compileResources.ARB_texture_rectangle
827 << ":EXT_draw_buffers:" << compileResources.EXT_draw_buffers
828 << ":FragmentPrecisionHigh:" << compileResources.FragmentPrecisionHigh
829 << ":MaxExpressionComplexity:" << compileResources.MaxExpressionComplexity
830 << ":MaxCallStackDepth:" << compileResources.MaxCallStackDepth
831 << ":MaxFunctionParameters:" << compileResources.MaxFunctionParameters
832 << ":EXT_blend_func_extended:" << compileResources.EXT_blend_func_extended
833 << ":EXT_frag_depth:" << compileResources.EXT_frag_depth
834 << ":EXT_shader_texture_lod:" << compileResources.EXT_shader_texture_lod
835 << ":EXT_shader_framebuffer_fetch:" << compileResources.EXT_shader_framebuffer_fetch
836 << ":NV_shader_framebuffer_fetch:" << compileResources.NV_shader_framebuffer_fetch
837 << ":ARM_shader_framebuffer_fetch:" << compileResources.ARM_shader_framebuffer_fetch
Martin Radev318f9aa2017-05-17 17:47:28 +0300838 << ":OVR_multiview:" << compileResources.OVR_multiview
Andrei Volykhina5527072017-03-22 16:46:30 +0300839 << ":EXT_YUV_target:" << compileResources.EXT_YUV_target
Jiawei Shaobd924af2017-11-16 15:28:04 +0800840 << ":EXT_geometry_shader:" << compileResources.EXT_geometry_shader
Jamie Madillacb4b812016-11-07 13:50:29 -0500841 << ":MaxVertexOutputVectors:" << compileResources.MaxVertexOutputVectors
842 << ":MaxFragmentInputVectors:" << compileResources.MaxFragmentInputVectors
843 << ":MinProgramTexelOffset:" << compileResources.MinProgramTexelOffset
844 << ":MaxProgramTexelOffset:" << compileResources.MaxProgramTexelOffset
845 << ":MaxDualSourceDrawBuffers:" << compileResources.MaxDualSourceDrawBuffers
Martin Radev318f9aa2017-05-17 17:47:28 +0300846 << ":MaxViewsOVR:" << compileResources.MaxViewsOVR
Jamie Madillacb4b812016-11-07 13:50:29 -0500847 << ":NV_draw_buffers:" << compileResources.NV_draw_buffers
848 << ":WEBGL_debug_shader_precision:" << compileResources.WEBGL_debug_shader_precision
Martin Radev84aa2dc2017-09-11 15:51:02 +0300849 << ":MinProgramTextureGatherOffset:" << compileResources.MinProgramTextureGatherOffset
850 << ":MaxProgramTextureGatherOffset:" << compileResources.MaxProgramTextureGatherOffset
Jamie Madillacb4b812016-11-07 13:50:29 -0500851 << ":MaxImageUnits:" << compileResources.MaxImageUnits
852 << ":MaxVertexImageUniforms:" << compileResources.MaxVertexImageUniforms
853 << ":MaxFragmentImageUniforms:" << compileResources.MaxFragmentImageUniforms
854 << ":MaxComputeImageUniforms:" << compileResources.MaxComputeImageUniforms
855 << ":MaxCombinedImageUniforms:" << compileResources.MaxCombinedImageUniforms
856 << ":MaxCombinedShaderOutputResources:" << compileResources.MaxCombinedShaderOutputResources
857 << ":MaxComputeWorkGroupCountX:" << compileResources.MaxComputeWorkGroupCount[0]
858 << ":MaxComputeWorkGroupCountY:" << compileResources.MaxComputeWorkGroupCount[1]
859 << ":MaxComputeWorkGroupCountZ:" << compileResources.MaxComputeWorkGroupCount[2]
860 << ":MaxComputeWorkGroupSizeX:" << compileResources.MaxComputeWorkGroupSize[0]
861 << ":MaxComputeWorkGroupSizeY:" << compileResources.MaxComputeWorkGroupSize[1]
862 << ":MaxComputeWorkGroupSizeZ:" << compileResources.MaxComputeWorkGroupSize[2]
863 << ":MaxComputeUniformComponents:" << compileResources.MaxComputeUniformComponents
864 << ":MaxComputeTextureImageUnits:" << compileResources.MaxComputeTextureImageUnits
865 << ":MaxComputeAtomicCounters:" << compileResources.MaxComputeAtomicCounters
866 << ":MaxComputeAtomicCounterBuffers:" << compileResources.MaxComputeAtomicCounterBuffers
867 << ":MaxVertexAtomicCounters:" << compileResources.MaxVertexAtomicCounters
868 << ":MaxFragmentAtomicCounters:" << compileResources.MaxFragmentAtomicCounters
869 << ":MaxCombinedAtomicCounters:" << compileResources.MaxCombinedAtomicCounters
870 << ":MaxAtomicCounterBindings:" << compileResources.MaxAtomicCounterBindings
871 << ":MaxVertexAtomicCounterBuffers:" << compileResources.MaxVertexAtomicCounterBuffers
872 << ":MaxFragmentAtomicCounterBuffers:" << compileResources.MaxFragmentAtomicCounterBuffers
873 << ":MaxCombinedAtomicCounterBuffers:" << compileResources.MaxCombinedAtomicCounterBuffers
Shaob5cc1192017-07-06 10:47:20 +0800874 << ":MaxAtomicCounterBufferSize:" << compileResources.MaxAtomicCounterBufferSize
Shaob5cc1192017-07-06 10:47:20 +0800875 << ":MaxGeometryUniformComponents:" << compileResources.MaxGeometryUniformComponents
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800876 << ":MaxGeometryUniformBlocks:" << compileResources.MaxGeometryUniformBlocks
877 << ":MaxGeometryInputComponents:" << compileResources.MaxGeometryInputComponents
878 << ":MaxGeometryOutputComponents:" << compileResources.MaxGeometryOutputComponents
879 << ":MaxGeometryOutputVertices:" << compileResources.MaxGeometryOutputVertices
880 << ":MaxGeometryTotalOutputComponents:" << compileResources.MaxGeometryTotalOutputComponents
881 << ":MaxGeometryTextureImageUnits:" << compileResources.MaxGeometryTextureImageUnits
882 << ":MaxGeometryAtomicCounterBuffers:" << compileResources.MaxGeometryAtomicCounterBuffers
883 << ":MaxGeometryAtomicCounters:" << compileResources.MaxGeometryAtomicCounters
884 << ":MaxGeometryShaderStorageBlocks:" << compileResources.MaxGeometryShaderStorageBlocks
885 << ":MaxGeometryShaderInvocations:" << compileResources.MaxGeometryShaderInvocations
886 << ":MaxGeometryImageUniforms:" << compileResources.MaxGeometryImageUniforms;
Geoff Langb66a9092016-05-16 15:59:14 -0400887 // clang-format on
Shannon Woods2d76e5f2014-05-16 17:46:41 -0400888
889 builtInResourcesString = strstream.str();
890}
891
Jiajia Qin9b11ea42017-07-11 16:50:08 +0800892void TCompiler::collectInterfaceBlocks()
893{
894 ASSERT(interfaceBlocks.empty());
Jiawei Shaod8105a02017-08-08 09:54:36 +0800895 interfaceBlocks.reserve(uniformBlocks.size() + shaderStorageBlocks.size() + inBlocks.size());
Jiajia Qin9b11ea42017-07-11 16:50:08 +0800896 interfaceBlocks.insert(interfaceBlocks.end(), uniformBlocks.begin(), uniformBlocks.end());
897 interfaceBlocks.insert(interfaceBlocks.end(), shaderStorageBlocks.begin(),
898 shaderStorageBlocks.end());
Jiawei Shaod8105a02017-08-08 09:54:36 +0800899 interfaceBlocks.insert(interfaceBlocks.end(), inBlocks.begin(), inBlocks.end());
Jiajia Qin9b11ea42017-07-11 16:50:08 +0800900}
901
alokp@chromium.org07620a52010-09-23 17:53:56 +0000902void TCompiler::clearResults()
903{
daniel@transgaming.com4167cc92013-01-11 04:11:53 +0000904 arrayBoundsClamper.Cleanup();
alokp@chromium.org07620a52010-09-23 17:53:56 +0000905 infoSink.info.erase();
906 infoSink.obj.erase();
907 infoSink.debug.erase();
Olli Etuaho77ba4082016-12-16 12:01:18 +0000908 mDiagnostics.resetErrorCount();
alokp@chromium.org07620a52010-09-23 17:53:56 +0000909
Jamie Madilled27c722014-07-02 15:31:23 -0400910 attributes.clear();
911 outputVariables.clear();
alokp@chromium.org07620a52010-09-23 17:53:56 +0000912 uniforms.clear();
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800913 inputVaryings.clear();
914 outputVaryings.clear();
Jamie Madilled27c722014-07-02 15:31:23 -0400915 interfaceBlocks.clear();
Jiajia Qin9b11ea42017-07-11 16:50:08 +0800916 uniformBlocks.clear();
917 shaderStorageBlocks.clear();
Jiawei Shaod8105a02017-08-08 09:54:36 +0800918 inBlocks.clear();
Kenneth Russellbccc65d2016-07-19 16:48:43 -0700919 variablesCollected = false;
Olli Etuahob12040c2017-06-27 14:20:45 +0300920 mGLPositionInitialized = false;
zmo@google.coma3b4ab42011-09-16 00:53:26 +0000921
Olli Etuaho09b04a22016-12-15 13:30:26 +0000922 mNumViews = -1;
923
Shaob5cc1192017-07-06 10:47:20 +0800924 mGeometryShaderInputPrimitiveType = EptUndefined;
925 mGeometryShaderOutputPrimitiveType = EptUndefined;
926 mGeometryShaderInvocations = 0;
927 mGeometryShaderMaxVertices = -1;
928
Olli Etuahodfa75e82017-01-23 09:43:06 -0800929 builtInFunctionEmulator.cleanup();
daniel@transgaming.com0aa3b5a2012-11-28 19:43:24 +0000930
931 nameMap.clear();
Olli Etuahoa3a5cc62015-02-13 13:12:22 +0200932
Yunchao Hed7297bf2017-04-19 15:27:10 +0800933 mSourcePath = nullptr;
Olli Etuaho5d69db12017-11-24 16:51:15 +0200934
935 symbolTable.clearCompilationResults();
alokp@chromium.org07620a52010-09-23 17:53:56 +0000936}
937
Corentin Wallez71d147f2015-02-11 11:15:24 -0800938bool TCompiler::initCallDag(TIntermNode *root)
zmo@google.comb1762df2011-07-30 02:04:23 +0000939{
Corentin Wallez71d147f2015-02-11 11:15:24 -0800940 mCallDag.clear();
941
Olli Etuaho77ba4082016-12-16 12:01:18 +0000942 switch (mCallDag.init(root, &mDiagnostics))
Zhenyao Mo4a667fe2014-02-11 12:35:01 -0800943 {
Jamie Madillacb4b812016-11-07 13:50:29 -0500944 case CallDAG::INITDAG_SUCCESS:
945 return true;
946 case CallDAG::INITDAG_RECURSION:
Jamie Madillacb4b812016-11-07 13:50:29 -0500947 case CallDAG::INITDAG_UNDEFINED:
Olli Etuaho77ba4082016-12-16 12:01:18 +0000948 // Error message has already been written out.
949 ASSERT(mDiagnostics.numErrors() > 0);
Jamie Madillacb4b812016-11-07 13:50:29 -0500950 return false;
Corentin Wallez71d147f2015-02-11 11:15:24 -0800951 }
952
953 UNREACHABLE();
954 return true;
955}
956
957bool TCompiler::checkCallDepth()
958{
959 std::vector<int> depths(mCallDag.size());
960
961 for (size_t i = 0; i < mCallDag.size(); i++)
962 {
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500963 int depth = 0;
Corentin Wallez71d147f2015-02-11 11:15:24 -0800964 auto &record = mCallDag.getRecordFromIndex(i);
965
966 for (auto &calleeIndex : record.callees)
967 {
968 depth = std::max(depth, depths[calleeIndex] + 1);
969 }
970
971 depths[i] = depth;
972
973 if (depth >= maxCallStackDepth)
974 {
975 // Trace back the function chain to have a meaningful info log.
Olli Etuaho77ba4082016-12-16 12:01:18 +0000976 std::stringstream errorStream;
977 errorStream << "Call stack too deep (larger than " << maxCallStackDepth
Olli Etuahoc33f1e82017-12-29 16:55:29 +0200978 << ") with the following call chain: "
979 << record.node->getFunction()->name();
Corentin Wallez71d147f2015-02-11 11:15:24 -0800980
Cooper Partin4d61f7e2015-08-12 10:56:50 -0700981 int currentFunction = static_cast<int>(i);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500982 int currentDepth = depth;
Corentin Wallez71d147f2015-02-11 11:15:24 -0800983
984 while (currentFunction != -1)
985 {
Olli Etuahoc33f1e82017-12-29 16:55:29 +0200986 errorStream
987 << " -> "
988 << mCallDag.getRecordFromIndex(currentFunction).node->getFunction()->name();
Corentin Wallez71d147f2015-02-11 11:15:24 -0800989
990 int nextFunction = -1;
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500991 for (auto &calleeIndex : mCallDag.getRecordFromIndex(currentFunction).callees)
Corentin Wallez71d147f2015-02-11 11:15:24 -0800992 {
993 if (depths[calleeIndex] == currentDepth - 1)
994 {
995 currentDepth--;
996 nextFunction = calleeIndex;
997 }
998 }
999
1000 currentFunction = nextFunction;
1001 }
1002
Olli Etuaho77ba4082016-12-16 12:01:18 +00001003 std::string errorStr = errorStream.str();
1004 mDiagnostics.globalError(errorStr.c_str());
1005
Corentin Wallez71d147f2015-02-11 11:15:24 -08001006 return false;
1007 }
1008 }
1009
1010 return true;
1011}
1012
1013bool TCompiler::tagUsedFunctions()
1014{
1015 // Search from main, starting from the end of the DAG as it usually is the root.
Cooper Partin4d61f7e2015-08-12 10:56:50 -07001016 for (size_t i = mCallDag.size(); i-- > 0;)
Corentin Wallez71d147f2015-02-11 11:15:24 -08001017 {
Olli Etuahoc33f1e82017-12-29 16:55:29 +02001018 if (mCallDag.getRecordFromIndex(i).node->getFunction()->isMain())
Corentin Wallez71d147f2015-02-11 11:15:24 -08001019 {
1020 internalTagUsedFunction(i);
1021 return true;
1022 }
1023 }
1024
Olli Etuaho77ba4082016-12-16 12:01:18 +00001025 mDiagnostics.globalError("Missing main()");
Corentin Wallez71d147f2015-02-11 11:15:24 -08001026 return false;
1027}
1028
1029void TCompiler::internalTagUsedFunction(size_t index)
1030{
1031 if (functionMetadata[index].used)
1032 {
1033 return;
1034 }
1035
1036 functionMetadata[index].used = true;
1037
1038 for (int calleeIndex : mCallDag.getRecordFromIndex(index).callees)
1039 {
1040 internalTagUsedFunction(calleeIndex);
zmo@google.comb1762df2011-07-30 02:04:23 +00001041 }
1042}
1043
Corentin Walleza094a8a2015-04-07 11:53:06 -07001044// A predicate for the stl that returns if a top-level node is unused
1045class TCompiler::UnusedPredicate
1046{
1047 public:
1048 UnusedPredicate(const CallDAG *callDag, const std::vector<FunctionMetadata> *metadatas)
Jamie Madillacb4b812016-11-07 13:50:29 -05001049 : mCallDag(callDag), mMetadatas(metadatas)
Corentin Walleza094a8a2015-04-07 11:53:06 -07001050 {
1051 }
1052
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001053 bool operator()(TIntermNode *node)
Corentin Walleza094a8a2015-04-07 11:53:06 -07001054 {
Olli Etuaho16c745a2017-01-16 17:02:27 +00001055 const TIntermFunctionPrototype *asFunctionPrototype = node->getAsFunctionPrototypeNode();
1056 const TIntermFunctionDefinition *asFunctionDefinition = node->getAsFunctionDefinition();
Corentin Walleza094a8a2015-04-07 11:53:06 -07001057
Olli Etuahobeb6dc72017-12-14 16:03:03 +02001058 const TFunction *func = nullptr;
Olli Etuaho336b1472016-10-05 16:37:55 +01001059
Olli Etuaho16c745a2017-01-16 17:02:27 +00001060 if (asFunctionDefinition)
Olli Etuaho336b1472016-10-05 16:37:55 +01001061 {
Olli Etuahobeb6dc72017-12-14 16:03:03 +02001062 func = asFunctionDefinition->getFunction();
Olli Etuaho336b1472016-10-05 16:37:55 +01001063 }
Olli Etuaho16c745a2017-01-16 17:02:27 +00001064 else if (asFunctionPrototype)
Olli Etuaho336b1472016-10-05 16:37:55 +01001065 {
Olli Etuahobeb6dc72017-12-14 16:03:03 +02001066 func = asFunctionPrototype->getFunction();
Olli Etuaho336b1472016-10-05 16:37:55 +01001067 }
Olli Etuahobeb6dc72017-12-14 16:03:03 +02001068 if (func == nullptr)
Corentin Walleza094a8a2015-04-07 11:53:06 -07001069 {
1070 return false;
1071 }
1072
Olli Etuahobeb6dc72017-12-14 16:03:03 +02001073 size_t callDagIndex = mCallDag->findIndex(func->uniqueId());
Corentin Walleza094a8a2015-04-07 11:53:06 -07001074 if (callDagIndex == CallDAG::InvalidIndex)
1075 {
1076 // This happens only for unimplemented prototypes which are thus unused
Olli Etuaho16c745a2017-01-16 17:02:27 +00001077 ASSERT(asFunctionPrototype);
Corentin Walleza094a8a2015-04-07 11:53:06 -07001078 return true;
1079 }
1080
1081 ASSERT(callDagIndex < mMetadatas->size());
1082 return !(*mMetadatas)[callDagIndex].used;
1083 }
1084
1085 private:
1086 const CallDAG *mCallDag;
1087 const std::vector<FunctionMetadata> *mMetadatas;
1088};
1089
Olli Etuahod10cf692017-11-02 11:06:14 +02001090void TCompiler::pruneUnusedFunctions(TIntermBlock *root)
Corentin Walleza094a8a2015-04-07 11:53:06 -07001091{
Corentin Walleza094a8a2015-04-07 11:53:06 -07001092 UnusedPredicate isUnused(&mCallDag, &functionMetadata);
Olli Etuaho6d40bbd2016-09-30 13:49:38 +01001093 TIntermSequence *sequence = root->getSequence();
Corentin Wallezb081e782015-07-20 05:40:04 -07001094
1095 if (!sequence->empty())
1096 {
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001097 sequence->erase(std::remove_if(sequence->begin(), sequence->end(), isUnused),
1098 sequence->end());
Corentin Wallezb081e782015-07-20 05:40:04 -07001099 }
Corentin Walleza094a8a2015-04-07 11:53:06 -07001100}
1101
Olli Etuahob4279202017-05-18 15:08:24 +03001102bool TCompiler::limitExpressionComplexity(TIntermBlock *root)
Jamie Madilleb1a0102013-07-08 13:31:38 -04001103{
Olli Etuahocccf2b02017-07-05 14:50:54 +03001104 if (!IsASTDepthBelowLimit(root, maxExpressionComplexity))
Jamie Madill6654bc92014-03-26 14:01:57 -04001105 {
Olli Etuaho77ba4082016-12-16 12:01:18 +00001106 mDiagnostics.globalError("Expression too complex.");
Jamie Madill6654bc92014-03-26 14:01:57 -04001107 return false;
1108 }
1109
Olli Etuahob4279202017-05-18 15:08:24 +03001110 if (!ValidateMaxParameters(root, maxFunctionParameters))
Olli Etuaho19d1dc92016-03-08 17:18:46 +02001111 {
Olli Etuaho77ba4082016-12-16 12:01:18 +00001112 mDiagnostics.globalError("Function has too many parameters.");
Olli Etuaho19d1dc92016-03-08 17:18:46 +02001113 return false;
1114 }
1115
Jamie Madilleb1a0102013-07-08 13:31:38 -04001116 return true;
1117}
1118
Corentin Wallez1df16022016-10-27 08:16:56 -04001119bool TCompiler::shouldCollectVariables(ShCompileOptions compileOptions)
1120{
1121 return (compileOptions & SH_VARIABLES) != 0;
1122}
1123
1124bool TCompiler::wereVariablesCollected() const
1125{
1126 return variablesCollected;
1127}
1128
Olli Etuaho9cbc07c2017-05-10 18:22:01 +03001129void TCompiler::initializeGLPosition(TIntermBlock *root)
Zhenyao Mo4a667fe2014-02-11 12:35:01 -08001130{
Zhenyao Mo72111912016-07-20 17:45:56 -07001131 InitVariableList list;
Olli Etuahoe7c28572017-10-23 16:29:33 +03001132 sh::ShaderVariable var(GL_FLOAT_VEC4);
Zhenyao Mo72111912016-07-20 17:45:56 -07001133 var.name = "gl_Position";
1134 list.push_back(var);
Olli Etuaho87cc90d2017-12-12 15:28:06 +02001135 InitializeVariables(root, list, &symbolTable, shaderVersion, extensionBehavior, false, false);
Zhenyao Mo4a667fe2014-02-11 12:35:01 -08001136}
1137
Olli Etuaho9cbc07c2017-05-10 18:22:01 +03001138void TCompiler::useAllMembersInUnusedStandardAndSharedBlocks(TIntermBlock *root)
Qin Jiajia7835b522016-10-08 11:20:17 +08001139{
1140 sh::InterfaceBlockList list;
1141
Jiajia Qin9b11ea42017-07-11 16:50:08 +08001142 for (auto block : uniformBlocks)
Qin Jiajia7835b522016-10-08 11:20:17 +08001143 {
1144 if (!block.staticUse &&
Qin Jiajiaca68d982017-09-18 16:41:56 +08001145 (block.layout == sh::BLOCKLAYOUT_STD140 || block.layout == sh::BLOCKLAYOUT_SHARED))
Qin Jiajia7835b522016-10-08 11:20:17 +08001146 {
1147 list.push_back(block);
1148 }
1149 }
1150
Zhenyao Mod7490962016-11-09 15:49:51 -08001151 sh::UseInterfaceBlockFields(root, list, symbolTable);
Qin Jiajia7835b522016-10-08 11:20:17 +08001152}
1153
Olli Etuaho9cbc07c2017-05-10 18:22:01 +03001154void TCompiler::initializeOutputVariables(TIntermBlock *root)
Zhenyao Mo4a667fe2014-02-11 12:35:01 -08001155{
Zhenyao Mo72111912016-07-20 17:45:56 -07001156 InitVariableList list;
Jiawei Shaobd924af2017-11-16 15:28:04 +08001157 if (shaderType == GL_VERTEX_SHADER || shaderType == GL_GEOMETRY_SHADER_EXT)
Zhenyao Mo4a667fe2014-02-11 12:35:01 -08001158 {
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +08001159 for (auto var : outputVaryings)
Zhenyao Mo4a667fe2014-02-11 12:35:01 -08001160 {
Zhenyao Mof9312682016-07-22 12:51:31 -07001161 list.push_back(var);
Olli Etuahob12040c2017-06-27 14:20:45 +03001162 if (var.name == "gl_Position")
1163 {
1164 ASSERT(!mGLPositionInitialized);
1165 mGLPositionInitialized = true;
1166 }
Zhenyao Mo4a667fe2014-02-11 12:35:01 -08001167 }
Zhenyao Mo4a667fe2014-02-11 12:35:01 -08001168 }
Zhenyao Mo72111912016-07-20 17:45:56 -07001169 else
1170 {
1171 ASSERT(shaderType == GL_FRAGMENT_SHADER);
1172 for (auto var : outputVariables)
1173 {
1174 list.push_back(var);
1175 }
1176 }
Olli Etuaho87cc90d2017-12-12 15:28:06 +02001177 InitializeVariables(root, list, &symbolTable, shaderVersion, extensionBehavior, false, false);
Zhenyao Mo4a667fe2014-02-11 12:35:01 -08001178}
1179
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001180const TExtensionBehavior &TCompiler::getExtensionBehavior() const
zmo@google.com5601ea02011-06-10 18:23:25 +00001181{
1182 return extensionBehavior;
1183}
zmo@google.com32e97312011-08-24 01:03:11 +00001184
Olli Etuahoa3a5cc62015-02-13 13:12:22 +02001185const char *TCompiler::getSourcePath() const
1186{
1187 return mSourcePath;
1188}
1189
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001190const ShBuiltInResources &TCompiler::getResources() const
shannon.woods%transgaming.com@gtempaccount.com18b4c4b2013-04-13 03:31:40 +00001191{
1192 return compileResources;
1193}
1194
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001195const ArrayBoundsClamper &TCompiler::getArrayBoundsClamper() const
daniel@transgaming.com4167cc92013-01-11 04:11:53 +00001196{
1197 return arrayBoundsClamper;
1198}
1199
shannon.woods@transgaming.com1d432bb2013-01-25 21:57:28 +00001200ShArrayIndexClampingStrategy TCompiler::getArrayIndexClampingStrategy() const
1201{
1202 return clampingStrategy;
1203}
1204
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001205const BuiltInFunctionEmulator &TCompiler::getBuiltInFunctionEmulator() const
shannon.woods@transgaming.com1d432bb2013-01-25 21:57:28 +00001206{
1207 return builtInFunctionEmulator;
1208}
Zhenyao Mo94ac7b72014-10-15 18:22:08 -07001209
Qiankun Miao7ebb97f2016-09-08 18:01:50 +08001210void TCompiler::writePragma(ShCompileOptions compileOptions)
Zhenyao Mo94ac7b72014-10-15 18:22:08 -07001211{
Kenneth Russellbccc65d2016-07-19 16:48:43 -07001212 if (!(compileOptions & SH_FLATTEN_PRAGMA_STDGL_INVARIANT_ALL))
1213 {
1214 TInfoSinkBase &sink = infoSink.obj;
1215 if (mPragma.stdgl.invariantAll)
1216 sink << "#pragma STDGL invariant(all)\n";
1217 }
1218}
1219
1220bool TCompiler::isVaryingDefined(const char *varyingName)
1221{
1222 ASSERT(variablesCollected);
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +08001223 for (size_t ii = 0; ii < inputVaryings.size(); ++ii)
Kenneth Russellbccc65d2016-07-19 16:48:43 -07001224 {
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +08001225 if (inputVaryings[ii].name == varyingName)
1226 {
1227 return true;
1228 }
1229 }
1230 for (size_t ii = 0; ii < outputVaryings.size(); ++ii)
1231 {
1232 if (outputVaryings[ii].name == varyingName)
Kenneth Russellbccc65d2016-07-19 16:48:43 -07001233 {
1234 return true;
1235 }
1236 }
1237
1238 return false;
Zhenyao Mo94ac7b72014-10-15 18:22:08 -07001239}
Jamie Madillacb4b812016-11-07 13:50:29 -05001240
1241} // namespace sh