Fix missing dependency on sparse binds
[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  * Copyright (c) 2016 The Android Open Source Project
8  *
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
12  *
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  *
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.
20  *
21  *//*!
22  * \file
23  * \brief Shader switch statement tests.
24  *
25  * Variables:
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  *//*--------------------------------------------------------------------*/
31
32 #include "vktShaderRenderSwitchTests.hpp"
33 #include "vktShaderRender.hpp"
34 #include "tcuStringTemplate.hpp"
35 #include "deMath.h"
36
37 namespace vkt
38 {
39 namespace sr
40 {
41 namespace
42 {
43
44 static void setUniforms(ShaderRenderCaseInstance& instance, const tcu::Vec4&)
45 {
46         instance.useUniform(0u, UI_TWO);
47 }
48
49 using std::string;
50
51 class ShaderSwitchCase : public ShaderRenderCase
52 {
53 public:
54                                                 ShaderSwitchCase                        (tcu::TestContext&      testCtx,
55                                                                                                          const string&          name,
56                                                                                                          const string&          description,
57                                                                                                          bool                           isVertexCase,
58                                                                                                          const string&          vtxSource,
59                                                                                                          const string&          fragSource,
60                                                                                                          ShaderEvalFunc         evalFunc,
61                                                                                                          UniformSetupFunc       setupUniformsFunc);
62         virtual                         ~ShaderSwitchCase                       (void);
63 };
64
65 ShaderSwitchCase::ShaderSwitchCase (tcu::TestContext&   testCtx,
66                                                                         const string&           name,
67                                                                         const string&           description,
68                                                                         bool                            isVertexCase,
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)
74 {
75         m_vertShaderSource      = vtxSource;
76         m_fragShaderSource      = fragSource;
77 }
78
79 ShaderSwitchCase::~ShaderSwitchCase (void)
80 {
81 }
82
83 enum SwitchType
84 {
85         SWITCHTYPE_STATIC = 0,
86         SWITCHTYPE_UNIFORM,
87         SWITCHTYPE_DYNAMIC,
88
89         SWITCHTYPE_LAST
90 };
91
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)
95 {
96         switch (int(deFloatFloor(evalCtx.coords.z()*1.5f + 2.0f)))
97         {
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;
103         }
104 }
105
106 static de::MovePtr<ShaderSwitchCase> makeSwitchCase (tcu::TestContext& testCtx, const string& name, const string& desc, SwitchType type, bool isVertex, const LineStream& switchBody)
107 {
108         std::ostringstream      vtx;
109         std::ostringstream      frag;
110         std::ostringstream&     op              = isVertex ? vtx : frag;
111
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";
117
118         if (isVertex)
119         {
120                 vtx << "layout(location = 0) out mediump vec4 v_color;\n";
121                 frag << "layout(location = 0) in mediump vec4 v_color;\n";
122         }
123         else
124         {
125                 vtx << "layout(location = 0) out highp vec4 v_coords;\n";
126                 frag << "layout(location = 0) in highp vec4 v_coords;\n";
127         }
128
129         if (type == SWITCHTYPE_UNIFORM)
130                 op << "layout (std140, set=0, binding=0) uniform buffer0 { highp int ui_two; };\n";
131
132         vtx << "\n"
133                 << "void main (void)\n"
134                 << "{\n"
135                 << "    gl_Position = a_position;\n";
136         frag << "\n"
137                  << "void main (void)\n"
138                  << "{\n";
139
140         // Setup.
141         op << " highp vec4 coords = " << (isVertex ? "a_coords" : "v_coords") << ";\n";
142         op << " mediump vec3 res = vec3(0.0);\n\n";
143
144         // Switch body.
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))"      : "???";
149
150         op << tcu::StringTemplate(switchBody.str()).specialize(params);
151         op << "\n";
152
153         if (isVertex)
154         {
155                 vtx << "        v_color = vec4(res, 1.0);\n";
156                 frag << "       o_color = v_color;\n";
157         }
158         else
159         {
160                 vtx << "        v_coords = a_coords;\n";
161                 frag << "       o_color = vec4(res, 1.0);\n";
162         }
163
164         vtx << "}\n";
165         frag << "}\n";
166
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));
172 }
173
174 class ShaderSwitchTests : public tcu::TestCaseGroup
175 {
176 public:
177                                                         ShaderSwitchTests               (tcu::TestContext& context);
178         virtual                                 ~ShaderSwitchTests              (void);
179
180         virtual void                    init                                    (void);
181
182 private:
183                                                         ShaderSwitchTests               (const ShaderSwitchTests&);             // not allowed!
184         ShaderSwitchTests&              operator=                               (const ShaderSwitchTests&);             // not allowed!
185
186         void                                    makeSwitchCases                 (const string& name, const string& desc, const LineStream& switchBody, const bool skipDynamicType = false);
187 };
188
189 ShaderSwitchTests::ShaderSwitchTests (tcu::TestContext& testCtx)
190         : tcu::TestCaseGroup (testCtx, "switch", "Switch statement tests")
191 {
192 }
193
194 ShaderSwitchTests::~ShaderSwitchTests (void)
195 {
196 }
197
198 void ShaderSwitchTests::makeSwitchCases (const string& name, const string& desc, const LineStream& switchBody, const bool skipDynamicType)
199 {
200         static const char* switchTypeNames[] = { "static", "uniform", "dynamic" };
201         DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(switchTypeNames) == SWITCHTYPE_LAST);
202
203         for (int type = 0; type < SWITCHTYPE_LAST; type++)
204         {
205                 if (skipDynamicType && (type == SWITCHTYPE_DYNAMIC))
206                         continue;
207
208                 addChild(makeSwitchCase(m_testCtx, (name + "_" + switchTypeNames[type] + "_vertex"),    desc, (SwitchType)type, true,   switchBody).release());
209                 addChild(makeSwitchCase(m_testCtx, (name + "_" + switchTypeNames[type] + "_fragment"),  desc, (SwitchType)type, false,  switchBody).release());
210         }
211 }
212
213 void ShaderSwitchTests::init (void)
214 {
215         // Expected swizzles:
216         // 0: xyz
217         // 1: wzy
218         // 2: yzw
219         // 3: zyx
220
221         makeSwitchCases("basic", "Basic switch statement usage",
222                 LineStream(1)
223                 << "switch (${CONDITION})"
224                 << "{"
225                 << "    case 0:         res = coords.xyz;       break;"
226                 << "    case 1:         res = coords.wzy;       break;"
227                 << "    case 2:         res = coords.yzw;       break;"
228                 << "    case 3:         res = coords.zyx;       break;"
229                 << "}");
230
231         makeSwitchCases("const_expr_in_label", "Constant expression in label",
232                 LineStream(1)
233                 << "const int t = 2;"
234                 << "switch (${CONDITION})"
235                 << "{"
236                 << "    case int(0.0):  res = coords.xyz;       break;"
237                 << "    case 2-1:               res = coords.wzy;       break;"
238                 << "    case 3&(1<<1):  res = coords.yzw;       break;"
239                 << "    case t+1:               res = coords.zyx;       break;"
240                 << "}");
241
242         makeSwitchCases("default_label", "Default label usage",
243                 LineStream(1)
244                 << "switch (${CONDITION})"
245                 << "{"
246                 << "    case 0:         res = coords.xyz;       break;"
247                 << "    case 1:         res = coords.wzy;       break;"
248                 << "    case 3:         res = coords.zyx;       break;"
249                 << "    default:        res = coords.yzw;"
250                 << "}");
251
252         makeSwitchCases("default_not_last", "Default label usage",
253                 LineStream(1)
254                 << "switch (${CONDITION})"
255                 << "{"
256                 << "    case 0:         res = coords.xyz;       break;"
257                 << "    default:        res = coords.yzw;       break;"
258                 << "    case 1:         res = coords.wzy;       break;"
259                 << "    case 3:         res = coords.zyx;       break;"
260                 << "}");
261
262         makeSwitchCases("no_default_label", "No match in switch without default label",
263                 LineStream(1)
264                 << "res = coords.yzw;\n"
265                 << "switch (${CONDITION})"
266                 << "{"
267                 << "    case 0:         res = coords.xyz;       break;"
268                 << "    case 1:         res = coords.wzy;       break;"
269                 << "    case 3:         res = coords.zyx;       break;"
270                 << "}");
271
272         makeSwitchCases("default_only", "Default case only",
273                 LineStream(1)
274                 << "switch (${CONDITION})"
275                 << "{"
276                 << "    default:"
277                 << "            res = coords.yzw;"
278                 << "}", true);
279
280         makeSwitchCases("empty_case_default", "Empty case and default",
281                 LineStream(1)
282                 << "switch (${CONDITION})"
283                 << "{"
284                 << "    case 2:"
285                 << "    default:"
286                 << "            res = coords.yzw;"
287                 << "}", true);
288
289         makeSwitchCases("fall_through", "Fall-through",
290                 LineStream(1)
291                 << "switch (${CONDITION})"
292                 << "{"
293                 << "    case 0:         res = coords.xyz;       break;"
294                 << "    case 1:         res = coords.wzy;       break;"
295                 << "    case 2:         coords = coords.yzwx;"
296                 << "    case 4:         res = vec3(coords);     break;"
297                 << "    case 3:         res = coords.zyx;       break;"
298                 << "}");
299
300         makeSwitchCases("fall_through_default", "Fall-through",
301                 LineStream(1)
302                 << "switch (${CONDITION})"
303                 << "{"
304                 << "    case 0:         res = coords.xyz;       break;"
305                 << "    case 1:         res = coords.wzy;       break;"
306                 << "    case 3:         res = coords.zyx;       break;"
307                 << "    case 2:         coords = coords.yzwx;"
308                 << "    default:        res = vec3(coords);"
309                 << "}");
310
311         makeSwitchCases("conditional_fall_through", "Fall-through",
312                 LineStream(1)
313                 << "highp vec4 tmp = coords;"
314                 << "switch (${CONDITION})"
315                 << "{"
316                 << "    case 0:         res = coords.xyz;       break;"
317                 << "    case 1:         res = coords.wzy;       break;"
318                 << "    case 2:"
319                 << "            tmp = coords.yzwx;"
320                 << "    case 3:"
321                 << "            res = vec3(tmp);"
322                 << "            if (${CONDITION} != 3)"
323                 << "                    break;"
324                 << "    default:        res = tmp.zyx;          break;"
325                 << "}");
326
327         makeSwitchCases("conditional_fall_through_2", "Fall-through",
328                 LineStream(1)
329                 << "highp vec4 tmp = coords;"
330                 << "mediump int c = ${CONDITION};"
331                 << "switch (c)"
332                 << "{"
333                 << "    case 0:         res = coords.xyz;       break;"
334                 << "    case 1:         res = coords.wzy;       break;"
335                 << "    case 2:"
336                 << "            c += ${CONDITION};"
337                 << "            tmp = coords.yzwx;"
338                 << "    case 3:"
339                 << "            res = vec3(tmp);"
340                 << "            if (c == 4)"
341                 << "                    break;"
342                 << "    default:        res = tmp.zyx;          break;"
343                 << "}");
344
345         makeSwitchCases("scope", "Basic switch statement usage",
346                 LineStream(1)
347                 << "switch (${CONDITION})"
348                 << "{"
349                 << "    case 0:         res = coords.xyz;       break;"
350                 << "    case 1:         res = coords.wzy;       break;"
351                 << "    case 2:"
352                 << "    {"
353                 << "            mediump vec3 t = coords.yzw;"
354                 << "            res = t;"
355                 << "            break;"
356                 << "    }"
357                 << "    case 3:         res = coords.zyx;       break;"
358                 << "}");
359
360         makeSwitchCases("switch_in_if", "Switch in for loop",
361                 LineStream(1)
362                 << "if (${CONDITION} >= 0)"
363                 << "{"
364                 << "    switch (${CONDITION})"
365                 << "    {"
366                 << "            case 0:         res = coords.xyz;       break;"
367                 << "            case 1:         res = coords.wzy;       break;"
368                 << "            case 2:         res = coords.yzw;       break;"
369                 << "            case 3:         res = coords.zyx;       break;"
370                 << "    }"
371                 << "}");
372
373         makeSwitchCases("switch_in_for_loop", "Switch in for loop",
374                 LineStream(1)
375                 << "for (int i = 0; i <= ${CONDITION}; i++)"
376                 << "{"
377                 << "    switch (i)"
378                 << "    {"
379                 << "            case 0:         res = coords.xyz;       break;"
380                 << "            case 1:         res = coords.wzy;       break;"
381                 << "            case 2:         res = coords.yzw;       break;"
382                 << "            case 3:         res = coords.zyx;       break;"
383                 << "    }"
384                 << "}");
385
386
387         makeSwitchCases("switch_in_while_loop", "Switch in while loop",
388                 LineStream(1)
389                 << "int i = 0;"
390                 << "while (i <= ${CONDITION})"
391                 << "{"
392                 << "    switch (i)"
393                 << "    {"
394                 << "            case 0:         res = coords.xyz;       break;"
395                 << "            case 1:         res = coords.wzy;       break;"
396                 << "            case 2:         res = coords.yzw;       break;"
397                 << "            case 3:         res = coords.zyx;       break;"
398                 << "    }"
399                 << "    i += 1;"
400                 << "}");
401
402         makeSwitchCases("switch_in_do_while_loop", "Switch in do-while loop",
403                 LineStream(1)
404                 << "int i = 0;"
405                 << "do"
406                 << "{"
407                 << "    switch (i)"
408                 << "    {"
409                 << "            case 0:         res = coords.xyz;       break;"
410                 << "            case 1:         res = coords.wzy;       break;"
411                 << "            case 2:         res = coords.yzw;       break;"
412                 << "            case 3:         res = coords.zyx;       break;"
413                 << "    }"
414                 << "    i += 1;"
415                 << "} while (i <= ${CONDITION});");
416
417         makeSwitchCases("if_in_switch", "Basic switch statement usage",
418                 LineStream(1)
419                 << "switch (${CONDITION})"
420                 << "{"
421                 << "    case 0:         res = coords.xyz;       break;"
422                 << "    case 1:         res = coords.wzy;       break;"
423                 << "    default:"
424                 << "            if (${CONDITION} == 2)"
425                 << "                    res = coords.yzw;"
426                 << "            else"
427                 << "                    res = coords.zyx;"
428                 << "            break;"
429                 << "}");
430
431         makeSwitchCases("for_loop_in_switch", "Basic switch statement usage",
432                 LineStream(1)
433                 << "switch (${CONDITION})"
434                 << "{"
435                 << "    case 0:         res = coords.xyz;       break;"
436                 << "    case 1:"
437                 << "    case 2:"
438                 << "    {"
439                 << "            highp vec3 t = coords.yzw;"
440                 << "            for (int i = 0; i < ${CONDITION}; i++)"
441                 << "                    t = t.zyx;"
442                 << "            res = t;"
443                 << "            break;"
444                 << "    }"
445                 << "    default:        res = coords.zyx;       break;"
446                 << "}");
447
448         makeSwitchCases("while_loop_in_switch", "Basic switch statement usage",
449                 LineStream(1)
450                 << "switch (${CONDITION})"
451                 << "{"
452                 << "    case 0:         res = coords.xyz;       break;"
453                 << "    case 1:"
454                 << "    case 2:"
455                 << "    {"
456                 << "            highp vec3 t = coords.yzw;"
457                 << "            int i = 0;"
458                 << "            while (i < ${CONDITION})"
459                 << "            {"
460                 << "                    t = t.zyx;"
461                 << "                    i += 1;"
462                 << "            }"
463                 << "            res = t;"
464                 << "            break;"
465                 << "    }"
466                 << "    default:        res = coords.zyx;       break;"
467                 << "}");
468
469         makeSwitchCases("do_while_loop_in_switch", "Basic switch statement usage",
470                 LineStream(1)
471                 << "switch (${CONDITION})"
472                 << "{"
473                 << "    case 0:         res = coords.xyz;       break;"
474                 << "    case 1:"
475                 << "    case 2:"
476                 << "    {"
477                 << "            highp vec3 t = coords.yzw;"
478                 << "            int i = 0;"
479                 << "            do"
480                 << "            {"
481                 << "                    t = t.zyx;"
482                 << "                    i += 1;"
483                 << "            } while (i < ${CONDITION});"
484                 << "            res = t;"
485                 << "            break;"
486                 << "    }"
487                 << "    default:        res = coords.zyx;       break;"
488                 << "}");
489
490         makeSwitchCases("switch_in_switch", "Basic switch statement usage",
491                 LineStream(1)
492                 << "switch (${CONDITION})"
493                 << "{"
494                 << "    case 0:         res = coords.xyz;       break;"
495                 << "    case 1:"
496                 << "    case 2:"
497                 << "            switch (${CONDITION} - 1)"
498                 << "            {"
499                 << "                    case 0:         res = coords.wzy;       break;"
500                 << "                    case 1:         res = coords.yzw;       break;"
501                 << "            }"
502                 << "            break;"
503                 << "    default:        res = coords.zyx;       break;"
504                 << "}");
505 }
506
507 } // anonymous
508
509 tcu::TestCaseGroup* createSwitchTests (tcu::TestContext& testCtx)
510 {
511         return new ShaderSwitchTests(testCtx);
512 }
513
514 } // sr
515 } // vkt