Fix missing dependency on sparse binds
[platform/upstream/VK-GL-CTS.git] / external / vulkancts / modules / vulkan / shaderrender / vktShaderRenderReturnTests.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 return statement tests.
24  *//*--------------------------------------------------------------------*/
25
26 #include "vktShaderRenderReturnTests.hpp"
27 #include "vktShaderRender.hpp"
28 #include "tcuStringTemplate.hpp"
29
30 #include <map>
31 #include <string>
32
33 namespace vkt
34 {
35 namespace sr
36 {
37 namespace
38 {
39
40 enum ReturnMode
41 {
42         RETURNMODE_ALWAYS = 0,
43         RETURNMODE_NEVER,
44         RETURNMODE_DYNAMIC,
45
46         RETURNMODE_LAST
47 };
48
49 // Evaluation functions
50 inline void evalReturnAlways    (ShaderEvalContext& c) { c.color.xyz() = c.coords.swizzle(0,1,2); }
51 inline void evalReturnNever             (ShaderEvalContext& c) { c.color.xyz() = c.coords.swizzle(3,2,1); }
52 inline void evalReturnDynamic   (ShaderEvalContext& c) { c.color.xyz() = (c.coords.x()+c.coords.y() >= 0.0f) ? c.coords.swizzle(0,1,2) : c.coords.swizzle(3,2,1); }
53
54 static ShaderEvalFunc getEvalFunc (ReturnMode mode)
55 {
56         switch (mode)
57         {
58                 case RETURNMODE_ALWAYS:         return evalReturnAlways;
59                 case RETURNMODE_NEVER:          return evalReturnNever;
60                 case RETURNMODE_DYNAMIC:        return evalReturnDynamic;
61                 default:
62                         DE_ASSERT(DE_FALSE);
63                         return (ShaderEvalFunc)DE_NULL;
64         }
65 }
66
67 class ShaderReturnCase : public ShaderRenderCase
68 {
69 public:
70                                                                 ShaderReturnCase                (tcu::TestContext&                      testCtx,
71                                                                                                                  const std::string&                     name,
72                                                                                                                  const std::string&                     description,
73                                                                                                                  bool                                           isVertexCase,
74                                                                                                                  const std::string&                     shaderSource,
75                                                                                                                  const ShaderEvalFunc           evalFunc,
76                                                                                                                  const UniformSetup*            uniformFunc);
77         virtual                                         ~ShaderReturnCase               (void);
78 };
79
80 ShaderReturnCase::ShaderReturnCase (tcu::TestContext&                   testCtx,
81                                                                         const std::string&                      name,
82                                                                         const std::string&                      description,
83                                                                         bool                                            isVertexCase,
84                                                                         const std::string&                      shaderSource,
85                                                                         const ShaderEvalFunc            evalFunc,
86                                                                         const UniformSetup*                     uniformFunc)
87         : ShaderRenderCase(testCtx, name, description, isVertexCase, evalFunc, uniformFunc, DE_NULL)
88 {
89         if (isVertexCase)
90         {
91                 m_vertShaderSource = shaderSource;
92                 m_fragShaderSource =
93                         "#version 310 es\n"
94                         "layout(location = 0) in mediump vec4 v_color;\n"
95                         "layout(location = 0) out mediump vec4 o_color;\n\n"
96                         "void main (void)\n"
97                         "{\n"
98                         "    o_color = v_color;\n"
99                         "}\n";
100         }
101         else
102         {
103                 m_fragShaderSource = shaderSource;
104                 m_vertShaderSource =
105                         "#version 310 es\n"
106                         "layout(location = 0) in  highp   vec4 a_position;\n"
107                         "layout(location = 1) in  highp   vec4 a_coords;\n"
108                         "layout(location = 0) out mediump vec4 v_coords;\n\n"
109                         "void main (void)\n"
110                         "{\n"
111                         "    gl_Position = a_position;\n"
112                         "    v_coords = a_coords;\n"
113                         "}\n";
114         }
115 }
116
117 ShaderReturnCase::~ShaderReturnCase (void)
118 {
119 }
120
121 class ReturnTestUniformSetup : public UniformSetup
122 {
123 public:
124                                                                 ReturnTestUniformSetup  (const BaseUniformType uniformType)
125                                                                         : m_uniformType(uniformType)
126                                                                 {}
127         virtual void                            setup                                   (ShaderRenderCaseInstance& instance, const tcu::Vec4&) const
128                                                                 {
129                                                                         instance.useUniform(0u, m_uniformType);
130                                                                 }
131
132 private:
133         const BaseUniformType           m_uniformType;
134 };
135
136 // Test case builders.
137
138 de::MovePtr<ShaderReturnCase> makeConditionalReturnInFuncCase (tcu::TestContext& context, const std::string& name, const std::string& description, ReturnMode returnMode, bool isVertex)
139 {
140         tcu::StringTemplate tmpl(
141                 "#version 310 es\n"
142                 "layout(location = ${COORDLOC}) in ${COORDPREC} vec4 ${COORDS};\n"
143                 "${EXTRADECL}\n"
144                 "${COORDPREC} vec4 getColor (void)\n"
145                 "{\n"
146                 "    if (${RETURNCOND})\n"
147                 "        return vec4(${COORDS}.xyz, 1.0);\n"
148                 "    return vec4(${COORDS}.wzy, 1.0);\n"
149                 "}\n\n"
150                 "void main (void)\n"
151                 "{\n"
152                 "${POSITIONWRITE}"
153                 "    ${OUTPUT} = getColor();\n"
154                 "}\n");
155
156         const char* coords = isVertex ? "a_coords" : "v_coords";
157
158         std::map<std::string, std::string> params;
159
160         params["COORDLOC"]              = isVertex ? "1"                        : "0";
161         params["COORDPREC"]             = isVertex ? "highp"            : "mediump";
162         params["OUTPUT"]                = isVertex ? "v_color"          : "o_color";
163         params["COORDS"]                = coords;
164         params["EXTRADECL"]             = isVertex ? "layout(location = 0) in highp vec4 a_position;\nlayout(location = 0) out mediump vec4 v_color;\n" : "layout(location = 0) out mediump vec4 o_color;\n";
165         params["POSITIONWRITE"] = isVertex ? "    gl_Position = a_position;\n" : "";
166
167         switch (returnMode)
168         {
169                 case RETURNMODE_ALWAYS:         params["RETURNCOND"] = "true";                                                                                  break;
170                 case RETURNMODE_NEVER:          params["RETURNCOND"] = "false";                                                                                 break;
171                 case RETURNMODE_DYNAMIC:        params["RETURNCOND"] = std::string(coords) + ".x+" + coords + ".y >= 0.0";      break;
172                 default:                                        DE_ASSERT(DE_FALSE);
173         }
174
175         return de::MovePtr<ShaderReturnCase>(new ShaderReturnCase(context, name, description, isVertex, tmpl.specialize(params), getEvalFunc(returnMode), DE_NULL));
176 }
177
178 de::MovePtr<ShaderReturnCase> makeOutputWriteReturnCase (tcu::TestContext& context, const std::string& name, const std::string& description, bool inFunction, ReturnMode returnMode, bool isVertex)
179 {
180         tcu::StringTemplate tmpl(
181                 inFunction
182                 ?
183                         "#version 310 es\n"
184                         "layout(location = ${COORDLOC}) in ${COORDPREC} vec4 ${COORDS};\n"
185                         "${EXTRADECL}\n"
186                         "void myfunc (void)\n"
187                         "{\n"
188                         "    ${OUTPUT} = vec4(${COORDS}.xyz, 1.0);\n"
189                         "    if (${RETURNCOND})\n"
190                         "        return;\n"
191                         "    ${OUTPUT} = vec4(${COORDS}.wzy, 1.0);\n"
192                         "}\n\n"
193                         "void main (void)\n"
194                         "{\n"
195                         "${POSITIONWRITE}"
196                         "    myfunc();\n"
197                         "}\n"
198                 :
199                         "#version 310 es\n"
200                         "layout(location = ${COORDLOC}) in ${COORDPREC} vec4 ${COORDS};\n"
201                         "${EXTRADECL}\n"
202                         "void main ()\n"
203                         "{\n"
204                         "${POSITIONWRITE}"
205                         "    ${OUTPUT} = vec4(${COORDS}.xyz, 1.0);\n"
206                         "    if (${RETURNCOND})\n"
207                         "        return;\n"
208                         "    ${OUTPUT} = vec4(${COORDS}.wzy, 1.0);\n"
209                         "}\n");
210
211         const char* coords = isVertex ? "a_coords" : "v_coords";
212
213         std::map<std::string, std::string> params;
214
215         params["COORDLOC"]              = isVertex ? "1"                        : "0";
216         params["COORDPREC"]             = isVertex ? "highp"            : "mediump";
217         params["COORDS"]                = coords;
218         params["OUTPUT"]                = isVertex ? "v_color"          : "o_color";
219         params["EXTRADECL"]             = isVertex ? "layout(location = 0) in highp vec4 a_position;\nlayout(location = 0) out mediump vec4 v_color;\n" : "layout(location = 0) out mediump vec4 o_color;\n";
220         params["POSITIONWRITE"] = isVertex ? "    gl_Position = a_position;\n" : "";
221
222         switch (returnMode)
223         {
224                 case RETURNMODE_ALWAYS:         params["RETURNCOND"] = "true";                                                                                  break;
225                 case RETURNMODE_NEVER:          params["RETURNCOND"] = "false";                                                                                 break;
226                 case RETURNMODE_DYNAMIC:        params["RETURNCOND"] = std::string(coords) + ".x+" + coords + ".y >= 0.0";      break;
227                 default:                                        DE_ASSERT(DE_FALSE);
228         }
229
230         return de::MovePtr<ShaderReturnCase>(new ShaderReturnCase(context, name, description, isVertex, tmpl.specialize(params), getEvalFunc(returnMode), DE_NULL));
231 }
232
233 de::MovePtr<ShaderReturnCase> makeReturnInLoopCase (tcu::TestContext& context, const std::string& name, const std::string& description, bool isDynamicLoop, ReturnMode returnMode, bool isVertex)
234 {
235         tcu::StringTemplate tmpl(
236                 "#version 310 es\n"
237                 "layout(location = ${COORDLOC}) in ${COORDPREC} vec4 ${COORDS};\n"
238                 "layout(binding = 0, std140) uniform something { mediump int ui_one; };\n"
239                 "${EXTRADECL}\n"
240                 "${COORDPREC} vec4 getCoords (void)\n"
241                 "{\n"
242                 "    ${COORDPREC} vec4 coords = ${COORDS};\n"
243                 "    for (int i = 0; i < ${ITERLIMIT}; i++)\n"
244                 "    {\n"
245                 "        if (${RETURNCOND})\n"
246                 "            return coords;\n"
247                 "        coords = coords.wzyx;\n"
248                 "    }\n"
249                 "    return coords;\n"
250                 "}\n\n"
251                 "void main (void)\n"
252                 "{\n"
253                 "${POSITIONWRITE}"
254                 "    ${OUTPUT} = vec4(getCoords().xyz, 1.0);\n"
255                 "}\n");
256
257         const char* coords = isVertex ? "a_coords" : "v_coords";
258
259         std::map<std::string, std::string> params;
260
261         params["COORDLOC"]              = isVertex ? "1"                        : "0";
262         params["COORDPREC"]             = isVertex ? "highp"            : "mediump";
263         params["OUTPUT"]                = isVertex ? "v_color"          : "o_color";
264         params["COORDS"]                = coords;
265         params["EXTRADECL"]             = isVertex ? "layout(location = 0) in highp vec4 a_position;\nlayout(location = 0) out mediump vec4 v_color;\n" : "layout(location = 0) out mediump vec4 o_color;\n";
266         params["POSITIONWRITE"] = isVertex ? "    gl_Position = a_position;\n" : "";
267         params["ITERLIMIT"]             = isDynamicLoop ? "ui_one" : "1";
268
269         switch (returnMode)
270         {
271                 case RETURNMODE_ALWAYS:         params["RETURNCOND"] = "true";                                                                                  break;
272                 case RETURNMODE_NEVER:          params["RETURNCOND"] = "false";                                                                                 break;
273                 case RETURNMODE_DYNAMIC:        params["RETURNCOND"] = std::string(coords) + ".x+" + coords + ".y >= 0.0";      break;
274                 default:                                        DE_ASSERT(DE_FALSE);
275         }
276
277         return de::MovePtr<ShaderReturnCase>(new ShaderReturnCase(context, name, description, isVertex, tmpl.specialize(params), getEvalFunc(returnMode), new ReturnTestUniformSetup(UI_ONE)));
278 }
279
280 static const char* getReturnModeName (ReturnMode mode)
281 {
282         switch (mode)
283         {
284                 case RETURNMODE_ALWAYS:         return "always";
285                 case RETURNMODE_NEVER:          return "never";
286                 case RETURNMODE_DYNAMIC:        return "dynamic";
287                 default:
288                         DE_ASSERT(DE_FALSE);
289                         return DE_NULL;
290         }
291 }
292
293 static const char* getReturnModeDesc (ReturnMode mode)
294 {
295         switch (mode)
296         {
297                 case RETURNMODE_ALWAYS:         return "Always return";
298                 case RETURNMODE_NEVER:          return "Never return";
299                 case RETURNMODE_DYNAMIC:        return "Return based on coords";
300                 default:
301                         DE_ASSERT(DE_FALSE);
302                         return DE_NULL;
303         }
304 }
305
306 class ShaderReturnTests : public tcu::TestCaseGroup
307 {
308 public:
309                                                         ShaderReturnTests               (tcu::TestContext& context);
310         virtual                                 ~ShaderReturnTests              (void);
311         virtual void                    init                                    (void);
312
313 private:
314                                                         ShaderReturnTests               (const ShaderReturnTests&);             // not allowed!
315         ShaderReturnTests&              operator=                               (const ShaderReturnTests&);             // not allowed!
316 };
317
318 ShaderReturnTests::ShaderReturnTests (tcu::TestContext& context)
319         : TestCaseGroup(context, "return", "Return Statement Tests")
320 {
321 }
322
323 ShaderReturnTests::~ShaderReturnTests (void)
324 {
325 }
326
327 void ShaderReturnTests::init (void)
328 {
329         addChild(new ShaderReturnCase(m_testCtx, "single_return_vertex", "Single return statement in function", true,
330                 "#version 310 es\n"
331                 "layout(location = 0) in highp vec4 a_position;\n"
332                 "layout(location = 1) in highp vec4 a_coords;\n"
333                 "layout(location = 0) out mediump vec4 v_color;\n\n"
334                 "vec4 getColor (void)\n"
335                 "{\n"
336                 "    return vec4(a_coords.xyz, 1.0);\n"
337                 "}\n\n"
338                 "void main (void)\n"
339                 "{\n"
340                 "    gl_Position = a_position;\n"
341                 "    v_color = getColor();\n"
342                 "}\n", evalReturnAlways, DE_NULL));
343         addChild(new ShaderReturnCase(m_testCtx, "single_return_fragment", "Single return statement in function", false,
344                 "#version 310 es\n"
345                 "layout(location = 0) in mediump vec4 v_coords;\n"
346                 "layout(location = 0) out mediump vec4 o_color;\n"
347                 "mediump vec4 getColor (void)\n"
348                 "{\n"
349                 "    return vec4(v_coords.xyz, 1.0);\n"
350                 "}\n\n"
351                 "void main (void)\n"
352                 "{\n"
353                 "    o_color = getColor();\n"
354                 "}\n", evalReturnAlways, DE_NULL));
355
356         // Conditional return statement in function.
357         for (int returnMode = 0; returnMode < RETURNMODE_LAST; returnMode++)
358         {
359                 for (int isFragment = 0; isFragment < 2; isFragment++)
360                 {
361                         std::string                                             name            = std::string("conditional_return_") + getReturnModeName((ReturnMode)returnMode) + (isFragment ? "_fragment" : "_vertex");
362                         std::string                                             description     = std::string(getReturnModeDesc((ReturnMode)returnMode)) + " in function";
363                         de::MovePtr<ShaderReturnCase>   testCase        (makeConditionalReturnInFuncCase(m_testCtx, name, description, (ReturnMode)returnMode, isFragment == 0));
364                         addChild(testCase.release());
365                 }
366         }
367
368         // Unconditional double return in function.
369         addChild(new ShaderReturnCase(m_testCtx, "double_return_vertex", "Unconditional double return in function", true,
370                 "#version 310 es\n"
371                 "layout(location = 0) in highp vec4 a_position;\n"
372                 "layout(location = 1) in highp vec4 a_coords;\n"
373                 "layout(location = 0) out mediump vec4 v_color;\n\n"
374                 "vec4 getColor (void)\n"
375                 "{\n"
376                 "    return vec4(a_coords.xyz, 1.0);\n"
377                 "    return vec4(a_coords.wzy, 1.0);\n"
378                 "}\n\n"
379                 "void main (void)\n"
380                 "{\n"
381                 "    gl_Position = a_position;\n"
382                 "    v_color = getColor();\n"
383                 "}\n", evalReturnAlways, DE_NULL));
384         addChild(new ShaderReturnCase(m_testCtx, "double_return_fragment", "Unconditional double return in function", false,
385                 "#version 310 es\n"
386                 "layout(location = 0) in mediump vec4 v_coords;\n"
387                 "layout(location = 0) out mediump vec4 o_color;\n\n"
388                 "mediump vec4 getColor (void)\n"
389                 "{\n"
390                 "    return vec4(v_coords.xyz, 1.0);\n"
391                 "    return vec4(v_coords.wzy, 1.0);\n"
392                 "}\n\n"
393                 "void main (void)\n"
394                 "{\n"
395                 "    o_color = getColor();\n"
396                 "}\n", evalReturnAlways, DE_NULL));
397
398         // Last statement in main.
399         addChild(new ShaderReturnCase(m_testCtx, "last_statement_in_main_vertex", "Return as a final statement in main()", true,
400                 "#version 310 es\n"
401                 "layout(location = 0) in highp vec4 a_position;\n"
402                 "layout(location = 1) in highp vec4 a_coords;\n"
403                 "layout(location = 0) out mediump vec4 v_color;\n\n"
404                 "void main (void)\n"
405                 "{\n"
406                 "    gl_Position = a_position;\n"
407                 "    v_color = vec4(a_coords.xyz, 1.0);\n"
408                 "    return;\n"
409                 "}\n", evalReturnAlways, DE_NULL));
410         addChild(new ShaderReturnCase(m_testCtx, "last_statement_in_main_fragment", "Return as a final statement in main()", false,
411                 "#version 310 es\n"
412                 "layout(location = 0) in mediump vec4 v_coords;\n"
413                 "layout(location = 0) out mediump vec4 o_color;\n\n"
414                 "void main (void)\n"
415                 "{\n"
416                 "    o_color = vec4(v_coords.xyz, 1.0);\n"
417                 "    return;\n"
418                 "}\n", evalReturnAlways, DE_NULL));
419
420         // Return between output variable writes.
421         for (int inFunc = 0; inFunc < 2; inFunc++)
422         {
423                 for (int returnMode = 0; returnMode < RETURNMODE_LAST; returnMode++)
424                 {
425                         for (int isFragment = 0; isFragment < 2; isFragment++)
426                         {
427                                 std::string                                             name            = std::string("output_write_") + (inFunc ? "in_func_" : "") + getReturnModeName((ReturnMode)returnMode) + (isFragment ? "_fragment" : "_vertex");
428                                 std::string                                             desc            = std::string(getReturnModeDesc((ReturnMode)returnMode)) + (inFunc ? " in user-defined function" : " in main()") + " between output writes";
429                                 de::MovePtr<ShaderReturnCase>   testCase        = (makeOutputWriteReturnCase(m_testCtx, name, desc, inFunc != 0, (ReturnMode)returnMode, isFragment == 0));
430                                 addChild(testCase.release());
431                         }
432                 }
433         }
434
435         // Conditional return statement in loop.
436         for (int isDynamicLoop = 0; isDynamicLoop < 2; isDynamicLoop++)
437         {
438                 for (int returnMode = 0; returnMode < RETURNMODE_LAST; returnMode++)
439                 {
440                         for (int isFragment = 0; isFragment < 2; isFragment++)
441                         {
442                                 std::string                                             name            = std::string("return_in_") + (isDynamicLoop ? "dynamic" : "static") + "_loop_" + getReturnModeName((ReturnMode)returnMode) + (isFragment ? "_fragment" : "_vertex");
443                                 std::string                                             description     = std::string(getReturnModeDesc((ReturnMode)returnMode)) + " in loop";
444                                 de::MovePtr<ShaderReturnCase>   testCase        (makeReturnInLoopCase(m_testCtx, name, description, isDynamicLoop != 0, (ReturnMode)returnMode, isFragment == 0));
445                                 addChild(testCase.release());
446                         }
447                 }
448         }
449
450         // Unconditional return in infinite loop.
451         addChild(new ShaderReturnCase(m_testCtx, "return_in_infinite_loop_vertex", "Return in infinite loop", true,
452                 "#version 310 es\n"
453                 "layout(location = 0) in highp vec4 a_position;\n"
454                 "layout(location = 1) in highp vec4 a_coords;\n"
455                 "layout(location = 0) out mediump vec4 v_color;\n"
456                 "layout(binding = 0, std140) uniform something { int ui_zero; };\n"
457                 "highp vec4 getCoords (void)\n"
458                 "{\n"
459                 "       for (int i = 1; i < 10; i += ui_zero)\n"
460                 "               return a_coords;\n"
461                 "       return a_coords.wzyx;\n"
462                 "}\n\n"
463                 "void main (void)\n"
464                 "{\n"
465                 "    gl_Position = a_position;\n"
466                 "    v_color = vec4(getCoords().xyz, 1.0);\n"
467                 "    return;\n"
468                 "}\n", evalReturnAlways, new ReturnTestUniformSetup(UI_ZERO)));
469         addChild(new ShaderReturnCase(m_testCtx, "return_in_infinite_loop_fragment", "Return in infinite loop", false,
470                 "#version 310 es\n"
471                 "layout(location = 0) in mediump vec4 v_coords;\n"
472                 "layout(location = 0) out mediump vec4 o_color;\n"
473                 "layout(binding = 0, std140) uniform something { int ui_zero; };\n\n"
474                 "mediump vec4 getCoords (void)\n"
475                 "{\n"
476                 "       for (int i = 1; i < 10; i += ui_zero)\n"
477                 "               return v_coords;\n"
478                 "       return v_coords.wzyx;\n"
479                 "}\n\n"
480                 "void main (void)\n"
481                 "{\n"
482                 "    o_color = vec4(getCoords().xyz, 1.0);\n"
483                 "    return;\n"
484                 "}\n", evalReturnAlways, new ReturnTestUniformSetup(UI_ZERO)));
485 }
486
487 } // anonymous
488
489 tcu::TestCaseGroup* createReturnTests (tcu::TestContext& testCtx)
490 {
491         return new ShaderReturnTests(testCtx);
492 }
493
494 } // sr
495 } // vkt