/*------------------------------------------------------------------------- * 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.es3fShaderIndexingTests'); goog.require('framework.common.tcuImageCompare'); 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('framework.opengl.gluTexture'); goog.require('modules.shared.glsShaderRenderCase'); goog.scope(function() { /** @type {?WebGL2RenderingContext} */ var gl; var es3fShaderIndexingTests = functional.gles3.es3fShaderIndexingTests; var deMath = framework.delibs.debase.deMath; var glsShaderRenderCase = modules.shared.glsShaderRenderCase; var gluShaderUtil = framework.opengl.gluShaderUtil; var gluTexture = framework.opengl.gluTexture; var gluShaderProgram = framework.opengl.gluShaderProgram; var tcuTestCase = framework.common.tcuTestCase; var tcuStringTemplate = framework.common.tcuStringTemplate; /** * @enum {number} */ es3fShaderIndexingTests.IndexAccessType = { STATIC: 0, DYNAMIC: 1, STATIC_LOOP: 2, DYNAMIC_LOOP: 3 }; /** * @param {es3fShaderIndexingTests.IndexAccessType} accessType * @return {string} */ es3fShaderIndexingTests.getIndexAccessTypeName = function(accessType) { /** @type {Array} */ var s_names = [ 'static', 'dynamic', 'static_loop', 'dynamic_loop' ]; return s_names[accessType]; }; /** * @enum {number} */ es3fShaderIndexingTests.VectorAccessType = { DIRECT: 0, COMPONENT: 1, SUBSCRIPT_STATIC: 2, SUBSCRIPT_DYNAMIC: 3, SUBSCRIPT_STATIC_LOOP: 4, SUBSCRIPT_DYNAMIC_LOOP: 5 }; /** * @param {es3fShaderIndexingTests.VectorAccessType} accessType * @return {string} */ es3fShaderIndexingTests.getVectorAccessTypeName = function(accessType) { /** @type {Array} */ var s_names = [ 'direct', 'component', 'static_subscript', 'dynamic_subscript', 'static_loop_subscript', 'dynamic_loop_subscript' ]; assertMsgOptions(deMath.deInBounds32(accessType, 0, s_names.length), 'Index out of bounds', false, true); return s_names[accessType]; }; /** @param {glsShaderRenderCase.ShaderEvalContext} c */ es3fShaderIndexingTests.evalArrayCoordsFloat = function(c) { c.color[0] = 1.875 * c.coords[0]; }; /** @param {glsShaderRenderCase.ShaderEvalContext} c */ es3fShaderIndexingTests.evalArrayCoordsVec2 = function(c) { var swizzled = deMath.swizzle(c.coords, [0, 1]); c.color[0] = 1.875 * swizzled[0]; c.color[1] = 1.875 * swizzled[1]; }; /** @param {glsShaderRenderCase.ShaderEvalContext} c */ es3fShaderIndexingTests.evalArrayCoordsVec3 = function(c) { var swizzled = deMath.swizzle(c.coords, [0, 1, 2]); c.color[0] = 1.875 * swizzled[0]; c.color[1] = 1.875 * swizzled[1]; c.color[2] = 1.875 * swizzled[2]; }; /** @param {glsShaderRenderCase.ShaderEvalContext} c */ es3fShaderIndexingTests.evalArrayCoordsVec4 = function(c) { c.color = deMath.scale(c.coords, 1.875); }; /** * @param {gluShaderUtil.DataType} dataType * @return {function(glsShaderRenderCase.ShaderEvalContext)} */ es3fShaderIndexingTests.getArrayCoordsEvalFunc = function(dataType) { if (dataType === gluShaderUtil.DataType.FLOAT) return es3fShaderIndexingTests.evalArrayCoordsFloat; else if (dataType === gluShaderUtil.DataType.FLOAT_VEC2) return es3fShaderIndexingTests.evalArrayCoordsVec2; else if (dataType === gluShaderUtil.DataType.FLOAT_VEC3) return es3fShaderIndexingTests.evalArrayCoordsVec3; else if (dataType === gluShaderUtil.DataType.FLOAT_VEC4) return es3fShaderIndexingTests.evalArrayCoordsVec4; else throw new Error('Invalid data type.'); }; /** @param {glsShaderRenderCase.ShaderEvalContext} c */ es3fShaderIndexingTests.evalArrayUniformFloat = function(c) { c.color[0] = 1.875 * c.constCoords[0]; }; /** @param {glsShaderRenderCase.ShaderEvalContext} c */ es3fShaderIndexingTests.evalArrayUniformVec2 = function(c) { var swizzled = deMath.swizzle(c.constCoords, [0, 1]); c.color[0] = 1.875 * swizzled[0]; c.color[1] = 1.875 * swizzled[1]; }; /** @param {glsShaderRenderCase.ShaderEvalContext} c */ es3fShaderIndexingTests.evalArrayUniformVec3 = function(c) { var swizzled = deMath.swizzle(c.constCoords, [0, 1, 2]); c.color[0] = 1.875 * swizzled[0]; c.color[1] = 1.875 * swizzled[1]; c.color[2] = 1.875 * swizzled[2]; }; /** @param {glsShaderRenderCase.ShaderEvalContext} c */ es3fShaderIndexingTests.evalArrayUniformVec4 = function(c) { c.color = deMath.scale(c.constCoords, 1.875); }; /** * @param {gluShaderUtil.DataType} dataType * @return {function(glsShaderRenderCase.ShaderEvalContext)} */ es3fShaderIndexingTests.getArrayUniformEvalFunc = function(dataType) { if (dataType === gluShaderUtil.DataType.FLOAT) return es3fShaderIndexingTests.evalArrayUniformFloat; else if (dataType === gluShaderUtil.DataType.FLOAT_VEC2) return es3fShaderIndexingTests.evalArrayUniformVec2; else if (dataType === gluShaderUtil.DataType.FLOAT_VEC3) return es3fShaderIndexingTests.evalArrayUniformVec3; else if (dataType === gluShaderUtil.DataType.FLOAT_VEC4) return es3fShaderIndexingTests.evalArrayUniformVec4; else throw new Error('Invalid data type.'); }; /** * @constructor * @extends {glsShaderRenderCase.ShaderRenderCase} * @param {string} name * @param {string} description * @param {boolean} isVertexCase * @param {gluShaderUtil.DataType} varType * @param {function(glsShaderRenderCase.ShaderEvalContext)} evalFunc * @param {string} vertShaderSource * @param {string} fragShaderSource */ es3fShaderIndexingTests.ShaderIndexingCase = function(name, description, isVertexCase, varType, evalFunc, vertShaderSource, fragShaderSource) { glsShaderRenderCase.ShaderRenderCase.call(this, name, description, isVertexCase, evalFunc); /** @type {gluShaderUtil.DataType} */ this.m_varType = varType; /** @type {string} */ this.m_vertShaderSource = vertShaderSource; /** @type {string} */ this.m_fragShaderSource = fragShaderSource; }; es3fShaderIndexingTests.ShaderIndexingCase.prototype = Object.create(glsShaderRenderCase.ShaderRenderCase.prototype); es3fShaderIndexingTests.ShaderIndexingCase.prototype.constructor = es3fShaderIndexingTests.ShaderIndexingCase; /** * @param {?WebGLProgram} programID * @param {Array} constCoords */ es3fShaderIndexingTests.ShaderIndexingCase.prototype.setupUniforms = function(programID, constCoords) { /** @type {(Array|Float32Array)} */ var arr = []; /** @type {Array} */ var array1d = []; /** @type {?WebGLUniformLocation} */ var arrLoc = gl.getUniformLocation(programID, 'u_arr'); if (arrLoc != null) { if (this.m_varType === gluShaderUtil.DataType.FLOAT) { arr[0] = constCoords[0]; arr[1] = constCoords[0] * 0.5; arr[2] = constCoords[0] * 0.25; arr[3] = constCoords[0] * 0.125; gl.uniform1fv(arrLoc, arr); } else if (this.m_varType === gluShaderUtil.DataType.FLOAT_VEC2) { arr[0] = deMath.swizzle(constCoords, [0, 1]); arr[1] = deMath.scale(deMath.swizzle(constCoords, [0, 1]), 0.5); arr[2] = deMath.scale(deMath.swizzle(constCoords, [0, 1]), 0.25); arr[3] = deMath.scale(deMath.swizzle(constCoords, [0, 1]), 0.125); for (var i = 0; i < arr.length; i++) array1d = array1d.concat(arr[i]); gl.uniform2fv(arrLoc, array1d); } else if (this.m_varType === gluShaderUtil.DataType.FLOAT_VEC3) { arr[0] = deMath.swizzle(constCoords, [0, 1, 2]); arr[1] = deMath.scale(deMath.swizzle(constCoords, [0, 1, 2]), 0.5); arr[2] = deMath.scale(deMath.swizzle(constCoords, [0, 1, 2]), 0.25); arr[3] = deMath.scale(deMath.swizzle(constCoords, [0, 1, 2]), 0.125); for (var i = 0; i < arr.length; i++) array1d = array1d.concat(arr[i]); gl.uniform3fv(arrLoc, array1d); } else if (this.m_varType === gluShaderUtil.DataType.FLOAT_VEC4) { arr[0] = deMath.swizzle(constCoords, [0,1,2,3]); arr[1] = deMath.scale(deMath.swizzle(constCoords, [0, 1, 2, 3]), 0.5); arr[2] = deMath.scale(deMath.swizzle(constCoords, [0, 1, 2, 3]), 0.25); arr[3] = deMath.scale(deMath.swizzle(constCoords, [0, 1, 2, 3]), 0.125); for (var i = 0; i < arr.length; i++) array1d = array1d.concat(arr[i]); gl.uniform4fv(arrLoc, array1d); } else throw new Error('u_arr should not have location assigned in this test case'); } }; /** * @param {string} caseName * @param {string} description * @param {gluShaderUtil.DataType} varType * @param {es3fShaderIndexingTests.IndexAccessType} vertAccess * @param {es3fShaderIndexingTests.IndexAccessType} fragAccess * @return {es3fShaderIndexingTests.ShaderIndexingCase} */ es3fShaderIndexingTests.createVaryingArrayCase = function(caseName, description, varType, vertAccess, fragAccess) { /** @type {string} */ var vtx = ''; vtx += '#version 300 es\n' + 'in highp vec4 a_position;\n' + 'in highp vec4 a_coords;\n'; if (vertAccess === es3fShaderIndexingTests.IndexAccessType.DYNAMIC) vtx += 'uniform mediump int ui_zero, ui_one, ui_two, ui_three;\n'; else if (vertAccess === es3fShaderIndexingTests.IndexAccessType.DYNAMIC_LOOP) vtx += 'uniform mediump int ui_four;\n'; vtx += 'out ${PRECISION} ${VAR_TYPE} var[${ARRAY_LEN}];\n' + '\n' + 'void main()\n' + '{\n' + ' gl_Position = a_position;\n'; if (vertAccess === es3fShaderIndexingTests.IndexAccessType.STATIC) { vtx += ' var[0] = ${VAR_TYPE}(a_coords);\n' + ' var[1] = ${VAR_TYPE}(a_coords) * 0.5;\n' + ' var[2] = ${VAR_TYPE}(a_coords) * 0.25;\n' + ' var[3] = ${VAR_TYPE}(a_coords) * 0.125;\n'; } else if (vertAccess === es3fShaderIndexingTests.IndexAccessType.DYNAMIC) { vtx += ' var[ui_zero] = ${VAR_TYPE}(a_coords);\n' + ' var[ui_one] = ${VAR_TYPE}(a_coords) * 0.5;\n' + ' var[ui_two] = ${VAR_TYPE}(a_coords) * 0.25;\n' + ' var[ui_three] = ${VAR_TYPE}(a_coords) * 0.125;\n'; } else if (vertAccess === es3fShaderIndexingTests.IndexAccessType.STATIC_LOOP) { vtx += ' ${PRECISION} ${VAR_TYPE} coords = ${VAR_TYPE}(a_coords);\n' + ' for (int i = 0; i < 4; i++)\n' + ' {\n' + ' var[i] = ${VAR_TYPE}(coords);\n' + ' coords = coords * 0.5;\n' + ' }\n'; } else { assertMsgOptions(vertAccess === es3fShaderIndexingTests.IndexAccessType.DYNAMIC_LOOP, 'Not Dynamic_Loop', false, true); vtx += ' ${PRECISION} ${VAR_TYPE} coords = ${VAR_TYPE}(a_coords);\n' + ' for (int i = 0; i < ui_four; i++)\n' + ' {\n' + ' var[i] = ${VAR_TYPE}(coords);\n' + ' coords = coords * 0.5;\n' + ' }\n'; } vtx += '}\n'; /** @type {string} */ var frag = ''; frag += '#version 300 es\n' + 'precision mediump int;\n' + 'layout(location = 0) out mediump vec4 o_color;\n'; if (fragAccess === es3fShaderIndexingTests.IndexAccessType.DYNAMIC) frag += 'uniform mediump int ui_zero, ui_one, ui_two, ui_three;\n'; else if (fragAccess === es3fShaderIndexingTests.IndexAccessType.DYNAMIC_LOOP) frag += 'uniform int ui_four;\n'; frag += 'in ${PRECISION} ${VAR_TYPE} var[${ARRAY_LEN}];\n' + '\n' + 'void main()\n' + '{\n' + ' ${PRECISION} ${VAR_TYPE} res = ${VAR_TYPE}(0.0);\n'; if (fragAccess === es3fShaderIndexingTests.IndexAccessType.STATIC) { frag += ' res += var[0];\n' + ' res += var[1];\n' + ' res += var[2];\n' + ' res += var[3];\n'; } else if (fragAccess === es3fShaderIndexingTests.IndexAccessType.DYNAMIC) { frag += ' res += var[ui_zero];\n' + ' res += var[ui_one];\n' + ' res += var[ui_two];\n' + ' res += var[ui_three];\n'; } else if (fragAccess === es3fShaderIndexingTests.IndexAccessType.STATIC_LOOP) { frag += ' for (int i = 0; i < 4; i++)\n' + ' res += var[i];\n'; } else { assertMsgOptions(fragAccess === es3fShaderIndexingTests.IndexAccessType.DYNAMIC_LOOP, 'Not Dynamic_Loop', false, true); frag += ' for (int i = 0; i < ui_four; i++)\n' + ' res += var[i];\n'; } frag += ' o_color = vec4(res${PADDING});\n' + '}\n'; // Fill in shader templates. /** @type {Object} */ var params = {}; params['VAR_TYPE'] = gluShaderUtil.getDataTypeName(varType); params['ARRAY_LEN'] = '4'; params['PRECISION'] = 'mediump'; if (varType === gluShaderUtil.DataType.FLOAT) params['PADDING'] = ', 0.0, 0.0, 1.0'; else if (varType === gluShaderUtil.DataType.FLOAT_VEC2) params['PADDING'] = ', 0.0, 1.0'; else if (varType === gluShaderUtil.DataType.FLOAT_VEC3) params['PADDING'] = ', 1.0'; else params['PADDING'] = ''; /** @type {string} */ var vertexShaderSource = tcuStringTemplate.specialize(vtx, params); /** @type {string} */ var fragmentShaderSource = tcuStringTemplate.specialize(frag, params); /** @type {function(glsShaderRenderCase.ShaderEvalContext)} */ var evalFunc = es3fShaderIndexingTests.getArrayCoordsEvalFunc(varType); return new es3fShaderIndexingTests.ShaderIndexingCase(caseName, description, true, varType, evalFunc, vertexShaderSource, fragmentShaderSource); }; /** * @param {string} caseName * @param {string} description * @param {boolean} isVertexCase * @param {gluShaderUtil.DataType} varType * @param {es3fShaderIndexingTests.IndexAccessType} readAccess * @return {es3fShaderIndexingTests.ShaderIndexingCase} */ es3fShaderIndexingTests.createUniformArrayCase = function(caseName, description, isVertexCase, varType, readAccess) { /** @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 (isVertexCase) { vtx += 'out mediump vec4 v_color;\n'; frag += 'in mediump vec4 v_color;\n'; } else { vtx += 'out mediump vec4 v_coords;\n'; frag += 'in mediump vec4 v_coords;\n'; } if (readAccess === es3fShaderIndexingTests.IndexAccessType.DYNAMIC) op += 'uniform mediump int ui_zero, ui_one, ui_two, ui_three;\n'; else if (readAccess === es3fShaderIndexingTests.IndexAccessType.DYNAMIC_LOOP) op += 'uniform mediump int ui_four;\n'; op += 'uniform ${PRECISION} ${VAR_TYPE} u_arr[${ARRAY_LEN}];\n'; vtx += isVertexCase ? op : ''; frag += isVertexCase ? '' : op; op = ''; vtx += '\n'; vtx += 'void main()\n'; vtx += '{\n'; vtx += ' gl_Position = a_position;\n'; frag += '\n'; frag += 'void main()\n'; frag += '{\n'; // Read array. op += ' ${PRECISION} ${VAR_TYPE} res = ${VAR_TYPE}(0.0);\n'; if (readAccess === es3fShaderIndexingTests.IndexAccessType.STATIC) { op += ' res += u_arr[0];\n'; op += ' res += u_arr[1];\n'; op += ' res += u_arr[2];\n'; op += ' res += u_arr[3];\n'; } else if (readAccess === es3fShaderIndexingTests.IndexAccessType.DYNAMIC) { op += ' res += u_arr[ui_zero];\n'; op += ' res += u_arr[ui_one];\n'; op += ' res += u_arr[ui_two];\n'; op += ' res += u_arr[ui_three];\n'; } else if (readAccess === es3fShaderIndexingTests.IndexAccessType.STATIC_LOOP) { op += ' for (int i = 0; i < 4; i++)\n'; op += ' res += u_arr[i];\n'; } else { assertMsgOptions(readAccess === es3fShaderIndexingTests.IndexAccessType.DYNAMIC_LOOP, 'readAccess not supported.', false, true); op += ' for (int i = 0; i < ui_four; i++)\n'; op += ' res += u_arr[i];\n'; } vtx += isVertexCase ? op : ''; frag += isVertexCase ? '' : op; op = ''; if (isVertexCase) { vtx += ' v_color = vec4(res${PADDING});\n'; frag += ' o_color = v_color;\n'; } else { vtx += ' v_coords = a_coords;\n'; frag += ' o_color = vec4(res${PADDING});\n'; } vtx += '}\n'; frag += '}\n'; // Fill in shader templates. /** @type {Object} */ var params = {}; params['VAR_TYPE'] = gluShaderUtil.getDataTypeName(varType); params['ARRAY_LEN'] = '4'; params['PRECISION'] = 'mediump'; if (varType === gluShaderUtil.DataType.FLOAT) params['PADDING'] = ', 0.0, 0.0, 1.0'; else if (varType === gluShaderUtil.DataType.FLOAT_VEC2) params['PADDING'] = ', 0.0, 1.0'; else if (varType === gluShaderUtil.DataType.FLOAT_VEC3) params['PADDING'] = ', 1.0'; else params['PADDING'] = ''; /** @type {string} */ var vertexShaderSource = tcuStringTemplate.specialize(vtx, params); /** @type {string} */ var fragmentShaderSource = tcuStringTemplate.specialize(frag, params); /** @type {function(glsShaderRenderCase.ShaderEvalContext)} */ var evalFunc = es3fShaderIndexingTests.getArrayUniformEvalFunc(varType); return new es3fShaderIndexingTests.ShaderIndexingCase(caseName, description, isVertexCase, varType, evalFunc, vertexShaderSource, fragmentShaderSource); }; /** * @param {string} caseName * @param {string} description * @param {boolean} isVertexCase * @param {gluShaderUtil.DataType} varType * @param {es3fShaderIndexingTests.IndexAccessType} writeAccess * @param {es3fShaderIndexingTests.IndexAccessType} readAccess * @return {es3fShaderIndexingTests.ShaderIndexingCase} */ es3fShaderIndexingTests.createTmpArrayCase = function(caseName, description, isVertexCase, varType, writeAccess, readAccess) { /** @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' + 'in highp vec4 a_coords;\n'; frag += 'layout(location = 0) out mediump vec4 o_color;\n'; if (isVertexCase) { vtx += 'out mediump vec4 v_color;\n'; frag += 'in mediump vec4 v_color;\n'; } else { vtx += 'out mediump vec4 v_coords;\n'; frag += 'in mediump vec4 v_coords;\n'; } if (writeAccess === es3fShaderIndexingTests.IndexAccessType.DYNAMIC || readAccess === es3fShaderIndexingTests.IndexAccessType.DYNAMIC) op += 'uniform mediump int ui_zero, ui_one, ui_two, ui_three;\n'; if (writeAccess === es3fShaderIndexingTests.IndexAccessType.DYNAMIC_LOOP || readAccess === es3fShaderIndexingTests.IndexAccessType.DYNAMIC_LOOP) op += 'uniform mediump int ui_four;\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'; // Write array. if (isVertexCase) op += ' ${PRECISION} ${VAR_TYPE} coords = ${VAR_TYPE}(a_coords);\n'; else op += ' ${PRECISION} ${VAR_TYPE} coords = ${VAR_TYPE}(v_coords);\n'; op += ' ${PRECISION} ${VAR_TYPE} arr[${ARRAY_LEN}];\n'; if (writeAccess === es3fShaderIndexingTests.IndexAccessType.STATIC) { op += ' arr[0] = ${VAR_TYPE}(coords);\n' + ' arr[1] = ${VAR_TYPE}(coords) * 0.5;\n' + ' arr[2] = ${VAR_TYPE}(coords) * 0.25;\n' + ' arr[3] = ${VAR_TYPE}(coords) * 0.125;\n'; } else if (writeAccess === es3fShaderIndexingTests.IndexAccessType.DYNAMIC) { op += ' arr[ui_zero] = ${VAR_TYPE}(coords);\n' + ' arr[ui_one] = ${VAR_TYPE}(coords) * 0.5;\n' + ' arr[ui_two] = ${VAR_TYPE}(coords) * 0.25;\n' + ' arr[ui_three] = ${VAR_TYPE}(coords) * 0.125;\n'; } else if (writeAccess === es3fShaderIndexingTests.IndexAccessType.STATIC_LOOP) { op += ' for (int i = 0; i < 4; i++)\n' + ' {\n' + ' arr[i] = ${VAR_TYPE}(coords);\n' + ' coords = coords * 0.5;\n' + ' }\n'; } else { assertMsgOptions(writeAccess === es3fShaderIndexingTests.IndexAccessType.DYNAMIC_LOOP, 'writeAccess not supported', false, true); op += ' for (int i = 0; i < ui_four; i++)\n' + ' {\n' + ' arr[i] = ${VAR_TYPE}(coords);\n' + ' coords = coords * 0.5;\n' + ' }\n'; } // Read array. op += ' ${PRECISION} ${VAR_TYPE} res = ${VAR_TYPE}(0.0);\n'; if (readAccess === es3fShaderIndexingTests.IndexAccessType.STATIC) { op += ' res += arr[0];\n' + ' res += arr[1];\n' + ' res += arr[2];\n' + ' res += arr[3];\n'; } else if (readAccess === es3fShaderIndexingTests.IndexAccessType.DYNAMIC) { op += ' res += arr[ui_zero];\n' + ' res += arr[ui_one];\n' + ' res += arr[ui_two];\n' + ' res += arr[ui_three];\n'; } else if (readAccess === es3fShaderIndexingTests.IndexAccessType.STATIC_LOOP) { op += ' for (int i = 0; i < 4; i++)\n' + ' res += arr[i];\n'; } else { assertMsgOptions(readAccess === es3fShaderIndexingTests.IndexAccessType.DYNAMIC_LOOP, 'readAccess not supported.', false, true); op += ' for (int i = 0; i < ui_four; i++)\n' + ' res += arr[i];\n'; } vtx += isVertexCase ? op : ''; frag += isVertexCase ? '' : op; op = ''; if (isVertexCase) { vtx += ' v_color = vec4(res${PADDING});\n'; frag += ' o_color = v_color;\n'; } else { vtx += ' v_coords = a_coords;\n'; frag += ' o_color = vec4(res${PADDING});\n'; } vtx += '}\n'; frag += '}\n'; // Fill in shader templates. /** @type {Object} */ var params = {}; params["VAR_TYPE"] = gluShaderUtil.getDataTypeName(varType); params["ARRAY_LEN"] = "4"; params["PRECISION"] = "mediump"; if (varType === gluShaderUtil.DataType.FLOAT) params['PADDING'] = ', 0.0, 0.0, 1.0'; else if (varType === gluShaderUtil.DataType.FLOAT_VEC2) params['PADDING'] = ', 0.0, 1.0'; else if (varType === gluShaderUtil.DataType.FLOAT_VEC3) params['PADDING'] = ', 1.0'; else params['PADDING'] = ''; /** @type {string} */ var vertexShaderSource = tcuStringTemplate.specialize(vtx, params); /** @type {string} */ var fragmentShaderSource = tcuStringTemplate.specialize(frag, params); /** @type {function(glsShaderRenderCase.ShaderEvalContext)} */ var evalFunc = es3fShaderIndexingTests.getArrayCoordsEvalFunc(varType); return new es3fShaderIndexingTests.ShaderIndexingCase(caseName, description, isVertexCase, varType, evalFunc, vertexShaderSource, fragmentShaderSource); }; // VECTOR SUBSCRIPT. /** @param {glsShaderRenderCase.ShaderEvalContext} c */ es3fShaderIndexingTests.evalSubscriptVec2 = function(c) { c.color[0] = c.coords[0] + 0.5 * c.coords[1]; c.color[1] = c.coords[0] + 0.5 * c.coords[1]; c.color[2] = c.coords[0] + 0.5 * c.coords[1]; }; /** @param {glsShaderRenderCase.ShaderEvalContext} c */ es3fShaderIndexingTests.evalSubscriptVec3 = function(c) { c.color[0] = c.coords[0] + 0.5 * c.coords[1] + 0.25 * c.coords[2]; c.color[1] = c.coords[0] + 0.5 * c.coords[1] + 0.25 * c.coords[2]; c.color[2] = c.coords[0] + 0.5 * c.coords[1] + 0.25 * c.coords[2]; }; /** @param {glsShaderRenderCase.ShaderEvalContext} c */ es3fShaderIndexingTests.evalSubscriptVec4 = function(c) { c.color[0] = c.coords[0] + 0.5 * c.coords[1] + 0.25 * c.coords[2] + 0.125 * c.coords[3]; c.color[1] = c.coords[0] + 0.5 * c.coords[1] + 0.25 * c.coords[2] + 0.125 * c.coords[3]; c.color[2] = c.coords[0] + 0.5 * c.coords[1] + 0.25 * c.coords[2] + 0.125 * c.coords[3]; }; /** * @param {gluShaderUtil.DataType} dataType * @return {function(glsShaderRenderCase.ShaderEvalContext)} */ es3fShaderIndexingTests.getVectorSubscriptEvalFunc = function(dataType) { if (dataType === gluShaderUtil.DataType.FLOAT_VEC2) return es3fShaderIndexingTests.evalSubscriptVec2; else if (dataType === gluShaderUtil.DataType.FLOAT_VEC3) return es3fShaderIndexingTests.evalSubscriptVec3; else if (dataType === gluShaderUtil.DataType.FLOAT_VEC4) return es3fShaderIndexingTests.evalSubscriptVec4; else throw new Error('Invalid data type.'); }; /** * @param {string} caseName * @param {string} description * @param {boolean} isVertexCase * @param {gluShaderUtil.DataType} varType * @param {es3fShaderIndexingTests.VectorAccessType} writeAccess * @param {es3fShaderIndexingTests.VectorAccessType} readAccess * @return {es3fShaderIndexingTests.ShaderIndexingCase} */ es3fShaderIndexingTests.createVectorSubscriptCase = function(caseName, description, isVertexCase, varType, writeAccess, readAccess) { /** @type {string} */ var vtx = ''; /** @type {string} */ var frag = ''; /** @type {string} */ var op = '' ; /** @type {number} */ var vecLen = gluShaderUtil.getDataTypeScalarSize(varType); /** @type {string} */ var vecLenName = glsShaderRenderCase.getIntUniformName(vecLen); vtx += '#version 300 es\n'; frag += '#version 300 es\n'; vtx += 'in highp vec4 a_position;\n' + 'in highp vec4 a_coords;\n'; frag += 'layout(location = 0) out mediump vec4 o_color;\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 (writeAccess === es3fShaderIndexingTests.VectorAccessType.SUBSCRIPT_DYNAMIC || readAccess === es3fShaderIndexingTests.VectorAccessType.SUBSCRIPT_DYNAMIC){ op += 'uniform mediump int ui_zero'; if (vecLen >= 2) op += ', ui_one'; if (vecLen >= 3) op += ', ui_two'; if (vecLen >= 4) op += ', ui_three'; op += ';\n'; } if (writeAccess === es3fShaderIndexingTests.VectorAccessType.SUBSCRIPT_DYNAMIC_LOOP || readAccess === es3fShaderIndexingTests.VectorAccessType.SUBSCRIPT_DYNAMIC_LOOP) op += 'uniform mediump int ' + vecLenName + ';\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'; // Write vector. if (isVertexCase) op += ' ${PRECISION} ${VAR_TYPE} coords = ${VAR_TYPE}(a_coords);\n'; else op += ' ${PRECISION} ${VAR_TYPE} coords = ${VAR_TYPE}(v_coords);\n'; op += ' ${PRECISION} ${VAR_TYPE} tmp;\n'; if (writeAccess === es3fShaderIndexingTests.VectorAccessType.DIRECT) op += ' tmp = coords.${SWIZZLE} * vec4(1.0, 0.5, 0.25, 0.125).${SWIZZLE};\n'; else if (writeAccess === es3fShaderIndexingTests.VectorAccessType.COMPONENT) { op += ' tmp.x = coords.x;\n'; if (vecLen >= 2) op += ' tmp.y = coords.y * 0.5;\n'; if (vecLen >= 3) op += ' tmp.z = coords.z * 0.25;\n'; if (vecLen >= 4) op += ' tmp.w = coords.w * 0.125;\n'; } else if (writeAccess === es3fShaderIndexingTests.VectorAccessType.SUBSCRIPT_STATIC) { op += ' tmp[0] = coords.x;\n'; if (vecLen >= 2) op += ' tmp[1] = coords.y * 0.5;\n'; if (vecLen >= 3) op += ' tmp[2] = coords.z * 0.25;\n'; if (vecLen >= 4) op += ' tmp[3] = coords.w * 0.125;\n'; } else if (writeAccess === es3fShaderIndexingTests.VectorAccessType.SUBSCRIPT_DYNAMIC) { op += ' tmp[ui_zero] = coords.x;\n'; if (vecLen >= 2) op += ' tmp[ui_one] = coords.y * 0.5;\n'; if (vecLen >= 3) op += ' tmp[ui_two] = coords.z * 0.25;\n'; if (vecLen >= 4) op += ' tmp[ui_three] = coords.w * 0.125;\n'; } else if (writeAccess === es3fShaderIndexingTests.VectorAccessType.SUBSCRIPT_STATIC_LOOP) { op += ' for (int i = 0; i < ' + vecLen + '; i++)\n'; op += ' {\n'; op += ' tmp[i] = coords.x;\n'; op += ' coords = coords.${ROT_SWIZZLE} * 0.5;\n'; op += ' }\n'; } else { assertMsgOptions(writeAccess === es3fShaderIndexingTests.VectorAccessType.SUBSCRIPT_DYNAMIC_LOOP, 'writeAccess not supported.', false, true); op += ' for (int i = 0; i < ' + vecLenName + '; i++)\n'; op += ' {\n'; op += ' tmp[i] = coords.x;\n'; op += ' coords = coords.${ROT_SWIZZLE} * 0.5;\n'; op += ' }\n'; } // Read vector. op += ' ${PRECISION} float res = 0.0;\n'; if (readAccess === es3fShaderIndexingTests.VectorAccessType.DIRECT) op += ' res = dot(tmp, ${VAR_TYPE}(1.0));\n'; else if (readAccess === es3fShaderIndexingTests.VectorAccessType.COMPONENT) { op += ' res += tmp.x;\n'; if (vecLen >= 2) op += ' res += tmp.y;\n'; if (vecLen >= 3) op += ' res += tmp.z;\n'; if (vecLen >= 4) op += ' res += tmp.w;\n'; } else if (readAccess === es3fShaderIndexingTests.VectorAccessType.SUBSCRIPT_STATIC) { op += ' res += tmp[0];\n'; if (vecLen >= 2) op += ' res += tmp[1];\n'; if (vecLen >= 3) op += ' res += tmp[2];\n'; if (vecLen >= 4) op += ' res += tmp[3];\n'; } else if (readAccess === es3fShaderIndexingTests.VectorAccessType.SUBSCRIPT_DYNAMIC) { op += ' res += tmp[ui_zero];\n'; if (vecLen >= 2) op += ' res += tmp[ui_one];\n'; if (vecLen >= 3) op += ' res += tmp[ui_two];\n'; if (vecLen >= 4) op += ' res += tmp[ui_three];\n'; } else if (readAccess === es3fShaderIndexingTests.VectorAccessType.SUBSCRIPT_STATIC_LOOP) { op += ' for (int i = 0; i < ' + vecLen + '; i++)\n'; op += ' res += tmp[i];\n'; } else { assertMsgOptions(readAccess === es3fShaderIndexingTests.VectorAccessType.SUBSCRIPT_DYNAMIC_LOOP, 'readAccess not supported', false, true); op += ' for (int i = 0; i < ' + vecLenName + '; i++)\n'; op += ' res += tmp[i];\n'; } vtx += isVertexCase ? op : ''; frag += isVertexCase ? '' : op; op = ''; if (isVertexCase) { vtx += ' v_color = vec3(res);\n'; frag += ' o_color = vec4(v_color.rgb, 1.0);\n'; } else { vtx += ' v_coords = a_coords;\n'; frag += ' o_color = vec4(vec3(res), 1.0);\n'; } vtx += '}\n'; frag += '}\n'; // Fill in shader templates. /** @type {Array} */ var s_swizzles = ['', 'x', 'xy', 'xyz', 'xyzw']; /** @type {Array} */ var s_rotSwizzles = ['', 'x', 'yx', 'yzx', 'yzwx']; /** @type {Object} */ var params = {}; params["VAR_TYPE"] = gluShaderUtil.getDataTypeName(varType); params["PRECISION"] = "mediump"; params["SWIZZLE"] = s_swizzles[vecLen]; params["ROT_SWIZZLE"] = s_rotSwizzles[vecLen]; /** @type {string} */ var vertexShaderSource = tcuStringTemplate.specialize(vtx, params); /** @type {string} */ var fragmentShaderSource = tcuStringTemplate.specialize(frag, params); /** @type {function(glsShaderRenderCase.ShaderEvalContext)} */ var evalFunc = es3fShaderIndexingTests.getVectorSubscriptEvalFunc(varType); return new es3fShaderIndexingTests.ShaderIndexingCase(caseName, description, isVertexCase, varType, evalFunc, vertexShaderSource, fragmentShaderSource); }; // MATRIX SUBSCRIPT. /** @param {glsShaderRenderCase.ShaderEvalContext} c */ es3fShaderIndexingTests.evalSubscriptMat2 = function(c) { var swizzle01 = deMath.swizzle(c.coords, [0, 1]); var swizzle12 = deMath.swizzle(c.coords, [1, 2]); c.color[0] = swizzle01[0] + 0.5 * swizzle12[0]; c.color[1] = swizzle01[1] + 0.5 * swizzle12[1]; }; /** @param {glsShaderRenderCase.ShaderEvalContext} c */ es3fShaderIndexingTests.evalSubscriptMat2x3 = function(c) { var swizzle012 = deMath.swizzle(c.coords, [0, 1, 2]); var swizzle123 = deMath.swizzle(c.coords, [1, 2, 3]); c.color[0] = swizzle012[0] + 0.5 * swizzle123[0]; c.color[1] = swizzle012[1] + 0.5 * swizzle123[1]; c.color[2] = swizzle012[2] + 0.5 * swizzle123[2]; }; /** @param {glsShaderRenderCase.ShaderEvalContext} c */ es3fShaderIndexingTests.evalSubscriptMat2x4 = function(c) { c.color = deMath.add( deMath.swizzle(c.coords, [0,1,2,3]), deMath.scale(deMath.swizzle(c.coords, [1,2,3,0]), 0.5)); }; /** @param {glsShaderRenderCase.ShaderEvalContext} c */ es3fShaderIndexingTests.evalSubscriptMat3x2 = function(c) { var swizzle01 = deMath.swizzle(c.coords, [0, 1]); var swizzle12 = deMath.swizzle(c.coords, [1, 2]); var swizzle23 = deMath.swizzle(c.coords, [2, 3]); c.color[0] = swizzle01[0] + 0.5 * swizzle12[0] + 0.25 * swizzle23[0]; c.color[1] = swizzle01[1] + 0.5 * swizzle12[1] + 0.25 * swizzle23[1]; }; /** @param {glsShaderRenderCase.ShaderEvalContext} c */ es3fShaderIndexingTests.evalSubscriptMat3 = function(c) { var swizzle012 = deMath.swizzle(c.coords, [0, 1, 2]); var swizzle123 = deMath.swizzle(c.coords, [1, 2, 3]); var swizzle230 = deMath.swizzle(c.coords, [2, 3, 0]); c.color[0] = swizzle012[0] + 0.5 * swizzle123[0] + 0.25 * swizzle230[0]; c.color[1] = swizzle012[1] + 0.5 * swizzle123[1] + 0.25 * swizzle230[1]; c.color[2] = swizzle012[2] + 0.5 * swizzle123[2] + 0.25 * swizzle230[2]; }; /** @param {glsShaderRenderCase.ShaderEvalContext} c */ es3fShaderIndexingTests.evalSubscriptMat3x4 = function(c) { var swizzle0123 = deMath.swizzle(c.coords, [0, 1, 2, 3]); var swizzle1230 = deMath.swizzle(c.coords, [1, 2, 3, 0]); var swizzle2301 = deMath.swizzle(c.coords, [2, 3, 0, 1]); c.color = deMath.add( swizzle0123, deMath.add( deMath.scale(swizzle1230, 0.5), deMath.scale(swizzle2301, 0.25))); }; /** @param {glsShaderRenderCase.ShaderEvalContext} c */ es3fShaderIndexingTests.evalSubscriptMat4x2 = function(c) { var swizzle01 = deMath.swizzle(c.coords, [0, 1]); var swizzle12 = deMath.swizzle(c.coords, [1, 2]); var swizzle23 = deMath.swizzle(c.coords, [2, 3]); var swizzle30 = deMath.swizzle(c.coords, [3, 0]); c.color[0] = swizzle01[0] + 0.5 * swizzle12[0] + 0.25 * swizzle23[0] + 0.125 * swizzle30[0]; c.color[1] = swizzle01[1] + 0.5 * swizzle12[1] + 0.25 * swizzle23[1] + 0.125 * swizzle30[1]; }; /** @param {glsShaderRenderCase.ShaderEvalContext} c */ es3fShaderIndexingTests.evalSubscriptMat4x3 = function(c) { var swizzle012 = deMath.swizzle(c.coords, [0, 1, 2]); var swizzle123 = deMath.swizzle(c.coords, [1, 2, 3]); var swizzle230 = deMath.swizzle(c.coords, [2, 3, 0]); var swizzle301 = deMath.swizzle(c.coords, [3, 0, 1]); c.color[0] = swizzle012[0] + 0.5 * swizzle123[0] + 0.25 * swizzle230[0] + 0.125 * swizzle301[0]; c.color[1] = swizzle012[1] + 0.5 * swizzle123[1] + 0.25 * swizzle230[1] + 0.125 * swizzle301[1]; c.color[2] = swizzle012[2] + 0.5 * swizzle123[2] + 0.25 * swizzle230[2] + 0.125 * swizzle301[2]; }; /** @param {glsShaderRenderCase.ShaderEvalContext} c */ es3fShaderIndexingTests.evalSubscriptMat4 = function(c) { var swizzle1230 = deMath.swizzle(c.coords, [1, 2, 3, 0]); var swizzle2301 = deMath.swizzle(c.coords, [2, 3, 0, 1]); var swizzle3012 = deMath.swizzle(c.coords, [3, 0, 1, 2]); c.color = deMath.add( c.coords, deMath.add( deMath.scale(swizzle1230, 0.5), deMath.add( deMath.scale(swizzle2301, 0.25), deMath.scale(swizzle3012, 0.125)))); }; /** * @param {gluShaderUtil.DataType} dataType * @return {function(glsShaderRenderCase.ShaderEvalContext)} */ es3fShaderIndexingTests.getMatrixSubscriptEvalFunc = function(dataType) { switch (dataType) { case gluShaderUtil.DataType.FLOAT_MAT2: return es3fShaderIndexingTests.evalSubscriptMat2; case gluShaderUtil.DataType.FLOAT_MAT2X3: return es3fShaderIndexingTests.evalSubscriptMat2x3; case gluShaderUtil.DataType.FLOAT_MAT2X4: return es3fShaderIndexingTests.evalSubscriptMat2x4; case gluShaderUtil.DataType.FLOAT_MAT3X2: return es3fShaderIndexingTests.evalSubscriptMat3x2; case gluShaderUtil.DataType.FLOAT_MAT3: return es3fShaderIndexingTests.evalSubscriptMat3; case gluShaderUtil.DataType.FLOAT_MAT3X4: return es3fShaderIndexingTests.evalSubscriptMat3x4; case gluShaderUtil.DataType.FLOAT_MAT4X2: return es3fShaderIndexingTests.evalSubscriptMat4x2; case gluShaderUtil.DataType.FLOAT_MAT4X3: return es3fShaderIndexingTests.evalSubscriptMat4x3; case gluShaderUtil.DataType.FLOAT_MAT4: return es3fShaderIndexingTests.evalSubscriptMat4; default: throw new Error('Invalid data type.'); } }; /** * @param {string} caseName * @param {string} description * @param {boolean} isVertexCase * @param {gluShaderUtil.DataType} varType * @param {es3fShaderIndexingTests.IndexAccessType} writeAccess * @param {es3fShaderIndexingTests.IndexAccessType} readAccess * @return {es3fShaderIndexingTests.ShaderIndexingCase} */ es3fShaderIndexingTests.createMatrixSubscriptCase = function(caseName, description, isVertexCase, varType, writeAccess, readAccess) { /** @type {string} */ var vtx = ''; /** @type {string} */ var frag = ''; /** @type {string} */ var op = ''; /** @type {number} */ var numCols = gluShaderUtil.getDataTypeMatrixNumColumns(varType); /** @type {number} */ var numRows = gluShaderUtil.getDataTypeMatrixNumRows(varType); /** @type {string} */ var matSizeName = glsShaderRenderCase.getIntUniformName(numCols); /** @type {gluShaderUtil.DataType} */ var vecType = gluShaderUtil.getDataTypeFloatVec(numRows); vtx += '#version 300 es\n'; frag += '#version 300 es\n'; vtx += 'in highp vec4 a_position;\n' + 'in highp vec4 a_coords;\n'; frag += 'layout(location = 0) out mediump vec4 o_color;\n'; if (isVertexCase) { vtx += 'out mediump vec4 v_color;\n'; frag += 'in mediump vec4 v_color;\n'; } else { vtx += 'out mediump vec4 v_coords;\n'; frag += 'in mediump vec4 v_coords;\n'; } if (writeAccess === es3fShaderIndexingTests.IndexAccessType.DYNAMIC || readAccess === es3fShaderIndexingTests.IndexAccessType.DYNAMIC) { op += 'uniform mediump int ui_zero'; if (numCols >= 2) op += ', ui_one'; if (numCols >= 3) op += ', ui_two'; if (numCols >= 4) op += ', ui_three'; op += ';\n'; } if (writeAccess === es3fShaderIndexingTests.IndexAccessType.DYNAMIC_LOOP || readAccess === es3fShaderIndexingTests.IndexAccessType.DYNAMIC_LOOP) op += 'uniform mediump int ' + matSizeName + ';\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'; // Write matrix. if (isVertexCase) op += ' ${PRECISION} vec4 coords = a_coords;\n'; else op += ' ${PRECISION} vec4 coords = v_coords;\n'; op += ' ${PRECISION} ${MAT_TYPE} tmp;\n'; if (writeAccess === es3fShaderIndexingTests.IndexAccessType.STATIC) { op += ' tmp[0] = ${VEC_TYPE}(coords);\n'; if (numCols >= 2) op += ' tmp[1] = ${VEC_TYPE}(coords.yzwx) * 0.5;\n'; if (numCols >= 3) op += ' tmp[2] = ${VEC_TYPE}(coords.zwxy) * 0.25;\n'; if (numCols >= 4) op += ' tmp[3] = ${VEC_TYPE}(coords.wxyz) * 0.125;\n'; } else if (writeAccess === es3fShaderIndexingTests.IndexAccessType.DYNAMIC) { op += ' tmp[ui_zero] = ${VEC_TYPE}(coords);\n'; if (numCols >= 2) op += ' tmp[ui_one] = ${VEC_TYPE}(coords.yzwx) * 0.5;\n'; if (numCols >= 3) op += ' tmp[ui_two] = ${VEC_TYPE}(coords.zwxy) * 0.25;\n'; if (numCols >= 4) op += ' tmp[ui_three] = ${VEC_TYPE}(coords.wxyz) * 0.125;\n'; } else if (writeAccess === es3fShaderIndexingTests.IndexAccessType.STATIC_LOOP) { op += ' for (int i = 0; i < ' + numCols + '; i++)\n'; op += ' {\n'; op += ' tmp[i] = ${VEC_TYPE}(coords);\n'; op += ' coords = coords.yzwx * 0.5;\n'; op += ' }\n'; } else { assertMsgOptions(writeAccess === es3fShaderIndexingTests.IndexAccessType.DYNAMIC_LOOP, 'writeAccess not supported', false, true); op += ' for (int i = 0; i < ' + matSizeName + '; i++)\n'; op += ' {\n'; op += ' tmp[i] = ${VEC_TYPE}(coords);\n'; op += ' coords = coords.yzwx * 0.5;\n'; op += ' }\n'; } // Read matrix. op += ' ${PRECISION} ${VEC_TYPE} res = ${VEC_TYPE}(0.0);\n'; if (readAccess === es3fShaderIndexingTests.IndexAccessType.STATIC) { op += ' res += tmp[0];\n'; if (numCols >= 2) op += ' res += tmp[1];\n'; if (numCols >= 3) op += ' res += tmp[2];\n'; if (numCols >= 4) op += ' res += tmp[3];\n'; } else if (readAccess === es3fShaderIndexingTests.IndexAccessType.DYNAMIC) { op += ' res += tmp[ui_zero];\n'; if (numCols >= 2) op += ' res += tmp[ui_one];\n'; if (numCols >= 3) op += ' res += tmp[ui_two];\n'; if (numCols >= 4) op += ' res += tmp[ui_three];\n'; } else if (readAccess === es3fShaderIndexingTests.IndexAccessType.STATIC_LOOP) { op += ' for (int i = 0; i < ' + numCols + '; i++)\n'; op += ' res += tmp[i];\n'; } else { assertMsgOptions(readAccess === es3fShaderIndexingTests.IndexAccessType.DYNAMIC_LOOP, 'readAccess not supported', false, true); op += ' for (int i = 0; i < ' + matSizeName + '; i++)\n'; op += ' res += tmp[i];\n'; } vtx += isVertexCase ? op : ''; frag += isVertexCase ? '' : op; op = ''; if (isVertexCase) { vtx += ' v_color = vec4(res${PADDING});\n'; frag += ' o_color = v_color;\n'; } else { vtx += ' v_coords = a_coords;\n'; frag += ' o_color = vec4(res${PADDING});\n'; } vtx += '}\n'; frag += '}\n'; // Fill in shader templates. /** @type {Object} */ var params = {}; params['MAT_TYPE'] = gluShaderUtil.getDataTypeName(varType); params['VEC_TYPE'] = gluShaderUtil.getDataTypeName(vecType); params['PRECISION'] = "mediump"; if (numRows === 2) params['PADDING'] = ', 0.0, 1.0'; else if (numRows === 3) params['PADDING'] = ', 1.0'; else params['PADDING'] = ''; /** @type {string} */ var vertexShaderSource = tcuStringTemplate.specialize(vtx, params); /** @type {string} */ var fragmentShaderSource = tcuStringTemplate.specialize(frag, params); /** @type {function(glsShaderRenderCase.ShaderEvalContext)} */ var evalFunc = es3fShaderIndexingTests.getMatrixSubscriptEvalFunc(varType); return new es3fShaderIndexingTests.ShaderIndexingCase(caseName, description, isVertexCase, varType, evalFunc, vertexShaderSource, fragmentShaderSource); }; /** * @constructor * @extends {tcuTestCase.DeqpTest} */ es3fShaderIndexingTests.ShaderIndexingTests = function() { tcuTestCase.DeqpTest.call(this, 'indexing', 'Indexing Tests'); }; es3fShaderIndexingTests.ShaderIndexingTests.prototype = Object.create(tcuTestCase.DeqpTest.prototype); es3fShaderIndexingTests.ShaderIndexingTests.prototype.constructor = es3fShaderIndexingTests.ShaderIndexingTests; es3fShaderIndexingTests.ShaderIndexingTests.prototype.init = function() { var testGroup = tcuTestCase.runner.testCases; /** @type {Array} */ var s_shaderTypes = [ gluShaderProgram.shaderType.VERTEX, gluShaderProgram.shaderType.FRAGMENT ]; /** @type {Array} */ var s_floatAndVecTypes = [ gluShaderUtil.DataType.FLOAT, gluShaderUtil.DataType.FLOAT_VEC2, gluShaderUtil.DataType.FLOAT_VEC3, gluShaderUtil.DataType.FLOAT_VEC4 ]; /** @type {string} */ var name; /** @type {string} */ var desc; /** @type {string} */ var shaderTypeName; /** @type {boolean} */ var isVertexCase; /** @type {gluShaderProgram.shaderType} */ var shaderType; /** @type {string} */ var writeAccessName; /** @type {string} */ var readAccessName; // Varying array access cases. /** @type {tcuTestCase.DeqpTest} */ var varyingGroup = tcuTestCase.newTest('varying_array', 'Varying array access tests.'); testGroup.addChild(varyingGroup); /** @type {gluShaderUtil.DataType} */ var varType; for (var typeNdx = 0; typeNdx < s_floatAndVecTypes.length; typeNdx++) { varType = s_floatAndVecTypes[typeNdx]; for (var vertAccessStr in es3fShaderIndexingTests.IndexAccessType) { for (var fragAccessStr in es3fShaderIndexingTests.IndexAccessType) { var vertAccess = es3fShaderIndexingTests.IndexAccessType[vertAccessStr]; var fragAccess = es3fShaderIndexingTests.IndexAccessType[fragAccessStr]; /** @type {string} */ var vertAccessName = es3fShaderIndexingTests.getIndexAccessTypeName(vertAccess); /** @type {string} */ var fragAccessName = es3fShaderIndexingTests.getIndexAccessTypeName(fragAccess); name = gluShaderUtil.getDataTypeName(varType) + '_' + vertAccessName + '_write_' + fragAccessName + '_read'; desc = 'Varying array with ' + vertAccessName + ' write in vertex shader and ' + fragAccessName + ' read in fragment shader.'; varyingGroup.addChild(es3fShaderIndexingTests.createVaryingArrayCase(name, desc, varType, vertAccess, fragAccess)); } } } // Uniform array access cases. /** @type {tcuTestCase.DeqpTest} */ var uniformGroup = tcuTestCase.newTest("uniform_array", "Uniform array access tests."); testGroup.addChild(uniformGroup); for (var typeNdx = 0; typeNdx < s_floatAndVecTypes.length; typeNdx++) { varType = s_floatAndVecTypes[typeNdx]; for (var readAccessStr in es3fShaderIndexingTests.IndexAccessType) { var readAccess = es3fShaderIndexingTests.IndexAccessType[readAccessStr]; readAccessName = es3fShaderIndexingTests.getIndexAccessTypeName(readAccess); for (var shaderTypeNdx = 0; shaderTypeNdx < s_shaderTypes.length; shaderTypeNdx++) { shaderType = s_shaderTypes[shaderTypeNdx]; shaderTypeName = gluShaderProgram.getShaderTypeName(shaderType); name = gluShaderUtil.getDataTypeName(varType) + "_" + readAccessName + "_read_" + shaderTypeName; desc = "Uniform array with " + readAccessName + " read in " + shaderTypeName + " shader."; isVertexCase = shaderType === gluShaderProgram.shaderType.VERTEX; uniformGroup.addChild(es3fShaderIndexingTests.createUniformArrayCase(name, desc, isVertexCase, varType, readAccess)); } } } // Temporary array access cases. /** @type {tcuTestCase.DeqpTest} */ var tmpGroup = tcuTestCase.newTest("tmp_array", "Temporary array access tests."); testGroup.addChild(tmpGroup); for (var typeNdx = 0; typeNdx < s_floatAndVecTypes.length; typeNdx++) { varType = s_floatAndVecTypes[typeNdx]; for (var writeAccess in es3fShaderIndexingTests.IndexAccessType) { for (var readAccess in es3fShaderIndexingTests.IndexAccessType) { writeAccessName = es3fShaderIndexingTests.getIndexAccessTypeName(es3fShaderIndexingTests.IndexAccessType[writeAccess]); readAccessName = es3fShaderIndexingTests.getIndexAccessTypeName(es3fShaderIndexingTests.IndexAccessType[readAccess]); for (var shaderTypeNdx = 0; shaderTypeNdx < s_shaderTypes.length; shaderTypeNdx++) { shaderType = s_shaderTypes[shaderTypeNdx]; shaderTypeName = gluShaderProgram.getShaderTypeName(shaderType); name = gluShaderUtil.getDataTypeName(varType) + "_" + writeAccessName + "_write_" + readAccessName + "_read_" + shaderTypeName; desc = "Temporary array with " + writeAccessName + " write and " + readAccessName + " read in " + shaderTypeName + " shader."; isVertexCase = (shaderType === gluShaderProgram.shaderType.VERTEX); tmpGroup.addChild(es3fShaderIndexingTests.createTmpArrayCase(name, desc, isVertexCase, varType, es3fShaderIndexingTests.IndexAccessType[writeAccess], es3fShaderIndexingTests.IndexAccessType[readAccess])); } } } } // Vector indexing with subscripts. /** @type {Array} */ var s_vectorTypes = [ gluShaderUtil.DataType.FLOAT_VEC2, gluShaderUtil.DataType.FLOAT_VEC3, gluShaderUtil.DataType.FLOAT_VEC4 ]; for (var typeNdx = 0; typeNdx < s_vectorTypes.length; typeNdx++) { /** @type {tcuTestCase.DeqpTest} */ var vecGroup = tcuTestCase.newTest("vector_subscript", "Vector subscript indexing."); testGroup.addChild(vecGroup); varType = s_vectorTypes[typeNdx]; for (var writeAccess in es3fShaderIndexingTests.VectorAccessType) { for (var readAccess in es3fShaderIndexingTests.VectorAccessType) { writeAccessName = es3fShaderIndexingTests.getVectorAccessTypeName(es3fShaderIndexingTests.VectorAccessType[writeAccess]); readAccessName = es3fShaderIndexingTests.getVectorAccessTypeName(es3fShaderIndexingTests.VectorAccessType[readAccess]); for (var shaderTypeNdx = 0; shaderTypeNdx < s_shaderTypes.length; shaderTypeNdx++) { shaderType = s_shaderTypes[shaderTypeNdx]; shaderTypeName = gluShaderProgram.getShaderTypeName(shaderType); name = gluShaderUtil.getDataTypeName(varType) + "_" + writeAccessName + "_write_" + readAccessName + "_read_" + shaderTypeName; desc = "Vector subscript access with " + writeAccessName + " write and " + readAccessName + " read in " + shaderTypeName + " shader."; isVertexCase = shaderType === gluShaderProgram.shaderType.VERTEX; vecGroup.addChild(es3fShaderIndexingTests.createVectorSubscriptCase(name, desc, isVertexCase, varType, es3fShaderIndexingTests.VectorAccessType[writeAccess], es3fShaderIndexingTests.VectorAccessType[readAccess])); } } } } // Matrix indexing with subscripts. /** @type {Array} */ var matGroup = [ tcuTestCase.newTest("matrix_subscript", "Matrix subscript indexing."), tcuTestCase.newTest("matrix_subscript", "Matrix subscript indexing."), tcuTestCase.newTest("matrix_subscript", "Matrix subscript indexing."), ]; for (var ii = 0; ii < matGroup.length; ++ii) { testGroup.addChild(matGroup[ii]); } /** @type {Array} */ var s_matrixTypes = [ gluShaderUtil.DataType.FLOAT_MAT2, gluShaderUtil.DataType.FLOAT_MAT2X3, gluShaderUtil.DataType.FLOAT_MAT2X4, gluShaderUtil.DataType.FLOAT_MAT3X2, gluShaderUtil.DataType.FLOAT_MAT3, gluShaderUtil.DataType.FLOAT_MAT3X4, gluShaderUtil.DataType.FLOAT_MAT4X2, gluShaderUtil.DataType.FLOAT_MAT4X3, gluShaderUtil.DataType.FLOAT_MAT4 ]; for (var typeNdx = 0; typeNdx < s_matrixTypes.length; typeNdx++) { varType = s_matrixTypes[typeNdx]; for (var writeAccess in es3fShaderIndexingTests.IndexAccessType) { for (var readAccess in es3fShaderIndexingTests.IndexAccessType) { writeAccessName = es3fShaderIndexingTests.getIndexAccessTypeName(es3fShaderIndexingTests.IndexAccessType[writeAccess]); readAccessName = es3fShaderIndexingTests.getIndexAccessTypeName(es3fShaderIndexingTests.IndexAccessType[readAccess]); for (var shaderTypeNdx = 0; shaderTypeNdx < s_shaderTypes.length; shaderTypeNdx++) { shaderType = s_shaderTypes[shaderTypeNdx]; shaderTypeName = gluShaderProgram.getShaderTypeName(shaderType); name = gluShaderUtil.getDataTypeName(varType) + "_" + writeAccessName + "_write_" + readAccessName + "_read_" + shaderTypeName; desc = "Vector subscript access with " + writeAccessName + " write and " + readAccessName + " read in " + shaderTypeName + " shader."; isVertexCase = shaderType === gluShaderProgram.shaderType.VERTEX; matGroup[typeNdx % matGroup.length].addChild(es3fShaderIndexingTests.createMatrixSubscriptCase( name, desc, isVertexCase, varType, es3fShaderIndexingTests.IndexAccessType[writeAccess], es3fShaderIndexingTests.IndexAccessType[readAccess])); } } } } }; /** * Run test * @param {WebGL2RenderingContext} context */ es3fShaderIndexingTests.run = function(context, range) { gl = context; //Set up Test Root parameters var state = tcuTestCase.runner; state.setRoot(new es3fShaderIndexingTests.ShaderIndexingTests()); //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 es3fShaderIndexingTests.run tests', false); tcuTestCase.runner.terminate(); } }; });