Backed out changeset 7272b7396c78 (bug 1932758) for causing fenix debug failures...
[gecko.git] / dom / canvas / test / webgl-conf / checkout / deqp / functional / gles3 / es3fShaderLoopTests.js
blob822b121bda6acd9fafa38c36625434cb6e48cfd0
1 /*-------------------------------------------------------------------------
2  * drawElements Quality Program OpenGL ES Utilities
3  * ------------------------------------------------
4  *
5  * Copyright 2014 The Android Open Source Project
6  *
7  * Licensed under the Apache License, Version 2.0 (the 'License');
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an 'AS IS' BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  */
21 'use strict';
22 goog.provide('functional.gles3.es3fShaderLoopTests');
23 goog.require('framework.common.tcuStringTemplate');
24 goog.require('framework.common.tcuTestCase');
25 goog.require('framework.delibs.debase.deMath');
26 goog.require('framework.opengl.gluShaderUtil');
27 goog.require('framework.opengl.gluShaderProgram');
28 goog.require('modules.shared.glsShaderRenderCase');
30 goog.scope(function() {
31 var es3fShaderLoopTests = functional.gles3.es3fShaderLoopTests;
32 var tcuTestCase = framework.common.tcuTestCase;
33 var deMath = framework.delibs.debase.deMath;
34 var gluShaderUtil = framework.opengl.gluShaderUtil;
35 var gluShaderProgram = framework.opengl.gluShaderProgram;
36 var glsShaderRenderCase = modules.shared.glsShaderRenderCase;
37 var tcuStringTemplate = framework.common.tcuStringTemplate;
38 // Repeated with for, while, do-while. Examples given as 'for' loops.
39 // Repeated for const, uniform, dynamic loops.
41 /**
42  * @enum {number}
43  */
44 es3fShaderLoopTests.LoopCase = {
45     LOOPCASE_EMPTY_BODY: 0,                                // for (...) { }
46     LOOPCASE_INFINITE_WITH_UNCONDITIONAL_BREAK_FIRST: 1,        // for (...) { break; <body>; }
47     LOOPCASE_INFINITE_WITH_UNCONDITIONAL_BREAK_LAST: 2,        // for (...) { <body>; break; }
48     LOOPCASE_INFINITE_WITH_CONDITIONAL_BREAK: 3,                // for (...) { <body>; if (cond) break; }
49     LOOPCASE_SINGLE_STATEMENT: 4,                                // for (...) statement;
50     LOOPCASE_COMPOUND_STATEMENT: 5,                            // for (...) { statement; statement; }
51     LOOPCASE_SEQUENCE_STATEMENT: 6,                            // for (...) statement, statement;
52     LOOPCASE_NO_ITERATIONS: 7,                                    // for (i=0; i<0; i++) ...
53     LOOPCASE_SINGLE_ITERATION: 8,                                // for (i=0; i<1; i++) ...
54     LOOPCASE_SELECT_ITERATION_COUNT: 9,                        // for (i=0; i<a?b:c; i++) ...
55     LOOPCASE_CONDITIONAL_CONTINUE: 10,                            // for (...) { if (cond) continue; }
56     LOOPCASE_UNCONDITIONAL_CONTINUE: 11,                        // for (...) { <body>; continue; }
57     LOOPCASE_ONLY_CONTINUE: 12,                                    // for (...) { continue; }
58     LOOPCASE_DOUBLE_CONTINUE: 13,                                // for (...) { if (cond) continue; <body>; continue; }
59     LOOPCASE_CONDITIONAL_BREAK: 14,                                // for (...) { if (cond) break; }
60     LOOPCASE_UNCONDITIONAL_BREAK: 15,                            // for (...) { <body>; break; }
61     LOOPCASE_PRE_INCREMENT: 16,                                    // for (...; ++i) { <body>; }
62     LOOPCASE_POST_INCREMENT: 17,                                // for (...; i++) { <body>; }
63     LOOPCASE_MIXED_BREAK_CONTINUE: 18,
64     LOOPCASE_VECTOR_COUNTER: 19,                                // for (ivec3 ndx = ...; ndx.x < ndx.y; ndx.x += ndx.z) { ... }
65     LOOPCASE_101_ITERATIONS: 20,                                // loop for 101 iterations
66     LOOPCASE_SEQUENCE: 21,                                        // two loops in sequence
67     LOOPCASE_NESTED: 22,                                        // two nested loops
68     LOOPCASE_NESTED_SEQUENCE: 23,                                // two loops in sequence nested inside a third
69     LOOPCASE_NESTED_TRICKY_DATAFLOW_1: 24,                        // nested loops with tricky data flow
70     LOOPCASE_NESTED_TRICKY_DATAFLOW_2: 25                        // nested loops with tricky data flow
73 /**
74  * @param {es3fShaderLoopTests.LoopCase} loopCase
75  * @return {string}
76  */
77 es3fShaderLoopTests.getLoopCaseName = function(loopCase) {
78     /** @type {Array<string>} */ var s_names = [
79         'empty_body',
80         'infinite_with_unconditional_break_first',
81         'infinite_with_unconditional_break_last',
82         'infinite_with_conditional_break',
83         'single_statement',
84         'compound_statement',
85         'sequence_statement',
86         'no_iterations',
87         'single_iteration',
88         'select_iteration_count',
89         'conditional_continue',
90         'unconditional_continue',
91         'only_continue',
92         'double_continue',
93         'conditional_break',
94         'unconditional_break',
95         'pre_increment',
96         'post_increment',
97         'mixed_break_continue',
98         'vector_counter',
99         '101_iterations',
100         'sequence',
101         'nested',
102         'nested_sequence',
103         'nested_tricky_dataflow_1',
104         'nested_tricky_dataflow_2'
105     ];
106     // DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(s_names) == es3fShaderLoopTests.LoopCase.LOOPCASE_LAST);
107     // DE_ASSERT(deInBounds32((int)loopCase, 0, LOOPCASE_LAST));
108     return s_names[loopCase];
111 // Complex loop cases.
113 /*enum LoopBody
115     LOOPBODY_READ_UNIFORM = 0,
116     LOOPBODY_READ_UNIFORM_ARRAY,
117     LOOPBODY_READ_
118 };*/
121  * @enum {number}
122  */
123 es3fShaderLoopTests.LoopType = {
124     LOOPTYPE_FOR: 0,
125     LOOPTYPE_WHILE: 1,
126     LOOPTYPE_DO_WHILE: 2
130  * @param {es3fShaderLoopTests.LoopType} loopType
131  * @return {string}
132  */
133 es3fShaderLoopTests.getLoopTypeName = function(loopType) {
134     /** @type {Array<string>} */ var s_names = [
135         'for',
136         'while',
137         'do_while'
138     ];
140     // DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(s_names) === es3fShaderLoopTests.LoopType.LOOPTYPE_LAST);
141     // DE_ASSERT(deInBounds32((int)loopType, 0, LOOPTYPE_LAST));
142     return s_names[loopType];
146  * @enum {number}
147  */
148 es3fShaderLoopTests.LoopCountType = {
149     LOOPCOUNT_CONSTANT: 0,
150     LOOPCOUNT_UNIFORM: 1,
151     LOOPCOUNT_DYNAMIC: 2
155  * @param {es3fShaderLoopTests.LoopCountType} countType
156  * @return {string}
157  */
158 es3fShaderLoopTests.getLoopCountTypeName = function(countType) {
159     /** @type {Array<string>} */ var s_names =    [
160         'constant',
161         'uniform',
162         'dynamic'
163     ];
165     // DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(s_names) == es3fShaderLoopTests.LoopCountType.LOOPCOUNT_LAST);
166     // DE_ASSERT(deInBounds32((int)countType, 0, es3fShaderLoopTests.LoopCountType.LOOPCOUNT_LAST));
167     return s_names[countType];
171  * @param {glsShaderRenderCase.ShaderEvalContext} c
172  */
173 es3fShaderLoopTests.evalLoop0Iters = function(c) {
174     var swizzled = deMath.swizzle(c.coords, [0, 1, 2]);
175     c.color[0] = swizzled[0];
176     c.color[1] = swizzled[1];
177     c.color[2] = swizzled[2];
181  * @param {glsShaderRenderCase.ShaderEvalContext} c
182  */
183 es3fShaderLoopTests.evalLoop1Iters = function(c) {
184     var swizzled = deMath.swizzle(c.coords, [1, 2, 3]);
185     c.color[0] = swizzled[0];
186     c.color[1] = swizzled[1];
187     c.color[2] = swizzled[2];
191  * @param {glsShaderRenderCase.ShaderEvalContext} c
192  */
193 es3fShaderLoopTests.evalLoop2Iters = function(c) {
194     var swizzled = deMath.swizzle(c.coords, [2, 3, 0]);
195     c.color[0] = swizzled[0];
196     c.color[1] = swizzled[1];
197     c.color[2] = swizzled[2];
201  * @param {glsShaderRenderCase.ShaderEvalContext} c
202  */
203 es3fShaderLoopTests.evalLoop3Iters = function(c) {
204     var swizzled = deMath.swizzle(c.coords, [3, 0, 1]);
205     c.color[0] = swizzled[0];
206     c.color[1] = swizzled[1];
207     c.color[2] = swizzled[2];
211  * @param {number} numIters
212  * @return {glsShaderRenderCase.ShaderEvalFunc}
213  */
214 es3fShaderLoopTests.getLoopEvalFunc = function(numIters) {
215     switch (numIters % 4) {
216         case 0: return es3fShaderLoopTests.evalLoop0Iters;
217         case 1:    return es3fShaderLoopTests.evalLoop1Iters;
218         case 2:    return es3fShaderLoopTests.evalLoop2Iters;
219         case 3:    return es3fShaderLoopTests.evalLoop3Iters;
220     }
222     throw new Error('Invalid loop iteration count.');
225 // ShaderLoopCase
228  * @constructor
229  * @extends {glsShaderRenderCase.ShaderRenderCase}
230  * @param {string} name
231  * @param {string} description
232  * @param {boolean} isVertexCase
233  * @param {glsShaderRenderCase.ShaderEvalFunc} evalFunc
234  * @param {string} vertShaderSource
235  * @param {string} fragShaderSource
236  */
237 es3fShaderLoopTests.ShaderLoopCase = function(name, description, isVertexCase, evalFunc, vertShaderSource, fragShaderSource) {
238     glsShaderRenderCase.ShaderRenderCase.call(this, name, description, isVertexCase, evalFunc);
239     /** @type {string} */ this.m_vertShaderSource = vertShaderSource;
240     /** @type {string} */ this.m_fragShaderSource = fragShaderSource;
243 es3fShaderLoopTests.ShaderLoopCase.prototype = Object.create(glsShaderRenderCase.ShaderRenderCase.prototype);
244 es3fShaderLoopTests.ShaderLoopCase.prototype.constructor = es3fShaderLoopTests.ShaderLoopCase;
246 // Test case creation.
249  * @param {string} caseName
250  * @param {string} description
251  * @param {boolean} isVertexCase
252  * @param {es3fShaderLoopTests.LoopType} loopType
253  * @param {es3fShaderLoopTests.LoopCountType} loopCountType
254  * @param {gluShaderUtil.precision} loopCountPrecision
255  * @param {gluShaderUtil.DataType} loopCountDataType
256  * @return {es3fShaderLoopTests.ShaderLoopCase}
257  */
258 es3fShaderLoopTests.createGenericLoopCase = function(caseName, description, isVertexCase, loopType, loopCountType, loopCountPrecision, loopCountDataType) {
259         /** @type {string} */ var vtx = '';
260     /** @type {string} */ var frag = '';
261     /** @type {string} */ var op = '';
263         vtx += '#version 300 es\n';
264         frag += '#version 300 es\n';
266         vtx += 'in highp vec4 a_position;\n';
267         vtx += 'in highp vec4 a_coords;\n';
268         frag += 'layout(location = 0) out mediump vec4 o_color;\n';
270         if (loopCountType === es3fShaderLoopTests.LoopCountType.LOOPCOUNT_DYNAMIC)
271                 vtx += 'in mediump float a_one;\n';
273         if (isVertexCase) {
274                 vtx += 'out mediump vec3 v_color;\n';
275                 frag += 'in mediump vec3 v_color;\n';
276         }
277         else {
278                 vtx += 'out mediump vec4 v_coords;\n';
279                 frag += 'in mediump vec4 v_coords;\n';
281                 if (loopCountType === es3fShaderLoopTests.LoopCountType.LOOPCOUNT_DYNAMIC) {
282                         vtx += 'out mediump float v_one;\n';
283                         frag += 'in mediump float v_one;\n';
284                 }
285         }
287         // \todo [petri] Pass numLoopIters from outside?
288         /** @type {number} */ var numLoopIters = 3;
289     /** @type {boolean} */ var isIntCounter = gluShaderUtil.isDataTypeIntOrIVec(loopCountDataType);
291         if (isIntCounter) {
292                 if (loopCountType === es3fShaderLoopTests.LoopCountType.LOOPCOUNT_UNIFORM || loopCountType === es3fShaderLoopTests.LoopCountType.LOOPCOUNT_DYNAMIC)
293                         op += 'uniform ${COUNTER_PRECISION} int ' + glsShaderRenderCase.getIntUniformName(numLoopIters) + ';\n';
294         }
295         else {
296                 if (loopCountType === es3fShaderLoopTests.LoopCountType.LOOPCOUNT_UNIFORM || loopCountType === es3fShaderLoopTests.LoopCountType.LOOPCOUNT_DYNAMIC)
297                         op += 'uniform ${COUNTER_PRECISION} float ' + glsShaderRenderCase.getFloatFractionUniformName(numLoopIters) + ';\n';
299                 if (numLoopIters != 1)
300                         op += 'uniform ${COUNTER_PRECISION} float uf_one;\n';
301         }
303         vtx += isVertexCase ? op : '';
304         frag += isVertexCase ? '' : op;
305         op = '';
307         vtx += "\n" +
308                "void main()\n" +
309                "{\n" +
310                "        gl_Position = a_position;\n";
312         frag += "\n" +
313                 "void main()\n" +
314                 "{\n";
316         if (isVertexCase)
317                 vtx += '        ${PRECISION} vec4 coords = a_coords;\n';
318         else
319                 frag += '       ${PRECISION} vec4 coords = v_coords;\n';
321         if (loopCountType === es3fShaderLoopTests.LoopCountType.LOOPCOUNT_DYNAMIC) {
322                 if (isIntCounter) {
323                         if (isVertexCase)
324                                 vtx += '        ${COUNTER_PRECISION} int one = int(a_one + 0.5);\n';
325                         else
326                                 frag += '       ${COUNTER_PRECISION} int one = int(v_one + 0.5);\n';
327                 }
328                 else {
329                         if (isVertexCase)
330                                 vtx += '        ${COUNTER_PRECISION} float one = a_one;\n';
331                         else
332                                 frag += '       ${COUNTER_PRECISION} float one = v_one;\n';
333                 }
334         }
336         // Read array.
337         op += ' ${PRECISION} vec4 res = coords;\n';
339         // Loop iteration count.
340         /** @type {string} */ var iterMaxStr;
342         if (isIntCounter) {
343                 if (loopCountType === es3fShaderLoopTests.LoopCountType.LOOPCOUNT_CONSTANT)
344                         iterMaxStr = numLoopIters.toString();
345                 else if (loopCountType === es3fShaderLoopTests.LoopCountType.LOOPCOUNT_UNIFORM)
346                         iterMaxStr = glsShaderRenderCase.getIntUniformName(numLoopIters);
347                 else if (loopCountType === es3fShaderLoopTests.LoopCountType.LOOPCOUNT_DYNAMIC)
348                         iterMaxStr = glsShaderRenderCase.getIntUniformName(numLoopIters) + '*one';
349                 else
350                         throw new Error('Loop Count Type not supported: ' + loopCountType);
351         }
352         else {
353                 if (loopCountType === es3fShaderLoopTests.LoopCountType.LOOPCOUNT_CONSTANT)
354                         iterMaxStr = '1.0';
355                 else if (loopCountType === es3fShaderLoopTests.LoopCountType.LOOPCOUNT_UNIFORM)
356                         iterMaxStr = 'uf_one';
357                 else if (loopCountType === es3fShaderLoopTests.LoopCountType.LOOPCOUNT_DYNAMIC)
358                         iterMaxStr = 'uf_one*one';
359                 else
360                         throw new Error('Loop Count Type not supported: ' + loopCountType);
361         }
363         // Loop operations.
364         /** @type {string} */ var initValue = isIntCounter ? '0' : '0.05';
365     /** @type {string} */ var loopCountDeclStr = '' + gluShaderUtil.getPrecisionName(loopCountPrecision) + ' ' + gluShaderUtil.getDataTypeName(loopCountDataType) + ' ndx = ' + initValue;
366     /** @type {string} */ var loopCmpStr = 'ndx < ' + iterMaxStr;
367     /** @type {string} */ var incrementStr;
369         if (isIntCounter)
370                 incrementStr = 'ndx++';
371         else {
372                 if (loopCountType === es3fShaderLoopTests.LoopCountType.LOOPCOUNT_CONSTANT)
373                         incrementStr = 'ndx += ' + (1.0 / numLoopIters);
374                 else if (loopCountType === es3fShaderLoopTests.LoopCountType.LOOPCOUNT_UNIFORM)
375                         incrementStr = 'ndx += ' + glsShaderRenderCase.getFloatFractionUniformName(numLoopIters);
376                 else if (loopCountType === es3fShaderLoopTests.LoopCountType.LOOPCOUNT_DYNAMIC)
377                         incrementStr = 'ndx += ' + glsShaderRenderCase.getFloatFractionUniformName(numLoopIters) + '*one';
378                 else
379                         throw new Error('Loop Count Type not supported: ' + loopCountType);
380         }
382         // Loop body.
383         /** @type {string} */ var loopBody = '          res = res.yzwx;\n';;
385         if (loopType === es3fShaderLoopTests.LoopType.LOOPTYPE_FOR) {
386                 op += ' for (' + loopCountDeclStr + '; ' + loopCmpStr + '; ' + incrementStr + ')\n' +
387                       ' {\n' +
388                       loopBody +
389                       ' }\n';
390         }
391         else if (loopType === es3fShaderLoopTests.LoopType.LOOPTYPE_WHILE) {
392                 op += '\t' + loopCountDeclStr + ';\n' +
393                       ' while (' + loopCmpStr + ')\n' +
394                       ' {\n' +
395                       loopBody +
396                       '\t\t' + incrementStr + ';\n' +
397                       ' }\n';
398         }
399         else if (loopType === es3fShaderLoopTests.LoopType.LOOPTYPE_DO_WHILE)
400         {
401                 op += '\t' + loopCountDeclStr + ';\n' +
402                       ' do\n' +
403                       ' {\n' +
404                       loopBody +
405                       '\t\t' + incrementStr + ';\n' +
406                       ' } while (' + loopCmpStr + ');\n';
407         }
408         else
409                 throw new Error('Loop Type not supported: ' + loopType);
411         vtx += isVertexCase ? op : '';
412         frag += isVertexCase ? '' : op;
413         op = '';
415         if (isVertexCase) {
416                 vtx += '        v_color = res.rgb;\n';
417                 frag += '       o_color = vec4(v_color.rgb, 1.0);\n';
418         }
419         else {
420                 vtx += '        v_coords = a_coords;\n';
421                 frag += '       o_color = vec4(res.rgb, 1.0);\n';
423                 if (loopCountType === es3fShaderLoopTests.LoopCountType.LOOPCOUNT_DYNAMIC)
424                         vtx += '        v_one = a_one;\n';
425         }
427         vtx += '}\n';
428         frag += '}\n';
430         // Fill in shader templates.
431         /** @type {Object} */ var params = {};
432         params['LOOP_VAR_TYPE'] = gluShaderUtil.getDataTypeName(loopCountDataType);
433         params['PRECISION'] = 'mediump';
434         params['COUNTER_PRECISION'] = gluShaderUtil.getPrecisionName(loopCountPrecision);
436         /** @type {string} */ var vertexShaderSource = tcuStringTemplate.specialize(vtx, params);
437         /** @type {string} */ var fragmentShaderSource = tcuStringTemplate.specialize(frag, params);
439         // Create the case.
440         /** @type {glsShaderRenderCase.ShaderEvalFunc} */
441         var evalFunc = es3fShaderLoopTests.getLoopEvalFunc(numLoopIters);
442     return new es3fShaderLoopTests.ShaderLoopCase(caseName, description, isVertexCase, evalFunc, vertexShaderSource, fragmentShaderSource);
445 // \todo [petri] Generalize to float as well?
448  * @param {string} caseName
449  * @param {string} description
450  * @param {boolean} isVertexCase
451  * @param {es3fShaderLoopTests.LoopCase} loopCase
452  * @param {es3fShaderLoopTests.LoopType} loopType
453  * @param {es3fShaderLoopTests.LoopCountType} loopCountType
454  * @return {es3fShaderLoopTests.ShaderLoopCase}
455  */
456 es3fShaderLoopTests.createSpecialLoopCase = function(caseName, description, isVertexCase, loopCase, loopType, loopCountType) {
457     /** @type {string} */ var vtx = '';
458     /** @type {string} */ var frag = '';
459     /** @type {string} */ var op = '';
461     vtx += '#version 300 es\n';
462     frag += '#version 300 es\n';
464     vtx += 'in highp vec4 a_position;\n';
465     vtx += 'in highp vec4 a_coords;\n';
466     frag += 'layout(location = 0) out mediump vec4 o_color;\n';
468     if (loopCountType === es3fShaderLoopTests.LoopCountType.LOOPCOUNT_DYNAMIC)
469         vtx += 'in mediump float a_one;\n';
471     // Attribute and varyings.
472     if (isVertexCase) {
473         vtx += 'out mediump vec3 v_color;\n';
474         frag += 'in mediump vec3 v_color;\n';
475     }
476     else {
477         vtx += 'out mediump vec4 v_coords;\n';
478         frag += 'in mediump vec4 v_coords;\n';
480         if (loopCountType === es3fShaderLoopTests.LoopCountType.LOOPCOUNT_DYNAMIC) {
481             vtx += 'out mediump float v_one;\n';
482             frag += 'in mediump float v_one;\n';
483         }
484     }
486     if (loopCase === es3fShaderLoopTests.LoopCase.LOOPCASE_SELECT_ITERATION_COUNT)
487         op += 'uniform bool ub_true;\n';
489     op += 'uniform ${COUNTER_PRECISION} int ui_zero, ui_one, ui_two, ui_three, ui_four, ui_five, ui_six;\n';
490     if (loopCase === es3fShaderLoopTests.LoopCase.LOOPCASE_101_ITERATIONS)
491         op += 'uniform ${COUNTER_PRECISION} int ui_oneHundredOne;\n';
493     vtx += isVertexCase ? op : '';
494     frag += isVertexCase ? '' : op;
495     op = '';
497     /** @type {number} */ var iterCount = 3; // value to use in loop
498     /** @type {number} */ var numIters = 3; // actual number of iterations
500     vtx += '\n' +
501            'void main()\n' +
502            '{\n' +
503            '    gl_Position = a_position;\n';
505     frag += '\n' +
506             'void main()\n' +
507             '{\n';
509     if (loopCountType === es3fShaderLoopTests.LoopCountType.LOOPCOUNT_DYNAMIC) {
510         if (isVertexCase)
511             vtx += '    ${COUNTER_PRECISION} int one = int(a_one + 0.5);\n';
512         else
513             frag += '    ${COUNTER_PRECISION} int one = int(v_one + 0.5);\n';
514     }
516     if (isVertexCase)
517         vtx += '    ${PRECISION} vec4 coords = a_coords;\n';
518     else
519         frag += '    ${PRECISION} vec4 coords = v_coords;\n';
521     // Read array.
522     op += '    ${PRECISION} vec4 res = coords;\n';
524     // Handle all loop types.
525     /** @type {string} */ var counterPrecisionStr = 'mediump';
526     /** @type {string} */ var forLoopStr = '';
527     /** @type {string} */ var whileLoopStr = '';
528     /** @type {string} */ var doWhileLoopPreStr = '';
529     /** @type {string} */ var doWhileLoopPostStr = '';
531     if (loopType === es3fShaderLoopTests.LoopType.LOOPTYPE_FOR) {
532         switch (loopCase) {
533             case es3fShaderLoopTests.LoopCase.LOOPCASE_EMPTY_BODY:
534                 numIters = 0;
535                 op += '    ${FOR_LOOP} {}\n';
536                 break;
538             case es3fShaderLoopTests.LoopCase.LOOPCASE_INFINITE_WITH_UNCONDITIONAL_BREAK_FIRST:
539                 numIters = 0;
540                 op += '    for (;;) { break; res = res.yzwx; }\n';
541                 break;
543             case es3fShaderLoopTests.LoopCase.LOOPCASE_INFINITE_WITH_UNCONDITIONAL_BREAK_LAST:
544                 numIters = 1;
545                 op += '    for (;;) { res = res.yzwx; break; }\n';
546                 break;
548             case es3fShaderLoopTests.LoopCase.LOOPCASE_INFINITE_WITH_CONDITIONAL_BREAK:
549                 numIters = 2;
550                 op += '    ${COUNTER_PRECISION} int i = 0;\n' +
551                       '    for (;;) { res = res.yzwx; if (i == ${ONE}) break; i++; }\n';
552                 break;
554             case es3fShaderLoopTests.LoopCase.LOOPCASE_SINGLE_STATEMENT:
555                 op += '    ${FOR_LOOP} res = res.yzwx;\n';
556                 break;
558             case es3fShaderLoopTests.LoopCase.LOOPCASE_COMPOUND_STATEMENT:
559                 iterCount = 2;
560                 numIters = 2 * iterCount;
561                 op += '    ${FOR_LOOP} { res = res.yzwx; res = res.yzwx; }\n';
562                 break;
564             case es3fShaderLoopTests.LoopCase.LOOPCASE_SEQUENCE_STATEMENT:
565                 iterCount = 2;
566                 numIters = 2 * iterCount;
567                 op += '    ${FOR_LOOP} res = res.yzwx, res = res.yzwx;\n';
568                 break;
570             case es3fShaderLoopTests.LoopCase.LOOPCASE_NO_ITERATIONS:
571                 iterCount = 0;
572                 numIters = 0;
573                 op += '    ${FOR_LOOP} res = res.yzwx;\n';
574                 break;
576             case es3fShaderLoopTests.LoopCase.LOOPCASE_SINGLE_ITERATION:
577                 iterCount = 1;
578                 numIters = 1;
579                 op += '    ${FOR_LOOP} res = res.yzwx;\n';
580                 break;
582             case es3fShaderLoopTests.LoopCase.LOOPCASE_SELECT_ITERATION_COUNT:
583                 op += '    for (int i = 0; i < (ub_true ? ${ITER_COUNT} : 0); i++) res = res.yzwx;\n';
584                 break;
586             case es3fShaderLoopTests.LoopCase.LOOPCASE_CONDITIONAL_CONTINUE:
587                 numIters = iterCount - 1;
588                 op += '    ${FOR_LOOP} { if (i == ${TWO}) continue; res = res.yzwx; }\n';
589                 break;
591             case es3fShaderLoopTests.LoopCase.LOOPCASE_UNCONDITIONAL_CONTINUE:
592                 op += '    ${FOR_LOOP} { res = res.yzwx; continue; }\n';
593                 break;
595             case es3fShaderLoopTests.LoopCase.LOOPCASE_ONLY_CONTINUE:
596                 numIters = 0;
597                 op += '    ${FOR_LOOP} { continue; }\n';
598                 break;
600             case es3fShaderLoopTests.LoopCase.LOOPCASE_DOUBLE_CONTINUE:
601                 numIters = iterCount - 1;
602                 op += '    ${FOR_LOOP} { if (i == ${TWO}) continue; res = res.yzwx; continue; }\n';
603                 break;
605             case es3fShaderLoopTests.LoopCase.LOOPCASE_CONDITIONAL_BREAK:
606                 numIters = 2;
607                 op += '    ${FOR_LOOP} { if (i == ${TWO}) break; res = res.yzwx; }\n';
608                 break;
610             case es3fShaderLoopTests.LoopCase.LOOPCASE_UNCONDITIONAL_BREAK:
611                 numIters = 1;
612                 op += '    ${FOR_LOOP} { res = res.yzwx; break; }\n';
613                 break;
615             case es3fShaderLoopTests.LoopCase.LOOPCASE_PRE_INCREMENT:
616                 op += '    for (int i = 0; i < ${ITER_COUNT}; ++i) { res = res.yzwx; }\n';
617                 break;
619             case es3fShaderLoopTests.LoopCase.LOOPCASE_POST_INCREMENT:
620                 op += '    ${FOR_LOOP} { res = res.yzwx; }\n';
621                 break;
623             case es3fShaderLoopTests.LoopCase.LOOPCASE_MIXED_BREAK_CONTINUE:
624                 numIters = 2;
625                 iterCount = 5;
626                 op += '    ${FOR_LOOP} { if (i == 0) continue; else if (i == 3) break; res = res.yzwx; }\n';
627                 break;
629             case es3fShaderLoopTests.LoopCase.LOOPCASE_VECTOR_COUNTER:
630                 op += '    for (${COUNTER_PRECISION} ivec4 i = ivec4(0, 1, ${ITER_COUNT}, 0); i.x < i.z; i.x += i.y) { res = res.yzwx; }\n';
631                 break;
633             case es3fShaderLoopTests.LoopCase.LOOPCASE_101_ITERATIONS:
634                 numIters = iterCount = 101;
635                 op += '    ${FOR_LOOP} res = res.yzwx;\n';
636                 break;
638             case es3fShaderLoopTests.LoopCase.LOOPCASE_SEQUENCE:
639                 iterCount = 5;
640                 numIters = 5;
641                 op += '    ${COUNTER_PRECISION} int i;\n' +
642                       '    for (i = 0; i < ${TWO}; i++) { res = res.yzwx; }\n' +
643                       '    for (; i < ${ITER_COUNT}; i++) { res = res.yzwx; }\n';
644                 break;
646             case es3fShaderLoopTests.LoopCase.LOOPCASE_NESTED:
647                 numIters = 2 * iterCount;
648                 op += '    for (${COUNTER_PRECISION} int i = 0; i < ${TWO}; i++)\n' +
649                       '    {\n' +
650                       '        for (${COUNTER_PRECISION} int j = 0; j < ${ITER_COUNT}; j++)\n' +
651                       '            res = res.yzwx;\n' +
652                       '    }\n';
653                 break;
655             case es3fShaderLoopTests.LoopCase.LOOPCASE_NESTED_SEQUENCE:
656                 numIters = 3 * iterCount;
657                 op += '    for (${COUNTER_PRECISION} int i = 0; i < ${ITER_COUNT}; i++)\n' +
658                       '    {\n' +
659                       '        for (${COUNTER_PRECISION} int j = 0; j < ${TWO}; j++)\n' +
660                       '            res = res.yzwx;\n' +
661                       '        for (${COUNTER_PRECISION} int j = 0; j < ${ONE}; j++)\n' +
662                       '            res = res.yzwx;\n' +
663                       '    }\n';
664                 break;
666             case es3fShaderLoopTests.LoopCase.LOOPCASE_NESTED_TRICKY_DATAFLOW_1:
667                 numIters = 2;
668                 op += '    ${FOR_LOOP}\n' +
669                       '    {\n' +
670                       '        res = coords; // ignore outer loop effect \n' +
671                       '        for (${COUNTER_PRECISION} int j = 0; j < ${TWO}; j++)\n' +
672                       '            res = res.yzwx;\n' +
673                       '    }\n';
674                 break;
676             case es3fShaderLoopTests.LoopCase.LOOPCASE_NESTED_TRICKY_DATAFLOW_2:
677                 numIters = iterCount;
678                 op += '    ${FOR_LOOP}\n' +
679                       '    {\n' +
680                       '        res = coords.wxyz;\n' +
681                       '        for (${COUNTER_PRECISION} int j = 0; j < ${TWO}; j++)\n' +
682                       '            res = res.yzwx;\n' +
683                       '        coords = res;\n' +
684                       '    }\n';
685                 break;
687             default:
688                 throw new Error('Case not supported: ' + loopCase);
689         }
691         if (loopCountType === es3fShaderLoopTests.LoopCountType.LOOPCOUNT_CONSTANT)
692             forLoopStr = 'for (' + counterPrecisionStr + ' int i = 0; i < ' + iterCount + '; i++)';
693         else if (loopCountType === es3fShaderLoopTests.LoopCountType.LOOPCOUNT_UNIFORM)
694             forLoopStr = 'for (' + counterPrecisionStr + ' int i = 0; i < ' + glsShaderRenderCase.getIntUniformName(iterCount) + '; i++)';
695         else if (loopCountType === es3fShaderLoopTests.LoopCountType.LOOPCOUNT_DYNAMIC)
696             forLoopStr = 'for (' + counterPrecisionStr + ' int i = 0; i < one*' + glsShaderRenderCase.getIntUniformName(iterCount) + '; i++)';
697         else
698             throw new Error('Loop Count Type not supported: ' + loopCountType);
699     }
700     else if (loopType === es3fShaderLoopTests.LoopType.LOOPTYPE_WHILE) {
701         switch (loopCase) {
702             case es3fShaderLoopTests.LoopCase.LOOPCASE_EMPTY_BODY:
703                 numIters = 0;
704                 op += '    ${WHILE_LOOP} {}\n';
705                 break;
707             case es3fShaderLoopTests.LoopCase.LOOPCASE_INFINITE_WITH_UNCONDITIONAL_BREAK_FIRST:
708                 numIters = 0;
709                 op += '    while (true) { break; res = res.yzwx; }\n';
710                 break;
712             case es3fShaderLoopTests.LoopCase.LOOPCASE_INFINITE_WITH_UNCONDITIONAL_BREAK_LAST:
713                 numIters = 1;
714                 op += '    while (true) { res = res.yzwx; break; }\n';
715                 break;
717             case es3fShaderLoopTests.LoopCase.LOOPCASE_INFINITE_WITH_CONDITIONAL_BREAK:
718                 numIters = 2;
719                 op += '    ${COUNTER_PRECISION} int i = 0;\n' +
720                       '    while (true) { res = res.yzwx; if (i == ${ONE}) break; i++; }\n';
721                 break;
723             case es3fShaderLoopTests.LoopCase.LOOPCASE_SINGLE_STATEMENT:
724                 op += '    ${WHILE_LOOP} res = res.yzwx;\n';
725                 break;
727             case es3fShaderLoopTests.LoopCase.LOOPCASE_COMPOUND_STATEMENT:
728                 iterCount = 2;
729                 numIters = 2 * iterCount;
730                 op += '    ${WHILE_LOOP} { res = res.yzwx; res = res.yzwx; }\n';
731                 break;
733             case es3fShaderLoopTests.LoopCase.LOOPCASE_SEQUENCE_STATEMENT:
734                 iterCount = 2;
735                 numIters = 2 * iterCount;
736                 op += '    ${WHILE_LOOP} res = res.yzwx, res = res.yzwx;\n';
737                 break;
739             case es3fShaderLoopTests.LoopCase.LOOPCASE_NO_ITERATIONS:
740                 iterCount = 0;
741                 numIters = 0;
742                 op += '    ${WHILE_LOOP} res = res.yzwx;\n';
743                 break;
745             case es3fShaderLoopTests.LoopCase.LOOPCASE_SINGLE_ITERATION:
746                 iterCount = 1;
747                 numIters = 1;
748                 op += '    ${WHILE_LOOP} res = res.yzwx;\n';
749                 break;
751             case es3fShaderLoopTests.LoopCase.LOOPCASE_SELECT_ITERATION_COUNT:
752                 op += '    ${COUNTER_PRECISION} int i = 0;\n' +
753                       '    while (i < (ub_true ? ${ITER_COUNT} : 0)) { res = res.yzwx; i++; }\n';
754                 break;
756             case es3fShaderLoopTests.LoopCase.LOOPCASE_CONDITIONAL_CONTINUE:
757                 numIters = iterCount - 1;
758                 op += '    ${WHILE_LOOP} { if (i == ${TWO}) continue; res = res.yzwx; }\n';
759                 break;
761             case es3fShaderLoopTests.LoopCase.LOOPCASE_UNCONDITIONAL_CONTINUE:
762                 op += '    ${WHILE_LOOP} { res = res.yzwx; continue; }\n';
763                 break;
765             case es3fShaderLoopTests.LoopCase.LOOPCASE_ONLY_CONTINUE:
766                 numIters = 0;
767                 op += '    ${WHILE_LOOP} { continue; }\n';
768                 break;
770             case es3fShaderLoopTests.LoopCase.LOOPCASE_DOUBLE_CONTINUE:
771                 numIters = iterCount - 1;
772                 op += '    ${WHILE_LOOP} { if (i == ${ONE}) continue; res = res.yzwx; continue; }\n';
773                 break;
775             case es3fShaderLoopTests.LoopCase.LOOPCASE_CONDITIONAL_BREAK:
776                 numIters = 2;
777                 op += '    ${WHILE_LOOP} { if (i == ${THREE}) break; res = res.yzwx; }\n';
778                 break;
780             case es3fShaderLoopTests.LoopCase.LOOPCASE_UNCONDITIONAL_BREAK:
781                 numIters = 1;
782                 op += '    ${WHILE_LOOP} { res = res.yzwx; break; }\n';
783                 break;
785             case es3fShaderLoopTests.LoopCase.LOOPCASE_PRE_INCREMENT:
786                 numIters = iterCount - 1;
787                 op += '    ${COUNTER_PRECISION} int i = 0;\n' +
788                       '    while (++i < ${ITER_COUNT}) { res = res.yzwx; }\n';
789                 break;
791             case es3fShaderLoopTests.LoopCase.LOOPCASE_POST_INCREMENT:
792                 op += '    ${COUNTER_PRECISION} int i = 0;\n' +
793                       '    while (i++ < ${ITER_COUNT}) { res = res.yzwx; }\n';
794                 break;
796             case es3fShaderLoopTests.LoopCase.LOOPCASE_MIXED_BREAK_CONTINUE:
797                 numIters = 2;
798                 iterCount = 5;
799                 op += '    ${WHILE_LOOP} { if (i == 0) continue; else if (i == 3) break; res = res.yzwx; }\n';
800                 break;
802             case es3fShaderLoopTests.LoopCase.LOOPCASE_VECTOR_COUNTER:
803                 op += '    ${COUNTER_PRECISION} ivec4 i = ivec4(0, 1, ${ITER_COUNT}, 0);\n' +
804                       '    while (i.x < i.z) { res = res.yzwx; i.x += i.y; }\n';
805                 break;
807             case es3fShaderLoopTests.LoopCase.LOOPCASE_101_ITERATIONS:
808                 numIters = iterCount = 101;
809                 op += '    ${WHILE_LOOP} res = res.yzwx;\n';
810                 break;
812             case es3fShaderLoopTests.LoopCase.LOOPCASE_SEQUENCE:
813                 iterCount    = 6;
814                 numIters    = iterCount - 1;
815                 op += '    ${COUNTER_PRECISION} int i = 0;\n' +
816                       '    while (i++ < ${TWO}) { res = res.yzwx; }\n' +
817                       '    while (i++ < ${ITER_COUNT}) { res = res.yzwx; }\n'; // \note skips one iteration
818                 break;
820             case es3fShaderLoopTests.LoopCase.LOOPCASE_NESTED:
821                 numIters = 2 * iterCount;
822                 op += '    ${COUNTER_PRECISION} int i = 0;\n' +
823                       '    while (i++ < ${TWO})\n' +
824                       '    {\n' +
825                       '        ${COUNTER_PRECISION} int j = 0;\n' +
826                       '        while (j++ < ${ITER_COUNT})\n' +
827                       '            res = res.yzwx;\n' +
828                       '    }\n';
829                 break;
831             case es3fShaderLoopTests.LoopCase.LOOPCASE_NESTED_SEQUENCE:
832                 numIters = 2 * iterCount;
833                 op += '    ${COUNTER_PRECISION} int i = 0;\n' +
834                       '    while (i++ < ${ITER_COUNT})\n' +
835                       '    {\n' +
836                       '        ${COUNTER_PRECISION} int j = 0;\n' +
837                       '        while (j++ < ${ONE})\n' +
838                       '            res = res.yzwx;\n' +
839                       '        while (j++ < ${THREE})\n' + // \note skips one iteration
840                       '            res = res.yzwx;\n' +
841                       '    }\n';
842                 break;
844             case es3fShaderLoopTests.LoopCase.LOOPCASE_NESTED_TRICKY_DATAFLOW_1:
845                 numIters = 2;
846                 op += '    ${WHILE_LOOP}\n' +
847                       '    {\n' +
848                       '        res = coords; // ignore outer loop effect \n' +
849                       '        ${COUNTER_PRECISION} int j = 0;\n' +
850                       '        while (j++ < ${TWO})\n' +
851                       '            res = res.yzwx;\n' +
852                       '    }\n';
853                 break;
855             case es3fShaderLoopTests.LoopCase.LOOPCASE_NESTED_TRICKY_DATAFLOW_2:
856                 numIters = iterCount;
857                 op += '    ${WHILE_LOOP}\n' +
858                       '    {\n' +
859                       '        res = coords.wxyz;\n' +
860                       '        ${COUNTER_PRECISION} int j = 0;\n' +
861                       '        while (j++ < ${TWO})\n' +
862                       '            res = res.yzwx;\n' +
863                       '        coords = res;\n' +
864                       '    }\n';
865                 break;
867             default:
868                 throw new Error('Loop Case not supported: ' + loopCase);
869         }
871         if (loopCountType === es3fShaderLoopTests.LoopCountType.LOOPCOUNT_CONSTANT)
872             whileLoopStr = '\t' + counterPrecisionStr + ' int i = 0;\n' + '    while(i++ < ' + iterCount + ')';
873         else if (loopCountType === es3fShaderLoopTests.LoopCountType.LOOPCOUNT_UNIFORM)
874             whileLoopStr = '\t' + counterPrecisionStr + ' int i = 0;\n' + '    while(i++ < ' + glsShaderRenderCase.getIntUniformName(iterCount) + ')';
875         else if (loopCountType === es3fShaderLoopTests.LoopCountType.LOOPCOUNT_DYNAMIC)
876             whileLoopStr = '\t' + counterPrecisionStr + ' int i = 0;\n' + '    while(i++ < one*' + glsShaderRenderCase.getIntUniformName(iterCount) + ')';
877         else
878             throw new Error('Loop Count Type not supported: ' + loopCountType);
879     }
880     else {
881         assertMsgOptions(loopType === es3fShaderLoopTests.LoopType.LOOPTYPE_DO_WHILE, 'Expected LOOPTYPE_DO_WHILE', false, true);
883         switch (loopCase) {
884             case es3fShaderLoopTests.LoopCase.LOOPCASE_EMPTY_BODY:
885                 numIters = 0;
886                 op += '    ${DO_WHILE_PRE} {} ${DO_WHILE_POST}\n';
887                 break;
889             case es3fShaderLoopTests.LoopCase.LOOPCASE_INFINITE_WITH_UNCONDITIONAL_BREAK_FIRST:
890                 numIters = 0;
891                 op += '    do { break; res = res.yzwx; } while (true);\n';
892                 break;
894             case es3fShaderLoopTests.LoopCase.LOOPCASE_INFINITE_WITH_UNCONDITIONAL_BREAK_LAST:
895                 numIters = 1;
896                 op += '    do { res = res.yzwx; break; } while (true);\n';
897                 break;
899             case es3fShaderLoopTests.LoopCase.LOOPCASE_INFINITE_WITH_CONDITIONAL_BREAK:
900                 numIters = 2;
901                 op += '    ${COUNTER_PRECISION} int i = 0;\n' +
902                       '    do { res = res.yzwx; if (i == ${ONE}) break; i++; } while (true);\n';
903                 break;
905             case es3fShaderLoopTests.LoopCase.LOOPCASE_SINGLE_STATEMENT:
906                 op += '    ${DO_WHILE_PRE} res = res.yzwx; ${DO_WHILE_POST}\n';
907                 break;
909             case es3fShaderLoopTests.LoopCase.LOOPCASE_COMPOUND_STATEMENT:
910                 iterCount = 2;
911                 numIters = 2 * iterCount;
912                 op += '    ${DO_WHILE_PRE} { res = res.yzwx; res = res.yzwx; } ${DO_WHILE_POST}\n';
913                 break;
915             case es3fShaderLoopTests.LoopCase.LOOPCASE_SEQUENCE_STATEMENT:
916                 iterCount = 2;
917                 numIters = 2 * iterCount;
918                 op += '    ${DO_WHILE_PRE} res = res.yzwx, res = res.yzwx; ${DO_WHILE_POST}\n';
919                 break;
921             case es3fShaderLoopTests.LoopCase.LOOPCASE_NO_ITERATIONS:
922                 //assertMsgOptions(false, 'LOOPCASE_NO_ITERATIONS', false, false);
923                 break;
925             case es3fShaderLoopTests.LoopCase.LOOPCASE_SINGLE_ITERATION:
926                 iterCount = 1;
927                 numIters = 1;
928                 op += '    ${DO_WHILE_PRE} res = res.yzwx; ${DO_WHILE_POST}\n';
929                 break;
931             case es3fShaderLoopTests.LoopCase.LOOPCASE_SELECT_ITERATION_COUNT:
932                 op += '    ${COUNTER_PRECISION} int i = 0;\n' +
933                       '    do { res = res.yzwx; } while (++i < (ub_true ? ${ITER_COUNT} : 0));\n';
934                 break;
936             case es3fShaderLoopTests.LoopCase.LOOPCASE_CONDITIONAL_CONTINUE:
937                 numIters = iterCount - 1;
938                 op += '    ${DO_WHILE_PRE} { if (i == ${TWO}) continue; res = res.yzwx; } ${DO_WHILE_POST}\n';
939                 break;
941             case es3fShaderLoopTests.LoopCase.LOOPCASE_UNCONDITIONAL_CONTINUE:
942                 op += '    ${DO_WHILE_PRE} { res = res.yzwx; continue; } ${DO_WHILE_POST}\n';
943                 break;
945             case es3fShaderLoopTests.LoopCase.LOOPCASE_ONLY_CONTINUE:
946                 numIters = 0;
947                 op += '    ${DO_WHILE_PRE} { continue; } ${DO_WHILE_POST}\n';
948                 break;
950             case es3fShaderLoopTests.LoopCase.LOOPCASE_DOUBLE_CONTINUE:
951                 numIters = iterCount - 1;
952                 op += '    ${DO_WHILE_PRE} { if (i == ${TWO}) continue; res = res.yzwx; continue; } ${DO_WHILE_POST}\n';
953                 break;
955             case es3fShaderLoopTests.LoopCase.LOOPCASE_CONDITIONAL_BREAK:
956                 numIters = 2;
957                 op += '    ${DO_WHILE_PRE} { res = res.yzwx; if (i == ${ONE}) break; } ${DO_WHILE_POST}\n';
958                 break;
960             case es3fShaderLoopTests.LoopCase.LOOPCASE_UNCONDITIONAL_BREAK:
961                 numIters = 1;
962                 op += '    ${DO_WHILE_PRE} { res = res.yzwx; break; } ${DO_WHILE_POST}\n';
963                 break;
965             case es3fShaderLoopTests.LoopCase.LOOPCASE_PRE_INCREMENT:
966                 op += '    ${COUNTER_PRECISION} int i = 0;\n' +
967                       '    do { res = res.yzwx; } while (++i < ${ITER_COUNT});\n';
968                 break;
970             case es3fShaderLoopTests.LoopCase.LOOPCASE_POST_INCREMENT:
971                 numIters = iterCount + 1;
972                 op += '    ${COUNTER_PRECISION} int i = 0;\n' +
973                       '    do { res = res.yzwx; } while (i++ < ${ITER_COUNT});\n';
974                 break;
976             case es3fShaderLoopTests.LoopCase.LOOPCASE_MIXED_BREAK_CONTINUE:
977                 numIters = 2;
978                 iterCount = 5;
979                 op += '    ${DO_WHILE_PRE} { if (i == 0) continue; else if (i == 3) break; res = res.yzwx; } ${DO_WHILE_POST}\n';
980                 break;
982             case es3fShaderLoopTests.LoopCase.LOOPCASE_VECTOR_COUNTER:
983                 op += '    ${COUNTER_PRECISION} ivec4 i = ivec4(0, 1, ${ITER_COUNT}, 0);\n' +
984                       '    do { res = res.yzwx; } while ((i.x += i.y) < i.z);\n';
985                 break;
987             case es3fShaderLoopTests.LoopCase.LOOPCASE_101_ITERATIONS:
988                 numIters = iterCount = 101;
989                 op += '    ${DO_WHILE_PRE} res = res.yzwx; ${DO_WHILE_POST}\n';
990                 break;
992             case es3fShaderLoopTests.LoopCase.LOOPCASE_SEQUENCE:
993                 iterCount = 5;
994                 numIters = 5;
995                 op += '    ${COUNTER_PRECISION} int i = 0;\n' +
996                       '    do { res = res.yzwx; } while (++i < ${TWO});\n' +
997                       '    do { res = res.yzwx; } while (++i < ${ITER_COUNT});\n';
998                 break;
1000             case es3fShaderLoopTests.LoopCase.LOOPCASE_NESTED:
1001                 numIters = 2 * iterCount;
1002                 op += '    ${COUNTER_PRECISION} int i = 0;\n' +
1003                       '    do\n' +
1004                       '    {\n' +
1005                       '        ${COUNTER_PRECISION} int j = 0;\n' +
1006                       '        do\n' +
1007                       '            res = res.yzwx;\n' +
1008                       '        while (++j < ${ITER_COUNT});\n' +
1009                       '    } while (++i < ${TWO});\n';
1010                 break;
1012             case es3fShaderLoopTests.LoopCase.LOOPCASE_NESTED_SEQUENCE:
1013                 numIters = 3 * iterCount;
1014                 op += '    ${COUNTER_PRECISION} int i = 0;\n' +
1015                       '    do\n' +
1016                       '    {\n' +
1017                       '        ${COUNTER_PRECISION} int j = 0;\n' +
1018                       '        do\n' +
1019                       '            res = res.yzwx;\n' +
1020                       '        while (++j < ${TWO});\n' +
1021                       '        do\n' +
1022                       '            res = res.yzwx;\n' +
1023                       '        while (++j < ${THREE});\n' +
1024                       '    } while (++i < ${ITER_COUNT});\n';
1025                 break;
1027             case es3fShaderLoopTests.LoopCase.LOOPCASE_NESTED_TRICKY_DATAFLOW_1:
1028                 numIters = 2;
1029                 op += '    ${DO_WHILE_PRE}\n' +
1030                       '    {\n' +
1031                       '        res = coords; // ignore outer loop effect \n' +
1032                       '        ${COUNTER_PRECISION} int j = 0;\n' +
1033                       '        do\n' +
1034                       '            res = res.yzwx;\n' +
1035                       '        while (++j < ${TWO});\n' +
1036                       '    } ${DO_WHILE_POST}\n';
1037                 break;
1039             case es3fShaderLoopTests.LoopCase.LOOPCASE_NESTED_TRICKY_DATAFLOW_2:
1040                 numIters = iterCount;
1041                 op += '    ${DO_WHILE_PRE}\n' +
1042                       '    {\n' +
1043                       '        res = coords.wxyz;\n' +
1044                       '        ${COUNTER_PRECISION} int j = 0;\n' +
1045                       '        while (j++ < ${TWO})\n' +
1046                       '            res = res.yzwx;\n' +
1047                       '        coords = res;\n' +
1048                       '    } ${DO_WHILE_POST}\n';
1049                 break;
1051             default:
1052                 throw new Error('Loop Case not supported: ' + loopCase);
1053         }
1055         doWhileLoopPreStr = '\t' + counterPrecisionStr + ' int i = 0;\n' + '\tdo ';
1056         if (loopCountType === es3fShaderLoopTests.LoopCountType.LOOPCOUNT_CONSTANT)
1057             doWhileLoopPostStr = ' while (++i < ' + iterCount + ');\n';
1058         else if (loopCountType === es3fShaderLoopTests.LoopCountType.LOOPCOUNT_UNIFORM)
1059             doWhileLoopPostStr = ' while (++i < ' + glsShaderRenderCase.getIntUniformName(iterCount) + ');\n';
1060         else if (loopCountType === es3fShaderLoopTests.LoopCountType.LOOPCOUNT_DYNAMIC)
1061             doWhileLoopPostStr = ' while (++i < one*' + glsShaderRenderCase.getIntUniformName(iterCount) + ');\n';
1062         else
1063             throw new Error('Loop Count Type not supported: ' + loopCountType);
1064     }
1066         vtx += isVertexCase ? op : '';
1067         frag += isVertexCase ? '' : op;
1068         op = '';
1070     // Shader footers.
1071     if (isVertexCase) {
1072         vtx += '    v_color = res.rgb;\n';
1073         frag += '    o_color = vec4(v_color.rgb, 1.0);\n';
1074     }
1075     else {
1076         vtx += '    v_coords = a_coords;\n';
1077         frag += '    o_color = vec4(res.rgb, 1.0);\n';
1079         if (loopCountType === es3fShaderLoopTests.LoopCountType.LOOPCOUNT_DYNAMIC)
1080             vtx += '    v_one = a_one;\n';
1081     }
1083     vtx += '}\n';
1084     frag += '}\n';
1086     // Constants.
1087         /** @type {string} */ var oneStr = '';
1088         /** @type {string} */ var twoStr = '';
1089         /** @type {string} */ var threeStr = '';
1090         /** @type {string} */ var iterCountStr = '';
1092     if (loopCountType === es3fShaderLoopTests.LoopCountType.LOOPCOUNT_CONSTANT) {
1093         oneStr = '1';
1094         twoStr = '2';
1095         threeStr = '3';
1096         iterCountStr = iterCount.toString();
1097     }
1098     else if (loopCountType === es3fShaderLoopTests.LoopCountType.LOOPCOUNT_UNIFORM) {
1099         oneStr = 'ui_one';
1100         twoStr = 'ui_two';
1101         threeStr = 'ui_three';
1102         iterCountStr = glsShaderRenderCase.getIntUniformName(iterCount);
1103     }
1104     else if (loopCountType === es3fShaderLoopTests.LoopCountType.LOOPCOUNT_DYNAMIC) {
1105         oneStr = 'one*ui_one';
1106         twoStr = 'one*ui_two';
1107         threeStr = 'one*ui_three';
1108         iterCountStr = 'one*' + glsShaderRenderCase.getIntUniformName(iterCount);
1109     }
1110     else throw new Error('Loop Count Type not supported: ' + loopCountType);
1112     // Fill in shader templates.
1113     /** @type {Object} */ var params = {};
1114     params["PRECISION"] = "mediump";
1115     params["ITER_COUNT"] = iterCountStr;
1116     params["COUNTER_PRECISION"] = counterPrecisionStr;
1117     params["FOR_LOOP"] = forLoopStr;
1118     params["WHILE_LOOP"] = whileLoopStr;
1119     params["DO_WHILE_PRE"] = doWhileLoopPreStr;
1120     params["DO_WHILE_POST"] = doWhileLoopPostStr;
1121     params["ONE"] = oneStr;
1122     params["TWO"] = twoStr;
1123     params["THREE"] = threeStr;
1125         /** @type {string} */ var vertexShaderSource = tcuStringTemplate.specialize(vtx, params);
1126         /** @type {string} */ var fragmentShaderSource = tcuStringTemplate.specialize(frag, params);
1128     // Create the case.
1129         /** @type {glsShaderRenderCase.ShaderEvalFunc} */
1130         var evalFunc = es3fShaderLoopTests.getLoopEvalFunc(numIters);
1131     return new es3fShaderLoopTests.ShaderLoopCase(caseName, description, isVertexCase, evalFunc, vertexShaderSource, fragmentShaderSource);
1134 // ShaderLoopTests.
1137  * @constructor
1138  * @extends {tcuTestCase.DeqpTest}
1139  */
1140 es3fShaderLoopTests.ShaderLoopTests = function() {
1141     tcuTestCase.DeqpTest.call(this, 'loops', 'Loop Tests');
1144 es3fShaderLoopTests.ShaderLoopTests.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
1145 es3fShaderLoopTests.ShaderLoopTests.prototype.constructor = es3fShaderLoopTests.ShaderLoopTests;
1147 es3fShaderLoopTests.ShaderLoopTests.prototype.init = function() {
1148     var testGroup = tcuTestCase.runner.testCases;
1149     // Loop cases.
1151     /** @type {Array<gluShaderProgram.shaderType>} */ var s_shaderTypes = [
1152         gluShaderProgram.shaderType.VERTEX,
1153         gluShaderProgram.shaderType.FRAGMENT
1154     ];
1156     /** @type {Array<gluShaderUtil.DataType>} */ var s_countDataType = [
1157         gluShaderUtil.DataType.INT,
1158         gluShaderUtil.DataType.FLOAT
1159     ];
1161     /** @type {gluShaderProgram.shaderType} */ var shaderType;
1162     /** @type {string} */ var shaderTypeName;
1163     /** @type {boolean} */ var isVertexCase;
1164     /** @type {string} */ var name;
1165     /** @type {string} */ var desc;
1167     for (var loopType in es3fShaderLoopTests.LoopType) {
1168         /** @type {string} */ var loopTypeName = es3fShaderLoopTests.getLoopTypeName(es3fShaderLoopTests.LoopType[loopType]);
1169         /** @type {tcuTestCase.DeqpTest} */ var loopTypeGroup = tcuTestCase.newTest(loopTypeName, 'Loop tests with ' + loopTypeName + ' loop type');
1170         testGroup.addChild(loopTypeGroup);
1172         for (var loopCountType in es3fShaderLoopTests.LoopCountType) {
1173             /** @type {string} */ var loopCountName = es3fShaderLoopTests.getLoopCountTypeName(es3fShaderLoopTests.LoopCountType[loopCountType]);
1175             /** @type {string} */ var groupName = loopCountName + '_iterations';
1176             /** @type {string} */ var groupDesc = 'Loop tests with ' + loopCountName + ' loop counter.';
1178             /** @type {tcuTestCase.DeqpTest} */ var group = tcuTestCase.newTest(groupName, groupDesc);
1179             loopTypeGroup.addChild(group);
1181             // Generic cases.
1183             for (var precision in gluShaderUtil.precision) {
1184                 /** @type {string} */ var precisionName = gluShaderUtil.getPrecisionName(gluShaderUtil.precision[precision]);
1186                 for (var dataTypeNdx = 0; dataTypeNdx < s_countDataType.length; dataTypeNdx++) {
1187                     /** @type {gluShaderUtil.DataType} */ var loopDataType = s_countDataType[dataTypeNdx];
1188                     /** @type {string} */ var dataTypeName = gluShaderUtil.getDataTypeName(loopDataType);
1190                     for (var shaderTypeNdx = 0; shaderTypeNdx < s_shaderTypes.length; shaderTypeNdx++) {
1191                         shaderType = s_shaderTypes[shaderTypeNdx];
1192                         shaderTypeName = gluShaderProgram.getShaderTypeName(shaderType);
1193                         isVertexCase    = (shaderType == gluShaderProgram.shaderType.VERTEX);
1196                         name = 'basic_' + precisionName + '_' + dataTypeName + '_' + shaderTypeName;
1197                         desc = loopTypeName + ' loop with ' + precisionName + dataTypeName + ' ' + loopCountName + ' iteration count in ' + shaderTypeName + ' shader.';
1198                         group.addChild(es3fShaderLoopTests.createGenericLoopCase(name, desc, isVertexCase, es3fShaderLoopTests.LoopType[loopType], es3fShaderLoopTests.LoopCountType[loopCountType], gluShaderUtil.precision[precision], loopDataType));
1199                     }
1200                 }
1201             }
1203             // Special cases.
1205             for (var loopCase in es3fShaderLoopTests.LoopCase) {
1206                 /** @type {string} */ var loopCaseName = es3fShaderLoopTests.getLoopCaseName(es3fShaderLoopTests.LoopCase[loopCase]);
1208                 // no-iterations not possible with do-while.
1209                 if ((es3fShaderLoopTests.LoopCase[loopCase] == es3fShaderLoopTests.LoopCase.LOOPCASE_NO_ITERATIONS) && (es3fShaderLoopTests.LoopType[loopType] == es3fShaderLoopTests.LoopType.LOOPTYPE_DO_WHILE))
1210                     continue;
1212                 for (var shaderTypeNdx = 0; shaderTypeNdx < s_shaderTypes.length; shaderTypeNdx++) {
1213                     shaderType = s_shaderTypes[shaderTypeNdx];
1214                     shaderTypeName = gluShaderProgram.getShaderTypeName(shaderType);
1215                     isVertexCase    = (shaderType == gluShaderProgram.shaderType.VERTEX);
1217                     name = loopCaseName + '_' + shaderTypeName;
1218                     desc = loopCaseName + ' loop with ' + loopTypeName + ' iteration count in ' + shaderTypeName + ' shader.';
1219                     group.addChild(es3fShaderLoopTests.createSpecialLoopCase(name, desc, isVertexCase, es3fShaderLoopTests.LoopCase[loopCase], es3fShaderLoopTests.LoopType[loopType], es3fShaderLoopTests.LoopCountType[loopCountType]));
1220                 }
1221             }
1222         }
1223     }
1227 * Run test
1228 * @param {WebGL2RenderingContext} context
1230 es3fShaderLoopTests.run = function(context, range) {
1231     gl = context;
1232     //Set up Test Root parameters
1233     var state = tcuTestCase.runner;
1234     state.setRoot(new es3fShaderLoopTests.ShaderLoopTests());
1236     //Set up name and description of this test series.
1237     setCurrentTestName(state.testCases.fullName());
1238     description(state.testCases.getDescription());
1239     try {
1240         if (range)
1241             state.setRange(range);
1242         //Run test cases
1243         tcuTestCase.runTestCases();
1244     }
1245     catch (err) {
1246         testFailedOptions('Failed to es3fShaderLoopTests.run tests', false);
1247         tcuTestCase.runner.terminate();
1248     }