Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / third_party / angle / tests / compiler_tests / ExpressionLimit_test.cpp
1 //
2 // Copyright (c) 2002-2013 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 #include <sstream>
7 #include <string>
8 #include <vector>
9 #include "angle_gl.h"
10 #include "gtest/gtest.h"
11 #include "GLSLANG/ShaderLang.h"
12
13 #define SHADER(Src) #Src
14
15 class ExpressionLimitTest : public testing::Test {
16 protected:
17     static const int kMaxExpressionComplexity = 16;
18     static const int kMaxCallStackDepth = 16;
19     static const char* kExpressionTooComplex;
20     static const char* kCallStackTooDeep;
21     static const char* kHasRecursion;
22
23     virtual void SetUp()
24     {
25         memset(&resources, 0, sizeof(resources));
26
27         GenerateResources(&resources);
28     }
29
30     // Set up the per compile resources
31     void GenerateResources(ShBuiltInResources* resources)
32     {
33         ShInitBuiltInResources(resources);
34
35         resources->MaxVertexAttribs = 8;
36         resources->MaxVertexUniformVectors = 128;
37         resources->MaxVaryingVectors = 8;
38         resources->MaxVertexTextureImageUnits = 0;
39         resources->MaxCombinedTextureImageUnits = 8;
40         resources->MaxTextureImageUnits = 8;
41         resources->MaxFragmentUniformVectors = 16;
42         resources->MaxDrawBuffers = 1;
43
44         resources->OES_standard_derivatives = 0;
45         resources->OES_EGL_image_external = 0;
46
47         resources->MaxExpressionComplexity = kMaxExpressionComplexity;
48         resources->MaxCallStackDepth = kMaxCallStackDepth;
49     }
50
51     void GenerateLongExpression(int length, std::stringstream* ss)
52     {
53         for (int ii = 0; ii < length; ++ii) {
54           *ss << "+ vec4(" << ii << ")";
55         }
56     }
57
58     std::string GenerateShaderWithLongExpression(int length)
59     {
60         static const char* shaderStart = SHADER(
61             precision mediump float;
62             uniform vec4 u_color;
63             void main()
64             {
65                gl_FragColor = u_color
66         );
67
68         std::stringstream ss;
69         ss << shaderStart;
70         GenerateLongExpression(length, &ss);
71         ss << "; }";
72
73         return ss.str();
74     }
75
76     std::string GenerateShaderWithUnusedLongExpression(int length)
77     {
78         static const char* shaderStart = SHADER(
79             precision mediump float;
80             uniform vec4 u_color;
81             void main()
82             {
83                gl_FragColor = u_color;
84             }
85             vec4 someFunction() {
86               return u_color
87         );
88
89         std::stringstream ss;
90
91         ss << shaderStart;
92         GenerateLongExpression(length, &ss);
93         ss << "; }";
94
95         return ss.str();
96     }
97
98     void GenerateDeepFunctionStack(int length, std::stringstream* ss)
99     {
100         static const char* shaderStart = SHADER(
101             precision mediump float;
102             uniform vec4 u_color;
103             vec4 function0()  {
104               return u_color;
105             }
106         );
107
108         *ss << shaderStart;
109         for (int ii = 0; ii < length; ++ii) {
110           *ss << "vec4 function" << (ii + 1) << "() {\n"
111               << "  return function" << ii << "();\n"
112               << "}\n";
113         }
114     }
115
116     std::string GenerateShaderWithDeepFunctionStack(int length)
117     {
118         std::stringstream ss;
119
120         GenerateDeepFunctionStack(length, &ss);
121
122         ss << "void main() {\n"
123            << "  gl_FragColor = function" << length << "();\n"
124            << "}";
125
126         return ss.str();
127     }
128
129     std::string GenerateShaderWithUnusedDeepFunctionStack(int length)
130     {
131         std::stringstream ss;
132
133         GenerateDeepFunctionStack(length, &ss);
134
135         ss << "void main() {\n"
136            << "  gl_FragColor = vec4(0,0,0,0);\n"
137            << "}";
138
139
140         return ss.str();
141     }
142
143     // Compiles a shader and if there's an error checks for a specific
144     // substring in the error log. This way we know the error is specific
145     // to the issue we are testing.
146     bool CheckShaderCompilation(ShHandle compiler,
147                                 const char *source,
148                                 int compileOptions,
149                                 const char *expected_error)
150     {
151         bool success = ShCompile(compiler, &source, 1, compileOptions) != 0;
152         if (success)
153         {
154             success = !expected_error;
155         }
156         else
157         {
158             std::string log = ShGetInfoLog(compiler);
159             if (expected_error)
160                 success = log.find(expected_error) != std::string::npos;
161
162             EXPECT_TRUE(success) << log << "\n----shader----\n" << source;
163         }
164         return success;
165     }
166
167     ShBuiltInResources resources;
168 };
169
170 const char* ExpressionLimitTest::kExpressionTooComplex =
171     "Expression too complex";
172 const char* ExpressionLimitTest::kCallStackTooDeep =
173     "call stack too deep";
174 const char* ExpressionLimitTest::kHasRecursion =
175     "Function recursion detected";
176
177 TEST_F(ExpressionLimitTest, ExpressionComplexity)
178 {
179     ShShaderSpec spec = SH_WEBGL_SPEC;
180     ShShaderOutput output = SH_ESSL_OUTPUT;
181     ShHandle vertexCompiler = ShConstructCompiler(
182         GL_FRAGMENT_SHADER, spec, output, &resources);
183     int compileOptions = SH_LIMIT_EXPRESSION_COMPLEXITY;
184
185     // Test expression under the limit passes.
186     EXPECT_TRUE(CheckShaderCompilation(
187         vertexCompiler,
188         GenerateShaderWithLongExpression(
189             kMaxExpressionComplexity - 10).c_str(),
190         compileOptions, NULL));
191     // Test expression over the limit fails.
192     EXPECT_TRUE(CheckShaderCompilation(
193         vertexCompiler,
194         GenerateShaderWithLongExpression(
195             kMaxExpressionComplexity + 10).c_str(),
196         compileOptions, kExpressionTooComplex));
197     // Test expression over the limit without a limit does not fail.
198     EXPECT_TRUE(CheckShaderCompilation(
199         vertexCompiler,
200         GenerateShaderWithLongExpression(
201             kMaxExpressionComplexity + 10).c_str(),
202         compileOptions & ~SH_LIMIT_EXPRESSION_COMPLEXITY, NULL));
203     ShDestruct(vertexCompiler);
204 }
205
206 TEST_F(ExpressionLimitTest, UnusedExpressionComplexity)
207 {
208     ShShaderSpec spec = SH_WEBGL_SPEC;
209     ShShaderOutput output = SH_ESSL_OUTPUT;
210     ShHandle vertexCompiler = ShConstructCompiler(
211         GL_FRAGMENT_SHADER, spec, output, &resources);
212     int compileOptions = SH_LIMIT_EXPRESSION_COMPLEXITY;
213
214     // Test expression under the limit passes.
215     EXPECT_TRUE(CheckShaderCompilation(
216         vertexCompiler,
217         GenerateShaderWithUnusedLongExpression(
218             kMaxExpressionComplexity - 10).c_str(),
219         compileOptions, NULL));
220     // Test expression over the limit fails.
221     EXPECT_TRUE(CheckShaderCompilation(
222         vertexCompiler,
223         GenerateShaderWithUnusedLongExpression(
224             kMaxExpressionComplexity + 10).c_str(),
225         compileOptions, kExpressionTooComplex));
226     // Test expression over the limit without a limit does not fail.
227     EXPECT_TRUE(CheckShaderCompilation(
228         vertexCompiler,
229         GenerateShaderWithUnusedLongExpression(
230             kMaxExpressionComplexity + 10).c_str(),
231         compileOptions & ~SH_LIMIT_EXPRESSION_COMPLEXITY, NULL));
232     ShDestruct(vertexCompiler);
233 }
234
235 TEST_F(ExpressionLimitTest, CallStackDepth)
236 {
237     ShShaderSpec spec = SH_WEBGL_SPEC;
238     ShShaderOutput output = SH_ESSL_OUTPUT;
239     ShHandle vertexCompiler = ShConstructCompiler(
240         GL_FRAGMENT_SHADER, spec, output, &resources);
241     int compileOptions = SH_LIMIT_CALL_STACK_DEPTH;
242
243     // Test call stack under the limit passes.
244     EXPECT_TRUE(CheckShaderCompilation(
245         vertexCompiler,
246         GenerateShaderWithDeepFunctionStack(
247             kMaxCallStackDepth - 10).c_str(),
248         compileOptions, NULL));
249     // Test call stack over the limit fails.
250     EXPECT_TRUE(CheckShaderCompilation(
251         vertexCompiler,
252         GenerateShaderWithDeepFunctionStack(
253             kMaxCallStackDepth + 10).c_str(),
254         compileOptions, kCallStackTooDeep));
255     // Test call stack over the limit without limit does not fail.
256     EXPECT_TRUE(CheckShaderCompilation(
257         vertexCompiler,
258         GenerateShaderWithDeepFunctionStack(
259             kMaxCallStackDepth + 10).c_str(),
260         compileOptions & ~SH_LIMIT_CALL_STACK_DEPTH, NULL));
261     ShDestruct(vertexCompiler);
262 }
263
264 TEST_F(ExpressionLimitTest, UnusedCallStackDepth)
265 {
266     ShShaderSpec spec = SH_WEBGL_SPEC;
267     ShShaderOutput output = SH_ESSL_OUTPUT;
268     ShHandle vertexCompiler = ShConstructCompiler(
269         GL_FRAGMENT_SHADER, spec, output, &resources);
270     int compileOptions = SH_LIMIT_CALL_STACK_DEPTH;
271
272     // Test call stack under the limit passes.
273     EXPECT_TRUE(CheckShaderCompilation(
274         vertexCompiler,
275         GenerateShaderWithUnusedDeepFunctionStack(
276             kMaxCallStackDepth - 10).c_str(),
277         compileOptions, NULL));
278     // Test call stack over the limit fails.
279     EXPECT_TRUE(CheckShaderCompilation(
280         vertexCompiler,
281         GenerateShaderWithUnusedDeepFunctionStack(
282             kMaxCallStackDepth + 10).c_str(),
283         compileOptions, kCallStackTooDeep));
284     // Test call stack over the limit without limit does not fail.
285     EXPECT_TRUE(CheckShaderCompilation(
286         vertexCompiler,
287         GenerateShaderWithUnusedDeepFunctionStack(
288             kMaxCallStackDepth + 10).c_str(),
289         compileOptions & ~SH_LIMIT_CALL_STACK_DEPTH, NULL));
290     ShDestruct(vertexCompiler);
291 }
292
293 TEST_F(ExpressionLimitTest, Recursion)
294 {
295     ShShaderSpec spec = SH_WEBGL_SPEC;
296     ShShaderOutput output = SH_ESSL_OUTPUT;
297     ShHandle vertexCompiler = ShConstructCompiler(
298         GL_FRAGMENT_SHADER, spec, output, &resources);
299     int compileOptions = 0;
300
301     static const char* shaderWithRecursion0 = SHADER(
302         precision mediump float;
303         uniform vec4 u_color;
304         vec4 someFunc()  {
305             return someFunc();
306         }
307
308         void main() {
309             gl_FragColor = u_color * someFunc();
310         }
311     );
312
313     static const char* shaderWithRecursion1 = SHADER(
314         precision mediump float;
315         uniform vec4 u_color;
316
317         vec4 someFunc();
318
319         vec4 someFunc1()  {
320             return someFunc();
321         }
322
323         vec4 someFunc()  {
324             return someFunc1();
325         }
326
327         void main() {
328             gl_FragColor = u_color * someFunc();
329         }
330     );
331
332     static const char* shaderWithRecursion2 = SHADER(
333         precision mediump float;
334         uniform vec4 u_color;
335         vec4 someFunc()  {
336             if (u_color.x > 0.5) {
337                 return someFunc();
338             } else {
339                 return vec4(1);
340             }
341         }
342
343         void main() {
344             gl_FragColor = someFunc();
345         }
346     );
347
348     static const char* shaderWithRecursion3 = SHADER(
349         precision mediump float;
350         uniform vec4 u_color;
351         vec4 someFunc()  {
352             if (u_color.x > 0.5) {
353                 return vec4(1);
354             } else {
355                 return someFunc();
356             }
357         }
358
359         void main() {
360             gl_FragColor = someFunc();
361         }
362     );
363
364     static const char* shaderWithRecursion4 = SHADER(
365         precision mediump float;
366         uniform vec4 u_color;
367         vec4 someFunc()  {
368             return (u_color.x > 0.5) ? vec4(1) : someFunc();
369         }
370
371         void main() {
372             gl_FragColor = someFunc();
373         }
374     );
375
376     static const char* shaderWithRecursion5 = SHADER(
377         precision mediump float;
378         uniform vec4 u_color;
379         vec4 someFunc()  {
380             return (u_color.x > 0.5) ? someFunc() : vec4(1);
381         }
382
383         void main() {
384             gl_FragColor = someFunc();
385         }
386     );
387
388     static const char* shaderWithRecursion6 = SHADER(
389         precision mediump float;
390         uniform vec4 u_color;
391         vec4 someFunc()  {
392             return someFunc();
393         }
394
395         void main() {
396             gl_FragColor = u_color;
397         }
398     );
399
400     static const char* shaderWithNoRecursion = SHADER(
401         precision mediump float;
402         uniform vec4 u_color;
403
404         vec3 rgb(int r, int g, int b) {
405             return vec3(float(r) / 255.0, float(g) / 255.0, float(b) / 255.0);
406         }
407
408         // these external calls used to incorrectly trigger
409         // recursion detection.
410         vec3 hairColor0 = rgb(151, 200, 234);
411         vec3 faceColor2 = rgb(183, 148, 133);
412
413         void main() {
414             gl_FragColor = u_color + vec4(hairColor0 + faceColor2, 0);
415         }
416     );
417
418     static const char* shaderWithRecursion7 = SHADER(
419         precision mediump float;
420         uniform vec4 u_color;
421
422         vec4 function2() {
423             return u_color;
424         }
425
426         vec4 function1() {
427             vec4 a = function2();
428             vec4 b = function1();
429             return a + b;
430         }
431
432         void main() {
433             gl_FragColor = function1();
434         }
435     );
436
437     static const char* shaderWithRecursion8 = SHADER(
438         precision mediump float;
439         uniform vec4 u_color;
440
441         vec4 function1();
442
443         vec4 function3() {
444             return function1();
445         }
446
447         vec4 function2() {
448             return function3();
449         }
450
451         vec4 function1() {
452             return function2();
453         }
454
455         void main() {
456             gl_FragColor = function1();
457         }
458     );
459
460     // Check simple recursions fails.
461     EXPECT_TRUE(CheckShaderCompilation(
462         vertexCompiler, shaderWithRecursion0,
463         compileOptions, kHasRecursion));
464     // Check simple recursions fails.
465     EXPECT_TRUE(CheckShaderCompilation(
466         vertexCompiler, shaderWithRecursion1,
467         compileOptions, kHasRecursion));
468     // Check if recursions fails.
469     EXPECT_TRUE(CheckShaderCompilation(
470         vertexCompiler, shaderWithRecursion2,
471         compileOptions, kHasRecursion));
472     // Check if recursions fails.
473     EXPECT_TRUE(CheckShaderCompilation(
474         vertexCompiler, shaderWithRecursion3,
475         compileOptions, kHasRecursion));
476     // Check ternary recursions fails.
477     EXPECT_TRUE(CheckShaderCompilation(
478         vertexCompiler, shaderWithRecursion4,
479         compileOptions, kHasRecursion));
480     // Check ternary recursions fails.
481     EXPECT_TRUE(CheckShaderCompilation(
482         vertexCompiler, shaderWithRecursion5,
483         compileOptions, kHasRecursion));
484     // Check unused recursions passes.
485     EXPECT_TRUE(CheckShaderCompilation(
486         vertexCompiler, shaderWithRecursion6,
487         compileOptions, NULL));
488     EXPECT_TRUE(CheckShaderCompilation(
489         vertexCompiler, shaderWithRecursion7,
490         compileOptions, kHasRecursion));
491     EXPECT_TRUE(CheckShaderCompilation(
492         vertexCompiler, shaderWithRecursion8,
493         compileOptions, kHasRecursion));
494     // Check unused recursions fails if limiting call stack
495     // since we check all paths.
496     EXPECT_TRUE(CheckShaderCompilation(
497         vertexCompiler, shaderWithRecursion6,
498         compileOptions | SH_LIMIT_CALL_STACK_DEPTH, kHasRecursion));
499
500     // Check unused recursions passes.
501     EXPECT_TRUE(CheckShaderCompilation(
502         vertexCompiler, shaderWithNoRecursion,
503         compileOptions, NULL));
504     // Check unused recursions passes if limiting call stack.
505     EXPECT_TRUE(CheckShaderCompilation(
506         vertexCompiler, shaderWithNoRecursion,
507         compileOptions | SH_LIMIT_CALL_STACK_DEPTH, NULL));
508     ShDestruct(vertexCompiler);
509 }
510