Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / third_party / angle / src / compiler / translator / Compiler.cpp
1 //
2 // Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6
7 #include "compiler/translator/BuiltInFunctionEmulator.h"
8 #include "compiler/translator/Compiler.h"
9 #include "compiler/translator/DetectCallDepth.h"
10 #include "compiler/translator/ForLoopUnroll.h"
11 #include "compiler/translator/Initialize.h"
12 #include "compiler/translator/InitializeParseContext.h"
13 #include "compiler/translator/InitializeVariables.h"
14 #include "compiler/translator/ParseContext.h"
15 #include "compiler/translator/RegenerateStructNames.h"
16 #include "compiler/translator/RenameFunction.h"
17 #include "compiler/translator/ScalarizeVecAndMatConstructorArgs.h"
18 #include "compiler/translator/UnfoldShortCircuitAST.h"
19 #include "compiler/translator/ValidateLimitations.h"
20 #include "compiler/translator/ValidateOutputs.h"
21 #include "compiler/translator/VariablePacker.h"
22 #include "compiler/translator/depgraph/DependencyGraph.h"
23 #include "compiler/translator/depgraph/DependencyGraphOutput.h"
24 #include "compiler/translator/timing/RestrictFragmentShaderTiming.h"
25 #include "compiler/translator/timing/RestrictVertexShaderTiming.h"
26 #include "third_party/compiler/ArrayBoundsClamper.h"
27 #include "angle_gl.h"
28 #include "common/utilities.h"
29
30 bool IsWebGLBasedSpec(ShShaderSpec spec)
31 {
32     return (spec == SH_WEBGL_SPEC ||
33             spec == SH_CSS_SHADERS_SPEC ||
34             spec == SH_WEBGL2_SPEC);
35 }
36
37 size_t GetGlobalMaxTokenSize(ShShaderSpec spec)
38 {
39     // WebGL defines a max token legnth of 256, while ES2 leaves max token
40     // size undefined. ES3 defines a max size of 1024 characters.
41     switch (spec)
42     {
43       case SH_WEBGL_SPEC:
44       case SH_CSS_SHADERS_SPEC:
45         return 256;
46       default:
47         return 1024;
48     }
49 }
50
51 namespace {
52
53 class TScopedPoolAllocator
54 {
55   public:
56     TScopedPoolAllocator(TPoolAllocator* allocator) : mAllocator(allocator)
57     {
58         mAllocator->push();
59         SetGlobalPoolAllocator(mAllocator);
60     }
61     ~TScopedPoolAllocator()
62     {
63         SetGlobalPoolAllocator(NULL);
64         mAllocator->pop();
65     }
66
67   private:
68     TPoolAllocator* mAllocator;
69 };
70
71 class TScopedSymbolTableLevel
72 {
73   public:
74     TScopedSymbolTableLevel(TSymbolTable* table) : mTable(table)
75     {
76         ASSERT(mTable->atBuiltInLevel());
77         mTable->push();
78     }
79     ~TScopedSymbolTableLevel()
80     {
81         while (!mTable->atBuiltInLevel())
82             mTable->pop();
83     }
84
85   private:
86     TSymbolTable* mTable;
87 };
88
89 int MapSpecToShaderVersion(ShShaderSpec spec)
90 {
91     switch (spec)
92     {
93       case SH_GLES2_SPEC:
94       case SH_WEBGL_SPEC:
95       case SH_CSS_SHADERS_SPEC:
96         return 100;
97       case SH_GLES3_SPEC:
98       case SH_WEBGL2_SPEC:
99         return 300;
100       default:
101         UNREACHABLE();
102         return 0;
103     }
104 }
105
106 }  // namespace
107
108 TShHandleBase::TShHandleBase()
109 {
110     allocator.push();
111     SetGlobalPoolAllocator(&allocator);
112 }
113
114 TShHandleBase::~TShHandleBase()
115 {
116     SetGlobalPoolAllocator(NULL);
117     allocator.popAll();
118 }
119
120 TCompiler::TCompiler(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output)
121     : shaderType(type),
122       shaderSpec(spec),
123       outputType(output),
124       maxUniformVectors(0),
125       maxExpressionComplexity(0),
126       maxCallStackDepth(0),
127       fragmentPrecisionHigh(false),
128       clampingStrategy(SH_CLAMP_WITH_CLAMP_INTRINSIC),
129       builtInFunctionEmulator(type)
130 {
131 }
132
133 TCompiler::~TCompiler()
134 {
135 }
136
137 bool TCompiler::Init(const ShBuiltInResources& resources)
138 {
139     shaderVersion = 100;
140     maxUniformVectors = (shaderType == GL_VERTEX_SHADER) ?
141         resources.MaxVertexUniformVectors :
142         resources.MaxFragmentUniformVectors;
143     maxExpressionComplexity = resources.MaxExpressionComplexity;
144     maxCallStackDepth = resources.MaxCallStackDepth;
145
146     SetGlobalPoolAllocator(&allocator);
147
148     // Generate built-in symbol table.
149     if (!InitBuiltInSymbolTable(resources))
150         return false;
151     InitExtensionBehavior(resources, extensionBehavior);
152     fragmentPrecisionHigh = resources.FragmentPrecisionHigh == 1;
153
154     arrayBoundsClamper.SetClampingStrategy(resources.ArrayIndexClampingStrategy);
155     clampingStrategy = resources.ArrayIndexClampingStrategy;
156
157     hashFunction = resources.HashFunction;
158
159     return true;
160 }
161
162 bool TCompiler::compile(const char* const shaderStrings[],
163                         size_t numStrings,
164                         int compileOptions)
165 {
166     TScopedPoolAllocator scopedAlloc(&allocator);
167     clearResults();
168
169     if (numStrings == 0)
170         return true;
171
172     // If compiling for WebGL, validate loop and indexing as well.
173     if (IsWebGLBasedSpec(shaderSpec))
174         compileOptions |= SH_VALIDATE_LOOP_INDEXING;
175
176     // First string is path of source file if flag is set. The actual source follows.
177     const char* sourcePath = NULL;
178     size_t firstSource = 0;
179     if (compileOptions & SH_SOURCE_PATH)
180     {
181         sourcePath = shaderStrings[0];
182         ++firstSource;
183     }
184
185     TIntermediate intermediate(infoSink);
186     TParseContext parseContext(symbolTable, extensionBehavior, intermediate,
187                                shaderType, shaderSpec, compileOptions, true,
188                                sourcePath, infoSink);
189     parseContext.fragmentPrecisionHigh = fragmentPrecisionHigh;
190     SetGlobalParseContext(&parseContext);
191
192     // We preserve symbols at the built-in level from compile-to-compile.
193     // Start pushing the user-defined symbols at global level.
194     TScopedSymbolTableLevel scopedSymbolLevel(&symbolTable);
195
196     // Parse shader.
197     bool success =
198         (PaParseStrings(numStrings - firstSource, &shaderStrings[firstSource], NULL, &parseContext) == 0) &&
199         (parseContext.treeRoot != NULL);
200
201     shaderVersion = parseContext.getShaderVersion();
202     if (success && MapSpecToShaderVersion(shaderSpec) < shaderVersion)
203     {
204         infoSink.info.prefix(EPrefixError);
205         infoSink.info << "unsupported shader version";
206         success = false;
207     }
208
209     if (success)
210     {
211         mPragma = parseContext.pragma();
212         if (mPragma.stdgl.invariantAll)
213         {
214             symbolTable.setGlobalInvariant();
215         }
216
217         TIntermNode* root = parseContext.treeRoot;
218         success = intermediate.postProcess(root);
219
220         // Disallow expressions deemed too complex.
221         if (success && (compileOptions & SH_LIMIT_EXPRESSION_COMPLEXITY))
222             success = limitExpressionComplexity(root);
223
224         if (success)
225             success = detectCallDepth(root, infoSink, (compileOptions & SH_LIMIT_CALL_STACK_DEPTH) != 0);
226
227         if (success && shaderVersion == 300 && shaderType == GL_FRAGMENT_SHADER)
228             success = validateOutputs(root);
229
230         if (success && (compileOptions & SH_VALIDATE_LOOP_INDEXING))
231             success = validateLimitations(root);
232
233         if (success && (compileOptions & SH_TIMING_RESTRICTIONS))
234             success = enforceTimingRestrictions(root, (compileOptions & SH_DEPENDENCY_GRAPH) != 0);
235
236         if (success && shaderSpec == SH_CSS_SHADERS_SPEC)
237             rewriteCSSShader(root);
238
239         // Unroll for-loop markup needs to happen after validateLimitations pass.
240         if (success && (compileOptions & SH_UNROLL_FOR_LOOP_WITH_INTEGER_INDEX))
241         {
242             ForLoopUnrollMarker marker(ForLoopUnrollMarker::kIntegerIndex);
243             root->traverse(&marker);
244         }
245         if (success && (compileOptions & SH_UNROLL_FOR_LOOP_WITH_SAMPLER_ARRAY_INDEX))
246         {
247             ForLoopUnrollMarker marker(ForLoopUnrollMarker::kSamplerArrayIndex);
248             root->traverse(&marker);
249             if (marker.samplerArrayIndexIsFloatLoopIndex())
250             {
251                 infoSink.info.prefix(EPrefixError);
252                 infoSink.info << "sampler array index is float loop index";
253                 success = false;
254             }
255         }
256
257         // Built-in function emulation needs to happen after validateLimitations pass.
258         if (success && (compileOptions & SH_EMULATE_BUILT_IN_FUNCTIONS))
259             builtInFunctionEmulator.MarkBuiltInFunctionsForEmulation(root);
260
261         // Clamping uniform array bounds needs to happen after validateLimitations pass.
262         if (success && (compileOptions & SH_CLAMP_INDIRECT_ARRAY_BOUNDS))
263             arrayBoundsClamper.MarkIndirectArrayBoundsForClamping(root);
264
265         if (success && shaderType == GL_VERTEX_SHADER && (compileOptions & SH_INIT_GL_POSITION))
266             initializeGLPosition(root);
267
268         if (success && (compileOptions & SH_UNFOLD_SHORT_CIRCUIT))
269         {
270             UnfoldShortCircuitAST unfoldShortCircuit;
271             root->traverse(&unfoldShortCircuit);
272             unfoldShortCircuit.updateTree();
273         }
274
275         if (success && (compileOptions & SH_VARIABLES))
276         {
277             collectVariables(root);
278             if (compileOptions & SH_ENFORCE_PACKING_RESTRICTIONS)
279             {
280                 success = enforcePackingRestrictions();
281                 if (!success)
282                 {
283                     infoSink.info.prefix(EPrefixError);
284                     infoSink.info << "too many uniforms";
285                 }
286             }
287             if (success && shaderType == GL_VERTEX_SHADER &&
288                 (compileOptions & SH_INIT_VARYINGS_WITHOUT_STATIC_USE))
289                 initializeVaryingsWithoutStaticUse(root);
290         }
291
292         if (success && (compileOptions & SH_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS))
293         {
294             ScalarizeVecAndMatConstructorArgs scalarizer(
295                 shaderType, fragmentPrecisionHigh);
296             root->traverse(&scalarizer);
297         }
298
299         if (success && (compileOptions & SH_REGENERATE_STRUCT_NAMES))
300         {
301             RegenerateStructNames gen(symbolTable, shaderVersion);
302             root->traverse(&gen);
303         }
304
305         if (success && (compileOptions & SH_INTERMEDIATE_TREE))
306             intermediate.outputTree(root);
307
308         if (success && (compileOptions & SH_OBJECT_CODE))
309             translate(root);
310     }
311
312     // Cleanup memory.
313     intermediate.remove(parseContext.treeRoot);
314     SetGlobalParseContext(NULL);
315     return success;
316 }
317
318 bool TCompiler::InitBuiltInSymbolTable(const ShBuiltInResources &resources)
319 {
320     compileResources = resources;
321     setResourceString();
322
323     assert(symbolTable.isEmpty());
324     symbolTable.push();   // COMMON_BUILTINS
325     symbolTable.push();   // ESSL1_BUILTINS
326     symbolTable.push();   // ESSL3_BUILTINS
327
328     TPublicType integer;
329     integer.type = EbtInt;
330     integer.primarySize = 1;
331     integer.secondarySize = 1;
332     integer.array = false;
333
334     TPublicType floatingPoint;
335     floatingPoint.type = EbtFloat;
336     floatingPoint.primarySize = 1;
337     floatingPoint.secondarySize = 1;
338     floatingPoint.array = false;
339
340     TPublicType sampler;
341     sampler.primarySize = 1;
342     sampler.secondarySize = 1;
343     sampler.array = false;
344
345     switch(shaderType)
346     {
347       case GL_FRAGMENT_SHADER:
348         symbolTable.setDefaultPrecision(integer, EbpMedium);
349         break;
350       case GL_VERTEX_SHADER:
351         symbolTable.setDefaultPrecision(integer, EbpHigh);
352         symbolTable.setDefaultPrecision(floatingPoint, EbpHigh);
353         break;
354       default:
355         assert(false && "Language not supported");
356     }
357     // We set defaults for all the sampler types, even those that are
358     // only available if an extension exists.
359     for (int samplerType = EbtGuardSamplerBegin + 1;
360          samplerType < EbtGuardSamplerEnd; ++samplerType)
361     {
362         sampler.type = static_cast<TBasicType>(samplerType);
363         symbolTable.setDefaultPrecision(sampler, EbpLow);
364     }
365
366     InsertBuiltInFunctions(shaderType, shaderSpec, resources, symbolTable);
367
368     IdentifyBuiltIns(shaderType, shaderSpec, resources, symbolTable);
369
370     return true;
371 }
372
373 void TCompiler::setResourceString()
374 {
375     std::ostringstream strstream;
376     strstream << ":MaxVertexAttribs:" << compileResources.MaxVertexAttribs
377               << ":MaxVertexUniformVectors:" << compileResources.MaxVertexUniformVectors
378               << ":MaxVaryingVectors:" << compileResources.MaxVaryingVectors
379               << ":MaxVertexTextureImageUnits:" << compileResources.MaxVertexTextureImageUnits
380               << ":MaxCombinedTextureImageUnits:" << compileResources.MaxCombinedTextureImageUnits
381               << ":MaxTextureImageUnits:" << compileResources.MaxTextureImageUnits
382               << ":MaxFragmentUniformVectors:" << compileResources.MaxFragmentUniformVectors
383               << ":MaxDrawBuffers:" << compileResources.MaxDrawBuffers
384               << ":OES_standard_derivatives:" << compileResources.OES_standard_derivatives
385               << ":OES_EGL_image_external:" << compileResources.OES_EGL_image_external
386               << ":ARB_texture_rectangle:" << compileResources.ARB_texture_rectangle
387               << ":EXT_draw_buffers:" << compileResources.EXT_draw_buffers
388               << ":FragmentPrecisionHigh:" << compileResources.FragmentPrecisionHigh
389               << ":MaxExpressionComplexity:" << compileResources.MaxExpressionComplexity
390               << ":MaxCallStackDepth:" << compileResources.MaxCallStackDepth
391               << ":EXT_frag_depth:" << compileResources.EXT_frag_depth
392               << ":EXT_shader_texture_lod:" << compileResources.EXT_shader_texture_lod
393               << ":MaxVertexOutputVectors:" << compileResources.MaxVertexOutputVectors
394               << ":MaxFragmentInputVectors:" << compileResources.MaxFragmentInputVectors
395               << ":MinProgramTexelOffset:" << compileResources.MinProgramTexelOffset
396               << ":MaxProgramTexelOffset:" << compileResources.MaxProgramTexelOffset
397               << ":NV_draw_buffers:" << compileResources.NV_draw_buffers;
398
399     builtInResourcesString = strstream.str();
400 }
401
402 void TCompiler::clearResults()
403 {
404     arrayBoundsClamper.Cleanup();
405     infoSink.info.erase();
406     infoSink.obj.erase();
407     infoSink.debug.erase();
408
409     attributes.clear();
410     outputVariables.clear();
411     uniforms.clear();
412     expandedUniforms.clear();
413     varyings.clear();
414     interfaceBlocks.clear();
415
416     builtInFunctionEmulator.Cleanup();
417
418     nameMap.clear();
419 }
420
421 bool TCompiler::detectCallDepth(TIntermNode* root, TInfoSink& infoSink, bool limitCallStackDepth)
422 {
423     DetectCallDepth detect(infoSink, limitCallStackDepth, maxCallStackDepth);
424     root->traverse(&detect);
425     switch (detect.detectCallDepth())
426     {
427       case DetectCallDepth::kErrorNone:
428         return true;
429       case DetectCallDepth::kErrorMissingMain:
430         infoSink.info.prefix(EPrefixError);
431         infoSink.info << "Missing main()";
432         return false;
433       case DetectCallDepth::kErrorRecursion:
434         infoSink.info.prefix(EPrefixError);
435         infoSink.info << "Function recursion detected";
436         return false;
437       case DetectCallDepth::kErrorMaxDepthExceeded:
438         infoSink.info.prefix(EPrefixError);
439         infoSink.info << "Function call stack too deep";
440         return false;
441       default:
442         UNREACHABLE();
443         return false;
444     }
445 }
446
447 bool TCompiler::validateOutputs(TIntermNode* root)
448 {
449     ValidateOutputs validateOutputs(infoSink.info, compileResources.MaxDrawBuffers);
450     root->traverse(&validateOutputs);
451     return (validateOutputs.numErrors() == 0);
452 }
453
454 void TCompiler::rewriteCSSShader(TIntermNode* root)
455 {
456     RenameFunction renamer("main(", "css_main(");
457     root->traverse(&renamer);
458 }
459
460 bool TCompiler::validateLimitations(TIntermNode* root)
461 {
462     ValidateLimitations validate(shaderType, infoSink.info);
463     root->traverse(&validate);
464     return validate.numErrors() == 0;
465 }
466
467 bool TCompiler::enforceTimingRestrictions(TIntermNode* root, bool outputGraph)
468 {
469     if (shaderSpec != SH_WEBGL_SPEC)
470     {
471         infoSink.info << "Timing restrictions must be enforced under the WebGL spec.";
472         return false;
473     }
474
475     if (shaderType == GL_FRAGMENT_SHADER)
476     {
477         TDependencyGraph graph(root);
478
479         // Output any errors first.
480         bool success = enforceFragmentShaderTimingRestrictions(graph);
481
482         // Then, output the dependency graph.
483         if (outputGraph)
484         {
485             TDependencyGraphOutput output(infoSink.info);
486             output.outputAllSpanningTrees(graph);
487         }
488
489         return success;
490     }
491     else
492     {
493         return enforceVertexShaderTimingRestrictions(root);
494     }
495 }
496
497 bool TCompiler::limitExpressionComplexity(TIntermNode* root)
498 {
499     TMaxDepthTraverser traverser(maxExpressionComplexity+1);
500     root->traverse(&traverser);
501
502     if (traverser.getMaxDepth() > maxExpressionComplexity)
503     {
504         infoSink.info << "Expression too complex.";
505         return false;
506     }
507
508     TDependencyGraph graph(root);
509
510     for (TFunctionCallVector::const_iterator iter = graph.beginUserDefinedFunctionCalls();
511          iter != graph.endUserDefinedFunctionCalls();
512          ++iter)
513     {
514         TGraphFunctionCall* samplerSymbol = *iter;
515         TDependencyGraphTraverser graphTraverser;
516         samplerSymbol->traverse(&graphTraverser);
517     }
518
519     return true;
520 }
521
522 bool TCompiler::enforceFragmentShaderTimingRestrictions(const TDependencyGraph& graph)
523 {
524     RestrictFragmentShaderTiming restrictor(infoSink.info);
525     restrictor.enforceRestrictions(graph);
526     return restrictor.numErrors() == 0;
527 }
528
529 bool TCompiler::enforceVertexShaderTimingRestrictions(TIntermNode* root)
530 {
531     RestrictVertexShaderTiming restrictor(infoSink.info);
532     restrictor.enforceRestrictions(root);
533     return restrictor.numErrors() == 0;
534 }
535
536 void TCompiler::collectVariables(TIntermNode* root)
537 {
538     sh::CollectVariables collect(&attributes,
539                                  &outputVariables,
540                                  &uniforms,
541                                  &varyings,
542                                  &interfaceBlocks,
543                                  hashFunction,
544                                  symbolTable);
545     root->traverse(&collect);
546
547     // This is for enforcePackingRestriction().
548     sh::ExpandUniforms(uniforms, &expandedUniforms);
549 }
550
551 bool TCompiler::enforcePackingRestrictions()
552 {
553     VariablePacker packer;
554     return packer.CheckVariablesWithinPackingLimits(maxUniformVectors, expandedUniforms);
555 }
556
557 void TCompiler::initializeGLPosition(TIntermNode* root)
558 {
559     InitializeVariables::InitVariableInfoList variables;
560     InitializeVariables::InitVariableInfo var(
561         "gl_Position", TType(EbtFloat, EbpUndefined, EvqPosition, 4));
562     variables.push_back(var);
563     InitializeVariables initializer(variables);
564     root->traverse(&initializer);
565 }
566
567 void TCompiler::initializeVaryingsWithoutStaticUse(TIntermNode* root)
568 {
569     InitializeVariables::InitVariableInfoList variables;
570     for (size_t ii = 0; ii < varyings.size(); ++ii)
571     {
572         const sh::Varying& varying = varyings[ii];
573         if (varying.staticUse)
574             continue;
575         unsigned char primarySize = static_cast<unsigned char>(gl::VariableColumnCount(varying.type));
576         unsigned char secondarySize = static_cast<unsigned char>(gl::VariableRowCount(varying.type));
577         TType type(EbtFloat, EbpUndefined, EvqVaryingOut, primarySize, secondarySize, varying.isArray());
578         TString name = varying.name.c_str();
579         if (varying.isArray())
580         {
581             type.setArraySize(varying.arraySize);
582             name = name.substr(0, name.find_first_of('['));
583         }
584
585         InitializeVariables::InitVariableInfo var(name, type);
586         variables.push_back(var);
587     }
588     InitializeVariables initializer(variables);
589     root->traverse(&initializer);
590 }
591
592 const TExtensionBehavior& TCompiler::getExtensionBehavior() const
593 {
594     return extensionBehavior;
595 }
596
597 const ShBuiltInResources& TCompiler::getResources() const
598 {
599     return compileResources;
600 }
601
602 const ArrayBoundsClamper& TCompiler::getArrayBoundsClamper() const
603 {
604     return arrayBoundsClamper;
605 }
606
607 ShArrayIndexClampingStrategy TCompiler::getArrayIndexClampingStrategy() const
608 {
609     return clampingStrategy;
610 }
611
612 const BuiltInFunctionEmulator& TCompiler::getBuiltInFunctionEmulator() const
613 {
614     return builtInFunctionEmulator;
615 }
616
617 void TCompiler::writePragma()
618 {
619     TInfoSinkBase &sink = infoSink.obj;
620     if (mPragma.stdgl.invariantAll)
621         sink << "#pragma STDGL invariant(all)\n";
622 }