1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
5 * Copyright (c) 2015 The Khronos Group Inc.
6 * Copyright (c) 2015 Samsung Electronics Co., Ltd.
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and/or associated documentation files (the
10 * "Materials"), to deal in the Materials without restriction, including
11 * without limitation the rights to use, copy, modify, merge, publish,
12 * distribute, sublicense, and/or sell copies of the Materials, and to
13 * permit persons to whom the Materials are furnished to do so, subject to
14 * the following conditions:
16 * The above copyright notice(s) and this permission notice shall be included
17 * in all copies or substantial portions of the Materials.
19 * The Materials are Confidential Information as defined by the
20 * Khronos Membership Agreement until designated non-confidential by Khronos,
21 * at which point this condition clause shall be removed.
23 * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
26 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
27 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
28 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
29 * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
33 * \brief Shader switch statement tests.
36 * + Selection expression type: static, uniform, dynamic
37 * + Switch layout - fall-through or use of default label
38 * + Switch nested in loop/conditional statement
39 * + Loop/conditional statement nested in switch
40 *//*--------------------------------------------------------------------*/
42 #include "vktShaderRenderSwitchTests.hpp"
43 #include "vktShaderRender.hpp"
44 #include "tcuStringTemplate.hpp"
54 static void setUniforms(ShaderRenderCaseInstance& instance, const tcu::Vec4&)
56 instance.useUniform(0u, UI_TWO);
61 class ShaderSwitchCase : public ShaderRenderCase
64 ShaderSwitchCase (tcu::TestContext& testCtx,
66 const string& description,
68 const string& vtxSource,
69 const string& fragSource,
70 ShaderEvalFunc evalFunc,
71 UniformSetupFunc setupUniformsFunc);
72 virtual ~ShaderSwitchCase (void);
75 ShaderSwitchCase::ShaderSwitchCase (tcu::TestContext& testCtx,
77 const string& description,
79 const string& vtxSource,
80 const string& fragSource,
81 ShaderEvalFunc evalFunc,
82 UniformSetupFunc setupUniformsFunc)
83 : ShaderRenderCase (testCtx, name, description, isVertexCase, evalFunc, new UniformSetup(setupUniformsFunc), DE_NULL)
85 m_vertShaderSource = vtxSource;
86 m_fragShaderSource = fragSource;
89 ShaderSwitchCase::~ShaderSwitchCase (void)
95 SWITCHTYPE_STATIC = 0,
102 static void evalSwitchStatic (ShaderEvalContext& evalCtx) { evalCtx.color.xyz() = evalCtx.coords.swizzle(1,2,3); }
103 static void evalSwitchUniform (ShaderEvalContext& evalCtx) { evalCtx.color.xyz() = evalCtx.coords.swizzle(1,2,3); }
104 static void evalSwitchDynamic (ShaderEvalContext& evalCtx)
106 switch (int(deFloatFloor(evalCtx.coords.z()*1.5f + 2.0f)))
108 case 0: evalCtx.color.xyz() = evalCtx.coords.swizzle(0,1,2); break;
109 case 1: evalCtx.color.xyz() = evalCtx.coords.swizzle(3,2,1); break;
110 case 2: evalCtx.color.xyz() = evalCtx.coords.swizzle(1,2,3); break;
111 case 3: evalCtx.color.xyz() = evalCtx.coords.swizzle(2,1,0); break;
112 default: evalCtx.color.xyz() = evalCtx.coords.swizzle(0,0,0); break;
116 static de::MovePtr<ShaderSwitchCase> makeSwitchCase (tcu::TestContext& testCtx, const string& name, const string& desc, SwitchType type, bool isVertex, const LineStream& switchBody)
118 std::ostringstream vtx;
119 std::ostringstream frag;
120 std::ostringstream& op = isVertex ? vtx : frag;
122 vtx << "#version 140\n"
123 << "#extension GL_ARB_separate_shader_objects : enable\n"
124 << "#extension GL_ARB_shading_language_420pack : enable\n"
125 << "layout(location = 0) in highp vec4 a_position;\n"
126 << "layout(location = 1) in highp vec4 a_coords;\n\n";
127 frag << "#version 140\n"
128 << "#extension GL_ARB_separate_shader_objects : enable\n"
129 << "#extension GL_ARB_shading_language_420pack : enable\n"
130 << "layout(location = 0) out mediump vec4 o_color;\n";
134 vtx << "layout(location = 0) out mediump vec4 v_color;\n";
135 frag << "layout(location = 0) in mediump vec4 v_color;\n";
139 vtx << "layout(location = 0) out highp vec4 v_coords;\n";
140 frag << "layout(location = 0) in highp vec4 v_coords;\n";
143 if (type == SWITCHTYPE_UNIFORM)
144 op << "layout (std140, set=0, binding=0) uniform buffer0 { highp int ui_two; };\n";
147 << "void main (void)\n"
149 << " gl_Position = a_position;\n";
151 << "void main (void)\n"
155 op << " highp vec4 coords = " << (isVertex ? "a_coords" : "v_coords") << ";\n";
156 op << " mediump vec3 res = vec3(0.0);\n\n";
159 std::map<string, string> params;
160 params["CONDITION"] = type == SWITCHTYPE_STATIC ? "2" :
161 type == SWITCHTYPE_UNIFORM ? "ui_two" :
162 type == SWITCHTYPE_DYNAMIC ? "int(floor(coords.z*1.5 + 2.0))" : "???";
164 op << tcu::StringTemplate(switchBody.str()).specialize(params);
169 vtx << " v_color = vec4(res, 1.0);\n";
170 frag << " o_color = v_color;\n";
174 vtx << " v_coords = a_coords;\n";
175 frag << " o_color = vec4(res, 1.0);\n";
181 return de::MovePtr<ShaderSwitchCase>(new ShaderSwitchCase(testCtx, name, desc, isVertex, vtx.str(), frag.str(),
182 type == SWITCHTYPE_STATIC ? evalSwitchStatic :
183 type == SWITCHTYPE_UNIFORM ? evalSwitchUniform :
184 type == SWITCHTYPE_DYNAMIC ? evalSwitchDynamic : (ShaderEvalFunc)DE_NULL,
185 type == SWITCHTYPE_UNIFORM ? setUniforms : DE_NULL));
188 class ShaderSwitchTests : public tcu::TestCaseGroup
191 ShaderSwitchTests (tcu::TestContext& context);
192 virtual ~ShaderSwitchTests (void);
194 virtual void init (void);
197 ShaderSwitchTests (const ShaderSwitchTests&); // not allowed!
198 ShaderSwitchTests& operator= (const ShaderSwitchTests&); // not allowed!
200 void makeSwitchCases (const string& name, const string& desc, const LineStream& switchBody);
203 ShaderSwitchTests::ShaderSwitchTests (tcu::TestContext& testCtx)
204 : tcu::TestCaseGroup (testCtx, "switch", "Switch statement tests")
208 ShaderSwitchTests::~ShaderSwitchTests (void)
212 void ShaderSwitchTests::makeSwitchCases (const string& name, const string& desc, const LineStream& switchBody)
214 static const char* switchTypeNames[] = { "static", "uniform", "dynamic" };
215 DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(switchTypeNames) == SWITCHTYPE_LAST);
217 for (int type = 0; type < SWITCHTYPE_LAST; type++)
219 addChild(makeSwitchCase(m_testCtx, (name + "_" + switchTypeNames[type] + "_vertex"), desc, (SwitchType)type, true, switchBody).release());
220 addChild(makeSwitchCase(m_testCtx, (name + "_" + switchTypeNames[type] + "_fragment"), desc, (SwitchType)type, false, switchBody).release());
224 void ShaderSwitchTests::init (void)
226 // Expected swizzles:
232 makeSwitchCases("basic", "Basic switch statement usage",
234 << "switch (${CONDITION})"
236 << " case 0: res = coords.xyz; break;"
237 << " case 1: res = coords.wzy; break;"
238 << " case 2: res = coords.yzw; break;"
239 << " case 3: res = coords.zyx; break;"
242 makeSwitchCases("const_expr_in_label", "Constant expression in label",
244 << "const int t = 2;"
245 << "switch (${CONDITION})"
247 << " case int(0.0): res = coords.xyz; break;"
248 << " case 2-1: res = coords.wzy; break;"
249 << " case 3&(1<<1): res = coords.yzw; break;"
250 << " case t+1: res = coords.zyx; break;"
253 makeSwitchCases("default_label", "Default label usage",
255 << "switch (${CONDITION})"
257 << " case 0: res = coords.xyz; break;"
258 << " case 1: res = coords.wzy; break;"
259 << " case 3: res = coords.zyx; break;"
260 << " default: res = coords.yzw;"
263 makeSwitchCases("default_not_last", "Default label usage",
265 << "switch (${CONDITION})"
267 << " case 0: res = coords.xyz; break;"
268 << " default: res = coords.yzw; break;"
269 << " case 1: res = coords.wzy; break;"
270 << " case 3: res = coords.zyx; break;"
273 makeSwitchCases("no_default_label", "No match in switch without default label",
275 << "res = coords.yzw;\n"
276 << "switch (${CONDITION})"
278 << " case 0: res = coords.xyz; break;"
279 << " case 1: res = coords.wzy; break;"
280 << " case 3: res = coords.zyx; break;"
283 makeSwitchCases("fall_through", "Fall-through",
285 << "switch (${CONDITION})"
287 << " case 0: res = coords.xyz; break;"
288 << " case 1: res = coords.wzy; break;"
289 << " case 2: coords = coords.yzwx;"
290 << " case 4: res = vec3(coords); break;"
291 << " case 3: res = coords.zyx; break;"
294 makeSwitchCases("fall_through_default", "Fall-through",
296 << "switch (${CONDITION})"
298 << " case 0: res = coords.xyz; break;"
299 << " case 1: res = coords.wzy; break;"
300 << " case 3: res = coords.zyx; break;"
301 << " case 2: coords = coords.yzwx;"
302 << " default: res = vec3(coords);"
305 makeSwitchCases("conditional_fall_through", "Fall-through",
307 << "highp vec4 tmp = coords;"
308 << "switch (${CONDITION})"
310 << " case 0: res = coords.xyz; break;"
311 << " case 1: res = coords.wzy; break;"
313 << " tmp = coords.yzwx;"
315 << " res = vec3(tmp);"
316 << " if (${CONDITION} != 3)"
318 << " default: res = tmp.zyx; break;"
321 makeSwitchCases("conditional_fall_through_2", "Fall-through",
323 << "highp vec4 tmp = coords;"
324 << "mediump int c = ${CONDITION};"
327 << " case 0: res = coords.xyz; break;"
328 << " case 1: res = coords.wzy; break;"
330 << " c += ${CONDITION};"
331 << " tmp = coords.yzwx;"
333 << " res = vec3(tmp);"
336 << " default: res = tmp.zyx; break;"
339 makeSwitchCases("scope", "Basic switch statement usage",
341 << "switch (${CONDITION})"
343 << " case 0: res = coords.xyz; break;"
344 << " case 1: res = coords.wzy; break;"
347 << " mediump vec3 t = coords.yzw;"
351 << " case 3: res = coords.zyx; break;"
354 makeSwitchCases("switch_in_if", "Switch in for loop",
356 << "if (${CONDITION} >= 0)"
358 << " switch (${CONDITION})"
360 << " case 0: res = coords.xyz; break;"
361 << " case 1: res = coords.wzy; break;"
362 << " case 2: res = coords.yzw; break;"
363 << " case 3: res = coords.zyx; break;"
367 makeSwitchCases("switch_in_for_loop", "Switch in for loop",
369 << "for (int i = 0; i <= ${CONDITION}; i++)"
373 << " case 0: res = coords.xyz; break;"
374 << " case 1: res = coords.wzy; break;"
375 << " case 2: res = coords.yzw; break;"
376 << " case 3: res = coords.zyx; break;"
381 makeSwitchCases("switch_in_while_loop", "Switch in while loop",
384 << "while (i <= ${CONDITION})"
388 << " case 0: res = coords.xyz; break;"
389 << " case 1: res = coords.wzy; break;"
390 << " case 2: res = coords.yzw; break;"
391 << " case 3: res = coords.zyx; break;"
396 makeSwitchCases("switch_in_do_while_loop", "Switch in do-while loop",
403 << " case 0: res = coords.xyz; break;"
404 << " case 1: res = coords.wzy; break;"
405 << " case 2: res = coords.yzw; break;"
406 << " case 3: res = coords.zyx; break;"
409 << "} while (i <= ${CONDITION});");
411 makeSwitchCases("if_in_switch", "Basic switch statement usage",
413 << "switch (${CONDITION})"
415 << " case 0: res = coords.xyz; break;"
416 << " case 1: res = coords.wzy; break;"
418 << " if (${CONDITION} == 2)"
419 << " res = coords.yzw;"
421 << " res = coords.zyx;"
425 makeSwitchCases("for_loop_in_switch", "Basic switch statement usage",
427 << "switch (${CONDITION})"
429 << " case 0: res = coords.xyz; break;"
433 << " highp vec3 t = coords.yzw;"
434 << " for (int i = 0; i < ${CONDITION}; i++)"
439 << " default: res = coords.zyx; break;"
442 makeSwitchCases("while_loop_in_switch", "Basic switch statement usage",
444 << "switch (${CONDITION})"
446 << " case 0: res = coords.xyz; break;"
450 << " highp vec3 t = coords.yzw;"
452 << " while (i < ${CONDITION})"
460 << " default: res = coords.zyx; break;"
463 makeSwitchCases("do_while_loop_in_switch", "Basic switch statement usage",
465 << "switch (${CONDITION})"
467 << " case 0: res = coords.xyz; break;"
471 << " highp vec3 t = coords.yzw;"
477 << " } while (i < ${CONDITION});"
481 << " default: res = coords.zyx; break;"
484 makeSwitchCases("switch_in_switch", "Basic switch statement usage",
486 << "switch (${CONDITION})"
488 << " case 0: res = coords.xyz; break;"
491 << " switch (${CONDITION} - 1)"
493 << " case 0: res = coords.wzy; break;"
494 << " case 1: res = coords.yzw; break;"
497 << " default: res = coords.zyx; break;"
503 tcu::TestCaseGroup* createSwitchTests (tcu::TestContext& testCtx)
505 return new ShaderSwitchTests(testCtx);