summaryrefslogtreecommitdiffstats
path: root/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fShaderLoopTests.js
diff options
context:
space:
mode:
Diffstat (limited to 'dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fShaderLoopTests.js')
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fShaderLoopTests.js1251
1 files changed, 1251 insertions, 0 deletions
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fShaderLoopTests.js b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fShaderLoopTests.js
new file mode 100644
index 0000000000..822b121bda
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fShaderLoopTests.js
@@ -0,0 +1,1251 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the 'License');
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an 'AS IS' BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+'use strict';
+goog.provide('functional.gles3.es3fShaderLoopTests');
+goog.require('framework.common.tcuStringTemplate');
+goog.require('framework.common.tcuTestCase');
+goog.require('framework.delibs.debase.deMath');
+goog.require('framework.opengl.gluShaderUtil');
+goog.require('framework.opengl.gluShaderProgram');
+goog.require('modules.shared.glsShaderRenderCase');
+
+goog.scope(function() {
+var es3fShaderLoopTests = functional.gles3.es3fShaderLoopTests;
+var tcuTestCase = framework.common.tcuTestCase;
+var deMath = framework.delibs.debase.deMath;
+var gluShaderUtil = framework.opengl.gluShaderUtil;
+var gluShaderProgram = framework.opengl.gluShaderProgram;
+var glsShaderRenderCase = modules.shared.glsShaderRenderCase;
+var tcuStringTemplate = framework.common.tcuStringTemplate;
+// Repeated with for, while, do-while. Examples given as 'for' loops.
+// Repeated for const, uniform, dynamic loops.
+
+/**
+ * @enum {number}
+ */
+es3fShaderLoopTests.LoopCase = {
+ LOOPCASE_EMPTY_BODY: 0, // for (...) { }
+ LOOPCASE_INFINITE_WITH_UNCONDITIONAL_BREAK_FIRST: 1, // for (...) { break; <body>; }
+ LOOPCASE_INFINITE_WITH_UNCONDITIONAL_BREAK_LAST: 2, // for (...) { <body>; break; }
+ LOOPCASE_INFINITE_WITH_CONDITIONAL_BREAK: 3, // for (...) { <body>; if (cond) break; }
+ LOOPCASE_SINGLE_STATEMENT: 4, // for (...) statement;
+ LOOPCASE_COMPOUND_STATEMENT: 5, // for (...) { statement; statement; }
+ LOOPCASE_SEQUENCE_STATEMENT: 6, // for (...) statement, statement;
+ LOOPCASE_NO_ITERATIONS: 7, // for (i=0; i<0; i++) ...
+ LOOPCASE_SINGLE_ITERATION: 8, // for (i=0; i<1; i++) ...
+ LOOPCASE_SELECT_ITERATION_COUNT: 9, // for (i=0; i<a?b:c; i++) ...
+ LOOPCASE_CONDITIONAL_CONTINUE: 10, // for (...) { if (cond) continue; }
+ LOOPCASE_UNCONDITIONAL_CONTINUE: 11, // for (...) { <body>; continue; }
+ LOOPCASE_ONLY_CONTINUE: 12, // for (...) { continue; }
+ LOOPCASE_DOUBLE_CONTINUE: 13, // for (...) { if (cond) continue; <body>; continue; }
+ LOOPCASE_CONDITIONAL_BREAK: 14, // for (...) { if (cond) break; }
+ LOOPCASE_UNCONDITIONAL_BREAK: 15, // for (...) { <body>; break; }
+ LOOPCASE_PRE_INCREMENT: 16, // for (...; ++i) { <body>; }
+ LOOPCASE_POST_INCREMENT: 17, // for (...; i++) { <body>; }
+ LOOPCASE_MIXED_BREAK_CONTINUE: 18,
+ LOOPCASE_VECTOR_COUNTER: 19, // for (ivec3 ndx = ...; ndx.x < ndx.y; ndx.x += ndx.z) { ... }
+ LOOPCASE_101_ITERATIONS: 20, // loop for 101 iterations
+ LOOPCASE_SEQUENCE: 21, // two loops in sequence
+ LOOPCASE_NESTED: 22, // two nested loops
+ LOOPCASE_NESTED_SEQUENCE: 23, // two loops in sequence nested inside a third
+ LOOPCASE_NESTED_TRICKY_DATAFLOW_1: 24, // nested loops with tricky data flow
+ LOOPCASE_NESTED_TRICKY_DATAFLOW_2: 25 // nested loops with tricky data flow
+};
+
+/**
+ * @param {es3fShaderLoopTests.LoopCase} loopCase
+ * @return {string}
+ */
+es3fShaderLoopTests.getLoopCaseName = function(loopCase) {
+ /** @type {Array<string>} */ var s_names = [
+ 'empty_body',
+ 'infinite_with_unconditional_break_first',
+ 'infinite_with_unconditional_break_last',
+ 'infinite_with_conditional_break',
+ 'single_statement',
+ 'compound_statement',
+ 'sequence_statement',
+ 'no_iterations',
+ 'single_iteration',
+ 'select_iteration_count',
+ 'conditional_continue',
+ 'unconditional_continue',
+ 'only_continue',
+ 'double_continue',
+ 'conditional_break',
+ 'unconditional_break',
+ 'pre_increment',
+ 'post_increment',
+ 'mixed_break_continue',
+ 'vector_counter',
+ '101_iterations',
+ 'sequence',
+ 'nested',
+ 'nested_sequence',
+ 'nested_tricky_dataflow_1',
+ 'nested_tricky_dataflow_2'
+ ];
+ // DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(s_names) == es3fShaderLoopTests.LoopCase.LOOPCASE_LAST);
+ // DE_ASSERT(deInBounds32((int)loopCase, 0, LOOPCASE_LAST));
+ return s_names[loopCase];
+};
+
+// Complex loop cases.
+
+/*enum LoopBody
+{
+ LOOPBODY_READ_UNIFORM = 0,
+ LOOPBODY_READ_UNIFORM_ARRAY,
+ LOOPBODY_READ_
+};*/
+
+/**
+ * @enum {number}
+ */
+es3fShaderLoopTests.LoopType = {
+ LOOPTYPE_FOR: 0,
+ LOOPTYPE_WHILE: 1,
+ LOOPTYPE_DO_WHILE: 2
+};
+
+/**
+ * @param {es3fShaderLoopTests.LoopType} loopType
+ * @return {string}
+ */
+es3fShaderLoopTests.getLoopTypeName = function(loopType) {
+ /** @type {Array<string>} */ var s_names = [
+ 'for',
+ 'while',
+ 'do_while'
+ ];
+
+ // DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(s_names) === es3fShaderLoopTests.LoopType.LOOPTYPE_LAST);
+ // DE_ASSERT(deInBounds32((int)loopType, 0, LOOPTYPE_LAST));
+ return s_names[loopType];
+};
+
+/**
+ * @enum {number}
+ */
+es3fShaderLoopTests.LoopCountType = {
+ LOOPCOUNT_CONSTANT: 0,
+ LOOPCOUNT_UNIFORM: 1,
+ LOOPCOUNT_DYNAMIC: 2
+};
+
+/**
+ * @param {es3fShaderLoopTests.LoopCountType} countType
+ * @return {string}
+ */
+es3fShaderLoopTests.getLoopCountTypeName = function(countType) {
+ /** @type {Array<string>} */ var s_names = [
+ 'constant',
+ 'uniform',
+ 'dynamic'
+ ];
+
+ // DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(s_names) == es3fShaderLoopTests.LoopCountType.LOOPCOUNT_LAST);
+ // DE_ASSERT(deInBounds32((int)countType, 0, es3fShaderLoopTests.LoopCountType.LOOPCOUNT_LAST));
+ return s_names[countType];
+};
+
+/**
+ * @param {glsShaderRenderCase.ShaderEvalContext} c
+ */
+es3fShaderLoopTests.evalLoop0Iters = function(c) {
+ var swizzled = deMath.swizzle(c.coords, [0, 1, 2]);
+ c.color[0] = swizzled[0];
+ c.color[1] = swizzled[1];
+ c.color[2] = swizzled[2];
+};
+
+/**
+ * @param {glsShaderRenderCase.ShaderEvalContext} c
+ */
+es3fShaderLoopTests.evalLoop1Iters = function(c) {
+ var swizzled = deMath.swizzle(c.coords, [1, 2, 3]);
+ c.color[0] = swizzled[0];
+ c.color[1] = swizzled[1];
+ c.color[2] = swizzled[2];
+};
+
+/**
+ * @param {glsShaderRenderCase.ShaderEvalContext} c
+ */
+es3fShaderLoopTests.evalLoop2Iters = function(c) {
+ var swizzled = deMath.swizzle(c.coords, [2, 3, 0]);
+ c.color[0] = swizzled[0];
+ c.color[1] = swizzled[1];
+ c.color[2] = swizzled[2];
+};
+
+/**
+ * @param {glsShaderRenderCase.ShaderEvalContext} c
+ */
+es3fShaderLoopTests.evalLoop3Iters = function(c) {
+ var swizzled = deMath.swizzle(c.coords, [3, 0, 1]);
+ c.color[0] = swizzled[0];
+ c.color[1] = swizzled[1];
+ c.color[2] = swizzled[2];
+};
+
+/**
+ * @param {number} numIters
+ * @return {glsShaderRenderCase.ShaderEvalFunc}
+ */
+es3fShaderLoopTests.getLoopEvalFunc = function(numIters) {
+ switch (numIters % 4) {
+ case 0: return es3fShaderLoopTests.evalLoop0Iters;
+ case 1: return es3fShaderLoopTests.evalLoop1Iters;
+ case 2: return es3fShaderLoopTests.evalLoop2Iters;
+ case 3: return es3fShaderLoopTests.evalLoop3Iters;
+ }
+
+ throw new Error('Invalid loop iteration count.');
+};
+
+// ShaderLoopCase
+
+/**
+ * @constructor
+ * @extends {glsShaderRenderCase.ShaderRenderCase}
+ * @param {string} name
+ * @param {string} description
+ * @param {boolean} isVertexCase
+ * @param {glsShaderRenderCase.ShaderEvalFunc} evalFunc
+ * @param {string} vertShaderSource
+ * @param {string} fragShaderSource
+ */
+es3fShaderLoopTests.ShaderLoopCase = function(name, description, isVertexCase, evalFunc, vertShaderSource, fragShaderSource) {
+ glsShaderRenderCase.ShaderRenderCase.call(this, name, description, isVertexCase, evalFunc);
+ /** @type {string} */ this.m_vertShaderSource = vertShaderSource;
+ /** @type {string} */ this.m_fragShaderSource = fragShaderSource;
+};
+
+es3fShaderLoopTests.ShaderLoopCase.prototype = Object.create(glsShaderRenderCase.ShaderRenderCase.prototype);
+es3fShaderLoopTests.ShaderLoopCase.prototype.constructor = es3fShaderLoopTests.ShaderLoopCase;
+
+// Test case creation.
+
+/**
+ * @param {string} caseName
+ * @param {string} description
+ * @param {boolean} isVertexCase
+ * @param {es3fShaderLoopTests.LoopType} loopType
+ * @param {es3fShaderLoopTests.LoopCountType} loopCountType
+ * @param {gluShaderUtil.precision} loopCountPrecision
+ * @param {gluShaderUtil.DataType} loopCountDataType
+ * @return {es3fShaderLoopTests.ShaderLoopCase}
+ */
+es3fShaderLoopTests.createGenericLoopCase = function(caseName, description, isVertexCase, loopType, loopCountType, loopCountPrecision, loopCountDataType) {
+ /** @type {string} */ var vtx = '';
+ /** @type {string} */ var frag = '';
+ /** @type {string} */ var op = '';
+
+ vtx += '#version 300 es\n';
+ frag += '#version 300 es\n';
+
+ vtx += 'in highp vec4 a_position;\n';
+ vtx += 'in highp vec4 a_coords;\n';
+ frag += 'layout(location = 0) out mediump vec4 o_color;\n';
+
+ if (loopCountType === es3fShaderLoopTests.LoopCountType.LOOPCOUNT_DYNAMIC)
+ vtx += 'in mediump float a_one;\n';
+
+ if (isVertexCase) {
+ vtx += 'out mediump vec3 v_color;\n';
+ frag += 'in mediump vec3 v_color;\n';
+ }
+ else {
+ vtx += 'out mediump vec4 v_coords;\n';
+ frag += 'in mediump vec4 v_coords;\n';
+
+ if (loopCountType === es3fShaderLoopTests.LoopCountType.LOOPCOUNT_DYNAMIC) {
+ vtx += 'out mediump float v_one;\n';
+ frag += 'in mediump float v_one;\n';
+ }
+ }
+
+ // \todo [petri] Pass numLoopIters from outside?
+ /** @type {number} */ var numLoopIters = 3;
+ /** @type {boolean} */ var isIntCounter = gluShaderUtil.isDataTypeIntOrIVec(loopCountDataType);
+
+ if (isIntCounter) {
+ if (loopCountType === es3fShaderLoopTests.LoopCountType.LOOPCOUNT_UNIFORM || loopCountType === es3fShaderLoopTests.LoopCountType.LOOPCOUNT_DYNAMIC)
+ op += 'uniform ${COUNTER_PRECISION} int ' + glsShaderRenderCase.getIntUniformName(numLoopIters) + ';\n';
+ }
+ else {
+ if (loopCountType === es3fShaderLoopTests.LoopCountType.LOOPCOUNT_UNIFORM || loopCountType === es3fShaderLoopTests.LoopCountType.LOOPCOUNT_DYNAMIC)
+ op += 'uniform ${COUNTER_PRECISION} float ' + glsShaderRenderCase.getFloatFractionUniformName(numLoopIters) + ';\n';
+
+ if (numLoopIters != 1)
+ op += 'uniform ${COUNTER_PRECISION} float uf_one;\n';
+ }
+
+ vtx += isVertexCase ? op : '';
+ frag += isVertexCase ? '' : op;
+ op = '';
+
+ vtx += "\n" +
+ "void main()\n" +
+ "{\n" +
+ " gl_Position = a_position;\n";
+
+ frag += "\n" +
+ "void main()\n" +
+ "{\n";
+
+ if (isVertexCase)
+ vtx += ' ${PRECISION} vec4 coords = a_coords;\n';
+ else
+ frag += ' ${PRECISION} vec4 coords = v_coords;\n';
+
+ if (loopCountType === es3fShaderLoopTests.LoopCountType.LOOPCOUNT_DYNAMIC) {
+ if (isIntCounter) {
+ if (isVertexCase)
+ vtx += ' ${COUNTER_PRECISION} int one = int(a_one + 0.5);\n';
+ else
+ frag += ' ${COUNTER_PRECISION} int one = int(v_one + 0.5);\n';
+ }
+ else {
+ if (isVertexCase)
+ vtx += ' ${COUNTER_PRECISION} float one = a_one;\n';
+ else
+ frag += ' ${COUNTER_PRECISION} float one = v_one;\n';
+ }
+ }
+
+ // Read array.
+ op += ' ${PRECISION} vec4 res = coords;\n';
+
+ // Loop iteration count.
+ /** @type {string} */ var iterMaxStr;
+
+ if (isIntCounter) {
+ if (loopCountType === es3fShaderLoopTests.LoopCountType.LOOPCOUNT_CONSTANT)
+ iterMaxStr = numLoopIters.toString();
+ else if (loopCountType === es3fShaderLoopTests.LoopCountType.LOOPCOUNT_UNIFORM)
+ iterMaxStr = glsShaderRenderCase.getIntUniformName(numLoopIters);
+ else if (loopCountType === es3fShaderLoopTests.LoopCountType.LOOPCOUNT_DYNAMIC)
+ iterMaxStr = glsShaderRenderCase.getIntUniformName(numLoopIters) + '*one';
+ else
+ throw new Error('Loop Count Type not supported: ' + loopCountType);
+ }
+ else {
+ if (loopCountType === es3fShaderLoopTests.LoopCountType.LOOPCOUNT_CONSTANT)
+ iterMaxStr = '1.0';
+ else if (loopCountType === es3fShaderLoopTests.LoopCountType.LOOPCOUNT_UNIFORM)
+ iterMaxStr = 'uf_one';
+ else if (loopCountType === es3fShaderLoopTests.LoopCountType.LOOPCOUNT_DYNAMIC)
+ iterMaxStr = 'uf_one*one';
+ else
+ throw new Error('Loop Count Type not supported: ' + loopCountType);
+ }
+
+ // Loop operations.
+ /** @type {string} */ var initValue = isIntCounter ? '0' : '0.05';
+ /** @type {string} */ var loopCountDeclStr = '' + gluShaderUtil.getPrecisionName(loopCountPrecision) + ' ' + gluShaderUtil.getDataTypeName(loopCountDataType) + ' ndx = ' + initValue;
+ /** @type {string} */ var loopCmpStr = 'ndx < ' + iterMaxStr;
+ /** @type {string} */ var incrementStr;
+
+ if (isIntCounter)
+ incrementStr = 'ndx++';
+ else {
+ if (loopCountType === es3fShaderLoopTests.LoopCountType.LOOPCOUNT_CONSTANT)
+ incrementStr = 'ndx += ' + (1.0 / numLoopIters);
+ else if (loopCountType === es3fShaderLoopTests.LoopCountType.LOOPCOUNT_UNIFORM)
+ incrementStr = 'ndx += ' + glsShaderRenderCase.getFloatFractionUniformName(numLoopIters);
+ else if (loopCountType === es3fShaderLoopTests.LoopCountType.LOOPCOUNT_DYNAMIC)
+ incrementStr = 'ndx += ' + glsShaderRenderCase.getFloatFractionUniformName(numLoopIters) + '*one';
+ else
+ throw new Error('Loop Count Type not supported: ' + loopCountType);
+ }
+
+ // Loop body.
+ /** @type {string} */ var loopBody = ' res = res.yzwx;\n';;
+
+ if (loopType === es3fShaderLoopTests.LoopType.LOOPTYPE_FOR) {
+ op += ' for (' + loopCountDeclStr + '; ' + loopCmpStr + '; ' + incrementStr + ')\n' +
+ ' {\n' +
+ loopBody +
+ ' }\n';
+ }
+ else if (loopType === es3fShaderLoopTests.LoopType.LOOPTYPE_WHILE) {
+ op += '\t' + loopCountDeclStr + ';\n' +
+ ' while (' + loopCmpStr + ')\n' +
+ ' {\n' +
+ loopBody +
+ '\t\t' + incrementStr + ';\n' +
+ ' }\n';
+ }
+ else if (loopType === es3fShaderLoopTests.LoopType.LOOPTYPE_DO_WHILE)
+ {
+ op += '\t' + loopCountDeclStr + ';\n' +
+ ' do\n' +
+ ' {\n' +
+ loopBody +
+ '\t\t' + incrementStr + ';\n' +
+ ' } while (' + loopCmpStr + ');\n';
+ }
+ else
+ throw new Error('Loop Type not supported: ' + loopType);
+
+ vtx += isVertexCase ? op : '';
+ frag += isVertexCase ? '' : op;
+ op = '';
+
+ if (isVertexCase) {
+ vtx += ' v_color = res.rgb;\n';
+ frag += ' o_color = vec4(v_color.rgb, 1.0);\n';
+ }
+ else {
+ vtx += ' v_coords = a_coords;\n';
+ frag += ' o_color = vec4(res.rgb, 1.0);\n';
+
+ if (loopCountType === es3fShaderLoopTests.LoopCountType.LOOPCOUNT_DYNAMIC)
+ vtx += ' v_one = a_one;\n';
+ }
+
+ vtx += '}\n';
+ frag += '}\n';
+
+ // Fill in shader templates.
+ /** @type {Object} */ var params = {};
+ params['LOOP_VAR_TYPE'] = gluShaderUtil.getDataTypeName(loopCountDataType);
+ params['PRECISION'] = 'mediump';
+ params['COUNTER_PRECISION'] = gluShaderUtil.getPrecisionName(loopCountPrecision);
+
+ /** @type {string} */ var vertexShaderSource = tcuStringTemplate.specialize(vtx, params);
+ /** @type {string} */ var fragmentShaderSource = tcuStringTemplate.specialize(frag, params);
+
+ // Create the case.
+ /** @type {glsShaderRenderCase.ShaderEvalFunc} */
+ var evalFunc = es3fShaderLoopTests.getLoopEvalFunc(numLoopIters);
+ return new es3fShaderLoopTests.ShaderLoopCase(caseName, description, isVertexCase, evalFunc, vertexShaderSource, fragmentShaderSource);
+};
+
+// \todo [petri] Generalize to float as well?
+
+/**
+ * @param {string} caseName
+ * @param {string} description
+ * @param {boolean} isVertexCase
+ * @param {es3fShaderLoopTests.LoopCase} loopCase
+ * @param {es3fShaderLoopTests.LoopType} loopType
+ * @param {es3fShaderLoopTests.LoopCountType} loopCountType
+ * @return {es3fShaderLoopTests.ShaderLoopCase}
+ */
+es3fShaderLoopTests.createSpecialLoopCase = function(caseName, description, isVertexCase, loopCase, loopType, loopCountType) {
+ /** @type {string} */ var vtx = '';
+ /** @type {string} */ var frag = '';
+ /** @type {string} */ var op = '';
+
+ vtx += '#version 300 es\n';
+ frag += '#version 300 es\n';
+
+ vtx += 'in highp vec4 a_position;\n';
+ vtx += 'in highp vec4 a_coords;\n';
+ frag += 'layout(location = 0) out mediump vec4 o_color;\n';
+
+ if (loopCountType === es3fShaderLoopTests.LoopCountType.LOOPCOUNT_DYNAMIC)
+ vtx += 'in mediump float a_one;\n';
+
+ // Attribute and varyings.
+ if (isVertexCase) {
+ vtx += 'out mediump vec3 v_color;\n';
+ frag += 'in mediump vec3 v_color;\n';
+ }
+ else {
+ vtx += 'out mediump vec4 v_coords;\n';
+ frag += 'in mediump vec4 v_coords;\n';
+
+ if (loopCountType === es3fShaderLoopTests.LoopCountType.LOOPCOUNT_DYNAMIC) {
+ vtx += 'out mediump float v_one;\n';
+ frag += 'in mediump float v_one;\n';
+ }
+ }
+
+ if (loopCase === es3fShaderLoopTests.LoopCase.LOOPCASE_SELECT_ITERATION_COUNT)
+ op += 'uniform bool ub_true;\n';
+
+ op += 'uniform ${COUNTER_PRECISION} int ui_zero, ui_one, ui_two, ui_three, ui_four, ui_five, ui_six;\n';
+ if (loopCase === es3fShaderLoopTests.LoopCase.LOOPCASE_101_ITERATIONS)
+ op += 'uniform ${COUNTER_PRECISION} int ui_oneHundredOne;\n';
+
+ vtx += isVertexCase ? op : '';
+ frag += isVertexCase ? '' : op;
+ op = '';
+
+ /** @type {number} */ var iterCount = 3; // value to use in loop
+ /** @type {number} */ var numIters = 3; // actual number of iterations
+
+ vtx += '\n' +
+ 'void main()\n' +
+ '{\n' +
+ ' gl_Position = a_position;\n';
+
+ frag += '\n' +
+ 'void main()\n' +
+ '{\n';
+
+ if (loopCountType === es3fShaderLoopTests.LoopCountType.LOOPCOUNT_DYNAMIC) {
+ if (isVertexCase)
+ vtx += ' ${COUNTER_PRECISION} int one = int(a_one + 0.5);\n';
+ else
+ frag += ' ${COUNTER_PRECISION} int one = int(v_one + 0.5);\n';
+ }
+
+ if (isVertexCase)
+ vtx += ' ${PRECISION} vec4 coords = a_coords;\n';
+ else
+ frag += ' ${PRECISION} vec4 coords = v_coords;\n';
+
+ // Read array.
+ op += ' ${PRECISION} vec4 res = coords;\n';
+
+ // Handle all loop types.
+ /** @type {string} */ var counterPrecisionStr = 'mediump';
+ /** @type {string} */ var forLoopStr = '';
+ /** @type {string} */ var whileLoopStr = '';
+ /** @type {string} */ var doWhileLoopPreStr = '';
+ /** @type {string} */ var doWhileLoopPostStr = '';
+
+ if (loopType === es3fShaderLoopTests.LoopType.LOOPTYPE_FOR) {
+ switch (loopCase) {
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_EMPTY_BODY:
+ numIters = 0;
+ op += ' ${FOR_LOOP} {}\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_INFINITE_WITH_UNCONDITIONAL_BREAK_FIRST:
+ numIters = 0;
+ op += ' for (;;) { break; res = res.yzwx; }\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_INFINITE_WITH_UNCONDITIONAL_BREAK_LAST:
+ numIters = 1;
+ op += ' for (;;) { res = res.yzwx; break; }\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_INFINITE_WITH_CONDITIONAL_BREAK:
+ numIters = 2;
+ op += ' ${COUNTER_PRECISION} int i = 0;\n' +
+ ' for (;;) { res = res.yzwx; if (i == ${ONE}) break; i++; }\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_SINGLE_STATEMENT:
+ op += ' ${FOR_LOOP} res = res.yzwx;\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_COMPOUND_STATEMENT:
+ iterCount = 2;
+ numIters = 2 * iterCount;
+ op += ' ${FOR_LOOP} { res = res.yzwx; res = res.yzwx; }\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_SEQUENCE_STATEMENT:
+ iterCount = 2;
+ numIters = 2 * iterCount;
+ op += ' ${FOR_LOOP} res = res.yzwx, res = res.yzwx;\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_NO_ITERATIONS:
+ iterCount = 0;
+ numIters = 0;
+ op += ' ${FOR_LOOP} res = res.yzwx;\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_SINGLE_ITERATION:
+ iterCount = 1;
+ numIters = 1;
+ op += ' ${FOR_LOOP} res = res.yzwx;\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_SELECT_ITERATION_COUNT:
+ op += ' for (int i = 0; i < (ub_true ? ${ITER_COUNT} : 0); i++) res = res.yzwx;\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_CONDITIONAL_CONTINUE:
+ numIters = iterCount - 1;
+ op += ' ${FOR_LOOP} { if (i == ${TWO}) continue; res = res.yzwx; }\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_UNCONDITIONAL_CONTINUE:
+ op += ' ${FOR_LOOP} { res = res.yzwx; continue; }\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_ONLY_CONTINUE:
+ numIters = 0;
+ op += ' ${FOR_LOOP} { continue; }\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_DOUBLE_CONTINUE:
+ numIters = iterCount - 1;
+ op += ' ${FOR_LOOP} { if (i == ${TWO}) continue; res = res.yzwx; continue; }\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_CONDITIONAL_BREAK:
+ numIters = 2;
+ op += ' ${FOR_LOOP} { if (i == ${TWO}) break; res = res.yzwx; }\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_UNCONDITIONAL_BREAK:
+ numIters = 1;
+ op += ' ${FOR_LOOP} { res = res.yzwx; break; }\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_PRE_INCREMENT:
+ op += ' for (int i = 0; i < ${ITER_COUNT}; ++i) { res = res.yzwx; }\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_POST_INCREMENT:
+ op += ' ${FOR_LOOP} { res = res.yzwx; }\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_MIXED_BREAK_CONTINUE:
+ numIters = 2;
+ iterCount = 5;
+ op += ' ${FOR_LOOP} { if (i == 0) continue; else if (i == 3) break; res = res.yzwx; }\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_VECTOR_COUNTER:
+ op += ' for (${COUNTER_PRECISION} ivec4 i = ivec4(0, 1, ${ITER_COUNT}, 0); i.x < i.z; i.x += i.y) { res = res.yzwx; }\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_101_ITERATIONS:
+ numIters = iterCount = 101;
+ op += ' ${FOR_LOOP} res = res.yzwx;\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_SEQUENCE:
+ iterCount = 5;
+ numIters = 5;
+ op += ' ${COUNTER_PRECISION} int i;\n' +
+ ' for (i = 0; i < ${TWO}; i++) { res = res.yzwx; }\n' +
+ ' for (; i < ${ITER_COUNT}; i++) { res = res.yzwx; }\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_NESTED:
+ numIters = 2 * iterCount;
+ op += ' for (${COUNTER_PRECISION} int i = 0; i < ${TWO}; i++)\n' +
+ ' {\n' +
+ ' for (${COUNTER_PRECISION} int j = 0; j < ${ITER_COUNT}; j++)\n' +
+ ' res = res.yzwx;\n' +
+ ' }\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_NESTED_SEQUENCE:
+ numIters = 3 * iterCount;
+ op += ' for (${COUNTER_PRECISION} int i = 0; i < ${ITER_COUNT}; i++)\n' +
+ ' {\n' +
+ ' for (${COUNTER_PRECISION} int j = 0; j < ${TWO}; j++)\n' +
+ ' res = res.yzwx;\n' +
+ ' for (${COUNTER_PRECISION} int j = 0; j < ${ONE}; j++)\n' +
+ ' res = res.yzwx;\n' +
+ ' }\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_NESTED_TRICKY_DATAFLOW_1:
+ numIters = 2;
+ op += ' ${FOR_LOOP}\n' +
+ ' {\n' +
+ ' res = coords; // ignore outer loop effect \n' +
+ ' for (${COUNTER_PRECISION} int j = 0; j < ${TWO}; j++)\n' +
+ ' res = res.yzwx;\n' +
+ ' }\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_NESTED_TRICKY_DATAFLOW_2:
+ numIters = iterCount;
+ op += ' ${FOR_LOOP}\n' +
+ ' {\n' +
+ ' res = coords.wxyz;\n' +
+ ' for (${COUNTER_PRECISION} int j = 0; j < ${TWO}; j++)\n' +
+ ' res = res.yzwx;\n' +
+ ' coords = res;\n' +
+ ' }\n';
+ break;
+
+ default:
+ throw new Error('Case not supported: ' + loopCase);
+ }
+
+ if (loopCountType === es3fShaderLoopTests.LoopCountType.LOOPCOUNT_CONSTANT)
+ forLoopStr = 'for (' + counterPrecisionStr + ' int i = 0; i < ' + iterCount + '; i++)';
+ else if (loopCountType === es3fShaderLoopTests.LoopCountType.LOOPCOUNT_UNIFORM)
+ forLoopStr = 'for (' + counterPrecisionStr + ' int i = 0; i < ' + glsShaderRenderCase.getIntUniformName(iterCount) + '; i++)';
+ else if (loopCountType === es3fShaderLoopTests.LoopCountType.LOOPCOUNT_DYNAMIC)
+ forLoopStr = 'for (' + counterPrecisionStr + ' int i = 0; i < one*' + glsShaderRenderCase.getIntUniformName(iterCount) + '; i++)';
+ else
+ throw new Error('Loop Count Type not supported: ' + loopCountType);
+ }
+ else if (loopType === es3fShaderLoopTests.LoopType.LOOPTYPE_WHILE) {
+ switch (loopCase) {
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_EMPTY_BODY:
+ numIters = 0;
+ op += ' ${WHILE_LOOP} {}\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_INFINITE_WITH_UNCONDITIONAL_BREAK_FIRST:
+ numIters = 0;
+ op += ' while (true) { break; res = res.yzwx; }\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_INFINITE_WITH_UNCONDITIONAL_BREAK_LAST:
+ numIters = 1;
+ op += ' while (true) { res = res.yzwx; break; }\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_INFINITE_WITH_CONDITIONAL_BREAK:
+ numIters = 2;
+ op += ' ${COUNTER_PRECISION} int i = 0;\n' +
+ ' while (true) { res = res.yzwx; if (i == ${ONE}) break; i++; }\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_SINGLE_STATEMENT:
+ op += ' ${WHILE_LOOP} res = res.yzwx;\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_COMPOUND_STATEMENT:
+ iterCount = 2;
+ numIters = 2 * iterCount;
+ op += ' ${WHILE_LOOP} { res = res.yzwx; res = res.yzwx; }\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_SEQUENCE_STATEMENT:
+ iterCount = 2;
+ numIters = 2 * iterCount;
+ op += ' ${WHILE_LOOP} res = res.yzwx, res = res.yzwx;\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_NO_ITERATIONS:
+ iterCount = 0;
+ numIters = 0;
+ op += ' ${WHILE_LOOP} res = res.yzwx;\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_SINGLE_ITERATION:
+ iterCount = 1;
+ numIters = 1;
+ op += ' ${WHILE_LOOP} res = res.yzwx;\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_SELECT_ITERATION_COUNT:
+ op += ' ${COUNTER_PRECISION} int i = 0;\n' +
+ ' while (i < (ub_true ? ${ITER_COUNT} : 0)) { res = res.yzwx; i++; }\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_CONDITIONAL_CONTINUE:
+ numIters = iterCount - 1;
+ op += ' ${WHILE_LOOP} { if (i == ${TWO}) continue; res = res.yzwx; }\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_UNCONDITIONAL_CONTINUE:
+ op += ' ${WHILE_LOOP} { res = res.yzwx; continue; }\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_ONLY_CONTINUE:
+ numIters = 0;
+ op += ' ${WHILE_LOOP} { continue; }\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_DOUBLE_CONTINUE:
+ numIters = iterCount - 1;
+ op += ' ${WHILE_LOOP} { if (i == ${ONE}) continue; res = res.yzwx; continue; }\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_CONDITIONAL_BREAK:
+ numIters = 2;
+ op += ' ${WHILE_LOOP} { if (i == ${THREE}) break; res = res.yzwx; }\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_UNCONDITIONAL_BREAK:
+ numIters = 1;
+ op += ' ${WHILE_LOOP} { res = res.yzwx; break; }\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_PRE_INCREMENT:
+ numIters = iterCount - 1;
+ op += ' ${COUNTER_PRECISION} int i = 0;\n' +
+ ' while (++i < ${ITER_COUNT}) { res = res.yzwx; }\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_POST_INCREMENT:
+ op += ' ${COUNTER_PRECISION} int i = 0;\n' +
+ ' while (i++ < ${ITER_COUNT}) { res = res.yzwx; }\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_MIXED_BREAK_CONTINUE:
+ numIters = 2;
+ iterCount = 5;
+ op += ' ${WHILE_LOOP} { if (i == 0) continue; else if (i == 3) break; res = res.yzwx; }\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_VECTOR_COUNTER:
+ op += ' ${COUNTER_PRECISION} ivec4 i = ivec4(0, 1, ${ITER_COUNT}, 0);\n' +
+ ' while (i.x < i.z) { res = res.yzwx; i.x += i.y; }\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_101_ITERATIONS:
+ numIters = iterCount = 101;
+ op += ' ${WHILE_LOOP} res = res.yzwx;\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_SEQUENCE:
+ iterCount = 6;
+ numIters = iterCount - 1;
+ op += ' ${COUNTER_PRECISION} int i = 0;\n' +
+ ' while (i++ < ${TWO}) { res = res.yzwx; }\n' +
+ ' while (i++ < ${ITER_COUNT}) { res = res.yzwx; }\n'; // \note skips one iteration
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_NESTED:
+ numIters = 2 * iterCount;
+ op += ' ${COUNTER_PRECISION} int i = 0;\n' +
+ ' while (i++ < ${TWO})\n' +
+ ' {\n' +
+ ' ${COUNTER_PRECISION} int j = 0;\n' +
+ ' while (j++ < ${ITER_COUNT})\n' +
+ ' res = res.yzwx;\n' +
+ ' }\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_NESTED_SEQUENCE:
+ numIters = 2 * iterCount;
+ op += ' ${COUNTER_PRECISION} int i = 0;\n' +
+ ' while (i++ < ${ITER_COUNT})\n' +
+ ' {\n' +
+ ' ${COUNTER_PRECISION} int j = 0;\n' +
+ ' while (j++ < ${ONE})\n' +
+ ' res = res.yzwx;\n' +
+ ' while (j++ < ${THREE})\n' + // \note skips one iteration
+ ' res = res.yzwx;\n' +
+ ' }\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_NESTED_TRICKY_DATAFLOW_1:
+ numIters = 2;
+ op += ' ${WHILE_LOOP}\n' +
+ ' {\n' +
+ ' res = coords; // ignore outer loop effect \n' +
+ ' ${COUNTER_PRECISION} int j = 0;\n' +
+ ' while (j++ < ${TWO})\n' +
+ ' res = res.yzwx;\n' +
+ ' }\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_NESTED_TRICKY_DATAFLOW_2:
+ numIters = iterCount;
+ op += ' ${WHILE_LOOP}\n' +
+ ' {\n' +
+ ' res = coords.wxyz;\n' +
+ ' ${COUNTER_PRECISION} int j = 0;\n' +
+ ' while (j++ < ${TWO})\n' +
+ ' res = res.yzwx;\n' +
+ ' coords = res;\n' +
+ ' }\n';
+ break;
+
+ default:
+ throw new Error('Loop Case not supported: ' + loopCase);
+ }
+
+ if (loopCountType === es3fShaderLoopTests.LoopCountType.LOOPCOUNT_CONSTANT)
+ whileLoopStr = '\t' + counterPrecisionStr + ' int i = 0;\n' + ' while(i++ < ' + iterCount + ')';
+ else if (loopCountType === es3fShaderLoopTests.LoopCountType.LOOPCOUNT_UNIFORM)
+ whileLoopStr = '\t' + counterPrecisionStr + ' int i = 0;\n' + ' while(i++ < ' + glsShaderRenderCase.getIntUniformName(iterCount) + ')';
+ else if (loopCountType === es3fShaderLoopTests.LoopCountType.LOOPCOUNT_DYNAMIC)
+ whileLoopStr = '\t' + counterPrecisionStr + ' int i = 0;\n' + ' while(i++ < one*' + glsShaderRenderCase.getIntUniformName(iterCount) + ')';
+ else
+ throw new Error('Loop Count Type not supported: ' + loopCountType);
+ }
+ else {
+ assertMsgOptions(loopType === es3fShaderLoopTests.LoopType.LOOPTYPE_DO_WHILE, 'Expected LOOPTYPE_DO_WHILE', false, true);
+
+ switch (loopCase) {
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_EMPTY_BODY:
+ numIters = 0;
+ op += ' ${DO_WHILE_PRE} {} ${DO_WHILE_POST}\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_INFINITE_WITH_UNCONDITIONAL_BREAK_FIRST:
+ numIters = 0;
+ op += ' do { break; res = res.yzwx; } while (true);\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_INFINITE_WITH_UNCONDITIONAL_BREAK_LAST:
+ numIters = 1;
+ op += ' do { res = res.yzwx; break; } while (true);\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_INFINITE_WITH_CONDITIONAL_BREAK:
+ numIters = 2;
+ op += ' ${COUNTER_PRECISION} int i = 0;\n' +
+ ' do { res = res.yzwx; if (i == ${ONE}) break; i++; } while (true);\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_SINGLE_STATEMENT:
+ op += ' ${DO_WHILE_PRE} res = res.yzwx; ${DO_WHILE_POST}\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_COMPOUND_STATEMENT:
+ iterCount = 2;
+ numIters = 2 * iterCount;
+ op += ' ${DO_WHILE_PRE} { res = res.yzwx; res = res.yzwx; } ${DO_WHILE_POST}\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_SEQUENCE_STATEMENT:
+ iterCount = 2;
+ numIters = 2 * iterCount;
+ op += ' ${DO_WHILE_PRE} res = res.yzwx, res = res.yzwx; ${DO_WHILE_POST}\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_NO_ITERATIONS:
+ //assertMsgOptions(false, 'LOOPCASE_NO_ITERATIONS', false, false);
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_SINGLE_ITERATION:
+ iterCount = 1;
+ numIters = 1;
+ op += ' ${DO_WHILE_PRE} res = res.yzwx; ${DO_WHILE_POST}\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_SELECT_ITERATION_COUNT:
+ op += ' ${COUNTER_PRECISION} int i = 0;\n' +
+ ' do { res = res.yzwx; } while (++i < (ub_true ? ${ITER_COUNT} : 0));\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_CONDITIONAL_CONTINUE:
+ numIters = iterCount - 1;
+ op += ' ${DO_WHILE_PRE} { if (i == ${TWO}) continue; res = res.yzwx; } ${DO_WHILE_POST}\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_UNCONDITIONAL_CONTINUE:
+ op += ' ${DO_WHILE_PRE} { res = res.yzwx; continue; } ${DO_WHILE_POST}\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_ONLY_CONTINUE:
+ numIters = 0;
+ op += ' ${DO_WHILE_PRE} { continue; } ${DO_WHILE_POST}\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_DOUBLE_CONTINUE:
+ numIters = iterCount - 1;
+ op += ' ${DO_WHILE_PRE} { if (i == ${TWO}) continue; res = res.yzwx; continue; } ${DO_WHILE_POST}\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_CONDITIONAL_BREAK:
+ numIters = 2;
+ op += ' ${DO_WHILE_PRE} { res = res.yzwx; if (i == ${ONE}) break; } ${DO_WHILE_POST}\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_UNCONDITIONAL_BREAK:
+ numIters = 1;
+ op += ' ${DO_WHILE_PRE} { res = res.yzwx; break; } ${DO_WHILE_POST}\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_PRE_INCREMENT:
+ op += ' ${COUNTER_PRECISION} int i = 0;\n' +
+ ' do { res = res.yzwx; } while (++i < ${ITER_COUNT});\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_POST_INCREMENT:
+ numIters = iterCount + 1;
+ op += ' ${COUNTER_PRECISION} int i = 0;\n' +
+ ' do { res = res.yzwx; } while (i++ < ${ITER_COUNT});\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_MIXED_BREAK_CONTINUE:
+ numIters = 2;
+ iterCount = 5;
+ op += ' ${DO_WHILE_PRE} { if (i == 0) continue; else if (i == 3) break; res = res.yzwx; } ${DO_WHILE_POST}\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_VECTOR_COUNTER:
+ op += ' ${COUNTER_PRECISION} ivec4 i = ivec4(0, 1, ${ITER_COUNT}, 0);\n' +
+ ' do { res = res.yzwx; } while ((i.x += i.y) < i.z);\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_101_ITERATIONS:
+ numIters = iterCount = 101;
+ op += ' ${DO_WHILE_PRE} res = res.yzwx; ${DO_WHILE_POST}\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_SEQUENCE:
+ iterCount = 5;
+ numIters = 5;
+ op += ' ${COUNTER_PRECISION} int i = 0;\n' +
+ ' do { res = res.yzwx; } while (++i < ${TWO});\n' +
+ ' do { res = res.yzwx; } while (++i < ${ITER_COUNT});\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_NESTED:
+ numIters = 2 * iterCount;
+ op += ' ${COUNTER_PRECISION} int i = 0;\n' +
+ ' do\n' +
+ ' {\n' +
+ ' ${COUNTER_PRECISION} int j = 0;\n' +
+ ' do\n' +
+ ' res = res.yzwx;\n' +
+ ' while (++j < ${ITER_COUNT});\n' +
+ ' } while (++i < ${TWO});\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_NESTED_SEQUENCE:
+ numIters = 3 * iterCount;
+ op += ' ${COUNTER_PRECISION} int i = 0;\n' +
+ ' do\n' +
+ ' {\n' +
+ ' ${COUNTER_PRECISION} int j = 0;\n' +
+ ' do\n' +
+ ' res = res.yzwx;\n' +
+ ' while (++j < ${TWO});\n' +
+ ' do\n' +
+ ' res = res.yzwx;\n' +
+ ' while (++j < ${THREE});\n' +
+ ' } while (++i < ${ITER_COUNT});\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_NESTED_TRICKY_DATAFLOW_1:
+ numIters = 2;
+ op += ' ${DO_WHILE_PRE}\n' +
+ ' {\n' +
+ ' res = coords; // ignore outer loop effect \n' +
+ ' ${COUNTER_PRECISION} int j = 0;\n' +
+ ' do\n' +
+ ' res = res.yzwx;\n' +
+ ' while (++j < ${TWO});\n' +
+ ' } ${DO_WHILE_POST}\n';
+ break;
+
+ case es3fShaderLoopTests.LoopCase.LOOPCASE_NESTED_TRICKY_DATAFLOW_2:
+ numIters = iterCount;
+ op += ' ${DO_WHILE_PRE}\n' +
+ ' {\n' +
+ ' res = coords.wxyz;\n' +
+ ' ${COUNTER_PRECISION} int j = 0;\n' +
+ ' while (j++ < ${TWO})\n' +
+ ' res = res.yzwx;\n' +
+ ' coords = res;\n' +
+ ' } ${DO_WHILE_POST}\n';
+ break;
+
+ default:
+ throw new Error('Loop Case not supported: ' + loopCase);
+ }
+
+ doWhileLoopPreStr = '\t' + counterPrecisionStr + ' int i = 0;\n' + '\tdo ';
+ if (loopCountType === es3fShaderLoopTests.LoopCountType.LOOPCOUNT_CONSTANT)
+ doWhileLoopPostStr = ' while (++i < ' + iterCount + ');\n';
+ else if (loopCountType === es3fShaderLoopTests.LoopCountType.LOOPCOUNT_UNIFORM)
+ doWhileLoopPostStr = ' while (++i < ' + glsShaderRenderCase.getIntUniformName(iterCount) + ');\n';
+ else if (loopCountType === es3fShaderLoopTests.LoopCountType.LOOPCOUNT_DYNAMIC)
+ doWhileLoopPostStr = ' while (++i < one*' + glsShaderRenderCase.getIntUniformName(iterCount) + ');\n';
+ else
+ throw new Error('Loop Count Type not supported: ' + loopCountType);
+ }
+
+ vtx += isVertexCase ? op : '';
+ frag += isVertexCase ? '' : op;
+ op = '';
+
+ // Shader footers.
+ if (isVertexCase) {
+ vtx += ' v_color = res.rgb;\n';
+ frag += ' o_color = vec4(v_color.rgb, 1.0);\n';
+ }
+ else {
+ vtx += ' v_coords = a_coords;\n';
+ frag += ' o_color = vec4(res.rgb, 1.0);\n';
+
+ if (loopCountType === es3fShaderLoopTests.LoopCountType.LOOPCOUNT_DYNAMIC)
+ vtx += ' v_one = a_one;\n';
+ }
+
+ vtx += '}\n';
+ frag += '}\n';
+
+ // Constants.
+ /** @type {string} */ var oneStr = '';
+ /** @type {string} */ var twoStr = '';
+ /** @type {string} */ var threeStr = '';
+ /** @type {string} */ var iterCountStr = '';
+
+ if (loopCountType === es3fShaderLoopTests.LoopCountType.LOOPCOUNT_CONSTANT) {
+ oneStr = '1';
+ twoStr = '2';
+ threeStr = '3';
+ iterCountStr = iterCount.toString();
+ }
+ else if (loopCountType === es3fShaderLoopTests.LoopCountType.LOOPCOUNT_UNIFORM) {
+ oneStr = 'ui_one';
+ twoStr = 'ui_two';
+ threeStr = 'ui_three';
+ iterCountStr = glsShaderRenderCase.getIntUniformName(iterCount);
+ }
+ else if (loopCountType === es3fShaderLoopTests.LoopCountType.LOOPCOUNT_DYNAMIC) {
+ oneStr = 'one*ui_one';
+ twoStr = 'one*ui_two';
+ threeStr = 'one*ui_three';
+ iterCountStr = 'one*' + glsShaderRenderCase.getIntUniformName(iterCount);
+ }
+ else throw new Error('Loop Count Type not supported: ' + loopCountType);
+
+ // Fill in shader templates.
+ /** @type {Object} */ var params = {};
+ params["PRECISION"] = "mediump";
+ params["ITER_COUNT"] = iterCountStr;
+ params["COUNTER_PRECISION"] = counterPrecisionStr;
+ params["FOR_LOOP"] = forLoopStr;
+ params["WHILE_LOOP"] = whileLoopStr;
+ params["DO_WHILE_PRE"] = doWhileLoopPreStr;
+ params["DO_WHILE_POST"] = doWhileLoopPostStr;
+ params["ONE"] = oneStr;
+ params["TWO"] = twoStr;
+ params["THREE"] = threeStr;
+
+ /** @type {string} */ var vertexShaderSource = tcuStringTemplate.specialize(vtx, params);
+ /** @type {string} */ var fragmentShaderSource = tcuStringTemplate.specialize(frag, params);
+
+ // Create the case.
+ /** @type {glsShaderRenderCase.ShaderEvalFunc} */
+ var evalFunc = es3fShaderLoopTests.getLoopEvalFunc(numIters);
+ return new es3fShaderLoopTests.ShaderLoopCase(caseName, description, isVertexCase, evalFunc, vertexShaderSource, fragmentShaderSource);
+};
+
+// ShaderLoopTests.
+
+/**
+ * @constructor
+ * @extends {tcuTestCase.DeqpTest}
+ */
+es3fShaderLoopTests.ShaderLoopTests = function() {
+ tcuTestCase.DeqpTest.call(this, 'loops', 'Loop Tests');
+};
+
+es3fShaderLoopTests.ShaderLoopTests.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
+es3fShaderLoopTests.ShaderLoopTests.prototype.constructor = es3fShaderLoopTests.ShaderLoopTests;
+
+es3fShaderLoopTests.ShaderLoopTests.prototype.init = function() {
+ var testGroup = tcuTestCase.runner.testCases;
+ // Loop cases.
+
+ /** @type {Array<gluShaderProgram.shaderType>} */ var s_shaderTypes = [
+ gluShaderProgram.shaderType.VERTEX,
+ gluShaderProgram.shaderType.FRAGMENT
+ ];
+
+ /** @type {Array<gluShaderUtil.DataType>} */ var s_countDataType = [
+ gluShaderUtil.DataType.INT,
+ gluShaderUtil.DataType.FLOAT
+ ];
+
+ /** @type {gluShaderProgram.shaderType} */ var shaderType;
+ /** @type {string} */ var shaderTypeName;
+ /** @type {boolean} */ var isVertexCase;
+ /** @type {string} */ var name;
+ /** @type {string} */ var desc;
+
+ for (var loopType in es3fShaderLoopTests.LoopType) {
+ /** @type {string} */ var loopTypeName = es3fShaderLoopTests.getLoopTypeName(es3fShaderLoopTests.LoopType[loopType]);
+ /** @type {tcuTestCase.DeqpTest} */ var loopTypeGroup = tcuTestCase.newTest(loopTypeName, 'Loop tests with ' + loopTypeName + ' loop type');
+ testGroup.addChild(loopTypeGroup);
+
+ for (var loopCountType in es3fShaderLoopTests.LoopCountType) {
+ /** @type {string} */ var loopCountName = es3fShaderLoopTests.getLoopCountTypeName(es3fShaderLoopTests.LoopCountType[loopCountType]);
+
+ /** @type {string} */ var groupName = loopCountName + '_iterations';
+ /** @type {string} */ var groupDesc = 'Loop tests with ' + loopCountName + ' loop counter.';
+
+ /** @type {tcuTestCase.DeqpTest} */ var group = tcuTestCase.newTest(groupName, groupDesc);
+ loopTypeGroup.addChild(group);
+
+ // Generic cases.
+
+ for (var precision in gluShaderUtil.precision) {
+ /** @type {string} */ var precisionName = gluShaderUtil.getPrecisionName(gluShaderUtil.precision[precision]);
+
+ for (var dataTypeNdx = 0; dataTypeNdx < s_countDataType.length; dataTypeNdx++) {
+ /** @type {gluShaderUtil.DataType} */ var loopDataType = s_countDataType[dataTypeNdx];
+ /** @type {string} */ var dataTypeName = gluShaderUtil.getDataTypeName(loopDataType);
+
+ for (var shaderTypeNdx = 0; shaderTypeNdx < s_shaderTypes.length; shaderTypeNdx++) {
+ shaderType = s_shaderTypes[shaderTypeNdx];
+ shaderTypeName = gluShaderProgram.getShaderTypeName(shaderType);
+ isVertexCase = (shaderType == gluShaderProgram.shaderType.VERTEX);
+
+
+ name = 'basic_' + precisionName + '_' + dataTypeName + '_' + shaderTypeName;
+ desc = loopTypeName + ' loop with ' + precisionName + dataTypeName + ' ' + loopCountName + ' iteration count in ' + shaderTypeName + ' shader.';
+ group.addChild(es3fShaderLoopTests.createGenericLoopCase(name, desc, isVertexCase, es3fShaderLoopTests.LoopType[loopType], es3fShaderLoopTests.LoopCountType[loopCountType], gluShaderUtil.precision[precision], loopDataType));
+ }
+ }
+ }
+
+ // Special cases.
+
+ for (var loopCase in es3fShaderLoopTests.LoopCase) {
+ /** @type {string} */ var loopCaseName = es3fShaderLoopTests.getLoopCaseName(es3fShaderLoopTests.LoopCase[loopCase]);
+
+ // no-iterations not possible with do-while.
+ if ((es3fShaderLoopTests.LoopCase[loopCase] == es3fShaderLoopTests.LoopCase.LOOPCASE_NO_ITERATIONS) && (es3fShaderLoopTests.LoopType[loopType] == es3fShaderLoopTests.LoopType.LOOPTYPE_DO_WHILE))
+ continue;
+
+ for (var shaderTypeNdx = 0; shaderTypeNdx < s_shaderTypes.length; shaderTypeNdx++) {
+ shaderType = s_shaderTypes[shaderTypeNdx];
+ shaderTypeName = gluShaderProgram.getShaderTypeName(shaderType);
+ isVertexCase = (shaderType == gluShaderProgram.shaderType.VERTEX);
+
+ name = loopCaseName + '_' + shaderTypeName;
+ desc = loopCaseName + ' loop with ' + loopTypeName + ' iteration count in ' + shaderTypeName + ' shader.';
+ group.addChild(es3fShaderLoopTests.createSpecialLoopCase(name, desc, isVertexCase, es3fShaderLoopTests.LoopCase[loopCase], es3fShaderLoopTests.LoopType[loopType], es3fShaderLoopTests.LoopCountType[loopCountType]));
+ }
+ }
+ }
+ }
+};
+
+/**
+* Run test
+* @param {WebGL2RenderingContext} context
+*/
+es3fShaderLoopTests.run = function(context, range) {
+ gl = context;
+ //Set up Test Root parameters
+ var state = tcuTestCase.runner;
+ state.setRoot(new es3fShaderLoopTests.ShaderLoopTests());
+
+ //Set up name and description of this test series.
+ setCurrentTestName(state.testCases.fullName());
+ description(state.testCases.getDescription());
+ try {
+ if (range)
+ state.setRange(range);
+ //Run test cases
+ tcuTestCase.runTestCases();
+ }
+ catch (err) {
+ testFailedOptions('Failed to es3fShaderLoopTests.run tests', false);
+ tcuTestCase.runner.terminate();
+ }
+};
+
+});