/*------------------------------------------------------------------------- * 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; ; } LOOPCASE_INFINITE_WITH_UNCONDITIONAL_BREAK_LAST: 2, // for (...) { ; break; } LOOPCASE_INFINITE_WITH_CONDITIONAL_BREAK: 3, // for (...) { ; 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; continue; } LOOPCASE_ONLY_CONTINUE: 12, // for (...) { continue; } LOOPCASE_DOUBLE_CONTINUE: 13, // for (...) { if (cond) continue; ; continue; } LOOPCASE_CONDITIONAL_BREAK: 14, // for (...) { if (cond) break; } LOOPCASE_UNCONDITIONAL_BREAK: 15, // for (...) { ; break; } LOOPCASE_PRE_INCREMENT: 16, // for (...; ++i) { ; } LOOPCASE_POST_INCREMENT: 17, // for (...; i++) { ; } 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} */ 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} */ 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} */ 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} */ var s_shaderTypes = [ gluShaderProgram.shaderType.VERTEX, gluShaderProgram.shaderType.FRAGMENT ]; /** @type {Array} */ 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(); } }; });