es3fShaderIndexingTests.js (59940B)
1 /*------------------------------------------------------------------------- 2 * drawElements Quality Program OpenGL ES Utilities 3 * ------------------------------------------------ 4 * 5 * Copyright 2014 The Android Open Source Project 6 * 7 * Licensed under the Apache License, Version 2.0 (the "License"); 8 * you may not use this file except in compliance with the License. 9 * You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, software 14 * distributed under the License is distributed on an "AS IS" BASIS, 15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 * See the License for the specific language governing permissions and 17 * limitations under the License. 18 * 19 */ 20 21 'use strict'; 22 goog.provide('functional.gles3.es3fShaderIndexingTests'); 23 goog.require('framework.common.tcuImageCompare'); 24 goog.require('framework.common.tcuStringTemplate'); 25 goog.require('framework.common.tcuTestCase'); 26 goog.require('framework.delibs.debase.deMath'); 27 goog.require('framework.opengl.gluShaderUtil'); 28 goog.require('framework.opengl.gluShaderProgram'); 29 goog.require('framework.opengl.gluTexture'); 30 goog.require('modules.shared.glsShaderRenderCase'); 31 32 goog.scope(function() { 33 /** @type {?WebGL2RenderingContext} */ var gl; 34 var es3fShaderIndexingTests = functional.gles3.es3fShaderIndexingTests; 35 var deMath = framework.delibs.debase.deMath; 36 var glsShaderRenderCase = modules.shared.glsShaderRenderCase; 37 var gluShaderUtil = framework.opengl.gluShaderUtil; 38 var gluTexture = framework.opengl.gluTexture; 39 var gluShaderProgram = framework.opengl.gluShaderProgram; 40 var tcuTestCase = framework.common.tcuTestCase; 41 var tcuStringTemplate = framework.common.tcuStringTemplate; 42 /** 43 * @enum {number} 44 */ 45 es3fShaderIndexingTests.IndexAccessType = { 46 STATIC: 0, 47 DYNAMIC: 1, 48 STATIC_LOOP: 2, 49 DYNAMIC_LOOP: 3 50 }; 51 52 /** 53 * @param {es3fShaderIndexingTests.IndexAccessType} accessType 54 * @return {string} 55 */ 56 es3fShaderIndexingTests.getIndexAccessTypeName = function(accessType) { 57 /** @type {Array<string>} */ var s_names = [ 58 'static', 59 'dynamic', 60 'static_loop', 61 'dynamic_loop' 62 ]; 63 return s_names[accessType]; 64 }; 65 66 /** 67 * @enum {number} 68 */ 69 es3fShaderIndexingTests.VectorAccessType = { 70 DIRECT: 0, 71 COMPONENT: 1, 72 SUBSCRIPT_STATIC: 2, 73 SUBSCRIPT_DYNAMIC: 3, 74 SUBSCRIPT_STATIC_LOOP: 4, 75 SUBSCRIPT_DYNAMIC_LOOP: 5 76 }; 77 78 /** 79 * @param {es3fShaderIndexingTests.VectorAccessType} accessType 80 * @return {string} 81 */ 82 es3fShaderIndexingTests.getVectorAccessTypeName = function(accessType) { 83 /** @type {Array<string>} */ var s_names = [ 84 'direct', 85 'component', 86 'static_subscript', 87 'dynamic_subscript', 88 'static_loop_subscript', 89 'dynamic_loop_subscript' 90 ]; 91 assertMsgOptions(deMath.deInBounds32(accessType, 0, s_names.length), 'Index out of bounds', false, true); 92 return s_names[accessType]; 93 }; 94 95 /** @param {glsShaderRenderCase.ShaderEvalContext} c */ 96 es3fShaderIndexingTests.evalArrayCoordsFloat = function(c) { 97 c.color[0] = 1.875 * c.coords[0]; 98 }; 99 100 /** @param {glsShaderRenderCase.ShaderEvalContext} c */ 101 es3fShaderIndexingTests.evalArrayCoordsVec2 = function(c) { 102 var swizzled = deMath.swizzle(c.coords, [0, 1]); 103 c.color[0] = 1.875 * swizzled[0]; 104 c.color[1] = 1.875 * swizzled[1]; 105 }; 106 107 /** @param {glsShaderRenderCase.ShaderEvalContext} c */ 108 es3fShaderIndexingTests.evalArrayCoordsVec3 = function(c) { 109 var swizzled = deMath.swizzle(c.coords, [0, 1, 2]); 110 c.color[0] = 1.875 * swizzled[0]; 111 c.color[1] = 1.875 * swizzled[1]; 112 c.color[2] = 1.875 * swizzled[2]; 113 }; 114 115 /** @param {glsShaderRenderCase.ShaderEvalContext} c */ 116 es3fShaderIndexingTests.evalArrayCoordsVec4 = function(c) { 117 c.color = deMath.scale(c.coords, 1.875); 118 }; 119 120 /** 121 * @param {gluShaderUtil.DataType} dataType 122 * @return {function(glsShaderRenderCase.ShaderEvalContext)} 123 */ 124 es3fShaderIndexingTests.getArrayCoordsEvalFunc = function(dataType) { 125 if (dataType === gluShaderUtil.DataType.FLOAT) return es3fShaderIndexingTests.evalArrayCoordsFloat; 126 else if (dataType === gluShaderUtil.DataType.FLOAT_VEC2) return es3fShaderIndexingTests.evalArrayCoordsVec2; 127 else if (dataType === gluShaderUtil.DataType.FLOAT_VEC3) return es3fShaderIndexingTests.evalArrayCoordsVec3; 128 else if (dataType === gluShaderUtil.DataType.FLOAT_VEC4) return es3fShaderIndexingTests.evalArrayCoordsVec4; 129 else throw new Error('Invalid data type.'); 130 }; 131 132 133 /** @param {glsShaderRenderCase.ShaderEvalContext} c */ 134 es3fShaderIndexingTests.evalArrayUniformFloat = function(c) { 135 c.color[0] = 1.875 * c.constCoords[0]; 136 }; 137 138 /** @param {glsShaderRenderCase.ShaderEvalContext} c */ 139 es3fShaderIndexingTests.evalArrayUniformVec2 = function(c) { 140 var swizzled = deMath.swizzle(c.constCoords, [0, 1]); 141 c.color[0] = 1.875 * swizzled[0]; 142 c.color[1] = 1.875 * swizzled[1]; 143 }; 144 145 /** @param {glsShaderRenderCase.ShaderEvalContext} c */ 146 es3fShaderIndexingTests.evalArrayUniformVec3 = function(c) { 147 var swizzled = deMath.swizzle(c.constCoords, [0, 1, 2]); 148 c.color[0] = 1.875 * swizzled[0]; 149 c.color[1] = 1.875 * swizzled[1]; 150 c.color[2] = 1.875 * swizzled[2]; 151 }; 152 153 /** @param {glsShaderRenderCase.ShaderEvalContext} c */ 154 es3fShaderIndexingTests.evalArrayUniformVec4 = function(c) { 155 c.color = deMath.scale(c.constCoords, 1.875); 156 }; 157 158 /** 159 * @param {gluShaderUtil.DataType} dataType 160 * @return {function(glsShaderRenderCase.ShaderEvalContext)} 161 */ 162 es3fShaderIndexingTests.getArrayUniformEvalFunc = function(dataType) { 163 if (dataType === gluShaderUtil.DataType.FLOAT) return es3fShaderIndexingTests.evalArrayUniformFloat; 164 else if (dataType === gluShaderUtil.DataType.FLOAT_VEC2) return es3fShaderIndexingTests.evalArrayUniformVec2; 165 else if (dataType === gluShaderUtil.DataType.FLOAT_VEC3) return es3fShaderIndexingTests.evalArrayUniformVec3; 166 else if (dataType === gluShaderUtil.DataType.FLOAT_VEC4) return es3fShaderIndexingTests.evalArrayUniformVec4; 167 else throw new Error('Invalid data type.'); 168 }; 169 170 /** 171 * @constructor 172 * @extends {glsShaderRenderCase.ShaderRenderCase} 173 * @param {string} name 174 * @param {string} description 175 * @param {boolean} isVertexCase 176 * @param {gluShaderUtil.DataType} varType 177 * @param {function(glsShaderRenderCase.ShaderEvalContext)} evalFunc 178 * @param {string} vertShaderSource 179 * @param {string} fragShaderSource 180 */ 181 es3fShaderIndexingTests.ShaderIndexingCase = function(name, description, isVertexCase, varType, evalFunc, vertShaderSource, fragShaderSource) { 182 glsShaderRenderCase.ShaderRenderCase.call(this, name, description, isVertexCase, evalFunc); 183 /** @type {gluShaderUtil.DataType} */ this.m_varType = varType; 184 /** @type {string} */ this.m_vertShaderSource = vertShaderSource; 185 /** @type {string} */ this.m_fragShaderSource = fragShaderSource; 186 }; 187 188 es3fShaderIndexingTests.ShaderIndexingCase.prototype = Object.create(glsShaderRenderCase.ShaderRenderCase.prototype); 189 es3fShaderIndexingTests.ShaderIndexingCase.prototype.constructor = es3fShaderIndexingTests.ShaderIndexingCase; 190 191 /** 192 * @param {?WebGLProgram} programID 193 * @param {Array<number>} constCoords 194 */ 195 es3fShaderIndexingTests.ShaderIndexingCase.prototype.setupUniforms = function(programID, constCoords) { 196 /** @type {(Array<number>|Float32Array)} */ var arr = []; 197 /** @type {Array<number>} */ var array1d = []; 198 /** @type {?WebGLUniformLocation} */ var arrLoc = gl.getUniformLocation(programID, 'u_arr'); 199 if (arrLoc != null) { 200 if (this.m_varType === gluShaderUtil.DataType.FLOAT) { 201 arr[0] = constCoords[0]; 202 arr[1] = constCoords[0] * 0.5; 203 arr[2] = constCoords[0] * 0.25; 204 arr[3] = constCoords[0] * 0.125; 205 gl.uniform1fv(arrLoc, arr); 206 } 207 else if (this.m_varType === gluShaderUtil.DataType.FLOAT_VEC2) { 208 arr[0] = deMath.swizzle(constCoords, [0, 1]); 209 arr[1] = deMath.scale(deMath.swizzle(constCoords, [0, 1]), 0.5); 210 arr[2] = deMath.scale(deMath.swizzle(constCoords, [0, 1]), 0.25); 211 arr[3] = deMath.scale(deMath.swizzle(constCoords, [0, 1]), 0.125); 212 for (var i = 0; i < arr.length; i++) 213 array1d = array1d.concat(arr[i]); 214 gl.uniform2fv(arrLoc, array1d); 215 } 216 else if (this.m_varType === gluShaderUtil.DataType.FLOAT_VEC3) { 217 arr[0] = deMath.swizzle(constCoords, [0, 1, 2]); 218 arr[1] = deMath.scale(deMath.swizzle(constCoords, [0, 1, 2]), 0.5); 219 arr[2] = deMath.scale(deMath.swizzle(constCoords, [0, 1, 2]), 0.25); 220 arr[3] = deMath.scale(deMath.swizzle(constCoords, [0, 1, 2]), 0.125); 221 for (var i = 0; i < arr.length; i++) 222 array1d = array1d.concat(arr[i]); 223 gl.uniform3fv(arrLoc, array1d); 224 } 225 else if (this.m_varType === gluShaderUtil.DataType.FLOAT_VEC4) { 226 arr[0] = deMath.swizzle(constCoords, [0,1,2,3]); 227 arr[1] = deMath.scale(deMath.swizzle(constCoords, [0, 1, 2, 3]), 0.5); 228 arr[2] = deMath.scale(deMath.swizzle(constCoords, [0, 1, 2, 3]), 0.25); 229 arr[3] = deMath.scale(deMath.swizzle(constCoords, [0, 1, 2, 3]), 0.125); 230 for (var i = 0; i < arr.length; i++) 231 array1d = array1d.concat(arr[i]); 232 gl.uniform4fv(arrLoc, array1d); 233 } 234 else 235 throw new Error('u_arr should not have location assigned in this test case'); 236 } 237 }; 238 239 /** 240 * @param {string} caseName 241 * @param {string} description 242 * @param {gluShaderUtil.DataType} varType 243 * @param {es3fShaderIndexingTests.IndexAccessType} vertAccess 244 * @param {es3fShaderIndexingTests.IndexAccessType} fragAccess 245 * @return {es3fShaderIndexingTests.ShaderIndexingCase} 246 */ 247 es3fShaderIndexingTests.createVaryingArrayCase = function(caseName, description, varType, vertAccess, fragAccess) { 248 /** @type {string} */ var vtx = ''; 249 vtx += '#version 300 es\n' + 250 'in highp vec4 a_position;\n' + 251 'in highp vec4 a_coords;\n'; 252 253 if (vertAccess === es3fShaderIndexingTests.IndexAccessType.DYNAMIC) 254 vtx += 'uniform mediump int ui_zero, ui_one, ui_two, ui_three;\n'; 255 else if (vertAccess === es3fShaderIndexingTests.IndexAccessType.DYNAMIC_LOOP) 256 vtx += 'uniform mediump int ui_four;\n'; 257 258 vtx += 'out ${PRECISION} ${VAR_TYPE} var[${ARRAY_LEN}];\n' + 259 '\n' + 260 'void main()\n' + 261 '{\n' + 262 ' gl_Position = a_position;\n'; 263 264 if (vertAccess === es3fShaderIndexingTests.IndexAccessType.STATIC) { 265 vtx += ' var[0] = ${VAR_TYPE}(a_coords);\n' + 266 ' var[1] = ${VAR_TYPE}(a_coords) * 0.5;\n' + 267 ' var[2] = ${VAR_TYPE}(a_coords) * 0.25;\n' + 268 ' var[3] = ${VAR_TYPE}(a_coords) * 0.125;\n'; 269 } 270 else if (vertAccess === es3fShaderIndexingTests.IndexAccessType.DYNAMIC) { 271 vtx += ' var[ui_zero] = ${VAR_TYPE}(a_coords);\n' + 272 ' var[ui_one] = ${VAR_TYPE}(a_coords) * 0.5;\n' + 273 ' var[ui_two] = ${VAR_TYPE}(a_coords) * 0.25;\n' + 274 ' var[ui_three] = ${VAR_TYPE}(a_coords) * 0.125;\n'; 275 } 276 else if (vertAccess === es3fShaderIndexingTests.IndexAccessType.STATIC_LOOP) { 277 vtx += ' ${PRECISION} ${VAR_TYPE} coords = ${VAR_TYPE}(a_coords);\n' + 278 ' for (int i = 0; i < 4; i++)\n' + 279 ' {\n' + 280 ' var[i] = ${VAR_TYPE}(coords);\n' + 281 ' coords = coords * 0.5;\n' + 282 ' }\n'; 283 } 284 else { 285 assertMsgOptions(vertAccess === es3fShaderIndexingTests.IndexAccessType.DYNAMIC_LOOP, 'Not Dynamic_Loop', false, true); 286 vtx += ' ${PRECISION} ${VAR_TYPE} coords = ${VAR_TYPE}(a_coords);\n' + 287 ' for (int i = 0; i < ui_four; i++)\n' + 288 ' {\n' + 289 ' var[i] = ${VAR_TYPE}(coords);\n' + 290 ' coords = coords * 0.5;\n' + 291 ' }\n'; 292 } 293 vtx += '}\n'; 294 295 /** @type {string} */ var frag = ''; 296 frag += '#version 300 es\n' + 297 'precision mediump int;\n' + 298 'layout(location = 0) out mediump vec4 o_color;\n'; 299 300 if (fragAccess === es3fShaderIndexingTests.IndexAccessType.DYNAMIC) 301 frag += 'uniform mediump int ui_zero, ui_one, ui_two, ui_three;\n'; 302 else if (fragAccess === es3fShaderIndexingTests.IndexAccessType.DYNAMIC_LOOP) 303 frag += 'uniform int ui_four;\n'; 304 305 frag += 'in ${PRECISION} ${VAR_TYPE} var[${ARRAY_LEN}];\n' + 306 '\n' + 307 'void main()\n' + 308 '{\n' + 309 ' ${PRECISION} ${VAR_TYPE} res = ${VAR_TYPE}(0.0);\n'; 310 311 if (fragAccess === es3fShaderIndexingTests.IndexAccessType.STATIC) { 312 frag += ' res += var[0];\n' + 313 ' res += var[1];\n' + 314 ' res += var[2];\n' + 315 ' res += var[3];\n'; 316 } 317 else if (fragAccess === es3fShaderIndexingTests.IndexAccessType.DYNAMIC) { 318 frag += ' res += var[ui_zero];\n' + 319 ' res += var[ui_one];\n' + 320 ' res += var[ui_two];\n' + 321 ' res += var[ui_three];\n'; 322 } 323 else if (fragAccess === es3fShaderIndexingTests.IndexAccessType.STATIC_LOOP) { 324 frag += ' for (int i = 0; i < 4; i++)\n' + 325 ' res += var[i];\n'; 326 } 327 else { 328 assertMsgOptions(fragAccess === es3fShaderIndexingTests.IndexAccessType.DYNAMIC_LOOP, 'Not Dynamic_Loop', false, true); 329 frag += ' for (int i = 0; i < ui_four; i++)\n' + 330 ' res += var[i];\n'; 331 } 332 frag += ' o_color = vec4(res${PADDING});\n' + 333 '}\n'; 334 335 // Fill in shader templates. 336 /** @type {Object} */ var params = {}; 337 params['VAR_TYPE'] = gluShaderUtil.getDataTypeName(varType); 338 params['ARRAY_LEN'] = '4'; 339 params['PRECISION'] = 'mediump'; 340 341 if (varType === gluShaderUtil.DataType.FLOAT) 342 params['PADDING'] = ', 0.0, 0.0, 1.0'; 343 else if (varType === gluShaderUtil.DataType.FLOAT_VEC2) 344 params['PADDING'] = ', 0.0, 1.0'; 345 else if (varType === gluShaderUtil.DataType.FLOAT_VEC3) 346 params['PADDING'] = ', 1.0'; 347 else 348 params['PADDING'] = ''; 349 350 /** @type {string} */ var vertexShaderSource = tcuStringTemplate.specialize(vtx, params); 351 /** @type {string} */ var fragmentShaderSource = tcuStringTemplate.specialize(frag, params); 352 353 /** @type {function(glsShaderRenderCase.ShaderEvalContext)} */ 354 var evalFunc = es3fShaderIndexingTests.getArrayCoordsEvalFunc(varType); 355 return new es3fShaderIndexingTests.ShaderIndexingCase(caseName, description, true, varType, evalFunc, vertexShaderSource, fragmentShaderSource); 356 }; 357 358 /** 359 * @param {string} caseName 360 * @param {string} description 361 * @param {boolean} isVertexCase 362 * @param {gluShaderUtil.DataType} varType 363 * @param {es3fShaderIndexingTests.IndexAccessType} readAccess 364 * @return {es3fShaderIndexingTests.ShaderIndexingCase} 365 */ 366 es3fShaderIndexingTests.createUniformArrayCase = function(caseName, description, isVertexCase, varType, readAccess) { 367 /** @type {string} */ var vtx = ''; 368 /** @type {string} */ var frag = ''; 369 /** @type {string} */ var op = ''; 370 371 vtx += '#version 300 es\n'; 372 frag += '#version 300 es\n'; 373 374 vtx += 'in highp vec4 a_position;\n'; 375 vtx += 'in highp vec4 a_coords;\n'; 376 frag += 'layout(location = 0) out mediump vec4 o_color;\n'; 377 378 if (isVertexCase) { 379 vtx += 'out mediump vec4 v_color;\n'; 380 frag += 'in mediump vec4 v_color;\n'; 381 } 382 else { 383 vtx += 'out mediump vec4 v_coords;\n'; 384 frag += 'in mediump vec4 v_coords;\n'; 385 } 386 387 if (readAccess === es3fShaderIndexingTests.IndexAccessType.DYNAMIC) 388 op += 'uniform mediump int ui_zero, ui_one, ui_two, ui_three;\n'; 389 else if (readAccess === es3fShaderIndexingTests.IndexAccessType.DYNAMIC_LOOP) 390 op += 'uniform mediump int ui_four;\n'; 391 392 op += 'uniform ${PRECISION} ${VAR_TYPE} u_arr[${ARRAY_LEN}];\n'; 393 394 vtx += isVertexCase ? op : ''; 395 frag += isVertexCase ? '' : op; 396 op = ''; 397 398 vtx += '\n'; 399 vtx += 'void main()\n'; 400 vtx += '{\n'; 401 vtx += ' gl_Position = a_position;\n'; 402 403 frag += '\n'; 404 frag += 'void main()\n'; 405 frag += '{\n'; 406 407 // Read array. 408 op += ' ${PRECISION} ${VAR_TYPE} res = ${VAR_TYPE}(0.0);\n'; 409 if (readAccess === es3fShaderIndexingTests.IndexAccessType.STATIC) { 410 op += ' res += u_arr[0];\n'; 411 op += ' res += u_arr[1];\n'; 412 op += ' res += u_arr[2];\n'; 413 op += ' res += u_arr[3];\n'; 414 } 415 else if (readAccess === es3fShaderIndexingTests.IndexAccessType.DYNAMIC) { 416 op += ' res += u_arr[ui_zero];\n'; 417 op += ' res += u_arr[ui_one];\n'; 418 op += ' res += u_arr[ui_two];\n'; 419 op += ' res += u_arr[ui_three];\n'; 420 } 421 else if (readAccess === es3fShaderIndexingTests.IndexAccessType.STATIC_LOOP) { 422 op += ' for (int i = 0; i < 4; i++)\n'; 423 op += ' res += u_arr[i];\n'; 424 } 425 else { 426 assertMsgOptions(readAccess === es3fShaderIndexingTests.IndexAccessType.DYNAMIC_LOOP, 'readAccess not supported.', false, true); 427 op += ' for (int i = 0; i < ui_four; i++)\n'; 428 op += ' res += u_arr[i];\n'; 429 } 430 431 vtx += isVertexCase ? op : ''; 432 frag += isVertexCase ? '' : op; 433 op = ''; 434 435 if (isVertexCase) { 436 vtx += ' v_color = vec4(res${PADDING});\n'; 437 frag += ' o_color = v_color;\n'; 438 } 439 else { 440 vtx += ' v_coords = a_coords;\n'; 441 frag += ' o_color = vec4(res${PADDING});\n'; 442 } 443 444 vtx += '}\n'; 445 frag += '}\n'; 446 447 // Fill in shader templates. 448 /** @type {Object} */ var params = {}; 449 params['VAR_TYPE'] = gluShaderUtil.getDataTypeName(varType); 450 params['ARRAY_LEN'] = '4'; 451 params['PRECISION'] = 'mediump'; 452 453 if (varType === gluShaderUtil.DataType.FLOAT) 454 params['PADDING'] = ', 0.0, 0.0, 1.0'; 455 else if (varType === gluShaderUtil.DataType.FLOAT_VEC2) 456 params['PADDING'] = ', 0.0, 1.0'; 457 else if (varType === gluShaderUtil.DataType.FLOAT_VEC3) 458 params['PADDING'] = ', 1.0'; 459 else 460 params['PADDING'] = ''; 461 462 463 /** @type {string} */ var vertexShaderSource = tcuStringTemplate.specialize(vtx, params); 464 /** @type {string} */ var fragmentShaderSource = tcuStringTemplate.specialize(frag, params); 465 466 /** @type {function(glsShaderRenderCase.ShaderEvalContext)} */ 467 var evalFunc = es3fShaderIndexingTests.getArrayUniformEvalFunc(varType); 468 return new es3fShaderIndexingTests.ShaderIndexingCase(caseName, description, isVertexCase, varType, evalFunc, vertexShaderSource, fragmentShaderSource); 469 }; 470 471 /** 472 * @param {string} caseName 473 * @param {string} description 474 * @param {boolean} isVertexCase 475 * @param {gluShaderUtil.DataType} varType 476 * @param {es3fShaderIndexingTests.IndexAccessType} writeAccess 477 * @param {es3fShaderIndexingTests.IndexAccessType} readAccess 478 * @return {es3fShaderIndexingTests.ShaderIndexingCase} 479 */ 480 es3fShaderIndexingTests.createTmpArrayCase = function(caseName, description, isVertexCase, varType, writeAccess, readAccess) { 481 /** @type {string} */ var vtx = ''; 482 /** @type {string} */ var frag = ''; 483 /** @type {string} */ var op = ''; 484 485 vtx += '#version 300 es\n'; 486 frag += '#version 300 es\n'; 487 488 vtx += 'in highp vec4 a_position;\n' + 489 'in highp vec4 a_coords;\n'; 490 frag += 'layout(location = 0) out mediump vec4 o_color;\n'; 491 492 if (isVertexCase) { 493 vtx += 'out mediump vec4 v_color;\n'; 494 frag += 'in mediump vec4 v_color;\n'; 495 } 496 else { 497 vtx += 'out mediump vec4 v_coords;\n'; 498 frag += 'in mediump vec4 v_coords;\n'; 499 } 500 501 if (writeAccess === es3fShaderIndexingTests.IndexAccessType.DYNAMIC || readAccess === es3fShaderIndexingTests.IndexAccessType.DYNAMIC) 502 op += 'uniform mediump int ui_zero, ui_one, ui_two, ui_three;\n'; 503 504 if (writeAccess === es3fShaderIndexingTests.IndexAccessType.DYNAMIC_LOOP || readAccess === es3fShaderIndexingTests.IndexAccessType.DYNAMIC_LOOP) 505 op += 'uniform mediump int ui_four;\n'; 506 507 vtx += isVertexCase ? op : ''; 508 frag += isVertexCase ? '' : op; 509 op = ''; 510 511 vtx += '\n' + 512 'void main()\n' + 513 '{\n' + 514 ' gl_Position = a_position;\n'; 515 516 frag += '\n' + 517 'void main()\n' + 518 '{\n'; 519 520 // Write array. 521 if (isVertexCase) 522 op += ' ${PRECISION} ${VAR_TYPE} coords = ${VAR_TYPE}(a_coords);\n'; 523 else 524 op += ' ${PRECISION} ${VAR_TYPE} coords = ${VAR_TYPE}(v_coords);\n'; 525 526 op += ' ${PRECISION} ${VAR_TYPE} arr[${ARRAY_LEN}];\n'; 527 if (writeAccess === es3fShaderIndexingTests.IndexAccessType.STATIC) { 528 op += ' arr[0] = ${VAR_TYPE}(coords);\n' + 529 ' arr[1] = ${VAR_TYPE}(coords) * 0.5;\n' + 530 ' arr[2] = ${VAR_TYPE}(coords) * 0.25;\n' + 531 ' arr[3] = ${VAR_TYPE}(coords) * 0.125;\n'; 532 } 533 else if (writeAccess === es3fShaderIndexingTests.IndexAccessType.DYNAMIC) { 534 op += ' arr[ui_zero] = ${VAR_TYPE}(coords);\n' + 535 ' arr[ui_one] = ${VAR_TYPE}(coords) * 0.5;\n' + 536 ' arr[ui_two] = ${VAR_TYPE}(coords) * 0.25;\n' + 537 ' arr[ui_three] = ${VAR_TYPE}(coords) * 0.125;\n'; 538 } 539 else if (writeAccess === es3fShaderIndexingTests.IndexAccessType.STATIC_LOOP) { 540 op += ' for (int i = 0; i < 4; i++)\n' + 541 ' {\n' + 542 ' arr[i] = ${VAR_TYPE}(coords);\n' + 543 ' coords = coords * 0.5;\n' + 544 ' }\n'; 545 } 546 else { 547 assertMsgOptions(writeAccess === es3fShaderIndexingTests.IndexAccessType.DYNAMIC_LOOP, 'writeAccess not supported', false, true); 548 op += ' for (int i = 0; i < ui_four; i++)\n' + 549 ' {\n' + 550 ' arr[i] = ${VAR_TYPE}(coords);\n' + 551 ' coords = coords * 0.5;\n' + 552 ' }\n'; 553 } 554 555 // Read array. 556 op += ' ${PRECISION} ${VAR_TYPE} res = ${VAR_TYPE}(0.0);\n'; 557 if (readAccess === es3fShaderIndexingTests.IndexAccessType.STATIC) { 558 op += ' res += arr[0];\n' + 559 ' res += arr[1];\n' + 560 ' res += arr[2];\n' + 561 ' res += arr[3];\n'; 562 } 563 else if (readAccess === es3fShaderIndexingTests.IndexAccessType.DYNAMIC) { 564 op += ' res += arr[ui_zero];\n' + 565 ' res += arr[ui_one];\n' + 566 ' res += arr[ui_two];\n' + 567 ' res += arr[ui_three];\n'; 568 } 569 else if (readAccess === es3fShaderIndexingTests.IndexAccessType.STATIC_LOOP) { 570 op += ' for (int i = 0; i < 4; i++)\n' + 571 ' res += arr[i];\n'; 572 } 573 else { 574 assertMsgOptions(readAccess === es3fShaderIndexingTests.IndexAccessType.DYNAMIC_LOOP, 'readAccess not supported.', false, true); 575 op += ' for (int i = 0; i < ui_four; i++)\n' + 576 ' res += arr[i];\n'; 577 } 578 579 vtx += isVertexCase ? op : ''; 580 frag += isVertexCase ? '' : op; 581 op = ''; 582 583 if (isVertexCase) { 584 vtx += ' v_color = vec4(res${PADDING});\n'; 585 frag += ' o_color = v_color;\n'; 586 } 587 else { 588 vtx += ' v_coords = a_coords;\n'; 589 frag += ' o_color = vec4(res${PADDING});\n'; 590 } 591 592 vtx += '}\n'; 593 frag += '}\n'; 594 595 // Fill in shader templates. 596 /** @type {Object} */ var params = {}; 597 params["VAR_TYPE"] = gluShaderUtil.getDataTypeName(varType); 598 params["ARRAY_LEN"] = "4"; 599 params["PRECISION"] = "mediump"; 600 601 if (varType === gluShaderUtil.DataType.FLOAT) 602 params['PADDING'] = ', 0.0, 0.0, 1.0'; 603 else if (varType === gluShaderUtil.DataType.FLOAT_VEC2) 604 params['PADDING'] = ', 0.0, 1.0'; 605 else if (varType === gluShaderUtil.DataType.FLOAT_VEC3) 606 params['PADDING'] = ', 1.0'; 607 else 608 params['PADDING'] = ''; 609 610 /** @type {string} */ var vertexShaderSource = tcuStringTemplate.specialize(vtx, params); 611 /** @type {string} */ var fragmentShaderSource = tcuStringTemplate.specialize(frag, params); 612 613 /** @type {function(glsShaderRenderCase.ShaderEvalContext)} */ 614 var evalFunc = es3fShaderIndexingTests.getArrayCoordsEvalFunc(varType); 615 return new es3fShaderIndexingTests.ShaderIndexingCase(caseName, description, isVertexCase, varType, evalFunc, vertexShaderSource, fragmentShaderSource); 616 }; 617 618 // VECTOR SUBSCRIPT. 619 620 /** @param {glsShaderRenderCase.ShaderEvalContext} c */ 621 es3fShaderIndexingTests.evalSubscriptVec2 = function(c) { 622 c.color[0] = c.coords[0] + 0.5 * c.coords[1]; 623 c.color[1] = c.coords[0] + 0.5 * c.coords[1]; 624 c.color[2] = c.coords[0] + 0.5 * c.coords[1]; 625 }; 626 /** @param {glsShaderRenderCase.ShaderEvalContext} c */ 627 es3fShaderIndexingTests.evalSubscriptVec3 = function(c) { 628 c.color[0] = c.coords[0] + 0.5 * c.coords[1] + 0.25 * c.coords[2]; 629 c.color[1] = c.coords[0] + 0.5 * c.coords[1] + 0.25 * c.coords[2]; 630 c.color[2] = c.coords[0] + 0.5 * c.coords[1] + 0.25 * c.coords[2]; 631 }; 632 /** @param {glsShaderRenderCase.ShaderEvalContext} c */ 633 es3fShaderIndexingTests.evalSubscriptVec4 = function(c) { 634 c.color[0] = c.coords[0] + 0.5 * c.coords[1] + 0.25 * c.coords[2] + 0.125 * c.coords[3]; 635 c.color[1] = c.coords[0] + 0.5 * c.coords[1] + 0.25 * c.coords[2] + 0.125 * c.coords[3]; 636 c.color[2] = c.coords[0] + 0.5 * c.coords[1] + 0.25 * c.coords[2] + 0.125 * c.coords[3]; 637 }; 638 639 /** 640 * @param {gluShaderUtil.DataType} dataType 641 * @return {function(glsShaderRenderCase.ShaderEvalContext)} 642 */ 643 es3fShaderIndexingTests.getVectorSubscriptEvalFunc = function(dataType) { 644 if (dataType === gluShaderUtil.DataType.FLOAT_VEC2) return es3fShaderIndexingTests.evalSubscriptVec2; 645 else if (dataType === gluShaderUtil.DataType.FLOAT_VEC3) return es3fShaderIndexingTests.evalSubscriptVec3; 646 else if (dataType === gluShaderUtil.DataType.FLOAT_VEC4) return es3fShaderIndexingTests.evalSubscriptVec4; 647 else throw new Error('Invalid data type.'); 648 }; 649 650 /** 651 * @param {string} caseName 652 * @param {string} description 653 * @param {boolean} isVertexCase 654 * @param {gluShaderUtil.DataType} varType 655 * @param {es3fShaderIndexingTests.VectorAccessType} writeAccess 656 * @param {es3fShaderIndexingTests.VectorAccessType} readAccess 657 * @return {es3fShaderIndexingTests.ShaderIndexingCase} 658 */ 659 es3fShaderIndexingTests.createVectorSubscriptCase = function(caseName, description, isVertexCase, varType, writeAccess, readAccess) { 660 /** @type {string} */ var vtx = ''; 661 /** @type {string} */ var frag = ''; 662 /** @type {string} */ var op = '' ; 663 664 /** @type {number} */ var vecLen = gluShaderUtil.getDataTypeScalarSize(varType); 665 /** @type {string} */ var vecLenName = glsShaderRenderCase.getIntUniformName(vecLen); 666 667 vtx += '#version 300 es\n'; 668 frag += '#version 300 es\n'; 669 670 vtx += 'in highp vec4 a_position;\n' + 671 'in highp vec4 a_coords;\n'; 672 frag += 'layout(location = 0) out mediump vec4 o_color;\n'; 673 674 if (isVertexCase) { 675 vtx += 'out mediump vec3 v_color;\n'; 676 frag += 'in mediump vec3 v_color;\n'; 677 } 678 else { 679 vtx += 'out mediump vec4 v_coords;\n'; 680 frag += 'in mediump vec4 v_coords;\n'; 681 } 682 683 if (writeAccess === es3fShaderIndexingTests.VectorAccessType.SUBSCRIPT_DYNAMIC || 684 readAccess === es3fShaderIndexingTests.VectorAccessType.SUBSCRIPT_DYNAMIC){ 685 op += 'uniform mediump int ui_zero'; 686 if (vecLen >= 2) op += ', ui_one'; 687 if (vecLen >= 3) op += ', ui_two'; 688 if (vecLen >= 4) op += ', ui_three'; 689 op += ';\n'; 690 } 691 692 if (writeAccess === es3fShaderIndexingTests.VectorAccessType.SUBSCRIPT_DYNAMIC_LOOP || 693 readAccess === es3fShaderIndexingTests.VectorAccessType.SUBSCRIPT_DYNAMIC_LOOP) 694 op += 'uniform mediump int ' + vecLenName + ';\n'; 695 696 vtx += isVertexCase ? op : ''; 697 frag += isVertexCase ? '' : op; 698 op = ''; 699 700 vtx += '\n' + 701 'void main()\n' + 702 '{\n' + 703 ' gl_Position = a_position;\n'; 704 705 frag += '\n' + 706 'void main()\n' + 707 '{\n'; 708 709 // Write vector. 710 if (isVertexCase) 711 op += ' ${PRECISION} ${VAR_TYPE} coords = ${VAR_TYPE}(a_coords);\n'; 712 else 713 op += ' ${PRECISION} ${VAR_TYPE} coords = ${VAR_TYPE}(v_coords);\n'; 714 715 op += ' ${PRECISION} ${VAR_TYPE} tmp;\n'; 716 if (writeAccess === es3fShaderIndexingTests.VectorAccessType.DIRECT) 717 op += ' tmp = coords.${SWIZZLE} * vec4(1.0, 0.5, 0.25, 0.125).${SWIZZLE};\n'; 718 else if (writeAccess === es3fShaderIndexingTests.VectorAccessType.COMPONENT) { 719 op += ' tmp.x = coords.x;\n'; 720 if (vecLen >= 2) op += ' tmp.y = coords.y * 0.5;\n'; 721 if (vecLen >= 3) op += ' tmp.z = coords.z * 0.25;\n'; 722 if (vecLen >= 4) op += ' tmp.w = coords.w * 0.125;\n'; 723 } 724 else if (writeAccess === es3fShaderIndexingTests.VectorAccessType.SUBSCRIPT_STATIC) { 725 op += ' tmp[0] = coords.x;\n'; 726 if (vecLen >= 2) op += ' tmp[1] = coords.y * 0.5;\n'; 727 if (vecLen >= 3) op += ' tmp[2] = coords.z * 0.25;\n'; 728 if (vecLen >= 4) op += ' tmp[3] = coords.w * 0.125;\n'; 729 } 730 else if (writeAccess === es3fShaderIndexingTests.VectorAccessType.SUBSCRIPT_DYNAMIC) { 731 op += ' tmp[ui_zero] = coords.x;\n'; 732 if (vecLen >= 2) op += ' tmp[ui_one] = coords.y * 0.5;\n'; 733 if (vecLen >= 3) op += ' tmp[ui_two] = coords.z * 0.25;\n'; 734 if (vecLen >= 4) op += ' tmp[ui_three] = coords.w * 0.125;\n'; 735 } 736 else if (writeAccess === es3fShaderIndexingTests.VectorAccessType.SUBSCRIPT_STATIC_LOOP) { 737 op += ' for (int i = 0; i < ' + vecLen + '; i++)\n'; 738 op += ' {\n'; 739 op += ' tmp[i] = coords.x;\n'; 740 op += ' coords = coords.${ROT_SWIZZLE} * 0.5;\n'; 741 op += ' }\n'; 742 } 743 else { 744 assertMsgOptions(writeAccess === es3fShaderIndexingTests.VectorAccessType.SUBSCRIPT_DYNAMIC_LOOP, 'writeAccess not supported.', false, true); 745 op += ' for (int i = 0; i < ' + vecLenName + '; i++)\n'; 746 op += ' {\n'; 747 op += ' tmp[i] = coords.x;\n'; 748 op += ' coords = coords.${ROT_SWIZZLE} * 0.5;\n'; 749 op += ' }\n'; 750 } 751 752 // Read vector. 753 op += ' ${PRECISION} float res = 0.0;\n'; 754 if (readAccess === es3fShaderIndexingTests.VectorAccessType.DIRECT) 755 op += ' res = dot(tmp, ${VAR_TYPE}(1.0));\n'; 756 else if (readAccess === es3fShaderIndexingTests.VectorAccessType.COMPONENT) { 757 op += ' res += tmp.x;\n'; 758 if (vecLen >= 2) op += ' res += tmp.y;\n'; 759 if (vecLen >= 3) op += ' res += tmp.z;\n'; 760 if (vecLen >= 4) op += ' res += tmp.w;\n'; 761 } 762 else if (readAccess === es3fShaderIndexingTests.VectorAccessType.SUBSCRIPT_STATIC) { 763 op += ' res += tmp[0];\n'; 764 if (vecLen >= 2) op += ' res += tmp[1];\n'; 765 if (vecLen >= 3) op += ' res += tmp[2];\n'; 766 if (vecLen >= 4) op += ' res += tmp[3];\n'; 767 } 768 else if (readAccess === es3fShaderIndexingTests.VectorAccessType.SUBSCRIPT_DYNAMIC) { 769 op += ' res += tmp[ui_zero];\n'; 770 if (vecLen >= 2) op += ' res += tmp[ui_one];\n'; 771 if (vecLen >= 3) op += ' res += tmp[ui_two];\n'; 772 if (vecLen >= 4) op += ' res += tmp[ui_three];\n'; 773 } 774 else if (readAccess === es3fShaderIndexingTests.VectorAccessType.SUBSCRIPT_STATIC_LOOP) { 775 op += ' for (int i = 0; i < ' + vecLen + '; i++)\n'; 776 op += ' res += tmp[i];\n'; 777 } 778 else { 779 assertMsgOptions(readAccess === es3fShaderIndexingTests.VectorAccessType.SUBSCRIPT_DYNAMIC_LOOP, 'readAccess not supported', false, true); 780 op += ' for (int i = 0; i < ' + vecLenName + '; i++)\n'; 781 op += ' res += tmp[i];\n'; 782 } 783 784 vtx += isVertexCase ? op : ''; 785 frag += isVertexCase ? '' : op; 786 op = ''; 787 788 if (isVertexCase) { 789 vtx += ' v_color = vec3(res);\n'; 790 frag += ' o_color = vec4(v_color.rgb, 1.0);\n'; 791 } 792 else { 793 vtx += ' v_coords = a_coords;\n'; 794 frag += ' o_color = vec4(vec3(res), 1.0);\n'; 795 } 796 797 vtx += '}\n'; 798 frag += '}\n'; 799 800 // Fill in shader templates. 801 /** @type {Array<string>} */ var s_swizzles = ['', 'x', 'xy', 'xyz', 'xyzw']; 802 /** @type {Array<string>} */ var s_rotSwizzles = ['', 'x', 'yx', 'yzx', 'yzwx']; 803 804 /** @type {Object} */ var params = {}; 805 params["VAR_TYPE"] = gluShaderUtil.getDataTypeName(varType); 806 params["PRECISION"] = "mediump"; 807 params["SWIZZLE"] = s_swizzles[vecLen]; 808 params["ROT_SWIZZLE"] = s_rotSwizzles[vecLen]; 809 810 /** @type {string} */ var vertexShaderSource = tcuStringTemplate.specialize(vtx, params); 811 /** @type {string} */ var fragmentShaderSource = tcuStringTemplate.specialize(frag, params); 812 813 /** @type {function(glsShaderRenderCase.ShaderEvalContext)} */ 814 var evalFunc = es3fShaderIndexingTests.getVectorSubscriptEvalFunc(varType); 815 return new es3fShaderIndexingTests.ShaderIndexingCase(caseName, description, isVertexCase, varType, evalFunc, vertexShaderSource, fragmentShaderSource); 816 }; 817 818 // MATRIX SUBSCRIPT. 819 820 /** @param {glsShaderRenderCase.ShaderEvalContext} c */ 821 es3fShaderIndexingTests.evalSubscriptMat2 = function(c) { 822 var swizzle01 = deMath.swizzle(c.coords, [0, 1]); 823 var swizzle12 = deMath.swizzle(c.coords, [1, 2]); 824 c.color[0] = swizzle01[0] + 0.5 * swizzle12[0]; 825 c.color[1] = swizzle01[1] + 0.5 * swizzle12[1]; 826 }; 827 828 /** @param {glsShaderRenderCase.ShaderEvalContext} c */ 829 es3fShaderIndexingTests.evalSubscriptMat2x3 = function(c) { 830 var swizzle012 = deMath.swizzle(c.coords, [0, 1, 2]); 831 var swizzle123 = deMath.swizzle(c.coords, [1, 2, 3]); 832 c.color[0] = swizzle012[0] + 0.5 * swizzle123[0]; 833 c.color[1] = swizzle012[1] + 0.5 * swizzle123[1]; 834 c.color[2] = swizzle012[2] + 0.5 * swizzle123[2]; 835 }; 836 837 /** @param {glsShaderRenderCase.ShaderEvalContext} c */ 838 es3fShaderIndexingTests.evalSubscriptMat2x4 = function(c) { 839 c.color = deMath.add( 840 deMath.swizzle(c.coords, [0,1,2,3]), 841 deMath.scale(deMath.swizzle(c.coords, [1,2,3,0]), 0.5)); 842 }; 843 844 /** @param {glsShaderRenderCase.ShaderEvalContext} c */ 845 es3fShaderIndexingTests.evalSubscriptMat3x2 = function(c) { 846 var swizzle01 = deMath.swizzle(c.coords, [0, 1]); 847 var swizzle12 = deMath.swizzle(c.coords, [1, 2]); 848 var swizzle23 = deMath.swizzle(c.coords, [2, 3]); 849 c.color[0] = swizzle01[0] + 0.5 * swizzle12[0] + 0.25 * swizzle23[0]; 850 c.color[1] = swizzle01[1] + 0.5 * swizzle12[1] + 0.25 * swizzle23[1]; 851 }; 852 853 /** @param {glsShaderRenderCase.ShaderEvalContext} c */ 854 es3fShaderIndexingTests.evalSubscriptMat3 = function(c) { 855 var swizzle012 = deMath.swizzle(c.coords, [0, 1, 2]); 856 var swizzle123 = deMath.swizzle(c.coords, [1, 2, 3]); 857 var swizzle230 = deMath.swizzle(c.coords, [2, 3, 0]); 858 c.color[0] = swizzle012[0] + 0.5 * swizzle123[0] + 0.25 * swizzle230[0]; 859 c.color[1] = swizzle012[1] + 0.5 * swizzle123[1] + 0.25 * swizzle230[1]; 860 c.color[2] = swizzle012[2] + 0.5 * swizzle123[2] + 0.25 * swizzle230[2]; 861 }; 862 863 /** @param {glsShaderRenderCase.ShaderEvalContext} c */ 864 es3fShaderIndexingTests.evalSubscriptMat3x4 = function(c) { 865 var swizzle0123 = deMath.swizzle(c.coords, [0, 1, 2, 3]); 866 var swizzle1230 = deMath.swizzle(c.coords, [1, 2, 3, 0]); 867 var swizzle2301 = deMath.swizzle(c.coords, [2, 3, 0, 1]); 868 c.color = deMath.add( 869 swizzle0123, 870 deMath.add( 871 deMath.scale(swizzle1230, 0.5), 872 deMath.scale(swizzle2301, 0.25))); 873 }; 874 875 /** @param {glsShaderRenderCase.ShaderEvalContext} c */ 876 es3fShaderIndexingTests.evalSubscriptMat4x2 = function(c) { 877 var swizzle01 = deMath.swizzle(c.coords, [0, 1]); 878 var swizzle12 = deMath.swizzle(c.coords, [1, 2]); 879 var swizzle23 = deMath.swizzle(c.coords, [2, 3]); 880 var swizzle30 = deMath.swizzle(c.coords, [3, 0]); 881 c.color[0] = swizzle01[0] + 0.5 * swizzle12[0] + 0.25 * swizzle23[0] + 0.125 * swizzle30[0]; 882 c.color[1] = swizzle01[1] + 0.5 * swizzle12[1] + 0.25 * swizzle23[1] + 0.125 * swizzle30[1]; 883 }; 884 885 /** @param {glsShaderRenderCase.ShaderEvalContext} c */ 886 es3fShaderIndexingTests.evalSubscriptMat4x3 = function(c) { 887 var swizzle012 = deMath.swizzle(c.coords, [0, 1, 2]); 888 var swizzle123 = deMath.swizzle(c.coords, [1, 2, 3]); 889 var swizzle230 = deMath.swizzle(c.coords, [2, 3, 0]); 890 var swizzle301 = deMath.swizzle(c.coords, [3, 0, 1]); 891 c.color[0] = swizzle012[0] + 0.5 * swizzle123[0] + 0.25 * swizzle230[0] + 0.125 * swizzle301[0]; 892 c.color[1] = swizzle012[1] + 0.5 * swizzle123[1] + 0.25 * swizzle230[1] + 0.125 * swizzle301[1]; 893 c.color[2] = swizzle012[2] + 0.5 * swizzle123[2] + 0.25 * swizzle230[2] + 0.125 * swizzle301[2]; 894 }; 895 896 /** @param {glsShaderRenderCase.ShaderEvalContext} c */ 897 es3fShaderIndexingTests.evalSubscriptMat4 = function(c) { 898 var swizzle1230 = deMath.swizzle(c.coords, [1, 2, 3, 0]); 899 var swizzle2301 = deMath.swizzle(c.coords, [2, 3, 0, 1]); 900 var swizzle3012 = deMath.swizzle(c.coords, [3, 0, 1, 2]); 901 c.color = deMath.add( 902 c.coords, 903 deMath.add( 904 deMath.scale(swizzle1230, 0.5), 905 deMath.add( 906 deMath.scale(swizzle2301, 0.25), 907 deMath.scale(swizzle3012, 0.125)))); 908 }; 909 910 /** 911 * @param {gluShaderUtil.DataType} dataType 912 * @return {function(glsShaderRenderCase.ShaderEvalContext)} 913 */ 914 es3fShaderIndexingTests.getMatrixSubscriptEvalFunc = function(dataType) { 915 switch (dataType) { 916 case gluShaderUtil.DataType.FLOAT_MAT2: return es3fShaderIndexingTests.evalSubscriptMat2; 917 case gluShaderUtil.DataType.FLOAT_MAT2X3: return es3fShaderIndexingTests.evalSubscriptMat2x3; 918 case gluShaderUtil.DataType.FLOAT_MAT2X4: return es3fShaderIndexingTests.evalSubscriptMat2x4; 919 case gluShaderUtil.DataType.FLOAT_MAT3X2: return es3fShaderIndexingTests.evalSubscriptMat3x2; 920 case gluShaderUtil.DataType.FLOAT_MAT3: return es3fShaderIndexingTests.evalSubscriptMat3; 921 case gluShaderUtil.DataType.FLOAT_MAT3X4: return es3fShaderIndexingTests.evalSubscriptMat3x4; 922 case gluShaderUtil.DataType.FLOAT_MAT4X2: return es3fShaderIndexingTests.evalSubscriptMat4x2; 923 case gluShaderUtil.DataType.FLOAT_MAT4X3: return es3fShaderIndexingTests.evalSubscriptMat4x3; 924 case gluShaderUtil.DataType.FLOAT_MAT4: return es3fShaderIndexingTests.evalSubscriptMat4; 925 default: 926 throw new Error('Invalid data type.'); 927 } 928 }; 929 930 /** 931 * @param {string} caseName 932 * @param {string} description 933 * @param {boolean} isVertexCase 934 * @param {gluShaderUtil.DataType} varType 935 * @param {es3fShaderIndexingTests.IndexAccessType} writeAccess 936 * @param {es3fShaderIndexingTests.IndexAccessType} readAccess 937 * @return {es3fShaderIndexingTests.ShaderIndexingCase} 938 */ 939 es3fShaderIndexingTests.createMatrixSubscriptCase = function(caseName, description, isVertexCase, varType, writeAccess, readAccess) { 940 /** @type {string} */ var vtx = ''; 941 /** @type {string} */ var frag = ''; 942 /** @type {string} */ var op = ''; 943 944 /** @type {number} */ var numCols = gluShaderUtil.getDataTypeMatrixNumColumns(varType); 945 /** @type {number} */ var numRows = gluShaderUtil.getDataTypeMatrixNumRows(varType); 946 /** @type {string} */ var matSizeName = glsShaderRenderCase.getIntUniformName(numCols); 947 /** @type {gluShaderUtil.DataType} */ var vecType = gluShaderUtil.getDataTypeFloatVec(numRows); 948 949 vtx += '#version 300 es\n'; 950 frag += '#version 300 es\n'; 951 952 vtx += 'in highp vec4 a_position;\n' + 953 'in highp vec4 a_coords;\n'; 954 frag += 'layout(location = 0) out mediump vec4 o_color;\n'; 955 956 if (isVertexCase) { 957 vtx += 'out mediump vec4 v_color;\n'; 958 frag += 'in mediump vec4 v_color;\n'; 959 } 960 else { 961 vtx += 'out mediump vec4 v_coords;\n'; 962 frag += 'in mediump vec4 v_coords;\n'; 963 } 964 965 if (writeAccess === es3fShaderIndexingTests.IndexAccessType.DYNAMIC || readAccess === es3fShaderIndexingTests.IndexAccessType.DYNAMIC) { 966 op += 'uniform mediump int ui_zero'; 967 if (numCols >= 2) op += ', ui_one'; 968 if (numCols >= 3) op += ', ui_two'; 969 if (numCols >= 4) op += ', ui_three'; 970 op += ';\n'; 971 } 972 973 if (writeAccess === es3fShaderIndexingTests.IndexAccessType.DYNAMIC_LOOP || readAccess === es3fShaderIndexingTests.IndexAccessType.DYNAMIC_LOOP) 974 op += 'uniform mediump int ' + matSizeName + ';\n'; 975 976 vtx += isVertexCase ? op : ''; 977 frag += isVertexCase ? '' : op; 978 op = ''; 979 980 vtx += '\n' + 981 'void main()\n' + 982 '{\n' + 983 ' gl_Position = a_position;\n'; 984 985 frag += '\n' + 986 'void main()\n' + 987 '{\n'; 988 989 // Write matrix. 990 if (isVertexCase) 991 op += ' ${PRECISION} vec4 coords = a_coords;\n'; 992 else 993 op += ' ${PRECISION} vec4 coords = v_coords;\n'; 994 995 op += ' ${PRECISION} ${MAT_TYPE} tmp;\n'; 996 if (writeAccess === es3fShaderIndexingTests.IndexAccessType.STATIC) { 997 op += ' tmp[0] = ${VEC_TYPE}(coords);\n'; 998 if (numCols >= 2) op += ' tmp[1] = ${VEC_TYPE}(coords.yzwx) * 0.5;\n'; 999 if (numCols >= 3) op += ' tmp[2] = ${VEC_TYPE}(coords.zwxy) * 0.25;\n'; 1000 if (numCols >= 4) op += ' tmp[3] = ${VEC_TYPE}(coords.wxyz) * 0.125;\n'; 1001 } 1002 else if (writeAccess === es3fShaderIndexingTests.IndexAccessType.DYNAMIC) { 1003 op += ' tmp[ui_zero] = ${VEC_TYPE}(coords);\n'; 1004 if (numCols >= 2) op += ' tmp[ui_one] = ${VEC_TYPE}(coords.yzwx) * 0.5;\n'; 1005 if (numCols >= 3) op += ' tmp[ui_two] = ${VEC_TYPE}(coords.zwxy) * 0.25;\n'; 1006 if (numCols >= 4) op += ' tmp[ui_three] = ${VEC_TYPE}(coords.wxyz) * 0.125;\n'; 1007 } 1008 else if (writeAccess === es3fShaderIndexingTests.IndexAccessType.STATIC_LOOP) { 1009 op += ' for (int i = 0; i < ' + numCols + '; i++)\n'; 1010 op += ' {\n'; 1011 op += ' tmp[i] = ${VEC_TYPE}(coords);\n'; 1012 op += ' coords = coords.yzwx * 0.5;\n'; 1013 op += ' }\n'; 1014 } 1015 else { 1016 assertMsgOptions(writeAccess === es3fShaderIndexingTests.IndexAccessType.DYNAMIC_LOOP, 'writeAccess not supported', false, true); 1017 op += ' for (int i = 0; i < ' + matSizeName + '; i++)\n'; 1018 op += ' {\n'; 1019 op += ' tmp[i] = ${VEC_TYPE}(coords);\n'; 1020 op += ' coords = coords.yzwx * 0.5;\n'; 1021 op += ' }\n'; 1022 } 1023 1024 // Read matrix. 1025 op += ' ${PRECISION} ${VEC_TYPE} res = ${VEC_TYPE}(0.0);\n'; 1026 if (readAccess === es3fShaderIndexingTests.IndexAccessType.STATIC) { 1027 op += ' res += tmp[0];\n'; 1028 if (numCols >= 2) op += ' res += tmp[1];\n'; 1029 if (numCols >= 3) op += ' res += tmp[2];\n'; 1030 if (numCols >= 4) op += ' res += tmp[3];\n'; 1031 } 1032 else if (readAccess === es3fShaderIndexingTests.IndexAccessType.DYNAMIC) { 1033 op += ' res += tmp[ui_zero];\n'; 1034 if (numCols >= 2) op += ' res += tmp[ui_one];\n'; 1035 if (numCols >= 3) op += ' res += tmp[ui_two];\n'; 1036 if (numCols >= 4) op += ' res += tmp[ui_three];\n'; 1037 } 1038 else if (readAccess === es3fShaderIndexingTests.IndexAccessType.STATIC_LOOP) { 1039 op += ' for (int i = 0; i < ' + numCols + '; i++)\n'; 1040 op += ' res += tmp[i];\n'; 1041 } 1042 else { 1043 assertMsgOptions(readAccess === es3fShaderIndexingTests.IndexAccessType.DYNAMIC_LOOP, 'readAccess not supported', false, true); 1044 op += ' for (int i = 0; i < ' + matSizeName + '; i++)\n'; 1045 op += ' res += tmp[i];\n'; 1046 } 1047 1048 vtx += isVertexCase ? op : ''; 1049 frag += isVertexCase ? '' : op; 1050 op = ''; 1051 1052 if (isVertexCase) { 1053 vtx += ' v_color = vec4(res${PADDING});\n'; 1054 frag += ' o_color = v_color;\n'; 1055 } 1056 else { 1057 vtx += ' v_coords = a_coords;\n'; 1058 frag += ' o_color = vec4(res${PADDING});\n'; 1059 } 1060 1061 vtx += '}\n'; 1062 frag += '}\n'; 1063 1064 // Fill in shader templates. 1065 1066 /** @type {Object} */ var params = {}; 1067 params['MAT_TYPE'] = gluShaderUtil.getDataTypeName(varType); 1068 params['VEC_TYPE'] = gluShaderUtil.getDataTypeName(vecType); 1069 params['PRECISION'] = "mediump"; 1070 1071 1072 if (numRows === 2) 1073 params['PADDING'] = ', 0.0, 1.0'; 1074 else if (numRows === 3) 1075 params['PADDING'] = ', 1.0'; 1076 else 1077 params['PADDING'] = ''; 1078 1079 /** @type {string} */ var vertexShaderSource = tcuStringTemplate.specialize(vtx, params); 1080 /** @type {string} */ var fragmentShaderSource = tcuStringTemplate.specialize(frag, params); 1081 1082 /** @type {function(glsShaderRenderCase.ShaderEvalContext)} */ 1083 var evalFunc = es3fShaderIndexingTests.getMatrixSubscriptEvalFunc(varType); 1084 return new es3fShaderIndexingTests.ShaderIndexingCase(caseName, description, isVertexCase, varType, evalFunc, vertexShaderSource, fragmentShaderSource); 1085 }; 1086 1087 /** 1088 * @constructor 1089 * @extends {tcuTestCase.DeqpTest} 1090 */ 1091 es3fShaderIndexingTests.ShaderIndexingTests = function() { 1092 tcuTestCase.DeqpTest.call(this, 'indexing', 'Indexing Tests'); 1093 }; 1094 1095 es3fShaderIndexingTests.ShaderIndexingTests.prototype = Object.create(tcuTestCase.DeqpTest.prototype); 1096 es3fShaderIndexingTests.ShaderIndexingTests.prototype.constructor = es3fShaderIndexingTests.ShaderIndexingTests; 1097 1098 es3fShaderIndexingTests.ShaderIndexingTests.prototype.init = function() { 1099 var testGroup = tcuTestCase.runner.testCases; 1100 /** @type {Array<gluShaderProgram.shaderType>} */ var s_shaderTypes = [ 1101 gluShaderProgram.shaderType.VERTEX, 1102 gluShaderProgram.shaderType.FRAGMENT 1103 ]; 1104 /** @type {Array<gluShaderUtil.DataType>} */ var s_floatAndVecTypes = [ 1105 gluShaderUtil.DataType.FLOAT, 1106 gluShaderUtil.DataType.FLOAT_VEC2, 1107 gluShaderUtil.DataType.FLOAT_VEC3, 1108 gluShaderUtil.DataType.FLOAT_VEC4 1109 ]; 1110 /** @type {string} */ var name; 1111 /** @type {string} */ var desc; 1112 /** @type {string} */ var shaderTypeName; 1113 /** @type {boolean} */ var isVertexCase; 1114 /** @type {gluShaderProgram.shaderType} */ var shaderType; 1115 /** @type {string} */ var writeAccessName; 1116 /** @type {string} */ var readAccessName; 1117 // Varying array access cases. 1118 /** @type {tcuTestCase.DeqpTest} */ var varyingGroup = tcuTestCase.newTest('varying_array', 'Varying array access tests.'); 1119 testGroup.addChild(varyingGroup); 1120 /** @type {gluShaderUtil.DataType} */ var varType; 1121 for (var typeNdx = 0; typeNdx < s_floatAndVecTypes.length; typeNdx++) { 1122 varType = s_floatAndVecTypes[typeNdx]; 1123 for (var vertAccessStr in es3fShaderIndexingTests.IndexAccessType) { 1124 for (var fragAccessStr in es3fShaderIndexingTests.IndexAccessType) { 1125 var vertAccess = es3fShaderIndexingTests.IndexAccessType[vertAccessStr]; 1126 var fragAccess = es3fShaderIndexingTests.IndexAccessType[fragAccessStr]; 1127 /** @type {string} */ var vertAccessName = es3fShaderIndexingTests.getIndexAccessTypeName(vertAccess); 1128 /** @type {string} */ var fragAccessName = es3fShaderIndexingTests.getIndexAccessTypeName(fragAccess); 1129 name = gluShaderUtil.getDataTypeName(varType) + '_' + vertAccessName + '_write_' + fragAccessName + '_read'; 1130 desc = 'Varying array with ' + vertAccessName + ' write in vertex shader and ' + fragAccessName + ' read in fragment shader.'; 1131 varyingGroup.addChild(es3fShaderIndexingTests.createVaryingArrayCase(name, desc, varType, vertAccess, fragAccess)); 1132 } 1133 } 1134 } 1135 1136 // Uniform array access cases. 1137 /** @type {tcuTestCase.DeqpTest} */ var uniformGroup = tcuTestCase.newTest("uniform_array", "Uniform array access tests."); 1138 testGroup.addChild(uniformGroup); 1139 1140 for (var typeNdx = 0; typeNdx < s_floatAndVecTypes.length; typeNdx++) { 1141 varType = s_floatAndVecTypes[typeNdx]; 1142 for (var readAccessStr in es3fShaderIndexingTests.IndexAccessType) { 1143 var readAccess = es3fShaderIndexingTests.IndexAccessType[readAccessStr]; 1144 readAccessName = es3fShaderIndexingTests.getIndexAccessTypeName(readAccess); 1145 for (var shaderTypeNdx = 0; shaderTypeNdx < s_shaderTypes.length; shaderTypeNdx++) { 1146 shaderType = s_shaderTypes[shaderTypeNdx]; 1147 shaderTypeName = gluShaderProgram.getShaderTypeName(shaderType); 1148 name = gluShaderUtil.getDataTypeName(varType) + "_" + readAccessName + "_read_" + shaderTypeName; 1149 desc = "Uniform array with " + readAccessName + " read in " + shaderTypeName + " shader."; 1150 isVertexCase = shaderType === gluShaderProgram.shaderType.VERTEX; 1151 uniformGroup.addChild(es3fShaderIndexingTests.createUniformArrayCase(name, desc, isVertexCase, varType, readAccess)); 1152 } 1153 } 1154 } 1155 1156 // Temporary array access cases. 1157 /** @type {tcuTestCase.DeqpTest} */ var tmpGroup = tcuTestCase.newTest("tmp_array", "Temporary array access tests."); 1158 testGroup.addChild(tmpGroup); 1159 1160 for (var typeNdx = 0; typeNdx < s_floatAndVecTypes.length; typeNdx++) { 1161 varType = s_floatAndVecTypes[typeNdx]; 1162 for (var writeAccess in es3fShaderIndexingTests.IndexAccessType) { 1163 for (var readAccess in es3fShaderIndexingTests.IndexAccessType) { 1164 writeAccessName = es3fShaderIndexingTests.getIndexAccessTypeName(es3fShaderIndexingTests.IndexAccessType[writeAccess]); 1165 readAccessName = es3fShaderIndexingTests.getIndexAccessTypeName(es3fShaderIndexingTests.IndexAccessType[readAccess]); 1166 1167 for (var shaderTypeNdx = 0; shaderTypeNdx < s_shaderTypes.length; shaderTypeNdx++) { 1168 shaderType = s_shaderTypes[shaderTypeNdx]; 1169 shaderTypeName = gluShaderProgram.getShaderTypeName(shaderType); 1170 name = gluShaderUtil.getDataTypeName(varType) + "_" + writeAccessName + "_write_" + readAccessName + "_read_" + shaderTypeName; 1171 desc = "Temporary array with " + writeAccessName + " write and " + readAccessName + " read in " + shaderTypeName + " shader."; 1172 isVertexCase = (shaderType === gluShaderProgram.shaderType.VERTEX); 1173 tmpGroup.addChild(es3fShaderIndexingTests.createTmpArrayCase(name, desc, isVertexCase, varType, es3fShaderIndexingTests.IndexAccessType[writeAccess], es3fShaderIndexingTests.IndexAccessType[readAccess])); 1174 } 1175 } 1176 } 1177 } 1178 1179 // Vector indexing with subscripts. 1180 1181 /** @type {Array<gluShaderUtil.DataType>} */ var s_vectorTypes = [ 1182 gluShaderUtil.DataType.FLOAT_VEC2, 1183 gluShaderUtil.DataType.FLOAT_VEC3, 1184 gluShaderUtil.DataType.FLOAT_VEC4 1185 ]; 1186 1187 for (var typeNdx = 0; typeNdx < s_vectorTypes.length; typeNdx++) { 1188 /** @type {tcuTestCase.DeqpTest} */ var vecGroup = tcuTestCase.newTest("vector_subscript", "Vector subscript indexing."); 1189 testGroup.addChild(vecGroup); 1190 1191 varType = s_vectorTypes[typeNdx]; 1192 for (var writeAccess in es3fShaderIndexingTests.VectorAccessType) { 1193 for (var readAccess in es3fShaderIndexingTests.VectorAccessType) { 1194 writeAccessName = es3fShaderIndexingTests.getVectorAccessTypeName(es3fShaderIndexingTests.VectorAccessType[writeAccess]); 1195 readAccessName = es3fShaderIndexingTests.getVectorAccessTypeName(es3fShaderIndexingTests.VectorAccessType[readAccess]); 1196 1197 for (var shaderTypeNdx = 0; shaderTypeNdx < s_shaderTypes.length; shaderTypeNdx++) { 1198 shaderType = s_shaderTypes[shaderTypeNdx]; 1199 shaderTypeName = gluShaderProgram.getShaderTypeName(shaderType); 1200 name = gluShaderUtil.getDataTypeName(varType) + "_" + writeAccessName + "_write_" + readAccessName + "_read_" + shaderTypeName; 1201 desc = "Vector subscript access with " + writeAccessName + " write and " + readAccessName + " read in " + shaderTypeName + " shader."; 1202 isVertexCase = shaderType === gluShaderProgram.shaderType.VERTEX; 1203 vecGroup.addChild(es3fShaderIndexingTests.createVectorSubscriptCase(name, desc, isVertexCase, varType, es3fShaderIndexingTests.VectorAccessType[writeAccess], es3fShaderIndexingTests.VectorAccessType[readAccess])); 1204 } 1205 } 1206 } 1207 } 1208 1209 // Matrix indexing with subscripts. 1210 /** @type {Array<tcuTestCase.DeqpTest>} */ var matGroup = [ 1211 tcuTestCase.newTest("matrix_subscript", "Matrix subscript indexing."), 1212 tcuTestCase.newTest("matrix_subscript", "Matrix subscript indexing."), 1213 tcuTestCase.newTest("matrix_subscript", "Matrix subscript indexing."), 1214 ]; 1215 for (var ii = 0; ii < matGroup.length; ++ii) { 1216 testGroup.addChild(matGroup[ii]); 1217 } 1218 1219 /** @type {Array<gluShaderUtil.DataType>} */ var s_matrixTypes = [ 1220 gluShaderUtil.DataType.FLOAT_MAT2, 1221 gluShaderUtil.DataType.FLOAT_MAT2X3, 1222 gluShaderUtil.DataType.FLOAT_MAT2X4, 1223 gluShaderUtil.DataType.FLOAT_MAT3X2, 1224 gluShaderUtil.DataType.FLOAT_MAT3, 1225 gluShaderUtil.DataType.FLOAT_MAT3X4, 1226 gluShaderUtil.DataType.FLOAT_MAT4X2, 1227 gluShaderUtil.DataType.FLOAT_MAT4X3, 1228 gluShaderUtil.DataType.FLOAT_MAT4 1229 ]; 1230 1231 for (var typeNdx = 0; typeNdx < s_matrixTypes.length; typeNdx++) { 1232 varType = s_matrixTypes[typeNdx]; 1233 for (var writeAccess in es3fShaderIndexingTests.IndexAccessType) { 1234 for (var readAccess in es3fShaderIndexingTests.IndexAccessType) { 1235 writeAccessName = es3fShaderIndexingTests.getIndexAccessTypeName(es3fShaderIndexingTests.IndexAccessType[writeAccess]); 1236 readAccessName = es3fShaderIndexingTests.getIndexAccessTypeName(es3fShaderIndexingTests.IndexAccessType[readAccess]); 1237 1238 for (var shaderTypeNdx = 0; shaderTypeNdx < s_shaderTypes.length; shaderTypeNdx++) { 1239 shaderType = s_shaderTypes[shaderTypeNdx]; 1240 shaderTypeName = gluShaderProgram.getShaderTypeName(shaderType); 1241 name = gluShaderUtil.getDataTypeName(varType) + "_" + writeAccessName + "_write_" + readAccessName + "_read_" + shaderTypeName; 1242 desc = "Vector subscript access with " + writeAccessName + " write and " + readAccessName + " read in " + shaderTypeName + " shader."; 1243 isVertexCase = shaderType === gluShaderProgram.shaderType.VERTEX; 1244 matGroup[typeNdx % matGroup.length].addChild(es3fShaderIndexingTests.createMatrixSubscriptCase( 1245 name, desc, isVertexCase, varType, es3fShaderIndexingTests.IndexAccessType[writeAccess], es3fShaderIndexingTests.IndexAccessType[readAccess])); 1246 } 1247 } 1248 } 1249 } 1250 }; 1251 1252 /** 1253 * Run test 1254 * @param {WebGL2RenderingContext} context 1255 */ 1256 es3fShaderIndexingTests.run = function(context, range) { 1257 gl = context; 1258 //Set up Test Root parameters 1259 var state = tcuTestCase.runner; 1260 state.setRoot(new es3fShaderIndexingTests.ShaderIndexingTests()); 1261 1262 //Set up name and description of this test series. 1263 setCurrentTestName(state.testCases.fullName()); 1264 description(state.testCases.getDescription()); 1265 1266 try { 1267 if (range) 1268 state.setRange(range); 1269 //Run test cases 1270 tcuTestCase.runTestCases(); 1271 } 1272 catch (err) { 1273 testFailedOptions('Failed to es3fShaderIndexingTests.run tests', false); 1274 tcuTestCase.runner.terminate(); 1275 } 1276 }; 1277 1278 });