1 /*-------------------------------------------------------------------------
2 * drawElements Quality Program OpenGL ES Utilities
3 * ------------------------------------------------
5 * Copyright 2014 The Android Open Source Project
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
22 goog.provide('functional.gles3.es3fShaderSwitchTests');
23 goog.require('framework.common.tcuStringTemplate');
24 goog.require('framework.common.tcuTestCase');
25 goog.require('modules.shared.glsShaderRenderCase');
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;
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
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;
50 es3fShaderSwitchTests.ShaderSwitchCase.prototype = Object.create(glsShaderRenderCase.ShaderRenderCase.prototype);
51 es3fShaderSwitchTests.ShaderSwitchCase.prototype.constructor = es3fShaderSwitchTests.ShaderSwitchCase;
56 es3fShaderSwitchTests.SwitchType = {
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];
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];
76 /** @param {glsShaderRenderCase.ShaderEvalContext} evalCtx */
77 es3fShaderSwitchTests.evalSwitchDynamic = function(evalCtx) {
78 switch (Math.floor(evalCtx.coords[2]*1.5 + 2.0)) {
80 evalCtx.color[0] = evalCtx.coords[0];
81 evalCtx.color[1] = evalCtx.coords[1];
82 evalCtx.color[2] = evalCtx.coords[2];
85 evalCtx.color[0] = evalCtx.coords[3];
86 evalCtx.color[1] = evalCtx.coords[2];
87 evalCtx.color[2] = evalCtx.coords[1];
90 evalCtx.color[0] = evalCtx.coords[1];
91 evalCtx.color[1] = evalCtx.coords[2];
92 evalCtx.color[2] = evalCtx.coords[3];
95 evalCtx.color[0] = evalCtx.coords[2];
96 evalCtx.color[1] = evalCtx.coords[1];
97 evalCtx.color[2] = evalCtx.coords[0];
100 evalCtx.color[0] = evalCtx.coords[0];
101 evalCtx.color[1] = evalCtx.coords[0];
102 evalCtx.color[2] = evalCtx.coords[0];
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}
115 es3fShaderSwitchTests.makeSwitchCase = function(name, desc, type, isVertex, switchBody) {
116 /** @type {string} */ var vtx = '';
117 /** @type {string} */ var frag = '';
118 /** @type {string} */ var op = '';
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";
127 vtx += "out mediump vec4 v_color;\n";
128 frag += "in mediump vec4 v_color;\n";
130 vtx += "out highp vec4 v_coords;\n";
131 frag += "in highp vec4 v_coords;\n";
134 if (type === es3fShaderSwitchTests.SwitchType.UNIFORM)
135 op += "uniform highp int ui_two;\n";
137 vtx += isVertex ? op : '';
138 frag += isVertex ? '' : op;
142 "void main (void)\n" +
144 " gl_Position = a_position;\n";
146 "void main (void)\n" +
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;
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))" : "???";
162 op += tcuStringTemplate.specialize(switchBody, params);
165 vtx += isVertex ? op : '';
166 frag += isVertex ? '' : op;
170 vtx += " v_color = vec4(res, 1.0);\n";
171 frag += " o_color = v_color;\n";
173 vtx += " v_coords = a_coords;\n";
174 frag += " o_color = vec4(res, 1.0);\n";
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);
187 * @param {tcuTestCase.DeqpTest} group
188 * @param {string} name
189 * @param {string} desc
190 * @param {string} switchBody
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));
202 * @extends {tcuTestCase.DeqpTest}
204 es3fShaderSwitchTests.ShaderSwitchTests = function() {
205 tcuTestCase.DeqpTest.call(this, 'switch', 'Switch statement tests');
208 es3fShaderSwitchTests.ShaderSwitchTests.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
209 es3fShaderSwitchTests.ShaderSwitchTests.prototype.constructor = es3fShaderSwitchTests.ShaderSwitchTests;
211 es3fShaderSwitchTests.ShaderSwitchTests.prototype.init = function() {
212 // Expected swizzles:
217 es3fShaderSwitchTests.makeSwitchCases(this, "basic", "Basic switch statement usage",
218 ' switch (${CONDITION})\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' +
226 es3fShaderSwitchTests.makeSwitchCases(this, "const_expr_in_label", "Constant expression in label",
227 ' const int t = 2;\n' +
228 ' switch (${CONDITION})\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' +
236 es3fShaderSwitchTests.makeSwitchCases(this, "default_label", "Default label usage",
237 ' switch (${CONDITION})\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' +
245 es3fShaderSwitchTests.makeSwitchCases(this, "default_not_last", "Default label usage",
246 ' switch (${CONDITION})\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' +
254 es3fShaderSwitchTests.makeSwitchCases(this, "no_default_label", "No match in switch without default label",
255 ' res = coords.yzw;\n\n' +
256 ' switch (${CONDITION})\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' +
263 es3fShaderSwitchTests.makeSwitchCases(this, "fall_through", "Fall-through",
264 ' switch (${CONDITION})\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' +
273 es3fShaderSwitchTests.makeSwitchCases(this, "fall_through_default", "Fall-through",
274 ' switch (${CONDITION})\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' +
283 es3fShaderSwitchTests.makeSwitchCases(this, "conditional_fall_through", "Fall-through",
284 ' highp vec4 tmp = coords;\n' +
285 ' switch (${CONDITION})\n' +
287 ' case 0: res = coords.xyz; break;\n' +
288 ' case 1: res = coords.wzy; break;\n' +
290 ' tmp = coords.yzwx;\n' +
292 ' res = vec3(tmp);\n' +
293 ' if (${CONDITION} != 3)\n' +
295 ' default: res = tmp.zyx; break;\n' +
298 es3fShaderSwitchTests.makeSwitchCases(this, "conditional_fall_through_2", "Fall-through",
299 ' highp vec4 tmp = coords;\n' +
300 ' mediump int c = ${CONDITION};\n' +
303 ' case 0: res = coords.xyz; break;\n' +
304 ' case 1: res = coords.wzy; break;\n' +
306 ' c += ${CONDITION};\n' +
307 ' tmp = coords.yzwx;\n' +
309 ' res = vec3(tmp);\n' +
312 ' default: res = tmp.zyx; break;\n' +
315 es3fShaderSwitchTests.makeSwitchCases(this, "scope", "Basic switch statement usage",
316 ' switch (${CONDITION})\n' +
318 ' case 0: res = coords.xyz; break;\n' +
319 ' case 1: res = coords.wzy; break;\n' +
322 ' mediump vec3 t = coords.yzw;\n' +
326 ' case 3: res = coords.zyx; break;\n' +
329 es3fShaderSwitchTests.makeSwitchCases(this, "switch_in_if", "Switch in for loop",
330 ' if (${CONDITION} >= 0)\n' +
332 ' switch (${CONDITION})\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' +
341 es3fShaderSwitchTests.makeSwitchCases(this, "switch_in_for_loop", "Switch in for loop",
342 ' for (int i = 0; i <= ${CONDITION}; i++)\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' +
353 es3fShaderSwitchTests.makeSwitchCases(this, "switch_in_while_loop", "Switch in while loop",
355 ' while (i <= ${CONDITION})\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' +
367 es3fShaderSwitchTests.makeSwitchCases(this, "switch_in_do_while_loop", "Switch in do-while loop",
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' +
379 ' } while (i <= ${CONDITION});\n');
381 es3fShaderSwitchTests.makeSwitchCases(this, "if_in_switch", "Basic switch statement usage",
382 ' switch (${CONDITION})\n' +
384 ' case 0: res = coords.xyz; break;\n' +
385 ' case 1: res = coords.wzy; break;\n' +
387 ' if (${CONDITION} == 2)\n' +
388 ' res = coords.yzw;\n' +
390 ' res = coords.zyx;\n' +
394 es3fShaderSwitchTests.makeSwitchCases(this, "for_loop_in_switch", "Basic switch statement usage",
395 ' switch (${CONDITION})\n' +
397 ' case 0: res = coords.xyz; break;\n' +
401 ' highp vec3 t = coords.yzw;\n' +
402 ' for (int i = 0; i < ${CONDITION}; i++)\n' +
407 ' default: res = coords.zyx; break;\n' +
410 es3fShaderSwitchTests.makeSwitchCases(this, "while_loop_in_switch", "Basic switch statement usage",
411 ' switch (${CONDITION})\n' +
413 ' case 0: res = coords.xyz; break;\n' +
417 ' highp vec3 t = coords.yzw;\n' +
419 ' while (i < ${CONDITION})\n' +
427 ' default: res = coords.zyx; break;\n' +
430 es3fShaderSwitchTests.makeSwitchCases(this, "do_while_loop_in_switch", "Basic switch statement usage",
431 ' switch (${CONDITION})\n' +
433 ' case 0: res = coords.xyz; break;\n' +
437 ' highp vec3 t = coords.yzw;\n' +
443 ' } while (i < ${CONDITION});\n' +
447 ' default: res = coords.zyx; break;\n' +
450 es3fShaderSwitchTests.makeSwitchCases(this, "switch_in_switch", "Basic switch statement usage",
451 ' switch (${CONDITION})\n' +
453 ' case 0: res = coords.xyz; break;\n' +
456 ' switch (${CONDITION} - 1)\n' +
458 ' case 0: res = coords.wzy; break;\n' +
459 ' case 1: res = coords.yzw; break;\n' +
462 ' default: res = coords.zyx; break;\n' +
466 // This is being tested somwhere else: data/gles3/shaders/switch.html
471 * @param {WebGL2RenderingContext} context
473 es3fShaderSwitchTests.run = function(context) {
475 //Set up Test Root parameters
476 var state = tcuTestCase.runner;
477 state.setRoot(new es3fShaderSwitchTests.ShaderSwitchTests());
479 //Set up name and description of this test series.
480 setCurrentTestName(state.testCases.fullName());
481 description(state.testCases.getDescription());
484 tcuTestCase.runTestCases();
487 testFailedOptions('Failed to es3fShaderSwitchTests.run tests', false);
488 tcuTestCase.runner.terminate();