Add CTS_KHR_no_error test implementation
[platform/upstream/VK-GL-CTS.git] / external / openglcts / modules / common / glcShaderSwitchTests.cpp
1 /*-------------------------------------------------------------------------
2  * OpenGL Conformance Test Suite
3  * -----------------------------
4  *
5  * Copyright (c) 2016 Google Inc.
6  * Copyright (c) 2016 The Khronos Group Inc.
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  */ /*!
21  * \file
22  * \brief Shader switch statement tests.
23  */ /*-------------------------------------------------------------------*/
24
25 #include "glcShaderSwitchTests.hpp"
26 #include "deMath.h"
27 #include "glcShaderLibrary.hpp"
28 #include "glcShaderRenderCase.hpp"
29 #include "tcuStringTemplate.hpp"
30
31 namespace deqp
32 {
33
34 using std::string;
35 using std::map;
36 using std::vector;
37
38 class ShaderSwitchCase : public ShaderRenderCase
39 {
40 public:
41         ShaderSwitchCase(Context& context, const char* name, const char* description, bool isVertexCase,
42                                          const char* vtxSource, const char* fragSource, ShaderEvalFunc evalFunc);
43         virtual ~ShaderSwitchCase(void);
44 };
45
46 ShaderSwitchCase::ShaderSwitchCase(Context& context, const char* name, const char* description, bool isVertexCase,
47                                                                    const char* vtxSource, const char* fragSource, ShaderEvalFunc evalFunc)
48         : ShaderRenderCase(context.getTestContext(), context.getRenderContext(), context.getContextInfo(), name,
49                                            description, isVertexCase, evalFunc)
50 {
51         m_vertShaderSource = vtxSource;
52         m_fragShaderSource = fragSource;
53 }
54
55 ShaderSwitchCase::~ShaderSwitchCase(void)
56 {
57 }
58
59 enum SwitchType
60 {
61         SWITCHTYPE_STATIC = 0,
62         SWITCHTYPE_UNIFORM,
63         SWITCHTYPE_DYNAMIC,
64
65         SWITCHTYPE_LAST
66 };
67
68 static void evalSwitchStatic(ShaderEvalContext& evalCtx)
69 {
70         evalCtx.color.xyz() = evalCtx.coords.swizzle(1, 2, 3);
71 }
72 static void evalSwitchUniform(ShaderEvalContext& evalCtx)
73 {
74         evalCtx.color.xyz() = evalCtx.coords.swizzle(1, 2, 3);
75 }
76 static void evalSwitchDynamic(ShaderEvalContext& evalCtx)
77 {
78         switch (int(deFloatFloor(evalCtx.coords.z() * 1.5f + 2.0f)))
79         {
80         case 0:
81                 evalCtx.color.xyz() = evalCtx.coords.swizzle(0, 1, 2);
82                 break;
83         case 1:
84                 evalCtx.color.xyz() = evalCtx.coords.swizzle(3, 2, 1);
85                 break;
86         case 2:
87                 evalCtx.color.xyz() = evalCtx.coords.swizzle(1, 2, 3);
88                 break;
89         case 3:
90                 evalCtx.color.xyz() = evalCtx.coords.swizzle(2, 1, 0);
91                 break;
92         default:
93                 evalCtx.color.xyz() = evalCtx.coords.swizzle(0, 0, 0);
94                 break;
95         }
96 }
97
98 static tcu::TestCase* makeSwitchCase(Context& context, glu::GLSLVersion glslVersion, const char* name, const char* desc,
99                                                                          SwitchType type, bool isVertex, const LineStream& switchBody)
100 {
101         std::ostringstream  vtx;
102         std::ostringstream  frag;
103         std::ostringstream& op = isVertex ? vtx : frag;
104
105         vtx << glu::getGLSLVersionDeclaration(glslVersion) << "\n"
106                 << "in highp vec4 a_position;\n"
107                 << "in highp vec4 a_coords;\n";
108         frag << glu::getGLSLVersionDeclaration(glslVersion) << "\n"
109                  << "layout(location = 0) out mediump vec4 o_color;\n";
110
111         if (isVertex)
112         {
113                 vtx << "out mediump vec4 v_color;\n";
114                 frag << "in mediump vec4 v_color;\n";
115         }
116         else
117         {
118                 vtx << "out highp vec4 v_coords;\n";
119                 frag << "in highp vec4 v_coords;\n";
120         }
121
122         if (type == SWITCHTYPE_UNIFORM)
123                 op << "uniform highp int ui_two;\n";
124
125         vtx << "\n"
126                 << "void main (void)\n"
127                 << "{\n"
128                 << "    gl_Position = a_position;\n";
129         frag << "\n"
130                  << "void main (void)\n"
131                  << "{\n";
132
133         // Setup.
134         op << " highp vec4 coords = " << (isVertex ? "a_coords" : "v_coords") << ";\n";
135         op << " mediump vec3 res = vec3(0.0);\n\n";
136
137         // Switch body.
138         map<string, string> params;
139         params["CONDITION"] = type == SWITCHTYPE_STATIC ?
140                                                           "2" :
141                                                           type == SWITCHTYPE_UNIFORM ?
142                                                           "ui_two" :
143                                                           type == SWITCHTYPE_DYNAMIC ? "int(floor(coords.z*1.5 + 2.0))" : "???";
144
145         op << tcu::StringTemplate(switchBody.str()).specialize(params).c_str();
146         op << "\n";
147
148         if (isVertex)
149         {
150                 vtx << "    v_color = vec4(res, 1.0);\n";
151                 frag << "   o_color = v_color;\n";
152         }
153         else
154         {
155                 vtx << "    v_coords = a_coords;\n";
156                 frag << "   o_color = vec4(res, 1.0);\n";
157         }
158
159         vtx << "}\n";
160         frag << "}\n";
161
162         return new ShaderSwitchCase(context, name, desc, isVertex, vtx.str().c_str(), frag.str().c_str(),
163                                                                 type == SWITCHTYPE_STATIC ?
164                                                                         evalSwitchStatic :
165                                                                         type == SWITCHTYPE_UNIFORM ?
166                                                                         evalSwitchUniform :
167                                                                         type == SWITCHTYPE_DYNAMIC ? evalSwitchDynamic : (ShaderEvalFunc)DE_NULL);
168 }
169
170 static void makeSwitchCases(TestCaseGroup* group, glu::GLSLVersion glslVersion, const char* name, const char* desc,
171                                                         const LineStream& switchBody)
172 {
173         static const char* switchTypeNames[] = { "static", "uniform", "dynamic" };
174         DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(switchTypeNames) == SWITCHTYPE_LAST);
175
176         for (int type = 0; type < SWITCHTYPE_LAST; type++)
177         {
178                 group->addChild(makeSwitchCase(group->getContext(), glslVersion,
179                                                                            (string(name) + "_" + switchTypeNames[type] + "_vertex").c_str(), desc,
180                                                                            (SwitchType)type, true, switchBody));
181                 group->addChild(makeSwitchCase(group->getContext(), glslVersion,
182                                                                            (string(name) + "_" + switchTypeNames[type] + "_fragment").c_str(), desc,
183                                                                            (SwitchType)type, false, switchBody));
184         }
185 }
186
187 ShaderSwitchTests::ShaderSwitchTests(Context& context, glu::GLSLVersion glslVersion)
188         : TestCaseGroup(context, "switch", "Switch statement tests"), m_glslVersion(glslVersion)
189 {
190         DE_ASSERT(glslVersion == glu::GLSL_VERSION_300_ES || glslVersion == glu::GLSL_VERSION_310_ES ||
191                           glslVersion == glu::GLSL_VERSION_330);
192 }
193
194 ShaderSwitchTests::~ShaderSwitchTests(void)
195 {
196 }
197
198 void ShaderSwitchTests::init(void)
199 {
200         // Expected swizzles:
201         // 0: xyz
202         // 1: wzy
203         // 2: yzw
204         // 3: zyx
205
206         makeSwitchCases(this, m_glslVersion, "basic", "Basic switch statement usage",
207                                         LineStream(1) << "switch (${CONDITION})"
208                                                                   << "{"
209                                                                   << "    case 0:     res = coords.xyz;   break;"
210                                                                   << "    case 1:     res = coords.wzy;   break;"
211                                                                   << "    case 2:     res = coords.yzw;   break;"
212                                                                   << "    case 3:     res = coords.zyx;   break;"
213                                                                   << "}");
214
215         makeSwitchCases(this, m_glslVersion, "const_expr_in_label", "Constant expression in label",
216                                         LineStream(1) << "const int t = 2;"
217                                                                   << "switch (${CONDITION})"
218                                                                   << "{"
219                                                                   << "    case int(0.0):  res = coords.xyz;   break;"
220                                                                   << "    case 2-1:       res = coords.wzy;   break;"
221                                                                   << "    case 3&(1<<1):  res = coords.yzw;   break;"
222                                                                   << "    case t+1:       res = coords.zyx;   break;"
223                                                                   << "}");
224
225         makeSwitchCases(this, m_glslVersion, "default_label", "Default label usage",
226                                         LineStream(1) << "switch (${CONDITION})"
227                                                                   << "{"
228                                                                   << "    case 0:     res = coords.xyz;   break;"
229                                                                   << "    case 1:     res = coords.wzy;   break;"
230                                                                   << "    case 3:     res = coords.zyx;   break;"
231                                                                   << "    default:    res = coords.yzw;"
232                                                                   << "}");
233
234         makeSwitchCases(this, m_glslVersion, "default_not_last", "Default label usage",
235                                         LineStream(1) << "switch (${CONDITION})"
236                                                                   << "{"
237                                                                   << "    case 0:     res = coords.xyz;   break;"
238                                                                   << "    default:    res = coords.yzw;   break;"
239                                                                   << "    case 1:     res = coords.wzy;   break;"
240                                                                   << "    case 3:     res = coords.zyx;   break;"
241                                                                   << "}");
242
243         makeSwitchCases(this, m_glslVersion, "no_default_label", "No match in switch without default label",
244                                         LineStream(1) << "res = coords.yzw;\n"
245                                                                   << "switch (${CONDITION})"
246                                                                   << "{"
247                                                                   << "    case 0:     res = coords.xyz;   break;"
248                                                                   << "    case 1:     res = coords.wzy;   break;"
249                                                                   << "    case 3:     res = coords.zyx;   break;"
250                                                                   << "}");
251
252         makeSwitchCases(this, m_glslVersion, "fall_through", "Fall-through",
253                                         LineStream(1) << "switch (${CONDITION})"
254                                                                   << "{"
255                                                                   << "    case 0:     res = coords.xyz;   break;"
256                                                                   << "    case 1:     res = coords.wzy;   break;"
257                                                                   << "    case 2:     coords = coords.yzwx;"
258                                                                   << "    case 4:     res = vec3(coords); break;"
259                                                                   << "    case 3:     res = coords.zyx;   break;"
260                                                                   << "}");
261
262         makeSwitchCases(this, m_glslVersion, "fall_through_default", "Fall-through",
263                                         LineStream(1) << "switch (${CONDITION})"
264                                                                   << "{"
265                                                                   << "    case 0:     res = coords.xyz;   break;"
266                                                                   << "    case 1:     res = coords.wzy;   break;"
267                                                                   << "    case 3:     res = coords.zyx;   break;"
268                                                                   << "    case 2:     coords = coords.yzwx;"
269                                                                   << "    default:    res = vec3(coords);"
270                                                                   << "}");
271
272         makeSwitchCases(this, m_glslVersion, "conditional_fall_through", "Fall-through",
273                                         LineStream(1) << "highp vec4 tmp = coords;"
274                                                                   << "switch (${CONDITION})"
275                                                                   << "{"
276                                                                   << "    case 0:     res = coords.xyz;   break;"
277                                                                   << "    case 1:     res = coords.wzy;   break;"
278                                                                   << "    case 2:"
279                                                                   << "        tmp = coords.yzwx;"
280                                                                   << "    case 3:"
281                                                                   << "        res = vec3(tmp);"
282                                                                   << "        if (${CONDITION} != 3)"
283                                                                   << "            break;"
284                                                                   << "    default:    res = tmp.zyx;      break;"
285                                                                   << "}");
286
287         makeSwitchCases(this, m_glslVersion, "conditional_fall_through_2", "Fall-through",
288                                         LineStream(1) << "highp vec4 tmp = coords;"
289                                                                   << "mediump int c = ${CONDITION};"
290                                                                   << "switch (c)"
291                                                                   << "{"
292                                                                   << "    case 0:     res = coords.xyz;   break;"
293                                                                   << "    case 1:     res = coords.wzy;   break;"
294                                                                   << "    case 2:"
295                                                                   << "        c += ${CONDITION};"
296                                                                   << "        tmp = coords.yzwx;"
297                                                                   << "    case 3:"
298                                                                   << "        res = vec3(tmp);"
299                                                                   << "        if (c == 4)"
300                                                                   << "            break;"
301                                                                   << "    default:    res = tmp.zyx;      break;"
302                                                                   << "}");
303
304         makeSwitchCases(this, m_glslVersion, "scope", "Basic switch statement usage",
305                                         LineStream(1) << "switch (${CONDITION})"
306                                                                   << "{"
307                                                                   << "    case 0:     res = coords.xyz;   break;"
308                                                                   << "    case 1:     res = coords.wzy;   break;"
309                                                                   << "    case 2:"
310                                                                   << "    {"
311                                                                   << "        mediump vec3 t = coords.yzw;"
312                                                                   << "        res = t;"
313                                                                   << "        break;"
314                                                                   << "    }"
315                                                                   << "    case 3:     res = coords.zyx;   break;"
316                                                                   << "}");
317
318         makeSwitchCases(this, m_glslVersion, "switch_in_if", "Switch in for loop",
319                                         LineStream(1) << "if (${CONDITION} >= 0)"
320                                                                   << "{"
321                                                                   << "    switch (${CONDITION})"
322                                                                   << "    {"
323                                                                   << "        case 0:     res = coords.xyz;   break;"
324                                                                   << "        case 1:     res = coords.wzy;   break;"
325                                                                   << "        case 2:     res = coords.yzw;   break;"
326                                                                   << "        case 3:     res = coords.zyx;   break;"
327                                                                   << "    }"
328                                                                   << "}");
329
330         makeSwitchCases(this, m_glslVersion, "switch_in_for_loop", "Switch in for loop",
331                                         LineStream(1) << "for (int i = 0; i <= ${CONDITION}; i++)"
332                                                                   << "{"
333                                                                   << "    switch (i)"
334                                                                   << "    {"
335                                                                   << "        case 0:     res = coords.xyz;   break;"
336                                                                   << "        case 1:     res = coords.wzy;   break;"
337                                                                   << "        case 2:     res = coords.yzw;   break;"
338                                                                   << "        case 3:     res = coords.zyx;   break;"
339                                                                   << "    }"
340                                                                   << "}");
341
342         makeSwitchCases(this, m_glslVersion, "switch_in_while_loop", "Switch in while loop",
343                                         LineStream(1) << "int i = 0;"
344                                                                   << "while (i <= ${CONDITION})"
345                                                                   << "{"
346                                                                   << "    switch (i)"
347                                                                   << "    {"
348                                                                   << "        case 0:     res = coords.xyz;   break;"
349                                                                   << "        case 1:     res = coords.wzy;   break;"
350                                                                   << "        case 2:     res = coords.yzw;   break;"
351                                                                   << "        case 3:     res = coords.zyx;   break;"
352                                                                   << "    }"
353                                                                   << "    i += 1;"
354                                                                   << "}");
355
356         makeSwitchCases(this, m_glslVersion, "switch_in_do_while_loop", "Switch in do-while loop",
357                                         LineStream(1) << "int i = 0;"
358                                                                   << "do"
359                                                                   << "{"
360                                                                   << "    switch (i)"
361                                                                   << "    {"
362                                                                   << "        case 0:     res = coords.xyz;   break;"
363                                                                   << "        case 1:     res = coords.wzy;   break;"
364                                                                   << "        case 2:     res = coords.yzw;   break;"
365                                                                   << "        case 3:     res = coords.zyx;   break;"
366                                                                   << "    }"
367                                                                   << "    i += 1;"
368                                                                   << "} while (i <= ${CONDITION});");
369
370         makeSwitchCases(this, m_glslVersion, "if_in_switch", "Basic switch statement usage",
371                                         LineStream(1) << "switch (${CONDITION})"
372                                                                   << "{"
373                                                                   << "    case 0:     res = coords.xyz;   break;"
374                                                                   << "    case 1:     res = coords.wzy;   break;"
375                                                                   << "    default:"
376                                                                   << "        if (${CONDITION} == 2)"
377                                                                   << "            res = coords.yzw;"
378                                                                   << "        else"
379                                                                   << "            res = coords.zyx;"
380                                                                   << "        break;"
381                                                                   << "}");
382
383         makeSwitchCases(this, m_glslVersion, "for_loop_in_switch", "Basic switch statement usage",
384                                         LineStream(1) << "switch (${CONDITION})"
385                                                                   << "{"
386                                                                   << "    case 0:     res = coords.xyz;   break;"
387                                                                   << "    case 1:"
388                                                                   << "    case 2:"
389                                                                   << "    {"
390                                                                   << "        highp vec3 t = coords.yzw;"
391                                                                   << "        for (int i = 0; i < ${CONDITION}; i++)"
392                                                                   << "            t = t.zyx;"
393                                                                   << "        res = t;"
394                                                                   << "        break;"
395                                                                   << "    }"
396                                                                   << "    default:    res = coords.zyx;   break;"
397                                                                   << "}");
398
399         makeSwitchCases(this, m_glslVersion, "while_loop_in_switch", "Basic switch statement usage",
400                                         LineStream(1) << "switch (${CONDITION})"
401                                                                   << "{"
402                                                                   << "    case 0:     res = coords.xyz;   break;"
403                                                                   << "    case 1:"
404                                                                   << "    case 2:"
405                                                                   << "    {"
406                                                                   << "        highp vec3 t = coords.yzw;"
407                                                                   << "        int i = 0;"
408                                                                   << "        while (i < ${CONDITION})"
409                                                                   << "        {"
410                                                                   << "            t = t.zyx;"
411                                                                   << "            i += 1;"
412                                                                   << "        }"
413                                                                   << "        res = t;"
414                                                                   << "        break;"
415                                                                   << "    }"
416                                                                   << "    default:    res = coords.zyx;   break;"
417                                                                   << "}");
418
419         makeSwitchCases(this, m_glslVersion, "do_while_loop_in_switch", "Basic switch statement usage",
420                                         LineStream(1) << "switch (${CONDITION})"
421                                                                   << "{"
422                                                                   << "    case 0:     res = coords.xyz;   break;"
423                                                                   << "    case 1:"
424                                                                   << "    case 2:"
425                                                                   << "    {"
426                                                                   << "        highp vec3 t = coords.yzw;"
427                                                                   << "        int i = 0;"
428                                                                   << "        do"
429                                                                   << "        {"
430                                                                   << "            t = t.zyx;"
431                                                                   << "            i += 1;"
432                                                                   << "        } while (i < ${CONDITION});"
433                                                                   << "        res = t;"
434                                                                   << "        break;"
435                                                                   << "    }"
436                                                                   << "    default:    res = coords.zyx;   break;"
437                                                                   << "}");
438
439         makeSwitchCases(this, m_glslVersion, "switch_in_switch", "Basic switch statement usage",
440                                         LineStream(1) << "switch (${CONDITION})"
441                                                                   << "{"
442                                                                   << "    case 0:     res = coords.xyz;   break;"
443                                                                   << "    case 1:"
444                                                                   << "    case 2:"
445                                                                   << "        switch (${CONDITION} - 1)"
446                                                                   << "        {"
447                                                                   << "            case 0:     res = coords.wzy;   break;"
448                                                                   << "            case 1:     res = coords.yzw;   break;"
449                                                                   << "        }"
450                                                                   << "        break;"
451                                                                   << "    default:    res = coords.zyx;   break;"
452                                                                   << "}");
453
454         // Negative cases.
455         {
456                 ShaderLibrary library(m_testCtx, m_context.getRenderContext());
457                 bool              isES3 = m_glslVersion == glu::GLSL_VERSION_300_ES || m_glslVersion == glu::GLSL_VERSION_310_ES;
458                 std::string   path  = "";
459
460                 if (!isES3)
461                 {
462                         path += "gl33/";
463                 }
464                 path += "switch.test";
465                 vector<tcu::TestNode*> negativeCases = library.loadShaderFile(path.c_str());
466
467                 for (vector<tcu::TestNode*>::iterator i = negativeCases.begin(); i != negativeCases.end(); i++)
468                         addChild(*i);
469         }
470 }
471
472 } // deqp