tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

es3fShaderLoopTests.js (52197B)


      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 */
     20 
     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');
     29 
     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.
     40 
     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
     71 };
     72 
     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];
    109 };
    110 
    111 // Complex loop cases.
    112 
    113 /*enum LoopBody
    114 {
    115    LOOPBODY_READ_UNIFORM = 0,
    116    LOOPBODY_READ_UNIFORM_ARRAY,
    117    LOOPBODY_READ_
    118 };*/
    119 
    120 /**
    121 * @enum {number}
    122 */
    123 es3fShaderLoopTests.LoopType = {
    124    LOOPTYPE_FOR: 0,
    125    LOOPTYPE_WHILE: 1,
    126    LOOPTYPE_DO_WHILE: 2
    127 };
    128 
    129 /**
    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    ];
    139 
    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];
    143 };
    144 
    145 /**
    146 * @enum {number}
    147 */
    148 es3fShaderLoopTests.LoopCountType = {
    149    LOOPCOUNT_CONSTANT: 0,
    150    LOOPCOUNT_UNIFORM: 1,
    151    LOOPCOUNT_DYNAMIC: 2
    152 };
    153 
    154 /**
    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    ];
    164 
    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];
    168 };
    169 
    170 /**
    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];
    178 };
    179 
    180 /**
    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];
    188 };
    189 
    190 /**
    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];
    198 };
    199 
    200 /**
    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];
    208 };
    209 
    210 /**
    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    }
    221 
    222    throw new Error('Invalid loop iteration count.');
    223 };
    224 
    225 // ShaderLoopCase
    226 
    227 /**
    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;
    241 };
    242 
    243 es3fShaderLoopTests.ShaderLoopCase.prototype = Object.create(glsShaderRenderCase.ShaderRenderCase.prototype);
    244 es3fShaderLoopTests.ShaderLoopCase.prototype.constructor = es3fShaderLoopTests.ShaderLoopCase;
    245 
    246 // Test case creation.
    247 
    248 /**
    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 = '';
    262 
    263 vtx += '#version 300 es\n';
    264 frag += '#version 300 es\n';
    265 
    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';
    269 
    270 if (loopCountType === es3fShaderLoopTests.LoopCountType.LOOPCOUNT_DYNAMIC)
    271 	vtx += 'in mediump float a_one;\n';
    272 
    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';
    280 
    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 }
    286 
    287 // \todo [petri] Pass numLoopIters from outside?
    288 /** @type {number} */ var numLoopIters = 3;
    289    /** @type {boolean} */ var isIntCounter = gluShaderUtil.isDataTypeIntOrIVec(loopCountDataType);
    290 
    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';
    298 
    299 	if (numLoopIters != 1)
    300 		op += 'uniform ${COUNTER_PRECISION} float uf_one;\n';
    301 }
    302 
    303 vtx += isVertexCase ? op : '';
    304 frag += isVertexCase ? '' : op;
    305 op = '';
    306 
    307 vtx += "\n" +
    308        "void main()\n" +
    309        "{\n" +
    310        "	gl_Position = a_position;\n";
    311 
    312 frag += "\n" +
    313         "void main()\n" +
    314         "{\n";
    315 
    316 if (isVertexCase)
    317 	vtx += '	${PRECISION} vec4 coords = a_coords;\n';
    318 else
    319 	frag += '	${PRECISION} vec4 coords = v_coords;\n';
    320 
    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 }
    335 
    336 // Read array.
    337 op += '	${PRECISION} vec4 res = coords;\n';
    338 
    339 // Loop iteration count.
    340 /** @type {string} */ var iterMaxStr;
    341 
    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 }
    362 
    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;
    368 
    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 }
    381 
    382 // Loop body.
    383 /** @type {string} */ var loopBody = '		res = res.yzwx;\n';;
    384 
    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);
    410 
    411 vtx += isVertexCase ? op : '';
    412 frag += isVertexCase ? '' : op;
    413 op = '';
    414 
    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';
    422 
    423 	if (loopCountType === es3fShaderLoopTests.LoopCountType.LOOPCOUNT_DYNAMIC)
    424 		vtx += '	v_one = a_one;\n';
    425 }
    426 
    427 vtx += '}\n';
    428 frag += '}\n';
    429 
    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);
    435 
    436 /** @type {string} */ var vertexShaderSource = tcuStringTemplate.specialize(vtx, params);
    437 /** @type {string} */ var fragmentShaderSource = tcuStringTemplate.specialize(frag, params);
    438 
    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);
    443 };
    444 
    445 // \todo [petri] Generalize to float as well?
    446 
    447 /**
    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 = '';
    460 
    461    vtx += '#version 300 es\n';
    462    frag += '#version 300 es\n';
    463 
    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';
    467 
    468    if (loopCountType === es3fShaderLoopTests.LoopCountType.LOOPCOUNT_DYNAMIC)
    469        vtx += 'in mediump float a_one;\n';
    470 
    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';
    479 
    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    }
    485 
    486    if (loopCase === es3fShaderLoopTests.LoopCase.LOOPCASE_SELECT_ITERATION_COUNT)
    487        op += 'uniform bool ub_true;\n';
    488 
    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';
    492 
    493    vtx += isVertexCase ? op : '';
    494    frag += isVertexCase ? '' : op;
    495    op = '';
    496 
    497    /** @type {number} */ var iterCount = 3; // value to use in loop
    498    /** @type {number} */ var numIters = 3; // actual number of iterations
    499 
    500    vtx += '\n' +
    501           'void main()\n' +
    502           '{\n' +
    503           '    gl_Position = a_position;\n';
    504 
    505    frag += '\n' +
    506            'void main()\n' +
    507            '{\n';
    508 
    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    }
    515 
    516    if (isVertexCase)
    517        vtx += '    ${PRECISION} vec4 coords = a_coords;\n';
    518    else
    519        frag += '    ${PRECISION} vec4 coords = v_coords;\n';
    520 
    521    // Read array.
    522    op += '    ${PRECISION} vec4 res = coords;\n';
    523 
    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 = '';
    530 
    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;
    537 
    538            case es3fShaderLoopTests.LoopCase.LOOPCASE_INFINITE_WITH_UNCONDITIONAL_BREAK_FIRST:
    539                numIters = 0;
    540                op += '    for (;;) { break; res = res.yzwx; }\n';
    541                break;
    542 
    543            case es3fShaderLoopTests.LoopCase.LOOPCASE_INFINITE_WITH_UNCONDITIONAL_BREAK_LAST:
    544                numIters = 1;
    545                op += '    for (;;) { res = res.yzwx; break; }\n';
    546                break;
    547 
    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;
    553 
    554            case es3fShaderLoopTests.LoopCase.LOOPCASE_SINGLE_STATEMENT:
    555                op += '    ${FOR_LOOP} res = res.yzwx;\n';
    556                break;
    557 
    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;
    563 
    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;
    569 
    570            case es3fShaderLoopTests.LoopCase.LOOPCASE_NO_ITERATIONS:
    571                iterCount = 0;
    572                numIters = 0;
    573                op += '    ${FOR_LOOP} res = res.yzwx;\n';
    574                break;
    575 
    576            case es3fShaderLoopTests.LoopCase.LOOPCASE_SINGLE_ITERATION:
    577                iterCount = 1;
    578                numIters = 1;
    579                op += '    ${FOR_LOOP} res = res.yzwx;\n';
    580                break;
    581 
    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;
    585 
    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;
    590 
    591            case es3fShaderLoopTests.LoopCase.LOOPCASE_UNCONDITIONAL_CONTINUE:
    592                op += '    ${FOR_LOOP} { res = res.yzwx; continue; }\n';
    593                break;
    594 
    595            case es3fShaderLoopTests.LoopCase.LOOPCASE_ONLY_CONTINUE:
    596                numIters = 0;
    597                op += '    ${FOR_LOOP} { continue; }\n';
    598                break;
    599 
    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;
    604 
    605            case es3fShaderLoopTests.LoopCase.LOOPCASE_CONDITIONAL_BREAK:
    606                numIters = 2;
    607                op += '    ${FOR_LOOP} { if (i == ${TWO}) break; res = res.yzwx; }\n';
    608                break;
    609 
    610            case es3fShaderLoopTests.LoopCase.LOOPCASE_UNCONDITIONAL_BREAK:
    611                numIters = 1;
    612                op += '    ${FOR_LOOP} { res = res.yzwx; break; }\n';
    613                break;
    614 
    615            case es3fShaderLoopTests.LoopCase.LOOPCASE_PRE_INCREMENT:
    616                op += '    for (int i = 0; i < ${ITER_COUNT}; ++i) { res = res.yzwx; }\n';
    617                break;
    618 
    619            case es3fShaderLoopTests.LoopCase.LOOPCASE_POST_INCREMENT:
    620                op += '    ${FOR_LOOP} { res = res.yzwx; }\n';
    621                break;
    622 
    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;
    628 
    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;
    632 
    633            case es3fShaderLoopTests.LoopCase.LOOPCASE_101_ITERATIONS:
    634                numIters = iterCount = 101;
    635                op += '    ${FOR_LOOP} res = res.yzwx;\n';
    636                break;
    637 
    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;
    645 
    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;
    654 
    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;
    665 
    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;
    675 
    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;
    686 
    687            default:
    688                throw new Error('Case not supported: ' + loopCase);
    689        }
    690 
    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;
    706 
    707            case es3fShaderLoopTests.LoopCase.LOOPCASE_INFINITE_WITH_UNCONDITIONAL_BREAK_FIRST:
    708                numIters = 0;
    709                op += '    while (true) { break; res = res.yzwx; }\n';
    710                break;
    711 
    712            case es3fShaderLoopTests.LoopCase.LOOPCASE_INFINITE_WITH_UNCONDITIONAL_BREAK_LAST:
    713                numIters = 1;
    714                op += '    while (true) { res = res.yzwx; break; }\n';
    715                break;
    716 
    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;
    722 
    723            case es3fShaderLoopTests.LoopCase.LOOPCASE_SINGLE_STATEMENT:
    724                op += '    ${WHILE_LOOP} res = res.yzwx;\n';
    725                break;
    726 
    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;
    732 
    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;
    738 
    739            case es3fShaderLoopTests.LoopCase.LOOPCASE_NO_ITERATIONS:
    740                iterCount = 0;
    741                numIters = 0;
    742                op += '    ${WHILE_LOOP} res = res.yzwx;\n';
    743                break;
    744 
    745            case es3fShaderLoopTests.LoopCase.LOOPCASE_SINGLE_ITERATION:
    746                iterCount = 1;
    747                numIters = 1;
    748                op += '    ${WHILE_LOOP} res = res.yzwx;\n';
    749                break;
    750 
    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;
    755 
    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;
    760 
    761            case es3fShaderLoopTests.LoopCase.LOOPCASE_UNCONDITIONAL_CONTINUE:
    762                op += '    ${WHILE_LOOP} { res = res.yzwx; continue; }\n';
    763                break;
    764 
    765            case es3fShaderLoopTests.LoopCase.LOOPCASE_ONLY_CONTINUE:
    766                numIters = 0;
    767                op += '    ${WHILE_LOOP} { continue; }\n';
    768                break;
    769 
    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;
    774 
    775            case es3fShaderLoopTests.LoopCase.LOOPCASE_CONDITIONAL_BREAK:
    776                numIters = 2;
    777                op += '    ${WHILE_LOOP} { if (i == ${THREE}) break; res = res.yzwx; }\n';
    778                break;
    779 
    780            case es3fShaderLoopTests.LoopCase.LOOPCASE_UNCONDITIONAL_BREAK:
    781                numIters = 1;
    782                op += '    ${WHILE_LOOP} { res = res.yzwx; break; }\n';
    783                break;
    784 
    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;
    790 
    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;
    795 
    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;
    801 
    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;
    806 
    807            case es3fShaderLoopTests.LoopCase.LOOPCASE_101_ITERATIONS:
    808                numIters = iterCount = 101;
    809                op += '    ${WHILE_LOOP} res = res.yzwx;\n';
    810                break;
    811 
    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;
    819 
    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;
    830 
    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;
    843 
    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;
    854 
    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;
    866 
    867            default:
    868                throw new Error('Loop Case not supported: ' + loopCase);
    869        }
    870 
    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);
    882 
    883        switch (loopCase) {
    884            case es3fShaderLoopTests.LoopCase.LOOPCASE_EMPTY_BODY:
    885                numIters = 0;
    886                op += '    ${DO_WHILE_PRE} {} ${DO_WHILE_POST}\n';
    887                break;
    888 
    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;
    893 
    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;
    898 
    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;
    904 
    905            case es3fShaderLoopTests.LoopCase.LOOPCASE_SINGLE_STATEMENT:
    906                op += '    ${DO_WHILE_PRE} res = res.yzwx; ${DO_WHILE_POST}\n';
    907                break;
    908 
    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;
    914 
    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;
    920 
    921            case es3fShaderLoopTests.LoopCase.LOOPCASE_NO_ITERATIONS:
    922                //assertMsgOptions(false, 'LOOPCASE_NO_ITERATIONS', false, false);
    923                break;
    924 
    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;
    930 
    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;
    935 
    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;
    940 
    941            case es3fShaderLoopTests.LoopCase.LOOPCASE_UNCONDITIONAL_CONTINUE:
    942                op += '    ${DO_WHILE_PRE} { res = res.yzwx; continue; } ${DO_WHILE_POST}\n';
    943                break;
    944 
    945            case es3fShaderLoopTests.LoopCase.LOOPCASE_ONLY_CONTINUE:
    946                numIters = 0;
    947                op += '    ${DO_WHILE_PRE} { continue; } ${DO_WHILE_POST}\n';
    948                break;
    949 
    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;
    954 
    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;
    959 
    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;
    964 
    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;
    969 
    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;
    975 
    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;
    981 
    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;
    986 
    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;
    991 
    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;
    999 
   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;
   1011 
   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;
   1026 
   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;
   1038 
   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;
   1050 
   1051            default:
   1052                throw new Error('Loop Case not supported: ' + loopCase);
   1053        }
   1054 
   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    }
   1065 
   1066 vtx += isVertexCase ? op : '';
   1067 frag += isVertexCase ? '' : op;
   1068 op = '';
   1069 
   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';
   1078 
   1079        if (loopCountType === es3fShaderLoopTests.LoopCountType.LOOPCOUNT_DYNAMIC)
   1080            vtx += '    v_one = a_one;\n';
   1081    }
   1082 
   1083    vtx += '}\n';
   1084    frag += '}\n';
   1085 
   1086    // Constants.
   1087 /** @type {string} */ var oneStr = '';
   1088 /** @type {string} */ var twoStr = '';
   1089 /** @type {string} */ var threeStr = '';
   1090 /** @type {string} */ var iterCountStr = '';
   1091 
   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);
   1111 
   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;
   1124 
   1125 /** @type {string} */ var vertexShaderSource = tcuStringTemplate.specialize(vtx, params);
   1126 /** @type {string} */ var fragmentShaderSource = tcuStringTemplate.specialize(frag, params);
   1127 
   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);
   1132 };
   1133 
   1134 // ShaderLoopTests.
   1135 
   1136 /**
   1137 * @constructor
   1138 * @extends {tcuTestCase.DeqpTest}
   1139 */
   1140 es3fShaderLoopTests.ShaderLoopTests = function() {
   1141    tcuTestCase.DeqpTest.call(this, 'loops', 'Loop Tests');
   1142 };
   1143 
   1144 es3fShaderLoopTests.ShaderLoopTests.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
   1145 es3fShaderLoopTests.ShaderLoopTests.prototype.constructor = es3fShaderLoopTests.ShaderLoopTests;
   1146 
   1147 es3fShaderLoopTests.ShaderLoopTests.prototype.init = function() {
   1148    var testGroup = tcuTestCase.runner.testCases;
   1149    // Loop cases.
   1150 
   1151    /** @type {Array<gluShaderProgram.shaderType>} */ var s_shaderTypes = [
   1152        gluShaderProgram.shaderType.VERTEX,
   1153        gluShaderProgram.shaderType.FRAGMENT
   1154    ];
   1155 
   1156    /** @type {Array<gluShaderUtil.DataType>} */ var s_countDataType = [
   1157        gluShaderUtil.DataType.INT,
   1158        gluShaderUtil.DataType.FLOAT
   1159    ];
   1160 
   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;
   1166 
   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);
   1171 
   1172        for (var loopCountType in es3fShaderLoopTests.LoopCountType) {
   1173            /** @type {string} */ var loopCountName = es3fShaderLoopTests.getLoopCountTypeName(es3fShaderLoopTests.LoopCountType[loopCountType]);
   1174 
   1175            /** @type {string} */ var groupName = loopCountName + '_iterations';
   1176            /** @type {string} */ var groupDesc = 'Loop tests with ' + loopCountName + ' loop counter.';
   1177 
   1178            /** @type {tcuTestCase.DeqpTest} */ var group = tcuTestCase.newTest(groupName, groupDesc);
   1179            loopTypeGroup.addChild(group);
   1180 
   1181            // Generic cases.
   1182 
   1183            for (var precision in gluShaderUtil.precision) {
   1184                /** @type {string} */ var precisionName = gluShaderUtil.getPrecisionName(gluShaderUtil.precision[precision]);
   1185 
   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);
   1189 
   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);
   1194 
   1195 
   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            }
   1202 
   1203            // Special cases.
   1204 
   1205            for (var loopCase in es3fShaderLoopTests.LoopCase) {
   1206                /** @type {string} */ var loopCaseName = es3fShaderLoopTests.getLoopCaseName(es3fShaderLoopTests.LoopCase[loopCase]);
   1207 
   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;
   1211 
   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);
   1216 
   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    }
   1224 };
   1225 
   1226 /**
   1227 * Run test
   1228 * @param {WebGL2RenderingContext} context
   1229 */
   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());
   1235 
   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    }
   1249 };
   1250 
   1251 });