Merge vk-gl-cts/opengl-es-cts-3.2.3 into vk-gl-cts/opengl-es-cts-3.2.4
[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);
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)
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                 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());
207         }
208 }
209
210 void ShaderSwitchTests::init (void)
211 {
212         // Expected swizzles:
213         // 0: xyz
214         // 1: wzy
215         // 2: yzw
216         // 3: zyx
217
218         makeSwitchCases("basic", "Basic switch statement usage",
219                 LineStream(1)
220                 << "switch (${CONDITION})"
221                 << "{"
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;"
226                 << "}");
227
228         makeSwitchCases("const_expr_in_label", "Constant expression in label",
229                 LineStream(1)
230                 << "const int t = 2;"
231                 << "switch (${CONDITION})"
232                 << "{"
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;"
237                 << "}");
238
239         makeSwitchCases("default_label", "Default label usage",
240                 LineStream(1)
241                 << "switch (${CONDITION})"
242                 << "{"
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;"
247                 << "}");
248
249         makeSwitchCases("default_not_last", "Default label usage",
250                 LineStream(1)
251                 << "switch (${CONDITION})"
252                 << "{"
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;"
257                 << "}");
258
259         makeSwitchCases("no_default_label", "No match in switch without default label",
260                 LineStream(1)
261                 << "res = coords.yzw;\n"
262                 << "switch (${CONDITION})"
263                 << "{"
264                 << "    case 0:         res = coords.xyz;       break;"
265                 << "    case 1:         res = coords.wzy;       break;"
266                 << "    case 3:         res = coords.zyx;       break;"
267                 << "}");
268
269         makeSwitchCases("fall_through", "Fall-through",
270                 LineStream(1)
271                 << "switch (${CONDITION})"
272                 << "{"
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;"
278                 << "}");
279
280         makeSwitchCases("fall_through_default", "Fall-through",
281                 LineStream(1)
282                 << "switch (${CONDITION})"
283                 << "{"
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);"
289                 << "}");
290
291         makeSwitchCases("conditional_fall_through", "Fall-through",
292                 LineStream(1)
293                 << "highp vec4 tmp = coords;"
294                 << "switch (${CONDITION})"
295                 << "{"
296                 << "    case 0:         res = coords.xyz;       break;"
297                 << "    case 1:         res = coords.wzy;       break;"
298                 << "    case 2:"
299                 << "            tmp = coords.yzwx;"
300                 << "    case 3:"
301                 << "            res = vec3(tmp);"
302                 << "            if (${CONDITION} != 3)"
303                 << "                    break;"
304                 << "    default:        res = tmp.zyx;          break;"
305                 << "}");
306
307         makeSwitchCases("conditional_fall_through_2", "Fall-through",
308                 LineStream(1)
309                 << "highp vec4 tmp = coords;"
310                 << "mediump int c = ${CONDITION};"
311                 << "switch (c)"
312                 << "{"
313                 << "    case 0:         res = coords.xyz;       break;"
314                 << "    case 1:         res = coords.wzy;       break;"
315                 << "    case 2:"
316                 << "            c += ${CONDITION};"
317                 << "            tmp = coords.yzwx;"
318                 << "    case 3:"
319                 << "            res = vec3(tmp);"
320                 << "            if (c == 4)"
321                 << "                    break;"
322                 << "    default:        res = tmp.zyx;          break;"
323                 << "}");
324
325         makeSwitchCases("scope", "Basic switch statement usage",
326                 LineStream(1)
327                 << "switch (${CONDITION})"
328                 << "{"
329                 << "    case 0:         res = coords.xyz;       break;"
330                 << "    case 1:         res = coords.wzy;       break;"
331                 << "    case 2:"
332                 << "    {"
333                 << "            mediump vec3 t = coords.yzw;"
334                 << "            res = t;"
335                 << "            break;"
336                 << "    }"
337                 << "    case 3:         res = coords.zyx;       break;"
338                 << "}");
339
340         makeSwitchCases("switch_in_if", "Switch in for loop",
341                 LineStream(1)
342                 << "if (${CONDITION} >= 0)"
343                 << "{"
344                 << "    switch (${CONDITION})"
345                 << "    {"
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;"
350                 << "    }"
351                 << "}");
352
353         makeSwitchCases("switch_in_for_loop", "Switch in for loop",
354                 LineStream(1)
355                 << "for (int i = 0; i <= ${CONDITION}; i++)"
356                 << "{"
357                 << "    switch (i)"
358                 << "    {"
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;"
363                 << "    }"
364                 << "}");
365
366
367         makeSwitchCases("switch_in_while_loop", "Switch in while loop",
368                 LineStream(1)
369                 << "int i = 0;"
370                 << "while (i <= ${CONDITION})"
371                 << "{"
372                 << "    switch (i)"
373                 << "    {"
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;"
378                 << "    }"
379                 << "    i += 1;"
380                 << "}");
381
382         makeSwitchCases("switch_in_do_while_loop", "Switch in do-while loop",
383                 LineStream(1)
384                 << "int i = 0;"
385                 << "do"
386                 << "{"
387                 << "    switch (i)"
388                 << "    {"
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;"
393                 << "    }"
394                 << "    i += 1;"
395                 << "} while (i <= ${CONDITION});");
396
397         makeSwitchCases("if_in_switch", "Basic switch statement usage",
398                 LineStream(1)
399                 << "switch (${CONDITION})"
400                 << "{"
401                 << "    case 0:         res = coords.xyz;       break;"
402                 << "    case 1:         res = coords.wzy;       break;"
403                 << "    default:"
404                 << "            if (${CONDITION} == 2)"
405                 << "                    res = coords.yzw;"
406                 << "            else"
407                 << "                    res = coords.zyx;"
408                 << "            break;"
409                 << "}");
410
411         makeSwitchCases("for_loop_in_switch", "Basic switch statement usage",
412                 LineStream(1)
413                 << "switch (${CONDITION})"
414                 << "{"
415                 << "    case 0:         res = coords.xyz;       break;"
416                 << "    case 1:"
417                 << "    case 2:"
418                 << "    {"
419                 << "            highp vec3 t = coords.yzw;"
420                 << "            for (int i = 0; i < ${CONDITION}; i++)"
421                 << "                    t = t.zyx;"
422                 << "            res = t;"
423                 << "            break;"
424                 << "    }"
425                 << "    default:        res = coords.zyx;       break;"
426                 << "}");
427
428         makeSwitchCases("while_loop_in_switch", "Basic switch statement usage",
429                 LineStream(1)
430                 << "switch (${CONDITION})"
431                 << "{"
432                 << "    case 0:         res = coords.xyz;       break;"
433                 << "    case 1:"
434                 << "    case 2:"
435                 << "    {"
436                 << "            highp vec3 t = coords.yzw;"
437                 << "            int i = 0;"
438                 << "            while (i < ${CONDITION})"
439                 << "            {"
440                 << "                    t = t.zyx;"
441                 << "                    i += 1;"
442                 << "            }"
443                 << "            res = t;"
444                 << "            break;"
445                 << "    }"
446                 << "    default:        res = coords.zyx;       break;"
447                 << "}");
448
449         makeSwitchCases("do_while_loop_in_switch", "Basic switch statement usage",
450                 LineStream(1)
451                 << "switch (${CONDITION})"
452                 << "{"
453                 << "    case 0:         res = coords.xyz;       break;"
454                 << "    case 1:"
455                 << "    case 2:"
456                 << "    {"
457                 << "            highp vec3 t = coords.yzw;"
458                 << "            int i = 0;"
459                 << "            do"
460                 << "            {"
461                 << "                    t = t.zyx;"
462                 << "                    i += 1;"
463                 << "            } while (i < ${CONDITION});"
464                 << "            res = t;"
465                 << "            break;"
466                 << "    }"
467                 << "    default:        res = coords.zyx;       break;"
468                 << "}");
469
470         makeSwitchCases("switch_in_switch", "Basic switch statement usage",
471                 LineStream(1)
472                 << "switch (${CONDITION})"
473                 << "{"
474                 << "    case 0:         res = coords.xyz;       break;"
475                 << "    case 1:"
476                 << "    case 2:"
477                 << "            switch (${CONDITION} - 1)"
478                 << "            {"
479                 << "                    case 0:         res = coords.wzy;       break;"
480                 << "                    case 1:         res = coords.yzw;       break;"
481                 << "            }"
482                 << "            break;"
483                 << "    default:        res = coords.zyx;       break;"
484                 << "}");
485 }
486
487 } // anonymous
488
489 tcu::TestCaseGroup* createSwitchTests (tcu::TestContext& testCtx)
490 {
491         return new ShaderSwitchTests(testCtx);
492 }
493
494 } // sr
495 } // vkt