LEFT | RIGHT |
1 // | 1 // |
2 // Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. | 2 // Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. |
3 // Use of this source code is governed by a BSD-style license that can be | 3 // Use of this source code is governed by a BSD-style license that can be |
4 // found in the LICENSE file. | 4 // found in the LICENSE file. |
5 // | 5 // |
6 | 6 |
7 #include "compiler/builtin_symbol_table.h" | 7 #include "compiler/builtin_symbol_table.h" |
8 #include "compiler/BuiltInFunctionEmulator.h" | 8 #include "compiler/BuiltInFunctionEmulator.h" |
9 #include "compiler/DetectRecursion.h" | 9 #include "compiler/DetectCallDepth.h" |
10 #include "compiler/ForLoopUnroll.h" | 10 #include "compiler/ForLoopUnroll.h" |
11 #include "compiler/Initialize.h" | 11 #include "compiler/Initialize.h" |
12 #include "compiler/InitializeParseContext.h" | 12 #include "compiler/InitializeParseContext.h" |
13 #include "compiler/MapLongVariableNames.h" | 13 #include "compiler/MapLongVariableNames.h" |
14 #include "compiler/ParseHelper.h" | 14 #include "compiler/ParseHelper.h" |
15 #include "compiler/RenameFunction.h" | 15 #include "compiler/RenameFunction.h" |
16 #include "compiler/ShHandle.h" | 16 #include "compiler/ShHandle.h" |
17 #include "compiler/ValidateLimitations.h" | 17 #include "compiler/ValidateLimitations.h" |
18 #include "compiler/VariablePacker.h" | 18 #include "compiler/VariablePacker.h" |
19 #include "compiler/depgraph/DependencyGraph.h" | 19 #include "compiler/depgraph/DependencyGraph.h" |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
99 } | 99 } |
100 | 100 |
101 TShHandleBase::~TShHandleBase() { | 101 TShHandleBase::~TShHandleBase() { |
102 SetGlobalPoolAllocator(NULL); | 102 SetGlobalPoolAllocator(NULL); |
103 allocator.popAll(); | 103 allocator.popAll(); |
104 } | 104 } |
105 | 105 |
106 TCompiler::TCompiler(ShShaderType type, ShShaderSpec spec) | 106 TCompiler::TCompiler(ShShaderType type, ShShaderSpec spec) |
107 : shaderType(type), | 107 : shaderType(type), |
108 shaderSpec(spec), | 108 shaderSpec(spec), |
| 109 maxUniformVectors(0), |
| 110 maxExpressionComplexity(0), |
| 111 maxCallStackDepth(0), |
109 fragmentPrecisionHigh(false), | 112 fragmentPrecisionHigh(false), |
110 clampingStrategy(SH_CLAMP_WITH_CLAMP_INTRINSIC), | 113 clampingStrategy(SH_CLAMP_WITH_CLAMP_INTRINSIC), |
111 builtInFunctionEmulator(type) | 114 builtInFunctionEmulator(type) |
112 { | 115 { |
113 longNameMap = LongNameMap::GetInstance(); | 116 longNameMap = LongNameMap::GetInstance(); |
114 } | 117 } |
115 | 118 |
116 TCompiler::~TCompiler() | 119 TCompiler::~TCompiler() |
117 { | 120 { |
118 ASSERT(longNameMap); | 121 ASSERT(longNameMap); |
119 longNameMap->Release(); | 122 longNameMap->Release(); |
120 } | 123 } |
121 | 124 |
122 bool TCompiler::Init(const ShBuiltInResources& resources) | 125 bool TCompiler::Init(const ShBuiltInResources& resources) |
123 { | 126 { |
124 maxUniformVectors = (shaderType == SH_VERTEX_SHADER) ? | 127 maxUniformVectors = (shaderType == SH_VERTEX_SHADER) ? |
125 resources.MaxVertexUniformVectors : | 128 resources.MaxVertexUniformVectors : |
126 resources.MaxFragmentUniformVectors; | 129 resources.MaxFragmentUniformVectors; |
| 130 maxExpressionComplexity = resources.MaxExpressionComplexity; |
| 131 maxCallStackDepth = resources.MaxCallStackDepth; |
127 TScopedPoolAllocator scopedAlloc(&allocator, false); | 132 TScopedPoolAllocator scopedAlloc(&allocator, false); |
128 | 133 |
129 // Generate built-in symbol table. | 134 // Generate built-in symbol table. |
130 if (!InitBuiltInSymbolTable(resources)) | 135 if (!InitBuiltInSymbolTable(resources)) |
131 return false; | 136 return false; |
132 | 137 |
133 InitExtensionBehavior(resources, extensionBehavior); | 138 InitExtensionBehavior(resources, extensionBehavior); |
134 fragmentPrecisionHigh = resources.FragmentPrecisionHigh == 1; | 139 fragmentPrecisionHigh = resources.FragmentPrecisionHigh == 1; |
135 | 140 |
136 arrayBoundsClamper.SetClampingStrategy(resources.ArrayIndexClampingStrategy)
; | 141 arrayBoundsClamper.SetClampingStrategy(resources.ArrayIndexClampingStrategy)
; |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
181 | 186 |
182 // Parse shader. | 187 // Parse shader. |
183 bool success = | 188 bool success = |
184 (PaParseStrings(numStrings - firstSource, &shaderStrings[firstSource], N
ULL, &parseContext) == 0) && | 189 (PaParseStrings(numStrings - firstSource, &shaderStrings[firstSource], N
ULL, &parseContext) == 0) && |
185 (parseContext.treeRoot != NULL); | 190 (parseContext.treeRoot != NULL); |
186 if (success) { | 191 if (success) { |
187 TIntermNode* root = parseContext.treeRoot; | 192 TIntermNode* root = parseContext.treeRoot; |
188 success = intermediate.postProcess(root); | 193 success = intermediate.postProcess(root); |
189 | 194 |
190 if (success) | 195 if (success) |
191 success = detectRecursion(root); | 196 success = detectCallDepth(root, infoSink, (compileOptions & SH_LIMIT
_CALL_STACK_DEPTH) != 0); |
192 | 197 |
193 if (success && (compileOptions & SH_VALIDATE_LOOP_INDEXING)) | 198 if (success && (compileOptions & SH_VALIDATE_LOOP_INDEXING)) |
194 success = validateLimitations(root); | 199 success = validateLimitations(root); |
195 | 200 |
196 if (success && (compileOptions & SH_TIMING_RESTRICTIONS)) | 201 if (success && (compileOptions & SH_TIMING_RESTRICTIONS)) |
197 success = enforceTimingRestrictions(root, (compileOptions & SH_DEPEN
DENCY_GRAPH) != 0); | 202 success = enforceTimingRestrictions(root, (compileOptions & SH_DEPEN
DENCY_GRAPH) != 0); |
198 | 203 |
199 if (success && shaderSpec == SH_CSS_SHADERS_SPEC) | 204 if (success && shaderSpec == SH_CSS_SHADERS_SPEC) |
200 rewriteCSSShader(root); | 205 rewriteCSSShader(root); |
201 | 206 |
202 // Unroll for-loop markup needs to happen after validateLimitations pass
. | 207 // Unroll for-loop markup needs to happen after validateLimitations pass
. |
203 if (success && (compileOptions & SH_UNROLL_FOR_LOOP_WITH_INTEGER_INDEX)) | 208 if (success && (compileOptions & SH_UNROLL_FOR_LOOP_WITH_INTEGER_INDEX)) |
204 ForLoopUnroll::MarkForLoopsWithIntegerIndicesForUnrolling(root); | 209 ForLoopUnroll::MarkForLoopsWithIntegerIndicesForUnrolling(root); |
205 | 210 |
206 // Built-in function emulation needs to happen after validateLimitations
pass. | 211 // Built-in function emulation needs to happen after validateLimitations
pass. |
207 if (success && (compileOptions & SH_EMULATE_BUILT_IN_FUNCTIONS)) | 212 if (success && (compileOptions & SH_EMULATE_BUILT_IN_FUNCTIONS)) |
208 builtInFunctionEmulator.MarkBuiltInFunctionsForEmulation(root); | 213 builtInFunctionEmulator.MarkBuiltInFunctionsForEmulation(root); |
209 | 214 |
210 // Clamping uniform array bounds needs to happen after validateLimitatio
ns pass. | 215 // Clamping uniform array bounds needs to happen after validateLimitatio
ns pass. |
211 if (success && (compileOptions & SH_CLAMP_INDIRECT_ARRAY_BOUNDS)) | 216 if (success && (compileOptions & SH_CLAMP_INDIRECT_ARRAY_BOUNDS)) |
212 arrayBoundsClamper.MarkIndirectArrayBoundsForClamping(root); | 217 arrayBoundsClamper.MarkIndirectArrayBoundsForClamping(root); |
| 218 |
| 219 // Disallow expressions deemed too complex. |
| 220 if (success && (compileOptions & SH_LIMIT_EXPRESSION_COMPLEXITY)) |
| 221 success = limitExpressionComplexity(root); |
213 | 222 |
214 // Call mapLongVariableNames() before collectAttribsUniforms() so in | 223 // Call mapLongVariableNames() before collectAttribsUniforms() so in |
215 // collectAttribsUniforms() we already have the mapped symbol names and | 224 // collectAttribsUniforms() we already have the mapped symbol names and |
216 // we could composite mapped and original variable names. | 225 // we could composite mapped and original variable names. |
217 // Also, if we hash all the names, then no need to do this for long name
s. | 226 // Also, if we hash all the names, then no need to do this for long name
s. |
218 if (success && (compileOptions & SH_MAP_LONG_VARIABLE_NAMES) && hashFunc
tion == NULL) | 227 if (success && (compileOptions & SH_MAP_LONG_VARIABLE_NAMES) && hashFunc
tion == NULL) |
219 mapLongVariableNames(root); | 228 mapLongVariableNames(root); |
220 | 229 |
221 if (success && (compileOptions & SH_ATTRIBUTES_UNIFORMS)) { | 230 if (success && (compileOptions & SH_ATTRIBUTES_UNIFORMS)) { |
222 collectAttribsUniforms(root); | 231 collectAttribsUniforms(root); |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
263 infoSink.debug.erase(); | 272 infoSink.debug.erase(); |
264 | 273 |
265 attribs.clear(); | 274 attribs.clear(); |
266 uniforms.clear(); | 275 uniforms.clear(); |
267 | 276 |
268 builtInFunctionEmulator.Cleanup(); | 277 builtInFunctionEmulator.Cleanup(); |
269 | 278 |
270 nameMap.clear(); | 279 nameMap.clear(); |
271 } | 280 } |
272 | 281 |
273 bool TCompiler::detectRecursion(TIntermNode* root) | 282 bool TCompiler::detectCallDepth(TIntermNode* root, TInfoSink& infoSink, bool lim
itCallStackDepth) |
274 { | 283 { |
275 DetectRecursion detect; | 284 DetectCallDepth detect(infoSink, limitCallStackDepth, maxCallStackDepth); |
276 root->traverse(&detect); | 285 root->traverse(&detect); |
277 switch (detect.detectRecursion()) { | 286 switch (detect.detectCallDepth()) { |
278 case DetectRecursion::kErrorNone: | 287 case DetectCallDepth::kErrorNone: |
279 return true; | 288 return true; |
280 case DetectRecursion::kErrorMissingMain: | 289 case DetectCallDepth::kErrorMissingMain: |
281 infoSink.info.prefix(EPrefixError); | 290 infoSink.info.prefix(EPrefixError); |
282 infoSink.info << "Missing main()"; | 291 infoSink.info << "Missing main()"; |
283 return false; | 292 return false; |
284 case DetectRecursion::kErrorRecursion: | 293 case DetectCallDepth::kErrorRecursion: |
285 infoSink.info.prefix(EPrefixError); | 294 infoSink.info.prefix(EPrefixError); |
286 infoSink.info << "Function recursion detected"; | 295 infoSink.info << "Function recursion detected"; |
| 296 return false; |
| 297 case DetectCallDepth::kErrorMaxDepthExceeded: |
| 298 infoSink.info.prefix(EPrefixError); |
| 299 infoSink.info << "Function call stack too deep"; |
287 return false; | 300 return false; |
288 default: | 301 default: |
289 UNREACHABLE(); | 302 UNREACHABLE(); |
290 return false; | 303 return false; |
291 } | 304 } |
292 } | 305 } |
293 | 306 |
294 void TCompiler::rewriteCSSShader(TIntermNode* root) | 307 void TCompiler::rewriteCSSShader(TIntermNode* root) |
295 { | 308 { |
296 RenameFunction renamer("main(", "css_main("); | 309 RenameFunction renamer("main(", "css_main("); |
(...skipping 25 matching lines...) Expand all Loading... |
322 output.outputAllSpanningTrees(graph); | 335 output.outputAllSpanningTrees(graph); |
323 } | 336 } |
324 ········ | 337 ········ |
325 return success; | 338 return success; |
326 } | 339 } |
327 else { | 340 else { |
328 return enforceVertexShaderTimingRestrictions(root); | 341 return enforceVertexShaderTimingRestrictions(root); |
329 } | 342 } |
330 } | 343 } |
331 | 344 |
| 345 bool TCompiler::limitExpressionComplexity(TIntermNode* root) |
| 346 { |
| 347 TIntermTraverser traverser; |
| 348 root->traverse(&traverser); |
| 349 TDependencyGraph graph(root); |
| 350 |
| 351 for (TFunctionCallVector::const_iterator iter = graph.beginUserDefinedFuncti
onCalls(); |
| 352 iter != graph.endUserDefinedFunctionCalls(); |
| 353 ++iter) |
| 354 { |
| 355 TGraphFunctionCall* samplerSymbol = *iter; |
| 356 TDependencyGraphTraverser graphTraverser; |
| 357 samplerSymbol->traverse(&graphTraverser); |
| 358 } |
| 359 |
| 360 if (traverser.getMaxDepth() > maxExpressionComplexity) { |
| 361 infoSink.info << "Expression too complex."; |
| 362 return false; |
| 363 } |
| 364 return true; |
| 365 } |
| 366 |
332 bool TCompiler::enforceFragmentShaderTimingRestrictions(const TDependencyGraph&
graph) | 367 bool TCompiler::enforceFragmentShaderTimingRestrictions(const TDependencyGraph&
graph) |
333 { | 368 { |
334 RestrictFragmentShaderTiming restrictor(infoSink.info); | 369 RestrictFragmentShaderTiming restrictor(infoSink.info); |
335 restrictor.enforceRestrictions(graph); | 370 restrictor.enforceRestrictions(graph); |
336 return restrictor.numErrors() == 0; | 371 return restrictor.numErrors() == 0; |
337 } | 372 } |
338 | 373 |
339 bool TCompiler::enforceVertexShaderTimingRestrictions(TIntermNode* root) | 374 bool TCompiler::enforceVertexShaderTimingRestrictions(TIntermNode* root) |
340 { | 375 { |
341 RestrictVertexShaderTiming restrictor(infoSink.info); | 376 RestrictVertexShaderTiming restrictor(infoSink.info); |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
379 | 414 |
380 ShArrayIndexClampingStrategy TCompiler::getArrayIndexClampingStrategy() const | 415 ShArrayIndexClampingStrategy TCompiler::getArrayIndexClampingStrategy() const |
381 { | 416 { |
382 return clampingStrategy; | 417 return clampingStrategy; |
383 } | 418 } |
384 | 419 |
385 const BuiltInFunctionEmulator& TCompiler::getBuiltInFunctionEmulator() const | 420 const BuiltInFunctionEmulator& TCompiler::getBuiltInFunctionEmulator() const |
386 { | 421 { |
387 return builtInFunctionEmulator; | 422 return builtInFunctionEmulator; |
388 } | 423 } |
LEFT | RIGHT |