blob: 9003d8fd1d57f43f285cb917e6fd89378e1ad4cc [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
Geoff Lang17732822013-08-29 13:46:49 -04007#include "compiler/translator/BuiltInFunctionEmulator.h"
8#include "compiler/translator/DetectCallDepth.h"
9#include "compiler/translator/ForLoopUnroll.h"
10#include "compiler/translator/Initialize.h"
Geoff Lang17732822013-08-29 13:46:49 -040011#include "compiler/translator/InitializeParseContext.h"
Zhenyao Mo4a667fe2014-02-11 12:35:01 -080012#include "compiler/translator/InitializeVariables.h"
Geoff Lang17732822013-08-29 13:46:49 -040013#include "compiler/translator/MapLongVariableNames.h"
Jamie Madill6b9cb252013-10-17 10:45:47 -040014#include "compiler/translator/ParseContext.h"
Geoff Lang17732822013-08-29 13:46:49 -040015#include "compiler/translator/RenameFunction.h"
16#include "compiler/translator/ShHandle.h"
Zhenyao Mo7cab38b2013-10-15 12:59:30 -070017#include "compiler/translator/UnfoldShortCircuitAST.h"
Geoff Lang17732822013-08-29 13:46:49 -040018#include "compiler/translator/ValidateLimitations.h"
19#include "compiler/translator/ValidateOutputs.h"
20#include "compiler/translator/VariablePacker.h"
21#include "compiler/translator/depgraph/DependencyGraph.h"
22#include "compiler/translator/depgraph/DependencyGraphOutput.h"
23#include "compiler/translator/timing/RestrictFragmentShaderTiming.h"
24#include "compiler/translator/timing/RestrictVertexShaderTiming.h"
shannon.woods@transgaming.comda1ed362013-01-25 21:54:57 +000025#include "third_party/compiler/ArrayBoundsClamper.h"
alokp@chromium.org07620a52010-09-23 17:53:56 +000026
maxvujovic@gmail.com430f5e02012-06-08 17:47:59 +000027bool isWebGLBasedSpec(ShShaderSpec spec)
28{
29 return spec == SH_WEBGL_SPEC || spec == SH_CSS_SHADERS_SPEC;
30}
31
Jamie Madill88f6e942014-02-19 10:27:53 -050032size_t GetGlobalMaxTokenSize()
33{
34 TParseContext *parseContext = GetGlobalParseContext();
35 // WebGL defines a max token legnth of 256, while ES2 leaves max token
36 // size undefined. ES3 defines a max size of 1024 characters.
37 if (isWebGLBasedSpec(parseContext->shaderSpec))
38 {
39 return 256;
40 }
41 else
42 {
43 return 1024;
44 }
45}
46
alokp@chromium.orgbafcbaa2010-11-23 19:07:43 +000047namespace {
Zhenyao Mo4a667fe2014-02-11 12:35:01 -080048class TScopedPoolAllocator
49{
50 public:
51 TScopedPoolAllocator(TPoolAllocator* allocator) : mAllocator(allocator)
52 {
Alok Priyadarshibc3f1ac2013-09-23 14:57:02 -040053 mAllocator->push();
alokp@chromium.orgbafcbaa2010-11-23 19:07:43 +000054 SetGlobalPoolAllocator(mAllocator);
55 }
Zhenyao Mo4a667fe2014-02-11 12:35:01 -080056 ~TScopedPoolAllocator()
57 {
alokp@chromium.orgbafcbaa2010-11-23 19:07:43 +000058 SetGlobalPoolAllocator(NULL);
Alok Priyadarshibc3f1ac2013-09-23 14:57:02 -040059 mAllocator->pop();
alokp@chromium.orgbafcbaa2010-11-23 19:07:43 +000060 }
61
Zhenyao Mo4a667fe2014-02-11 12:35:01 -080062 private:
alokp@chromium.orgbafcbaa2010-11-23 19:07:43 +000063 TPoolAllocator* mAllocator;
Alok Priyadarshibc3f1ac2013-09-23 14:57:02 -040064};
65
Zhenyao Mo4a667fe2014-02-11 12:35:01 -080066class TScopedSymbolTableLevel
67{
68 public:
69 TScopedSymbolTableLevel(TSymbolTable* table) : mTable(table)
70 {
Alok Priyadarshibc3f1ac2013-09-23 14:57:02 -040071 ASSERT(mTable->atBuiltInLevel());
72 mTable->push();
73 }
Zhenyao Mo4a667fe2014-02-11 12:35:01 -080074 ~TScopedSymbolTableLevel()
75 {
Alok Priyadarshibc3f1ac2013-09-23 14:57:02 -040076 while (!mTable->atBuiltInLevel())
77 mTable->pop();
78 }
79
Zhenyao Mo4a667fe2014-02-11 12:35:01 -080080 private:
Alok Priyadarshibc3f1ac2013-09-23 14:57:02 -040081 TSymbolTable* mTable;
alokp@chromium.orgbafcbaa2010-11-23 19:07:43 +000082};
83} // namespace
84
Zhenyao Mo4a667fe2014-02-11 12:35:01 -080085TShHandleBase::TShHandleBase()
86{
alokp@chromium.orgbafcbaa2010-11-23 19:07:43 +000087 allocator.push();
88 SetGlobalPoolAllocator(&allocator);
89}
90
Zhenyao Mo4a667fe2014-02-11 12:35:01 -080091TShHandleBase::~TShHandleBase()
92{
alokp@chromium.orgbafcbaa2010-11-23 19:07:43 +000093 SetGlobalPoolAllocator(NULL);
94 allocator.popAll();
95}
96
alokp@chromium.org4888ceb2010-10-01 21:13:12 +000097TCompiler::TCompiler(ShShaderType type, ShShaderSpec spec)
98 : shaderType(type),
zmo@google.comf420c422011-09-12 18:27:59 +000099 shaderSpec(spec),
Jamie Madilleb1a0102013-07-08 13:31:38 -0400100 maxUniformVectors(0),
101 maxExpressionComplexity(0),
102 maxCallStackDepth(0),
shannon.woods%transgaming.com@gtempaccount.comcbb6b6a2013-04-13 03:27:47 +0000103 fragmentPrecisionHigh(false),
shannon.woods@transgaming.com1d432bb2013-01-25 21:57:28 +0000104 clampingStrategy(SH_CLAMP_WITH_CLAMP_INTRINSIC),
zmo@google.com9996b8e2012-01-19 01:43:55 +0000105 builtInFunctionEmulator(type)
alokp@chromium.org4888ceb2010-10-01 21:13:12 +0000106{
zmo@google.comb9f64aa2012-01-20 00:35:15 +0000107 longNameMap = LongNameMap::GetInstance();
alokp@chromium.org4888ceb2010-10-01 21:13:12 +0000108}
109
110TCompiler::~TCompiler()
111{
zmo@google.comb9f64aa2012-01-20 00:35:15 +0000112 ASSERT(longNameMap);
113 longNameMap->Release();
alokp@chromium.org4888ceb2010-10-01 21:13:12 +0000114}
115
116bool TCompiler::Init(const ShBuiltInResources& resources)
alokp@chromium.org07620a52010-09-23 17:53:56 +0000117{
shannon.woods%transgaming.com@gtempaccount.com0bbed382013-04-13 03:38:07 +0000118 shaderVersion = 100;
gman@chromium.org8d804792012-10-17 21:33:48 +0000119 maxUniformVectors = (shaderType == SH_VERTEX_SHADER) ?
120 resources.MaxVertexUniformVectors :
121 resources.MaxFragmentUniformVectors;
Jamie Madilleb1a0102013-07-08 13:31:38 -0400122 maxExpressionComplexity = resources.MaxExpressionComplexity;
123 maxCallStackDepth = resources.MaxCallStackDepth;
Alok Priyadarshibc3f1ac2013-09-23 14:57:02 -0400124
125 SetGlobalPoolAllocator(&allocator);
alokp@chromium.orgbafcbaa2010-11-23 19:07:43 +0000126
alokp@chromium.org07620a52010-09-23 17:53:56 +0000127 // Generate built-in symbol table.
128 if (!InitBuiltInSymbolTable(resources))
129 return false;
alokp@chromium.org07620a52010-09-23 17:53:56 +0000130 InitExtensionBehavior(resources, extensionBehavior);
shannon.woods%transgaming.com@gtempaccount.comcbb6b6a2013-04-13 03:27:47 +0000131 fragmentPrecisionHigh = resources.FragmentPrecisionHigh == 1;
alokp@chromium.orgbafcbaa2010-11-23 19:07:43 +0000132
shannon.woods@transgaming.com1d432bb2013-01-25 21:57:28 +0000133 arrayBoundsClamper.SetClampingStrategy(resources.ArrayIndexClampingStrategy);
134 clampingStrategy = resources.ArrayIndexClampingStrategy;
135
daniel@transgaming.comc23f4612012-11-28 19:42:57 +0000136 hashFunction = resources.HashFunction;
137
alokp@chromium.org07620a52010-09-23 17:53:56 +0000138 return true;
139}
140
141bool TCompiler::compile(const char* const shaderStrings[],
shannon.woods@transgaming.comd64b3da2013-02-28 23:19:26 +0000142 size_t numStrings,
alokp@chromium.org07620a52010-09-23 17:53:56 +0000143 int compileOptions)
144{
Alok Priyadarshibc3f1ac2013-09-23 14:57:02 -0400145 TScopedPoolAllocator scopedAlloc(&allocator);
alokp@chromium.org07620a52010-09-23 17:53:56 +0000146 clearResults();
147
148 if (numStrings == 0)
149 return true;
150
alokp@chromium.orgb59a7782010-11-24 18:38:33 +0000151 // If compiling for WebGL, validate loop and indexing as well.
maxvujovic@gmail.com430f5e02012-06-08 17:47:59 +0000152 if (isWebGLBasedSpec(shaderSpec))
alokp@chromium.orgb59a7782010-11-24 18:38:33 +0000153 compileOptions |= SH_VALIDATE_LOOP_INDEXING;
alokp@chromium.org1f299542010-11-12 15:50:23 +0000154
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +0000155 // First string is path of source file if flag is set. The actual source follows.
156 const char* sourcePath = NULL;
shannon.woods@transgaming.comd64b3da2013-02-28 23:19:26 +0000157 size_t firstSource = 0;
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +0000158 if (compileOptions & SH_SOURCE_PATH)
159 {
160 sourcePath = shaderStrings[0];
161 ++firstSource;
162 }
163
alokp@chromium.org07620a52010-09-23 17:53:56 +0000164 TIntermediate intermediate(infoSink);
165 TParseContext parseContext(symbolTable, extensionBehavior, intermediate,
zmo@google.comdc4b4f82011-06-17 00:42:53 +0000166 shaderType, shaderSpec, compileOptions, true,
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +0000167 sourcePath, infoSink);
shannon.woods%transgaming.com@gtempaccount.comcbb6b6a2013-04-13 03:27:47 +0000168 parseContext.fragmentPrecisionHigh = fragmentPrecisionHigh;
Alok Priyadarshi8156b6b2013-09-23 14:56:58 -0400169 SetGlobalParseContext(&parseContext);
alokp@chromium.org07620a52010-09-23 17:53:56 +0000170
171 // We preserve symbols at the built-in level from compile-to-compile.
172 // Start pushing the user-defined symbols at global level.
Alok Priyadarshibc3f1ac2013-09-23 14:57:02 -0400173 TScopedSymbolTableLevel scopedSymbolLevel(&symbolTable);
alokp@chromium.org07620a52010-09-23 17:53:56 +0000174
175 // Parse shader.
176 bool success =
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +0000177 (PaParseStrings(numStrings - firstSource, &shaderStrings[firstSource], NULL, &parseContext) == 0) &&
alokp@chromium.org07620a52010-09-23 17:53:56 +0000178 (parseContext.treeRoot != NULL);
shannon.woods%transgaming.com@gtempaccount.com0bbed382013-04-13 03:38:07 +0000179
shannon.woods%transgaming.com@gtempaccount.com5524db02013-04-13 03:38:16 +0000180 shaderVersion = parseContext.getShaderVersion();
shannon.woods%transgaming.com@gtempaccount.com0bbed382013-04-13 03:38:07 +0000181
Zhenyao Mo4a667fe2014-02-11 12:35:01 -0800182 if (success)
183 {
alokp@chromium.orgb59a7782010-11-24 18:38:33 +0000184 TIntermNode* root = parseContext.treeRoot;
185 success = intermediate.postProcess(root);
186
zmo@google.comb1762df2011-07-30 02:04:23 +0000187 if (success)
Jamie Madilleb1a0102013-07-08 13:31:38 -0400188 success = detectCallDepth(root, infoSink, (compileOptions & SH_LIMIT_CALL_STACK_DEPTH) != 0);
zmo@google.comb1762df2011-07-30 02:04:23 +0000189
Jamie Madill05a80ce2013-06-20 11:55:49 -0400190 if (success && shaderVersion == 300 && shaderType == SH_FRAGMENT_SHADER)
191 success = validateOutputs(root);
192
alokp@chromium.orgb59a7782010-11-24 18:38:33 +0000193 if (success && (compileOptions & SH_VALIDATE_LOOP_INDEXING))
194 success = validateLimitations(root);
alokp@chromium.org07620a52010-09-23 17:53:56 +0000195
maxvujovic@gmail.com66ebd012012-05-30 22:18:11 +0000196 if (success && (compileOptions & SH_TIMING_RESTRICTIONS))
maxvujovic@gmail.com77222c92012-06-04 21:06:05 +0000197 success = enforceTimingRestrictions(root, (compileOptions & SH_DEPENDENCY_GRAPH) != 0);
maxvujovic@gmail.com66ebd012012-05-30 22:18:11 +0000198
maxvujovic@gmail.com430f5e02012-06-08 17:47:59 +0000199 if (success && shaderSpec == SH_CSS_SHADERS_SPEC)
200 rewriteCSSShader(root);
201
zmo@google.com0c6bb7a2011-08-17 19:39:58 +0000202 // Unroll for-loop markup needs to happen after validateLimitations pass.
203 if (success && (compileOptions & SH_UNROLL_FOR_LOOP_WITH_INTEGER_INDEX))
204 ForLoopUnroll::MarkForLoopsWithIntegerIndicesForUnrolling(root);
205
zmo@google.com32e97312011-08-24 01:03:11 +0000206 // Built-in function emulation needs to happen after validateLimitations pass.
207 if (success && (compileOptions & SH_EMULATE_BUILT_IN_FUNCTIONS))
208 builtInFunctionEmulator.MarkBuiltInFunctionsForEmulation(root);
209
daniel@transgaming.com4167cc92013-01-11 04:11:53 +0000210 // Clamping uniform array bounds needs to happen after validateLimitations pass.
211 if (success && (compileOptions & SH_CLAMP_INDIRECT_ARRAY_BOUNDS))
212 arrayBoundsClamper.MarkIndirectArrayBoundsForClamping(root);
213
Jamie Madilleb1a0102013-07-08 13:31:38 -0400214 // Disallow expressions deemed too complex.
215 if (success && (compileOptions & SH_LIMIT_EXPRESSION_COMPLEXITY))
216 success = limitExpressionComplexity(root);
217
zmo@google.comfd747b82011-04-23 01:30:07 +0000218 // Call mapLongVariableNames() before collectAttribsUniforms() so in
219 // collectAttribsUniforms() we already have the mapped symbol names and
220 // we could composite mapped and original variable names.
daniel@transgaming.com0aa3b5a2012-11-28 19:43:24 +0000221 // Also, if we hash all the names, then no need to do this for long names.
222 if (success && (compileOptions & SH_MAP_LONG_VARIABLE_NAMES) && hashFunction == NULL)
zmo@google.comfd747b82011-04-23 01:30:07 +0000223 mapLongVariableNames(root);
224
Zhenyao Mo4a667fe2014-02-11 12:35:01 -0800225 if (success && shaderType == SH_VERTEX_SHADER && (compileOptions & SH_INIT_GL_POSITION))
226 initializeGLPosition(root);
Zhenyao Moac44cd22013-09-23 14:57:09 -0400227
Zhenyao Mo4a667fe2014-02-11 12:35:01 -0800228 if (success && (compileOptions & SH_UNFOLD_SHORT_CIRCUIT))
229 {
Zhenyao Mo7cab38b2013-10-15 12:59:30 -0700230 UnfoldShortCircuitAST unfoldShortCircuit;
231 root->traverse(&unfoldShortCircuit);
232 unfoldShortCircuit.updateTree();
233 }
234
Zhenyao Mo4a667fe2014-02-11 12:35:01 -0800235 if (success && (compileOptions & SH_VARIABLES))
236 {
Zhenyao Mo74da9f22013-09-23 14:57:01 -0400237 collectVariables(root);
Zhenyao Mo4a667fe2014-02-11 12:35:01 -0800238 if (compileOptions & SH_ENFORCE_PACKING_RESTRICTIONS)
239 {
gman@chromium.org8d804792012-10-17 21:33:48 +0000240 success = enforcePackingRestrictions();
Zhenyao Mo4a667fe2014-02-11 12:35:01 -0800241 if (!success)
242 {
Jamie Madill075edd82013-07-08 13:30:19 -0400243 infoSink.info.prefix(EPrefixError);
244 infoSink.info << "too many uniforms";
gman@chromium.org8d804792012-10-17 21:33:48 +0000245 }
246 }
Zhenyao Mo4a667fe2014-02-11 12:35:01 -0800247 if (success && shaderType == SH_VERTEX_SHADER &&
248 (compileOptions & SH_INIT_VARYINGS_WITHOUT_STATIC_USE))
249 initializeVaryingsWithoutStaticUse(root);
gman@chromium.org8d804792012-10-17 21:33:48 +0000250 }
zmo@google.comfd747b82011-04-23 01:30:07 +0000251
alokp@chromium.org4888ceb2010-10-01 21:13:12 +0000252 if (success && (compileOptions & SH_INTERMEDIATE_TREE))
alokp@chromium.orgb59a7782010-11-24 18:38:33 +0000253 intermediate.outputTree(root);
alokp@chromium.org07620a52010-09-23 17:53:56 +0000254
alokp@chromium.org4888ceb2010-10-01 21:13:12 +0000255 if (success && (compileOptions & SH_OBJECT_CODE))
alokp@chromium.orgb59a7782010-11-24 18:38:33 +0000256 translate(root);
alokp@chromium.org07620a52010-09-23 17:53:56 +0000257 }
258
259 // Cleanup memory.
260 intermediate.remove(parseContext.treeRoot);
alokp@chromium.org07620a52010-09-23 17:53:56 +0000261
262 return success;
263}
264
Nicolas Capens49a88872013-06-20 09:54:03 -0400265bool TCompiler::InitBuiltInSymbolTable(const ShBuiltInResources &resources)
alokp@chromium.org07620a52010-09-23 17:53:56 +0000266{
shannon.woods%transgaming.com@gtempaccount.com18b4c4b2013-04-13 03:31:40 +0000267 compileResources = resources;
shannonwoods@chromium.org2ac0be92013-05-30 00:02:27 +0000268
Nicolas Capens49a88872013-06-20 09:54:03 -0400269 assert(symbolTable.isEmpty());
270 symbolTable.push(); // COMMON_BUILTINS
271 symbolTable.push(); // ESSL1_BUILTINS
272 symbolTable.push(); // ESSL3_BUILTINS
shannonwoods@chromium.org2ac0be92013-05-30 00:02:27 +0000273
Nicolas Capens49a88872013-06-20 09:54:03 -0400274 TPublicType integer;
275 integer.type = EbtInt;
276 integer.primarySize = 1;
277 integer.secondarySize = 1;
278 integer.array = false;
279
280 TPublicType floatingPoint;
281 floatingPoint.type = EbtFloat;
282 floatingPoint.primarySize = 1;
283 floatingPoint.secondarySize = 1;
284 floatingPoint.array = false;
285
Zhenyao Moa5a1dfc2013-09-23 14:57:03 -0400286 TPublicType sampler;
287 sampler.primarySize = 1;
288 sampler.secondarySize = 1;
289 sampler.array = false;
290
Nicolas Capens49a88872013-06-20 09:54:03 -0400291 switch(shaderType)
292 {
293 case SH_FRAGMENT_SHADER:
294 symbolTable.setDefaultPrecision(integer, EbpMedium);
295 break;
296 case SH_VERTEX_SHADER:
297 symbolTable.setDefaultPrecision(integer, EbpHigh);
298 symbolTable.setDefaultPrecision(floatingPoint, EbpHigh);
299 break;
Zhenyao Mo4a667fe2014-02-11 12:35:01 -0800300 default:
301 assert(false && "Language not supported");
Nicolas Capens49a88872013-06-20 09:54:03 -0400302 }
Zhenyao Moa5a1dfc2013-09-23 14:57:03 -0400303 // We set defaults for all the sampler types, even those that are
304 // only available if an extension exists.
305 for (int samplerType = EbtGuardSamplerBegin + 1;
Zhenyao Mo4a667fe2014-02-11 12:35:01 -0800306 samplerType < EbtGuardSamplerEnd; ++samplerType)
307 {
Zhenyao Moa5a1dfc2013-09-23 14:57:03 -0400308 sampler.type = static_cast<TBasicType>(samplerType);
309 symbolTable.setDefaultPrecision(sampler, EbpLow);
310 }
Nicolas Capens49a88872013-06-20 09:54:03 -0400311
Jamie Madill1b452142013-07-12 14:51:11 -0400312 InsertBuiltInFunctions(shaderType, shaderSpec, resources, symbolTable);
Nicolas Capens49a88872013-06-20 09:54:03 -0400313
314 IdentifyBuiltIns(shaderType, shaderSpec, resources, symbolTable);
315
316 return true;
alokp@chromium.org07620a52010-09-23 17:53:56 +0000317}
318
319void TCompiler::clearResults()
320{
daniel@transgaming.com4167cc92013-01-11 04:11:53 +0000321 arrayBoundsClamper.Cleanup();
alokp@chromium.org07620a52010-09-23 17:53:56 +0000322 infoSink.info.erase();
323 infoSink.obj.erase();
324 infoSink.debug.erase();
325
326 attribs.clear();
327 uniforms.clear();
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400328 varyings.clear();
zmo@google.coma3b4ab42011-09-16 00:53:26 +0000329
330 builtInFunctionEmulator.Cleanup();
daniel@transgaming.com0aa3b5a2012-11-28 19:43:24 +0000331
332 nameMap.clear();
alokp@chromium.org07620a52010-09-23 17:53:56 +0000333}
334
Jamie Madilleb1a0102013-07-08 13:31:38 -0400335bool TCompiler::detectCallDepth(TIntermNode* root, TInfoSink& infoSink, bool limitCallStackDepth)
zmo@google.comb1762df2011-07-30 02:04:23 +0000336{
Jamie Madilleb1a0102013-07-08 13:31:38 -0400337 DetectCallDepth detect(infoSink, limitCallStackDepth, maxCallStackDepth);
zmo@google.comb1762df2011-07-30 02:04:23 +0000338 root->traverse(&detect);
Zhenyao Mo4a667fe2014-02-11 12:35:01 -0800339 switch (detect.detectCallDepth())
340 {
341 case DetectCallDepth::kErrorNone:
342 return true;
343 case DetectCallDepth::kErrorMissingMain:
344 infoSink.info.prefix(EPrefixError);
345 infoSink.info << "Missing main()";
346 return false;
347 case DetectCallDepth::kErrorRecursion:
348 infoSink.info.prefix(EPrefixError);
349 infoSink.info << "Function recursion detected";
350 return false;
351 case DetectCallDepth::kErrorMaxDepthExceeded:
352 infoSink.info.prefix(EPrefixError);
353 infoSink.info << "Function call stack too deep";
354 return false;
355 default:
356 UNREACHABLE();
357 return false;
zmo@google.comb1762df2011-07-30 02:04:23 +0000358 }
359}
360
Jamie Madill05a80ce2013-06-20 11:55:49 -0400361bool TCompiler::validateOutputs(TIntermNode* root)
362{
363 ValidateOutputs validateOutputs(infoSink.info, compileResources.MaxDrawBuffers);
364 root->traverse(&validateOutputs);
365 return (validateOutputs.numErrors() == 0);
366}
367
maxvujovic@gmail.com430f5e02012-06-08 17:47:59 +0000368void TCompiler::rewriteCSSShader(TIntermNode* root)
369{
370 RenameFunction renamer("main(", "css_main(");
371 root->traverse(&renamer);
372}
373
Zhenyao Mo4a667fe2014-02-11 12:35:01 -0800374bool TCompiler::validateLimitations(TIntermNode* root)
375{
alokp@chromium.orgb59a7782010-11-24 18:38:33 +0000376 ValidateLimitations validate(shaderType, infoSink.info);
377 root->traverse(&validate);
378 return validate.numErrors() == 0;
379}
380
maxvujovic@gmail.com77222c92012-06-04 21:06:05 +0000381bool TCompiler::enforceTimingRestrictions(TIntermNode* root, bool outputGraph)
maxvujovic@gmail.com66ebd012012-05-30 22:18:11 +0000382{
Zhenyao Mo4a667fe2014-02-11 12:35:01 -0800383 if (shaderSpec != SH_WEBGL_SPEC)
384 {
maxvujovic@gmail.com66ebd012012-05-30 22:18:11 +0000385 infoSink.info << "Timing restrictions must be enforced under the WebGL spec.";
386 return false;
387 }
388
Zhenyao Mo4a667fe2014-02-11 12:35:01 -0800389 if (shaderType == SH_FRAGMENT_SHADER)
390 {
maxvujovic@gmail.com66ebd012012-05-30 22:18:11 +0000391 TDependencyGraph graph(root);
392
393 // Output any errors first.
maxvujovic@gmail.com77222c92012-06-04 21:06:05 +0000394 bool success = enforceFragmentShaderTimingRestrictions(graph);
maxvujovic@gmail.com66ebd012012-05-30 22:18:11 +0000395
396 // Then, output the dependency graph.
Zhenyao Mo4a667fe2014-02-11 12:35:01 -0800397 if (outputGraph)
398 {
maxvujovic@gmail.com66ebd012012-05-30 22:18:11 +0000399 TDependencyGraphOutput output(infoSink.info);
400 output.outputAllSpanningTrees(graph);
401 }
402
403 return success;
404 }
Zhenyao Mo4a667fe2014-02-11 12:35:01 -0800405 else
406 {
maxvujovic@gmail.com77222c92012-06-04 21:06:05 +0000407 return enforceVertexShaderTimingRestrictions(root);
maxvujovic@gmail.com66ebd012012-05-30 22:18:11 +0000408 }
409}
410
Jamie Madilleb1a0102013-07-08 13:31:38 -0400411bool TCompiler::limitExpressionComplexity(TIntermNode* root)
412{
413 TIntermTraverser traverser;
414 root->traverse(&traverser);
415 TDependencyGraph graph(root);
416
417 for (TFunctionCallVector::const_iterator iter = graph.beginUserDefinedFunctionCalls();
418 iter != graph.endUserDefinedFunctionCalls();
419 ++iter)
420 {
421 TGraphFunctionCall* samplerSymbol = *iter;
422 TDependencyGraphTraverser graphTraverser;
423 samplerSymbol->traverse(&graphTraverser);
424 }
425
Zhenyao Mo4a667fe2014-02-11 12:35:01 -0800426 if (traverser.getMaxDepth() > maxExpressionComplexity)
427 {
Jamie Madilleb1a0102013-07-08 13:31:38 -0400428 infoSink.info << "Expression too complex.";
429 return false;
430 }
431 return true;
432}
433
maxvujovic@gmail.com77222c92012-06-04 21:06:05 +0000434bool TCompiler::enforceFragmentShaderTimingRestrictions(const TDependencyGraph& graph)
maxvujovic@gmail.com66ebd012012-05-30 22:18:11 +0000435{
maxvujovic@gmail.com77222c92012-06-04 21:06:05 +0000436 RestrictFragmentShaderTiming restrictor(infoSink.info);
maxvujovic@gmail.com66ebd012012-05-30 22:18:11 +0000437 restrictor.enforceRestrictions(graph);
438 return restrictor.numErrors() == 0;
439}
440
maxvujovic@gmail.com77222c92012-06-04 21:06:05 +0000441bool TCompiler::enforceVertexShaderTimingRestrictions(TIntermNode* root)
maxvujovic@gmail.com66ebd012012-05-30 22:18:11 +0000442{
maxvujovic@gmail.com77222c92012-06-04 21:06:05 +0000443 RestrictVertexShaderTiming restrictor(infoSink.info);
maxvujovic@gmail.com66ebd012012-05-30 22:18:11 +0000444 restrictor.enforceRestrictions(root);
445 return restrictor.numErrors() == 0;
446}
447
Zhenyao Mo74da9f22013-09-23 14:57:01 -0400448void TCompiler::collectVariables(TIntermNode* root)
alokp@chromium.org07620a52010-09-23 17:53:56 +0000449{
Zhenyao Mo74da9f22013-09-23 14:57:01 -0400450 CollectVariables collect(attribs, uniforms, varyings, hashFunction);
alokp@chromium.org07620a52010-09-23 17:53:56 +0000451 root->traverse(&collect);
452}
zmo@google.comfd747b82011-04-23 01:30:07 +0000453
gman@chromium.org8d804792012-10-17 21:33:48 +0000454bool TCompiler::enforcePackingRestrictions()
455{
456 VariablePacker packer;
457 return packer.CheckVariablesWithinPackingLimits(maxUniformVectors, uniforms);
458}
459
Zhenyao Mo4a667fe2014-02-11 12:35:01 -0800460void TCompiler::initializeGLPosition(TIntermNode* root)
461{
462 InitializeVariables::InitVariableInfoList variables;
463 InitializeVariables::InitVariableInfo var(
464 "gl_Position", TType(EbtFloat, EbpUndefined, EvqPosition, 4));
465 variables.push_back(var);
466 InitializeVariables initializer(variables);
467 root->traverse(&initializer);
468}
469
470void TCompiler::initializeVaryingsWithoutStaticUse(TIntermNode* root)
471{
472 InitializeVariables::InitVariableInfoList variables;
473 for (size_t ii = 0; ii < varyings.size(); ++ii)
474 {
475 const TVariableInfo& varying = varyings[ii];
476 if (varying.staticUse)
477 continue;
478 unsigned char size = 0;
479 bool matrix = false;
480 switch (varying.type)
481 {
482 case SH_FLOAT:
483 size = 1;
484 break;
485 case SH_FLOAT_VEC2:
486 size = 2;
487 break;
488 case SH_FLOAT_VEC3:
489 size = 3;
490 break;
491 case SH_FLOAT_VEC4:
492 size = 4;
493 break;
494 case SH_FLOAT_MAT2:
495 size = 2;
496 matrix = true;
497 break;
498 case SH_FLOAT_MAT3:
499 size = 3;
500 matrix = true;
501 break;
502 case SH_FLOAT_MAT4:
503 size = 4;
504 matrix = true;
505 break;
506 default:
507 ASSERT(false);
508 }
509 TType type(EbtFloat, EbpUndefined, EvqVaryingOut, size, matrix, varying.isArray);
510 TString name = varying.name.c_str();
511 if (varying.isArray)
512 {
513 type.setArraySize(varying.size);
514 name = name.substr(0, name.find_first_of('['));
515 }
516
517 InitializeVariables::InitVariableInfo var(name, type);
518 variables.push_back(var);
519 }
520 InitializeVariables initializer(variables);
521 root->traverse(&initializer);
522}
523
zmo@google.comfd747b82011-04-23 01:30:07 +0000524void TCompiler::mapLongVariableNames(TIntermNode* root)
525{
zmo@google.comb9f64aa2012-01-20 00:35:15 +0000526 ASSERT(longNameMap);
527 MapLongVariableNames map(longNameMap);
zmo@google.com9996b8e2012-01-19 01:43:55 +0000528 root->traverse(&map);
zmo@google.comfd747b82011-04-23 01:30:07 +0000529}
530
531int TCompiler::getMappedNameMaxLength() const
532{
kbr@chromium.org22152112011-10-26 01:18:28 +0000533 return MAX_SHORTENED_IDENTIFIER_SIZE + 1;
zmo@google.comfd747b82011-04-23 01:30:07 +0000534}
zmo@google.com5601ea02011-06-10 18:23:25 +0000535
536const TExtensionBehavior& TCompiler::getExtensionBehavior() const
537{
538 return extensionBehavior;
539}
zmo@google.com32e97312011-08-24 01:03:11 +0000540
shannon.woods%transgaming.com@gtempaccount.com18b4c4b2013-04-13 03:31:40 +0000541const ShBuiltInResources& TCompiler::getResources() const
542{
543 return compileResources;
544}
545
daniel@transgaming.com4167cc92013-01-11 04:11:53 +0000546const ArrayBoundsClamper& TCompiler::getArrayBoundsClamper() const
547{
548 return arrayBoundsClamper;
549}
550
shannon.woods@transgaming.com1d432bb2013-01-25 21:57:28 +0000551ShArrayIndexClampingStrategy TCompiler::getArrayIndexClampingStrategy() const
552{
553 return clampingStrategy;
554}
555
556const BuiltInFunctionEmulator& TCompiler::getBuiltInFunctionEmulator() const
557{
558 return builtInFunctionEmulator;
559}