1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
5 * Copyright (c) 2015 The Khronos Group Inc.
6 * Copyright (c) 2015 Samsung Electronics Co., Ltd.
7 * Copyright (c) 2016 The Android Open Source Project
9 * Licensed under the Apache License, Version 2.0 (the "License");
10 * you may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
13 * http://www.apache.org/licenses/LICENSE-2.0
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
23 * \brief Shader switch statement tests.
26 * + Selection expression type: static, uniform, dynamic
27 * + Switch layout - fall-through or use of default label
28 * + Switch nested in loop/conditional statement
29 * + Loop/conditional statement nested in switch
30 *//*--------------------------------------------------------------------*/
32 #include "vktShaderRenderSwitchTests.hpp"
33 #include "vktShaderRender.hpp"
34 #include "tcuStringTemplate.hpp"
44 static void setUniforms(ShaderRenderCaseInstance& instance, const tcu::Vec4&)
46 instance.useUniform(0u, UI_TWO);
51 class ShaderSwitchCase : public ShaderRenderCase
54 ShaderSwitchCase (tcu::TestContext& testCtx,
56 const string& description,
58 const string& vtxSource,
59 const string& fragSource,
60 ShaderEvalFunc evalFunc,
61 UniformSetupFunc setupUniformsFunc);
62 virtual ~ShaderSwitchCase (void);
65 ShaderSwitchCase::ShaderSwitchCase (tcu::TestContext& testCtx,
67 const string& description,
69 const string& vtxSource,
70 const string& fragSource,
71 ShaderEvalFunc evalFunc,
72 UniformSetupFunc setupUniformsFunc)
73 : ShaderRenderCase (testCtx, name, description, isVertexCase, evalFunc, new UniformSetup(setupUniformsFunc), DE_NULL)
75 m_vertShaderSource = vtxSource;
76 m_fragShaderSource = fragSource;
79 ShaderSwitchCase::~ShaderSwitchCase (void)
85 SWITCHTYPE_STATIC = 0,
92 static void evalSwitchStatic (ShaderEvalContext& evalCtx) { evalCtx.color.xyz() = evalCtx.coords.swizzle(1,2,3); }
93 static void evalSwitchUniform (ShaderEvalContext& evalCtx) { evalCtx.color.xyz() = evalCtx.coords.swizzle(1,2,3); }
94 static void evalSwitchDynamic (ShaderEvalContext& evalCtx)
96 switch (int(deFloatFloor(evalCtx.coords.z()*1.5f + 2.0f)))
98 case 0: evalCtx.color.xyz() = evalCtx.coords.swizzle(0,1,2); break;
99 case 1: evalCtx.color.xyz() = evalCtx.coords.swizzle(3,2,1); break;
100 case 2: evalCtx.color.xyz() = evalCtx.coords.swizzle(1,2,3); break;
101 case 3: evalCtx.color.xyz() = evalCtx.coords.swizzle(2,1,0); break;
102 default: evalCtx.color.xyz() = evalCtx.coords.swizzle(0,0,0); break;
106 static de::MovePtr<ShaderSwitchCase> makeSwitchCase (tcu::TestContext& testCtx, const string& name, const string& desc, SwitchType type, bool isVertex, const LineStream& switchBody)
108 std::ostringstream vtx;
109 std::ostringstream frag;
110 std::ostringstream& op = isVertex ? vtx : frag;
112 vtx << "#version 310 es\n"
113 << "layout(location = 0) in highp vec4 a_position;\n"
114 << "layout(location = 1) in highp vec4 a_coords;\n\n";
115 frag << "#version 310 es\n"
116 << "layout(location = 0) out mediump vec4 o_color;\n";
120 vtx << "layout(location = 0) out mediump vec4 v_color;\n";
121 frag << "layout(location = 0) in mediump vec4 v_color;\n";
125 vtx << "layout(location = 0) out highp vec4 v_coords;\n";
126 frag << "layout(location = 0) in highp vec4 v_coords;\n";
129 if (type == SWITCHTYPE_UNIFORM)
130 op << "layout (std140, set=0, binding=0) uniform buffer0 { highp int ui_two; };\n";
133 << "void main (void)\n"
135 << " gl_Position = a_position;\n";
137 << "void main (void)\n"
141 op << " highp vec4 coords = " << (isVertex ? "a_coords" : "v_coords") << ";\n";
142 op << " mediump vec3 res = vec3(0.0);\n\n";
145 std::map<string, string> params;
146 params["CONDITION"] = type == SWITCHTYPE_STATIC ? "2" :
147 type == SWITCHTYPE_UNIFORM ? "ui_two" :
148 type == SWITCHTYPE_DYNAMIC ? "int(floor(coords.z*1.5 + 2.0))" : "???";
150 op << tcu::StringTemplate(switchBody.str()).specialize(params);
155 vtx << " v_color = vec4(res, 1.0);\n";
156 frag << " o_color = v_color;\n";
160 vtx << " v_coords = a_coords;\n";
161 frag << " o_color = vec4(res, 1.0);\n";
167 return de::MovePtr<ShaderSwitchCase>(new ShaderSwitchCase(testCtx, name, desc, isVertex, vtx.str(), frag.str(),
168 type == SWITCHTYPE_STATIC ? evalSwitchStatic :
169 type == SWITCHTYPE_UNIFORM ? evalSwitchUniform :
170 type == SWITCHTYPE_DYNAMIC ? evalSwitchDynamic : (ShaderEvalFunc)DE_NULL,
171 type == SWITCHTYPE_UNIFORM ? setUniforms : DE_NULL));
174 class ShaderSwitchTests : public tcu::TestCaseGroup
177 ShaderSwitchTests (tcu::TestContext& context);
178 virtual ~ShaderSwitchTests (void);
180 virtual void init (void);
183 ShaderSwitchTests (const ShaderSwitchTests&); // not allowed!
184 ShaderSwitchTests& operator= (const ShaderSwitchTests&); // not allowed!
186 void makeSwitchCases (const string& name, const string& desc, const LineStream& switchBody);
189 ShaderSwitchTests::ShaderSwitchTests (tcu::TestContext& testCtx)
190 : tcu::TestCaseGroup (testCtx, "switch", "Switch statement tests")
194 ShaderSwitchTests::~ShaderSwitchTests (void)
198 void ShaderSwitchTests::makeSwitchCases (const string& name, const string& desc, const LineStream& switchBody)
200 static const char* switchTypeNames[] = { "static", "uniform", "dynamic" };
201 DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(switchTypeNames) == SWITCHTYPE_LAST);
203 for (int type = 0; type < SWITCHTYPE_LAST; type++)
205 addChild(makeSwitchCase(m_testCtx, (name + "_" + switchTypeNames[type] + "_vertex"), desc, (SwitchType)type, true, switchBody).release());
206 addChild(makeSwitchCase(m_testCtx, (name + "_" + switchTypeNames[type] + "_fragment"), desc, (SwitchType)type, false, switchBody).release());
210 void ShaderSwitchTests::init (void)
212 // Expected swizzles:
218 makeSwitchCases("basic", "Basic switch statement usage",
220 << "switch (${CONDITION})"
222 << " case 0: res = coords.xyz; break;"
223 << " case 1: res = coords.wzy; break;"
224 << " case 2: res = coords.yzw; break;"
225 << " case 3: res = coords.zyx; break;"
228 makeSwitchCases("const_expr_in_label", "Constant expression in label",
230 << "const int t = 2;"
231 << "switch (${CONDITION})"
233 << " case int(0.0): res = coords.xyz; break;"
234 << " case 2-1: res = coords.wzy; break;"
235 << " case 3&(1<<1): res = coords.yzw; break;"
236 << " case t+1: res = coords.zyx; break;"
239 makeSwitchCases("default_label", "Default label usage",
241 << "switch (${CONDITION})"
243 << " case 0: res = coords.xyz; break;"
244 << " case 1: res = coords.wzy; break;"
245 << " case 3: res = coords.zyx; break;"
246 << " default: res = coords.yzw;"
249 makeSwitchCases("default_not_last", "Default label usage",
251 << "switch (${CONDITION})"
253 << " case 0: res = coords.xyz; break;"
254 << " default: res = coords.yzw; break;"
255 << " case 1: res = coords.wzy; break;"
256 << " case 3: res = coords.zyx; break;"
259 makeSwitchCases("no_default_label", "No match in switch without default label",
261 << "res = coords.yzw;\n"
262 << "switch (${CONDITION})"
264 << " case 0: res = coords.xyz; break;"
265 << " case 1: res = coords.wzy; break;"
266 << " case 3: res = coords.zyx; break;"
269 makeSwitchCases("fall_through", "Fall-through",
271 << "switch (${CONDITION})"
273 << " case 0: res = coords.xyz; break;"
274 << " case 1: res = coords.wzy; break;"
275 << " case 2: coords = coords.yzwx;"
276 << " case 4: res = vec3(coords); break;"
277 << " case 3: res = coords.zyx; break;"
280 makeSwitchCases("fall_through_default", "Fall-through",
282 << "switch (${CONDITION})"
284 << " case 0: res = coords.xyz; break;"
285 << " case 1: res = coords.wzy; break;"
286 << " case 3: res = coords.zyx; break;"
287 << " case 2: coords = coords.yzwx;"
288 << " default: res = vec3(coords);"
291 makeSwitchCases("conditional_fall_through", "Fall-through",
293 << "highp vec4 tmp = coords;"
294 << "switch (${CONDITION})"
296 << " case 0: res = coords.xyz; break;"
297 << " case 1: res = coords.wzy; break;"
299 << " tmp = coords.yzwx;"
301 << " res = vec3(tmp);"
302 << " if (${CONDITION} != 3)"
304 << " default: res = tmp.zyx; break;"
307 makeSwitchCases("conditional_fall_through_2", "Fall-through",
309 << "highp vec4 tmp = coords;"
310 << "mediump int c = ${CONDITION};"
313 << " case 0: res = coords.xyz; break;"
314 << " case 1: res = coords.wzy; break;"
316 << " c += ${CONDITION};"
317 << " tmp = coords.yzwx;"
319 << " res = vec3(tmp);"
322 << " default: res = tmp.zyx; break;"
325 makeSwitchCases("scope", "Basic switch statement usage",
327 << "switch (${CONDITION})"
329 << " case 0: res = coords.xyz; break;"
330 << " case 1: res = coords.wzy; break;"
333 << " mediump vec3 t = coords.yzw;"
337 << " case 3: res = coords.zyx; break;"
340 makeSwitchCases("switch_in_if", "Switch in for loop",
342 << "if (${CONDITION} >= 0)"
344 << " switch (${CONDITION})"
346 << " case 0: res = coords.xyz; break;"
347 << " case 1: res = coords.wzy; break;"
348 << " case 2: res = coords.yzw; break;"
349 << " case 3: res = coords.zyx; break;"
353 makeSwitchCases("switch_in_for_loop", "Switch in for loop",
355 << "for (int i = 0; i <= ${CONDITION}; i++)"
359 << " case 0: res = coords.xyz; break;"
360 << " case 1: res = coords.wzy; break;"
361 << " case 2: res = coords.yzw; break;"
362 << " case 3: res = coords.zyx; break;"
367 makeSwitchCases("switch_in_while_loop", "Switch in while loop",
370 << "while (i <= ${CONDITION})"
374 << " case 0: res = coords.xyz; break;"
375 << " case 1: res = coords.wzy; break;"
376 << " case 2: res = coords.yzw; break;"
377 << " case 3: res = coords.zyx; break;"
382 makeSwitchCases("switch_in_do_while_loop", "Switch in do-while loop",
389 << " case 0: res = coords.xyz; break;"
390 << " case 1: res = coords.wzy; break;"
391 << " case 2: res = coords.yzw; break;"
392 << " case 3: res = coords.zyx; break;"
395 << "} while (i <= ${CONDITION});");
397 makeSwitchCases("if_in_switch", "Basic switch statement usage",
399 << "switch (${CONDITION})"
401 << " case 0: res = coords.xyz; break;"
402 << " case 1: res = coords.wzy; break;"
404 << " if (${CONDITION} == 2)"
405 << " res = coords.yzw;"
407 << " res = coords.zyx;"
411 makeSwitchCases("for_loop_in_switch", "Basic switch statement usage",
413 << "switch (${CONDITION})"
415 << " case 0: res = coords.xyz; break;"
419 << " highp vec3 t = coords.yzw;"
420 << " for (int i = 0; i < ${CONDITION}; i++)"
425 << " default: res = coords.zyx; break;"
428 makeSwitchCases("while_loop_in_switch", "Basic switch statement usage",
430 << "switch (${CONDITION})"
432 << " case 0: res = coords.xyz; break;"
436 << " highp vec3 t = coords.yzw;"
438 << " while (i < ${CONDITION})"
446 << " default: res = coords.zyx; break;"
449 makeSwitchCases("do_while_loop_in_switch", "Basic switch statement usage",
451 << "switch (${CONDITION})"
453 << " case 0: res = coords.xyz; break;"
457 << " highp vec3 t = coords.yzw;"
463 << " } while (i < ${CONDITION});"
467 << " default: res = coords.zyx; break;"
470 makeSwitchCases("switch_in_switch", "Basic switch statement usage",
472 << "switch (${CONDITION})"
474 << " case 0: res = coords.xyz; break;"
477 << " switch (${CONDITION} - 1)"
479 << " case 0: res = coords.wzy; break;"
480 << " case 1: res = coords.yzw; break;"
483 << " default: res = coords.zyx; break;"
489 tcu::TestCaseGroup* createSwitchTests (tcu::TestContext& testCtx)
491 return new ShaderSwitchTests(testCtx);