es3fShaderSwitchTests.js (21053B)
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.es3fShaderSwitchTests'); 23 goog.require('framework.common.tcuStringTemplate'); 24 goog.require('framework.common.tcuTestCase'); 25 goog.require('modules.shared.glsShaderRenderCase'); 26 27 28 goog.scope(function() { 29 var es3fShaderSwitchTests = functional.gles3.es3fShaderSwitchTests; 30 var glsShaderRenderCase = modules.shared.glsShaderRenderCase; 31 var tcuTestCase = framework.common.tcuTestCase; 32 var tcuStringTemplate = framework.common.tcuStringTemplate; 33 34 /** 35 * @constructor 36 * @extends {glsShaderRenderCase.ShaderRenderCase} 37 * @param {string} name 38 * @param {string} description 39 * @param {boolean} isVertexCase 40 * @param {string} vtxSource 41 * @param {string} fragSource 42 * @param {glsShaderRenderCase.ShaderEvalFunc=} evalFunc 43 */ 44 es3fShaderSwitchTests.ShaderSwitchCase = function(name, description, isVertexCase, vtxSource, fragSource, evalFunc) { 45 glsShaderRenderCase.ShaderRenderCase.call(this, name, description, isVertexCase, evalFunc); 46 /** @type {string} */ this.m_vertShaderSource = vtxSource; 47 /** @type {string} */ this.m_fragShaderSource = fragSource; 48 }; 49 50 es3fShaderSwitchTests.ShaderSwitchCase.prototype = Object.create(glsShaderRenderCase.ShaderRenderCase.prototype); 51 es3fShaderSwitchTests.ShaderSwitchCase.prototype.constructor = es3fShaderSwitchTests.ShaderSwitchCase; 52 53 /** 54 * @enum {number} 55 */ 56 es3fShaderSwitchTests.SwitchType = { 57 STATIC: 0, 58 UNIFORM: 1, 59 DYNAMIC: 2 60 }; 61 62 /** @param {glsShaderRenderCase.ShaderEvalContext} evalCtx */ 63 es3fShaderSwitchTests.evalSwitchStatic = function(evalCtx) { 64 evalCtx.color[0] = evalCtx.coords[1]; 65 evalCtx.color[1] = evalCtx.coords[2]; 66 evalCtx.color[2] = evalCtx.coords[3]; 67 }; 68 69 /** @param {glsShaderRenderCase.ShaderEvalContext} evalCtx */ 70 es3fShaderSwitchTests.evalSwitchUniform = function(evalCtx) { 71 evalCtx.color[0] = evalCtx.coords[1]; 72 evalCtx.color[1] = evalCtx.coords[2]; 73 evalCtx.color[2] = evalCtx.coords[3]; 74 }; 75 76 /** @param {glsShaderRenderCase.ShaderEvalContext} evalCtx */ 77 es3fShaderSwitchTests.evalSwitchDynamic = function(evalCtx) { 78 switch (Math.floor(evalCtx.coords[2]*1.5 + 2.0)) { 79 case 0: 80 evalCtx.color[0] = evalCtx.coords[0]; 81 evalCtx.color[1] = evalCtx.coords[1]; 82 evalCtx.color[2] = evalCtx.coords[2]; 83 break; 84 case 1: 85 evalCtx.color[0] = evalCtx.coords[3]; 86 evalCtx.color[1] = evalCtx.coords[2]; 87 evalCtx.color[2] = evalCtx.coords[1]; 88 break; 89 case 2: 90 evalCtx.color[0] = evalCtx.coords[1]; 91 evalCtx.color[1] = evalCtx.coords[2]; 92 evalCtx.color[2] = evalCtx.coords[3]; 93 break; 94 case 3: 95 evalCtx.color[0] = evalCtx.coords[2]; 96 evalCtx.color[1] = evalCtx.coords[1]; 97 evalCtx.color[2] = evalCtx.coords[0]; 98 break; 99 default: 100 evalCtx.color[0] = evalCtx.coords[0]; 101 evalCtx.color[1] = evalCtx.coords[0]; 102 evalCtx.color[2] = evalCtx.coords[0]; 103 break; 104 } 105 }; 106 107 /** 108 * @param {string} name 109 * @param {string} desc 110 * @param {es3fShaderSwitchTests.SwitchType} type 111 * @param {boolean} isVertex 112 * @param {string} switchBody 113 * @return {es3fShaderSwitchTests.ShaderSwitchCase} 114 */ 115 es3fShaderSwitchTests.makeSwitchCase = function(name, desc, type, isVertex, switchBody) { 116 /** @type {string} */ var vtx = ''; 117 /** @type {string} */ var frag = ''; 118 /** @type {string} */ var op = ''; 119 120 vtx += "#version 300 es\n" + 121 "in highp vec4 a_position;\n" + 122 "in highp vec4 a_coords;\n"; 123 frag += "#version 300 es\n" + 124 "layout(location = 0) out mediump vec4 o_color;\n"; 125 126 if (isVertex) { 127 vtx += "out mediump vec4 v_color;\n"; 128 frag += "in mediump vec4 v_color;\n"; 129 } else { 130 vtx += "out highp vec4 v_coords;\n"; 131 frag += "in highp vec4 v_coords;\n"; 132 } 133 134 if (type === es3fShaderSwitchTests.SwitchType.UNIFORM) 135 op += "uniform highp int ui_two;\n"; 136 137 vtx += isVertex ? op : ''; 138 frag += isVertex ? '' : op; 139 op = ''; 140 141 vtx += "\n" + 142 "void main (void)\n" + 143 "{\n" + 144 " gl_Position = a_position;\n"; 145 frag += "\n" + 146 "void main (void)\n" + 147 "{\n"; 148 149 // Setup. 150 op += " highp vec4 coords = " + (isVertex ? "a_coords" : "v_coords") + ";\n"; 151 op += " mediump vec3 res = vec3(0.0);\n\n"; 152 vtx += isVertex ? op : ''; 153 frag += isVertex ? '' : op; 154 op = ''; 155 156 // Switch body. 157 var params = {}; 158 params["CONDITION"] = type == es3fShaderSwitchTests.SwitchType.STATIC ? "2" : 159 type == es3fShaderSwitchTests.SwitchType.UNIFORM ? "ui_two" : 160 type == es3fShaderSwitchTests.SwitchType.DYNAMIC ? "int(floor(coords.z*1.5 + 2.0))" : "???"; 161 162 op += tcuStringTemplate.specialize(switchBody, params); 163 op += "\n"; 164 165 vtx += isVertex ? op : ''; 166 frag += isVertex ? '' : op; 167 op = ''; 168 169 if (isVertex) { 170 vtx += " v_color = vec4(res, 1.0);\n"; 171 frag += " o_color = v_color;\n"; 172 } else { 173 vtx += " v_coords = a_coords;\n"; 174 frag += " o_color = vec4(res, 1.0);\n"; 175 } 176 177 vtx += "}\n"; 178 frag += "}\n"; 179 180 return new es3fShaderSwitchTests.ShaderSwitchCase(name, desc, isVertex, vtx, frag, 181 type === es3fShaderSwitchTests.SwitchType.STATIC ? es3fShaderSwitchTests.evalSwitchStatic : 182 type === es3fShaderSwitchTests.SwitchType.UNIFORM ? es3fShaderSwitchTests.evalSwitchUniform : 183 type === es3fShaderSwitchTests.SwitchType.DYNAMIC ? es3fShaderSwitchTests.evalSwitchDynamic : undefined); 184 }; 185 186 /** 187 * @param {tcuTestCase.DeqpTest} group 188 * @param {string} name 189 * @param {string} desc 190 * @param {string} switchBody 191 */ 192 es3fShaderSwitchTests.makeSwitchCases = function(group, name, desc, switchBody) { 193 /** @type {Array<string>} */ var switchTypeNames = ["static", "uniform", "dynamic"]; 194 for (var type in es3fShaderSwitchTests.SwitchType) { 195 group.addChild(es3fShaderSwitchTests.makeSwitchCase(name + "_" + switchTypeNames[es3fShaderSwitchTests.SwitchType[type]] + "_vertex", desc, es3fShaderSwitchTests.SwitchType[type], true, switchBody)); 196 group.addChild(es3fShaderSwitchTests.makeSwitchCase(name + "_" + switchTypeNames[es3fShaderSwitchTests.SwitchType[type]] + "_fragment", desc, es3fShaderSwitchTests.SwitchType[type], false, switchBody)); 197 } 198 }; 199 200 /** 201 * @constructor 202 * @extends {tcuTestCase.DeqpTest} 203 */ 204 es3fShaderSwitchTests.ShaderSwitchTests = function() { 205 tcuTestCase.DeqpTest.call(this, 'switch', 'Switch statement tests'); 206 }; 207 208 es3fShaderSwitchTests.ShaderSwitchTests.prototype = Object.create(tcuTestCase.DeqpTest.prototype); 209 es3fShaderSwitchTests.ShaderSwitchTests.prototype.constructor = es3fShaderSwitchTests.ShaderSwitchTests; 210 211 es3fShaderSwitchTests.ShaderSwitchTests.prototype.init = function() { 212 // Expected swizzles: 213 // 0: xyz 214 // 1: wzy 215 // 2: yzw 216 // 3: zyx 217 es3fShaderSwitchTests.makeSwitchCases(this, "basic", "Basic switch statement usage", 218 ' switch (${CONDITION})\n' + 219 ' {\n' + 220 ' case 0: res = coords.xyz; break;\n' + 221 ' case 1: res = coords.wzy; break;\n' + 222 ' case 2: res = coords.yzw; break;\n' + 223 ' case 3: res = coords.zyx; break;\n' + 224 ' }\n'); 225 226 es3fShaderSwitchTests.makeSwitchCases(this, "const_expr_in_label", "Constant expression in label", 227 ' const int t = 2;\n' + 228 ' switch (${CONDITION})\n' + 229 ' {\n' + 230 ' case int(0.0): res = coords.xyz; break;\n' + 231 ' case 2-1: res = coords.wzy; break;\n' + 232 ' case 3&(1<<1): res = coords.yzw; break;\n' + 233 ' case t+1: res = coords.zyx; break;\n' + 234 ' }\n'); 235 236 es3fShaderSwitchTests.makeSwitchCases(this, "default_label", "Default label usage", 237 ' switch (${CONDITION})\n' + 238 ' {\n' + 239 ' case 0: res = coords.xyz; break;\n' + 240 ' case 1: res = coords.wzy; break;\n' + 241 ' case 3: res = coords.zyx; break;\n' + 242 ' default: res = coords.yzw;\n' + 243 ' }\n'); 244 245 es3fShaderSwitchTests.makeSwitchCases(this, "default_not_last", "Default label usage", 246 ' switch (${CONDITION})\n' + 247 ' {\n' + 248 ' case 0: res = coords.xyz; break;\n' + 249 ' default: res = coords.yzw; break;\n' + 250 ' case 1: res = coords.wzy; break;\n' + 251 ' case 3: res = coords.zyx; break;\n' + 252 ' }\n'); 253 254 es3fShaderSwitchTests.makeSwitchCases(this, "no_default_label", "No match in switch without default label", 255 ' res = coords.yzw;\n\n' + 256 ' switch (${CONDITION})\n' + 257 ' {\n' + 258 ' case 0: res = coords.xyz; break;\n' + 259 ' case 1: res = coords.wzy; break;\n' + 260 ' case 3: res = coords.zyx; break;\n' + 261 ' }\n'); 262 263 es3fShaderSwitchTests.makeSwitchCases(this, "fall_through", "Fall-through", 264 ' switch (${CONDITION})\n' + 265 ' {\n' + 266 ' case 0: res = coords.xyz; break;\n' + 267 ' case 1: res = coords.wzy; break;\n' + 268 ' case 2: coords = coords.yzwx;\n' + 269 ' case 4: res = vec3(coords); break;\n' + 270 ' case 3: res = coords.zyx; break;\n' + 271 ' }\n'); 272 273 es3fShaderSwitchTests.makeSwitchCases(this, "fall_through_default", "Fall-through", 274 ' switch (${CONDITION})\n' + 275 ' {\n' + 276 ' case 0: res = coords.xyz; break;\n' + 277 ' case 1: res = coords.wzy; break;\n' + 278 ' case 3: res = coords.zyx; break;\n' + 279 ' case 2: coords = coords.yzwx;\n' + 280 ' default: res = vec3(coords);\n' + 281 ' }\n'); 282 283 es3fShaderSwitchTests.makeSwitchCases(this, "conditional_fall_through", "Fall-through", 284 ' highp vec4 tmp = coords;\n' + 285 ' switch (${CONDITION})\n' + 286 ' {\n' + 287 ' case 0: res = coords.xyz; break;\n' + 288 ' case 1: res = coords.wzy; break;\n' + 289 ' case 2:\n' + 290 ' tmp = coords.yzwx;\n' + 291 ' case 3:\n' + 292 ' res = vec3(tmp);\n' + 293 ' if (${CONDITION} != 3)\n' + 294 ' break;\n' + 295 ' default: res = tmp.zyx; break;\n' + 296 ' }\n'); 297 298 es3fShaderSwitchTests.makeSwitchCases(this, "conditional_fall_through_2", "Fall-through", 299 ' highp vec4 tmp = coords;\n' + 300 ' mediump int c = ${CONDITION};\n' + 301 ' switch (c)\n' + 302 ' {\n' + 303 ' case 0: res = coords.xyz; break;\n' + 304 ' case 1: res = coords.wzy; break;\n' + 305 ' case 2:\n' + 306 ' c += ${CONDITION};\n' + 307 ' tmp = coords.yzwx;\n' + 308 ' case 3:\n' + 309 ' res = vec3(tmp);\n' + 310 ' if (c == 4)\n' + 311 ' break;\n' + 312 ' default: res = tmp.zyx; break;\n' + 313 ' }\n'); 314 315 es3fShaderSwitchTests.makeSwitchCases(this, "scope", "Basic switch statement usage", 316 ' switch (${CONDITION})\n' + 317 ' {\n' + 318 ' case 0: res = coords.xyz; break;\n' + 319 ' case 1: res = coords.wzy; break;\n' + 320 ' case 2:\n' + 321 ' {\n' + 322 ' mediump vec3 t = coords.yzw;\n' + 323 ' res = t;\n' + 324 ' break;\n' + 325 ' }\n' + 326 ' case 3: res = coords.zyx; break;\n' + 327 ' }\n'); 328 329 es3fShaderSwitchTests.makeSwitchCases(this, "switch_in_if", "Switch in for loop", 330 ' if (${CONDITION} >= 0)\n' + 331 ' {\n' + 332 ' switch (${CONDITION})\n' + 333 ' {\n' + 334 ' case 0: res = coords.xyz; break;\n' + 335 ' case 1: res = coords.wzy; break;\n' + 336 ' case 2: res = coords.yzw; break;\n' + 337 ' case 3: res = coords.zyx; break;\n' + 338 ' }\n' + 339 ' }\n'); 340 341 es3fShaderSwitchTests.makeSwitchCases(this, "switch_in_for_loop", "Switch in for loop", 342 ' for (int i = 0; i <= ${CONDITION}; i++)\n' + 343 ' {\n' + 344 ' switch (i)\n' + 345 ' {\n' + 346 ' case 0: res = coords.xyz; break;\n' + 347 ' case 1: res = coords.wzy; break;\n' + 348 ' case 2: res = coords.yzw; break;\n' + 349 ' case 3: res = coords.zyx; break;\n' + 350 ' }\n' + 351 ' }\n'); 352 353 es3fShaderSwitchTests.makeSwitchCases(this, "switch_in_while_loop", "Switch in while loop", 354 ' int i = 0;\n' + 355 ' while (i <= ${CONDITION})\n' + 356 ' {\n' + 357 ' switch (i)\n' + 358 ' {\n' + 359 ' case 0: res = coords.xyz; break;\n' + 360 ' case 1: res = coords.wzy; break;\n' + 361 ' case 2: res = coords.yzw; break;\n' + 362 ' case 3: res = coords.zyx; break;\n' + 363 ' }\n' + 364 ' i += 1;\n' + 365 ' }\n'); 366 367 es3fShaderSwitchTests.makeSwitchCases(this, "switch_in_do_while_loop", "Switch in do-while loop", 368 ' int i = 0;\n' + 369 ' do\n' + 370 ' {\n' + 371 ' switch (i)\n' + 372 ' {\n' + 373 ' case 0: res = coords.xyz; break;\n' + 374 ' case 1: res = coords.wzy; break;\n' + 375 ' case 2: res = coords.yzw; break;\n' + 376 ' case 3: res = coords.zyx; break;\n' + 377 ' }\n' + 378 ' i += 1;\n' + 379 ' } while (i <= ${CONDITION});\n'); 380 381 es3fShaderSwitchTests.makeSwitchCases(this, "if_in_switch", "Basic switch statement usage", 382 ' switch (${CONDITION})\n' + 383 ' {\n' + 384 ' case 0: res = coords.xyz; break;\n' + 385 ' case 1: res = coords.wzy; break;\n' + 386 ' default:\n' + 387 ' if (${CONDITION} == 2)\n' + 388 ' res = coords.yzw;\n' + 389 ' else\n' + 390 ' res = coords.zyx;\n' + 391 ' break;\n' + 392 ' }\n'); 393 394 es3fShaderSwitchTests.makeSwitchCases(this, "for_loop_in_switch", "Basic switch statement usage", 395 ' switch (${CONDITION})\n' + 396 ' {\n' + 397 ' case 0: res = coords.xyz; break;\n' + 398 ' case 1:\n' + 399 ' case 2:\n' + 400 ' {\n' + 401 ' highp vec3 t = coords.yzw;\n' + 402 ' for (int i = 0; i < ${CONDITION}; i++)\n' + 403 ' t = t.zyx;\n' + 404 ' res = t;\n' + 405 ' break;\n' + 406 ' }\n' + 407 ' default: res = coords.zyx; break;\n' + 408 ' }\n'); 409 410 es3fShaderSwitchTests.makeSwitchCases(this, "while_loop_in_switch", "Basic switch statement usage", 411 ' switch (${CONDITION})\n' + 412 ' {\n' + 413 ' case 0: res = coords.xyz; break;\n' + 414 ' case 1:\n' + 415 ' case 2:\n' + 416 ' {\n' + 417 ' highp vec3 t = coords.yzw;\n' + 418 ' int i = 0;\n' + 419 ' while (i < ${CONDITION})\n' + 420 ' {\n' + 421 ' t = t.zyx;\n' + 422 ' i += 1;\n' + 423 ' }\n' + 424 ' res = t;\n' + 425 ' break;\n' + 426 ' }\n' + 427 ' default: res = coords.zyx; break;\n' + 428 ' }\n'); 429 430 es3fShaderSwitchTests.makeSwitchCases(this, "do_while_loop_in_switch", "Basic switch statement usage", 431 ' switch (${CONDITION})\n' + 432 ' {\n' + 433 ' case 0: res = coords.xyz; break;\n' + 434 ' case 1:\n' + 435 ' case 2:\n' + 436 ' {\n' + 437 ' highp vec3 t = coords.yzw;\n' + 438 ' int i = 0;\n' + 439 ' do\n' + 440 ' {\n' + 441 ' t = t.zyx;\n' + 442 ' i += 1;\n' + 443 ' } while (i < ${CONDITION});\n' + 444 ' res = t;\n' + 445 ' break;\n' + 446 ' }\n' + 447 ' default: res = coords.zyx; break;\n' + 448 ' }\n'); 449 450 es3fShaderSwitchTests.makeSwitchCases(this, "switch_in_switch", "Basic switch statement usage", 451 ' switch (${CONDITION})\n' + 452 ' {\n' + 453 ' case 0: res = coords.xyz; break;\n' + 454 ' case 1:\n' + 455 ' case 2:\n' + 456 ' switch (${CONDITION} - 1)\n' + 457 ' {\n' + 458 ' case 0: res = coords.wzy; break;\n' + 459 ' case 1: res = coords.yzw; break;\n' + 460 ' }\n' + 461 ' break;\n' + 462 ' default: res = coords.zyx; break;\n' + 463 '}\n'); 464 465 // Negative cases. 466 // This is being tested somwhere else: data/gles3/shaders/switch.html 467 }; 468 469 /** 470 * Run test 471 * @param {WebGL2RenderingContext} context 472 */ 473 es3fShaderSwitchTests.run = function(context) { 474 gl = context; 475 //Set up Test Root parameters 476 var state = tcuTestCase.runner; 477 state.setRoot(new es3fShaderSwitchTests.ShaderSwitchTests()); 478 479 //Set up name and description of this test series. 480 setCurrentTestName(state.testCases.fullName()); 481 description(state.testCases.getDescription()); 482 try { 483 //Run test cases 484 tcuTestCase.runTestCases(); 485 } 486 catch (err) { 487 testFailedOptions('Failed to es3fShaderSwitchTests.run tests', false); 488 tcuTestCase.runner.terminate(); 489 } 490 }; 491 492 });