Merge branch 'jekstrand_renderpass_transfer_bit_fix' into 'master'
[platform/upstream/VK-GL-CTS.git] / external / vulkancts / modules / vulkan / shaderrender / vktShaderRenderSwitchTests.cpp
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2015 The Khronos Group Inc.
6  * Copyright (c) 2015 Samsung Electronics Co., Ltd.
7  *
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:
15  *
16  * The above copyright notice(s) and this permission notice shall be included
17  * in all copies or substantial portions of the Materials.
18  *
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.
22  *
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.
30  *
31  *//*!
32  * \file
33  * \brief Shader switch statement tests.
34  *
35  * Variables:
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  *//*--------------------------------------------------------------------*/
41
42 #include "vktShaderRenderSwitchTests.hpp"
43 #include "vktShaderRender.hpp"
44 #include "tcuStringTemplate.hpp"
45 #include "deMath.h"
46
47 namespace vkt
48 {
49 namespace sr
50 {
51 namespace
52 {
53
54 static void setUniforms(ShaderRenderCaseInstance& instance, const tcu::Vec4&)
55 {
56         instance.useUniform(0u, UI_TWO);
57 }
58
59 using std::string;
60
61 class ShaderSwitchCase : public ShaderRenderCase
62 {
63 public:
64                                                 ShaderSwitchCase                        (tcu::TestContext&      testCtx,
65                                                                                                          const string&          name,
66                                                                                                          const string&          description,
67                                                                                                          bool                           isVertexCase,
68                                                                                                          const string&          vtxSource,
69                                                                                                          const string&          fragSource,
70                                                                                                          ShaderEvalFunc         evalFunc,
71                                                                                                          UniformSetupFunc       setupUniformsFunc);
72         virtual                         ~ShaderSwitchCase                       (void);
73 };
74
75 ShaderSwitchCase::ShaderSwitchCase (tcu::TestContext&   testCtx,
76                                                                         const string&           name,
77                                                                         const string&           description,
78                                                                         bool                            isVertexCase,
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)
84 {
85         m_vertShaderSource      = vtxSource;
86         m_fragShaderSource      = fragSource;
87 }
88
89 ShaderSwitchCase::~ShaderSwitchCase (void)
90 {
91 }
92
93 enum SwitchType
94 {
95         SWITCHTYPE_STATIC = 0,
96         SWITCHTYPE_UNIFORM,
97         SWITCHTYPE_DYNAMIC,
98
99         SWITCHTYPE_LAST
100 };
101
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)
105 {
106         switch (int(deFloatFloor(evalCtx.coords.z()*1.5f + 2.0f)))
107         {
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;
113         }
114 }
115
116 static de::MovePtr<ShaderSwitchCase> makeSwitchCase (tcu::TestContext& testCtx, const string& name, const string& desc, SwitchType type, bool isVertex, const LineStream& switchBody)
117 {
118         std::ostringstream      vtx;
119         std::ostringstream      frag;
120         std::ostringstream&     op              = isVertex ? vtx : frag;
121
122         vtx << "#version 310 es\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 310 es\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";
131
132         if (isVertex)
133         {
134                 vtx << "layout(location = 0) out mediump vec4 v_color;\n";
135                 frag << "layout(location = 0) in mediump vec4 v_color;\n";
136         }
137         else
138         {
139                 vtx << "layout(location = 0) out highp vec4 v_coords;\n";
140                 frag << "layout(location = 0) in highp vec4 v_coords;\n";
141         }
142
143         if (type == SWITCHTYPE_UNIFORM)
144                 op << "layout (std140, set=0, binding=0) uniform buffer0 { highp int ui_two; };\n";
145
146         vtx << "\n"
147                 << "void main (void)\n"
148                 << "{\n"
149                 << "    gl_Position = a_position;\n";
150         frag << "\n"
151                  << "void main (void)\n"
152                  << "{\n";
153
154         // Setup.
155         op << " highp vec4 coords = " << (isVertex ? "a_coords" : "v_coords") << ";\n";
156         op << " mediump vec3 res = vec3(0.0);\n\n";
157
158         // Switch body.
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))"      : "???";
163
164         op << tcu::StringTemplate(switchBody.str()).specialize(params);
165         op << "\n";
166
167         if (isVertex)
168         {
169                 vtx << "        v_color = vec4(res, 1.0);\n";
170                 frag << "       o_color = v_color;\n";
171         }
172         else
173         {
174                 vtx << "        v_coords = a_coords;\n";
175                 frag << "       o_color = vec4(res, 1.0);\n";
176         }
177
178         vtx << "}\n";
179         frag << "}\n";
180
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));
186 }
187
188 class ShaderSwitchTests : public tcu::TestCaseGroup
189 {
190 public:
191                                                         ShaderSwitchTests               (tcu::TestContext& context);
192         virtual                                 ~ShaderSwitchTests              (void);
193
194         virtual void                    init                                    (void);
195
196 private:
197                                                         ShaderSwitchTests               (const ShaderSwitchTests&);             // not allowed!
198         ShaderSwitchTests&              operator=                               (const ShaderSwitchTests&);             // not allowed!
199
200         void                                    makeSwitchCases                 (const string& name, const string& desc, const LineStream& switchBody);
201 };
202
203 ShaderSwitchTests::ShaderSwitchTests (tcu::TestContext& testCtx)
204         : tcu::TestCaseGroup (testCtx, "switch", "Switch statement tests")
205 {
206 }
207
208 ShaderSwitchTests::~ShaderSwitchTests (void)
209 {
210 }
211
212 void ShaderSwitchTests::makeSwitchCases (const string& name, const string& desc, const LineStream& switchBody)
213 {
214         static const char* switchTypeNames[] = { "static", "uniform", "dynamic" };
215         DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(switchTypeNames) == SWITCHTYPE_LAST);
216
217         for (int type = 0; type < SWITCHTYPE_LAST; type++)
218         {
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());
221         }
222 }
223
224 void ShaderSwitchTests::init (void)
225 {
226         // Expected swizzles:
227         // 0: xyz
228         // 1: wzy
229         // 2: yzw
230         // 3: zyx
231
232         makeSwitchCases("basic", "Basic switch statement usage",
233                 LineStream(1)
234                 << "switch (${CONDITION})"
235                 << "{"
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;"
240                 << "}");
241
242         makeSwitchCases("const_expr_in_label", "Constant expression in label",
243                 LineStream(1)
244                 << "const int t = 2;"
245                 << "switch (${CONDITION})"
246                 << "{"
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;"
251                 << "}");
252
253         makeSwitchCases("default_label", "Default label usage",
254                 LineStream(1)
255                 << "switch (${CONDITION})"
256                 << "{"
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;"
261                 << "}");
262
263         makeSwitchCases("default_not_last", "Default label usage",
264                 LineStream(1)
265                 << "switch (${CONDITION})"
266                 << "{"
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;"
271                 << "}");
272
273         makeSwitchCases("no_default_label", "No match in switch without default label",
274                 LineStream(1)
275                 << "res = coords.yzw;\n"
276                 << "switch (${CONDITION})"
277                 << "{"
278                 << "    case 0:         res = coords.xyz;       break;"
279                 << "    case 1:         res = coords.wzy;       break;"
280                 << "    case 3:         res = coords.zyx;       break;"
281                 << "}");
282
283         makeSwitchCases("fall_through", "Fall-through",
284                 LineStream(1)
285                 << "switch (${CONDITION})"
286                 << "{"
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;"
292                 << "}");
293
294         makeSwitchCases("fall_through_default", "Fall-through",
295                 LineStream(1)
296                 << "switch (${CONDITION})"
297                 << "{"
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);"
303                 << "}");
304
305         makeSwitchCases("conditional_fall_through", "Fall-through",
306                 LineStream(1)
307                 << "highp vec4 tmp = coords;"
308                 << "switch (${CONDITION})"
309                 << "{"
310                 << "    case 0:         res = coords.xyz;       break;"
311                 << "    case 1:         res = coords.wzy;       break;"
312                 << "    case 2:"
313                 << "            tmp = coords.yzwx;"
314                 << "    case 3:"
315                 << "            res = vec3(tmp);"
316                 << "            if (${CONDITION} != 3)"
317                 << "                    break;"
318                 << "    default:        res = tmp.zyx;          break;"
319                 << "}");
320
321         makeSwitchCases("conditional_fall_through_2", "Fall-through",
322                 LineStream(1)
323                 << "highp vec4 tmp = coords;"
324                 << "mediump int c = ${CONDITION};"
325                 << "switch (c)"
326                 << "{"
327                 << "    case 0:         res = coords.xyz;       break;"
328                 << "    case 1:         res = coords.wzy;       break;"
329                 << "    case 2:"
330                 << "            c += ${CONDITION};"
331                 << "            tmp = coords.yzwx;"
332                 << "    case 3:"
333                 << "            res = vec3(tmp);"
334                 << "            if (c == 4)"
335                 << "                    break;"
336                 << "    default:        res = tmp.zyx;          break;"
337                 << "}");
338
339         makeSwitchCases("scope", "Basic switch statement usage",
340                 LineStream(1)
341                 << "switch (${CONDITION})"
342                 << "{"
343                 << "    case 0:         res = coords.xyz;       break;"
344                 << "    case 1:         res = coords.wzy;       break;"
345                 << "    case 2:"
346                 << "    {"
347                 << "            mediump vec3 t = coords.yzw;"
348                 << "            res = t;"
349                 << "            break;"
350                 << "    }"
351                 << "    case 3:         res = coords.zyx;       break;"
352                 << "}");
353
354         makeSwitchCases("switch_in_if", "Switch in for loop",
355                 LineStream(1)
356                 << "if (${CONDITION} >= 0)"
357                 << "{"
358                 << "    switch (${CONDITION})"
359                 << "    {"
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;"
364                 << "    }"
365                 << "}");
366
367         makeSwitchCases("switch_in_for_loop", "Switch in for loop",
368                 LineStream(1)
369                 << "for (int i = 0; i <= ${CONDITION}; i++)"
370                 << "{"
371                 << "    switch (i)"
372                 << "    {"
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;"
377                 << "    }"
378                 << "}");
379
380
381         makeSwitchCases("switch_in_while_loop", "Switch in while loop",
382                 LineStream(1)
383                 << "int i = 0;"
384                 << "while (i <= ${CONDITION})"
385                 << "{"
386                 << "    switch (i)"
387                 << "    {"
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;"
392                 << "    }"
393                 << "    i += 1;"
394                 << "}");
395
396         makeSwitchCases("switch_in_do_while_loop", "Switch in do-while loop",
397                 LineStream(1)
398                 << "int i = 0;"
399                 << "do"
400                 << "{"
401                 << "    switch (i)"
402                 << "    {"
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;"
407                 << "    }"
408                 << "    i += 1;"
409                 << "} while (i <= ${CONDITION});");
410
411         makeSwitchCases("if_in_switch", "Basic switch statement usage",
412                 LineStream(1)
413                 << "switch (${CONDITION})"
414                 << "{"
415                 << "    case 0:         res = coords.xyz;       break;"
416                 << "    case 1:         res = coords.wzy;       break;"
417                 << "    default:"
418                 << "            if (${CONDITION} == 2)"
419                 << "                    res = coords.yzw;"
420                 << "            else"
421                 << "                    res = coords.zyx;"
422                 << "            break;"
423                 << "}");
424
425         makeSwitchCases("for_loop_in_switch", "Basic switch statement usage",
426                 LineStream(1)
427                 << "switch (${CONDITION})"
428                 << "{"
429                 << "    case 0:         res = coords.xyz;       break;"
430                 << "    case 1:"
431                 << "    case 2:"
432                 << "    {"
433                 << "            highp vec3 t = coords.yzw;"
434                 << "            for (int i = 0; i < ${CONDITION}; i++)"
435                 << "                    t = t.zyx;"
436                 << "            res = t;"
437                 << "            break;"
438                 << "    }"
439                 << "    default:        res = coords.zyx;       break;"
440                 << "}");
441
442         makeSwitchCases("while_loop_in_switch", "Basic switch statement usage",
443                 LineStream(1)
444                 << "switch (${CONDITION})"
445                 << "{"
446                 << "    case 0:         res = coords.xyz;       break;"
447                 << "    case 1:"
448                 << "    case 2:"
449                 << "    {"
450                 << "            highp vec3 t = coords.yzw;"
451                 << "            int i = 0;"
452                 << "            while (i < ${CONDITION})"
453                 << "            {"
454                 << "                    t = t.zyx;"
455                 << "                    i += 1;"
456                 << "            }"
457                 << "            res = t;"
458                 << "            break;"
459                 << "    }"
460                 << "    default:        res = coords.zyx;       break;"
461                 << "}");
462
463         makeSwitchCases("do_while_loop_in_switch", "Basic switch statement usage",
464                 LineStream(1)
465                 << "switch (${CONDITION})"
466                 << "{"
467                 << "    case 0:         res = coords.xyz;       break;"
468                 << "    case 1:"
469                 << "    case 2:"
470                 << "    {"
471                 << "            highp vec3 t = coords.yzw;"
472                 << "            int i = 0;"
473                 << "            do"
474                 << "            {"
475                 << "                    t = t.zyx;"
476                 << "                    i += 1;"
477                 << "            } while (i < ${CONDITION});"
478                 << "            res = t;"
479                 << "            break;"
480                 << "    }"
481                 << "    default:        res = coords.zyx;       break;"
482                 << "}");
483
484         makeSwitchCases("switch_in_switch", "Basic switch statement usage",
485                 LineStream(1)
486                 << "switch (${CONDITION})"
487                 << "{"
488                 << "    case 0:         res = coords.xyz;       break;"
489                 << "    case 1:"
490                 << "    case 2:"
491                 << "            switch (${CONDITION} - 1)"
492                 << "            {"
493                 << "                    case 0:         res = coords.wzy;       break;"
494                 << "                    case 1:         res = coords.yzw;       break;"
495                 << "            }"
496                 << "            break;"
497                 << "    default:        res = coords.zyx;       break;"
498                 << "}");
499 }
500
501 } // anonymous
502
503 tcu::TestCaseGroup* createSwitchTests (tcu::TestContext& testCtx)
504 {
505         return new ShaderSwitchTests(testCtx);
506 }
507
508 } // sr
509 } // vkt