Fix missing dependency on sparse binds
[platform/upstream/VK-GL-CTS.git] / external / vulkancts / modules / vulkan / shaderrender / vktShaderRenderDiscardTests.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 discard statement tests.
24  *//*--------------------------------------------------------------------*/
25
26 #include "vktShaderRenderDiscardTests.hpp"
27 #include "vktShaderRender.hpp"
28 #include "tcuStringTemplate.hpp"
29 #include "gluTexture.hpp"
30
31 #include <string>
32
33 using tcu::StringTemplate;
34
35 namespace vkt
36 {
37 namespace sr
38 {
39 namespace
40 {
41
42 class SamplerUniformSetup : public UniformSetup
43 {
44 public:
45                                                 SamplerUniformSetup                     (bool useSampler)
46                                                         : m_useSampler(useSampler)
47                                                 {}
48
49         virtual void            setup                                            (ShaderRenderCaseInstance& instance, const tcu::Vec4&) const
50                                                 {
51                                                         instance.useUniform(0u, UI_ONE);
52                                                         instance.useUniform(1u, UI_TWO);
53                                                         if (m_useSampler)
54                                                                 instance.useSampler(2u, 0u); // To the uniform binding location 2 bind the texture 0
55                                                 }
56
57 private:
58         const bool                      m_useSampler;
59 };
60
61
62 class ShaderDiscardCaseInstance : public ShaderRenderCaseInstance
63 {
64 public:
65                                                 ShaderDiscardCaseInstance       (Context&                               context,
66                                                                                                         bool                                    isVertexCase,
67                                                                                                         const ShaderEvaluator&  evaluator,
68                                                                                                         const UniformSetup&             uniformSetup,
69                                                                                                         bool                                    usesTexture,
70                                                                                                         bool                                    fuzzyCompare);
71         virtual                         ~ShaderDiscardCaseInstance      (void);
72 };
73
74 ShaderDiscardCaseInstance::ShaderDiscardCaseInstance (Context&                                  context,
75                                                                                                          bool                                           isVertexCase,
76                                                                                                          const ShaderEvaluator&         evaluator,
77                                                                                                          const UniformSetup&            uniformSetup,
78                                                                                                          bool                                           usesTexture,
79                                                                                                          bool                                           fuzzyCompare)
80         : ShaderRenderCaseInstance      (context, isVertexCase, evaluator, uniformSetup, DE_NULL, IMAGE_BACKING_MODE_REGULAR, static_cast<deUint32>(GRID_SIZE_DEFAULTS), fuzzyCompare)
81 {
82         if (usesTexture)
83         {
84                 de::SharedPtr<TextureBinding> brickTexture(new TextureBinding(m_context.getTestContext().getArchive(),
85                                                                                                                                           "vulkan/data/brick.png",
86                                                                                                                                           TextureBinding::TYPE_2D,
87                                                                                                                                           tcu::Sampler(tcu::Sampler::CLAMP_TO_EDGE,
88                                                                                                                                                                         tcu::Sampler::CLAMP_TO_EDGE,
89                                                                                                                                                                         tcu::Sampler::CLAMP_TO_EDGE,
90                                                                                                                                                                         tcu::Sampler::LINEAR,
91                                                                                                                                                                         tcu::Sampler::LINEAR,
92                                                                                                                                                                         0.0f,
93                                                                                                                                                                         true,
94                                                                                                                                                                         tcu::Sampler::COMPAREMODE_NONE,
95                                                                                                                                                                         0,
96                                                                                                                                                                         tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f),
97                                                                                                                                                                         true)));
98                 m_textures.push_back(brickTexture);
99         }
100 }
101
102 ShaderDiscardCaseInstance::~ShaderDiscardCaseInstance (void)
103 {
104 }
105
106 class ShaderDiscardCase : public ShaderRenderCase
107 {
108 public:
109                                                         ShaderDiscardCase                       (tcu::TestContext&              testCtx,
110                                                                                                                  const char*                    name,
111                                                                                                                  const char*                    description,
112                                                                                                                  const char*                    shaderSource,
113                                                                                                                  const ShaderEvalFunc   evalFunc,
114                                                                                                                  bool                                   usesTexture,
115                                                                                                                  bool                                   fuzzyCompare,
116                                                                                                                  bool                                   demote);
117         virtual TestInstance*   createInstance                          (Context& context) const
118                                                         {
119                                                                 DE_ASSERT(m_evaluator != DE_NULL);
120                                                                 DE_ASSERT(m_uniformSetup != DE_NULL);
121                                                                 return new ShaderDiscardCaseInstance(context, m_isVertexCase, *m_evaluator, *m_uniformSetup, m_usesTexture, m_fuzzyCompare);
122                                                         }
123
124         virtual void                            checkSupport                                    (Context& context) const;
125
126 private:
127         const bool                              m_usesTexture;
128         const bool                              m_fuzzyCompare;
129 #ifndef CTS_USES_VULKANSC
130         const bool                              m_demote;
131 #endif // CTS_USES_VULKANSC
132 };
133
134 ShaderDiscardCase::ShaderDiscardCase (tcu::TestContext&         testCtx,
135                                                                           const char*                   name,
136                                                                           const char*                   description,
137                                                                           const char*                   shaderSource,
138                                                                           const ShaderEvalFunc  evalFunc,
139                                                                           bool                                  usesTexture,
140                                                                           bool                                  fuzzyCompare,
141                                                                           bool                                  demote)
142         : ShaderRenderCase      (testCtx, name, description, false, evalFunc, new SamplerUniformSetup(usesTexture), DE_NULL)
143         , m_usesTexture         (usesTexture)
144         , m_fuzzyCompare        (fuzzyCompare)
145 #ifndef CTS_USES_VULKANSC
146         , m_demote(demote)
147 #endif // CTS_USES_VULKANSC
148 {
149 #ifdef CTS_USES_VULKANSC
150         DE_UNREF(demote);
151 #endif // CTS_USES_VULKANSC
152
153         m_fragShaderSource      = shaderSource;
154         m_vertShaderSource      =
155                 "#version 310 es\n"
156                 "layout(location=0) in  highp   vec4 a_position;\n"
157                 "layout(location=1) in  highp   vec4 a_coords;\n"
158                 "layout(location=2) in  highp   vec4 a_one;\n"
159                 "layout(location=0) out mediump vec4 v_color;\n"
160                 "layout(location=1) out mediump vec4 v_coords;\n\n"
161                 "layout(location=2) out mediump vec4 v_one;\n"
162                 "void main (void)\n"
163                 "{\n"
164                 "    gl_Position = a_position;\n"
165                 "    v_color = vec4(a_coords.xyz, 1.0);\n"
166                 "    v_coords = a_coords;\n"
167                 "    v_one = a_one;\n"
168                 "}\n";
169 }
170
171 void ShaderDiscardCase::checkSupport(Context& context) const
172 {
173 #ifndef CTS_USES_VULKANSC
174         if (m_demote && !context.getShaderDemoteToHelperInvocationFeatures().shaderDemoteToHelperInvocation)
175                 TCU_THROW(NotSupportedError, "VK_EXT_shader_demote_to_helper_invocation not supported");
176 #else
177         DE_UNREF(context);
178 #endif // CTS_USES_VULKANSC
179 }
180
181 enum DiscardMode
182 {
183         DISCARDMODE_ALWAYS = 0,
184         DISCARDMODE_NEVER,
185         DISCARDMODE_UNIFORM,
186         DISCARDMODE_DYNAMIC,
187         DISCARDMODE_TEXTURE,
188         DISCARDMODE_DERIV,
189
190         DISCARDMODE_LAST
191 };
192
193 enum DiscardTemplate
194 {
195         DISCARDTEMPLATE_MAIN_BASIC = 0,
196         DISCARDTEMPLATE_FUNCTION_BASIC,
197         DISCARDTEMPLATE_MAIN_STATIC_LOOP,
198         DISCARDTEMPLATE_MAIN_DYNAMIC_LOOP,
199         DISCARDTEMPLATE_FUNCTION_STATIC_LOOP,
200
201         DISCARDTEMPLATE_LAST
202 };
203
204 // Evaluation functions
205 inline void evalDiscardAlways   (ShaderEvalContext& c) { c.discard(); }
206 inline void evalDiscardNever    (ShaderEvalContext& c) { c.color.xyz() = c.coords.swizzle(0,1,2); }
207 inline void evalDiscardDynamic  (ShaderEvalContext& c) { c.color.xyz() = c.coords.swizzle(0,1,2); if (c.coords.x()+c.coords.y() > 0.0f) c.discard(); }
208
209 inline void evalDiscardTexture (ShaderEvalContext& c)
210 {
211         c.color.xyz() = c.coords.swizzle(0,1,2);
212         if (c.texture2D(0, c.coords.swizzle(0,1) * 0.25f + 0.5f).x() < 0.7f)
213                 c.discard();
214 }
215
216 static ShaderEvalFunc getEvalFunc (DiscardMode mode)
217 {
218         switch (mode)
219         {
220                 case DISCARDMODE_ALWAYS:        return evalDiscardAlways;
221                 case DISCARDMODE_NEVER:         return evalDiscardNever;
222                 case DISCARDMODE_UNIFORM:       return evalDiscardAlways;
223                 case DISCARDMODE_DYNAMIC:       return evalDiscardDynamic;
224                 case DISCARDMODE_TEXTURE:       return evalDiscardTexture;
225                 case DISCARDMODE_DERIV:         return evalDiscardAlways;
226                 default:
227                         DE_ASSERT(DE_FALSE);
228                         return evalDiscardAlways;
229         }
230 }
231
232 static const char* getTemplate (DiscardTemplate variant)
233 {
234         #define GLSL_SHADER_TEMPLATE_HEADER \
235                                 "#version 310 es\n"     \
236                                 "#extension GL_EXT_demote_to_helper_invocation : enable\n"      \
237                                 "layout(location = 0) in mediump vec4 v_color;\n"       \
238                                 "layout(location = 1) in mediump vec4 v_coords;\n"      \
239                                 "layout(location = 2) in mediump vec4 a_one;\n" \
240                                 "layout(location = 0) out mediump vec4 o_color;\n"      \
241                                 "layout(set = 0, binding = 2) uniform sampler2D    ut_brick;\n" \
242                                 "layout(set = 0, binding = 0) uniform block0 { mediump int  ui_one; };\n\n"
243
244         switch (variant)
245         {
246                 case DISCARDTEMPLATE_MAIN_BASIC:
247                         return GLSL_SHADER_TEMPLATE_HEADER
248                                    "void main (void)\n"
249                                    "{\n"
250                                    "    o_color = v_color;\n"
251                                    "    ${DISCARD};\n"
252                                    "}\n";
253
254                 case DISCARDTEMPLATE_FUNCTION_BASIC:
255                         return GLSL_SHADER_TEMPLATE_HEADER
256                                    "void myfunc (void)\n"
257                                    "{\n"
258                                    "    ${DISCARD};\n"
259                                    "}\n\n"
260                                    "void main (void)\n"
261                                    "{\n"
262                                    "    o_color = v_color;\n"
263                                    "    myfunc();\n"
264                                    "}\n";
265
266                 case DISCARDTEMPLATE_MAIN_STATIC_LOOP:
267                         return GLSL_SHADER_TEMPLATE_HEADER
268                                    "void main (void)\n"
269                                    "{\n"
270                                    "    o_color = v_color;\n"
271                                    "    for (int i = 0; i < 2; i++)\n"
272                                    "    {\n"
273                                    "        if (i > 0) {\n"
274                                    "            ${DISCARD};\n"
275                                    "        }\n"
276                                    "    }\n"
277                                    "}\n";
278
279                 case DISCARDTEMPLATE_MAIN_DYNAMIC_LOOP:
280                         return GLSL_SHADER_TEMPLATE_HEADER
281                                    "layout(set = 0, binding = 1) uniform block1 { mediump int  ui_two; };\n\n"
282                                    "void main (void)\n"
283                                    "{\n"
284                                    "    o_color = v_color;\n"
285                                    "    for (int i = 0; i < ui_two; i++)\n"
286                                    "    {\n"
287                                    "        if (i > 0) {\n"
288                                    "            ${DISCARD};\n"
289                                    "        }\n"
290                                    "    }\n"
291                                    "}\n";
292
293                 case DISCARDTEMPLATE_FUNCTION_STATIC_LOOP:
294                         return GLSL_SHADER_TEMPLATE_HEADER
295                                    "void myfunc (void)\n"
296                                    "{\n"
297                                    "    for (int i = 0; i < 2; i++)\n"
298                                    "    {\n"
299                                    "        if (i > 0) {\n"
300                                    "            ${DISCARD};\n"
301                                    "        }\n"
302                                    "    }\n"
303                                    "}\n\n"
304                                    "void main (void)\n"
305                                    "{\n"
306                                    "    o_color = v_color;\n"
307                                    "    myfunc();\n"
308                                    "}\n";
309
310                 default:
311                         DE_ASSERT(DE_FALSE);
312                         return DE_NULL;
313         }
314
315         #undef GLSL_SHADER_TEMPLATE_HEADER
316 }
317
318 static const char* getTemplateName (DiscardTemplate variant)
319 {
320         switch (variant)
321         {
322                 case DISCARDTEMPLATE_MAIN_BASIC:                        return "basic";
323                 case DISCARDTEMPLATE_FUNCTION_BASIC:            return "function";
324                 case DISCARDTEMPLATE_MAIN_STATIC_LOOP:          return "static_loop";
325                 case DISCARDTEMPLATE_MAIN_DYNAMIC_LOOP:         return "dynamic_loop";
326                 case DISCARDTEMPLATE_FUNCTION_STATIC_LOOP:      return "function_static_loop";
327                 default:
328                         DE_ASSERT(DE_FALSE);
329                         return DE_NULL;
330         }
331 }
332
333 static const char* getModeName (DiscardMode mode)
334 {
335         switch (mode)
336         {
337                 case DISCARDMODE_ALWAYS:        return "always";
338                 case DISCARDMODE_NEVER:         return "never";
339                 case DISCARDMODE_UNIFORM:       return "uniform";
340                 case DISCARDMODE_DYNAMIC:       return "dynamic";
341                 case DISCARDMODE_TEXTURE:       return "texture";
342                 case DISCARDMODE_DERIV:         return "deriv";
343                 default:
344                         DE_ASSERT(DE_FALSE);
345                         return DE_NULL;
346         }
347 }
348
349 static const char* getTemplateDesc (DiscardTemplate variant)
350 {
351         switch (variant)
352         {
353                 case DISCARDTEMPLATE_MAIN_BASIC:                        return "main";
354                 case DISCARDTEMPLATE_FUNCTION_BASIC:            return "function";
355                 case DISCARDTEMPLATE_MAIN_STATIC_LOOP:          return "static loop";
356                 case DISCARDTEMPLATE_MAIN_DYNAMIC_LOOP:         return "dynamic loop";
357                 case DISCARDTEMPLATE_FUNCTION_STATIC_LOOP:      return "static loop in function";
358                 default:
359                         DE_ASSERT(DE_FALSE);
360                         return DE_NULL;
361         }
362 }
363
364 static const char* getModeDesc (DiscardMode mode)
365 {
366         switch (mode)
367         {
368                 case DISCARDMODE_ALWAYS:        return "Always discard";
369                 case DISCARDMODE_NEVER:         return "Never discard";
370                 case DISCARDMODE_UNIFORM:       return "Discard based on uniform value";
371                 case DISCARDMODE_DYNAMIC:       return "Discard based on varying values";
372                 case DISCARDMODE_TEXTURE:       return "Discard based on texture value";
373                 case DISCARDMODE_DERIV:         return "Discard based on derivatives after an earlier discard";
374                 default:
375                         DE_ASSERT(DE_FALSE);
376                         return DE_NULL;
377         }
378 }
379
380 de::MovePtr<ShaderDiscardCase> makeDiscardCase (tcu::TestContext& testCtx, DiscardTemplate tmpl, DiscardMode mode, const std::string& discardStr)
381 {
382         StringTemplate shaderTemplate(getTemplate(tmpl));
383
384         std::map<std::string, std::string> params;
385
386         switch (mode)
387         {
388                 case DISCARDMODE_ALWAYS:        params["DISCARD"] = discardStr;                                                                                                                         break;
389                 case DISCARDMODE_NEVER:         params["DISCARD"] = "if (false) " + discardStr;                                                                                         break;
390                 case DISCARDMODE_UNIFORM:       params["DISCARD"] = "if (ui_one > 0) " + discardStr;                                                                            break;
391                 case DISCARDMODE_DYNAMIC:       params["DISCARD"] = "if (v_coords.x+v_coords.y > 0.0) " + discardStr;                                           break;
392                 case DISCARDMODE_TEXTURE:       params["DISCARD"] = "if (texture(ut_brick, v_coords.xy*0.25+0.5).x < 0.7) " + discardStr;       break;
393                 case DISCARDMODE_DERIV:         params["DISCARD"] =
394                                                                                 // First demote pixels where fragCoord.xy LSBs are not both zero, leaving only one
395                                                                                 // non-helper pixel per quad. Then compute derivatives of "one+fragCoord" and check they
396                                                                                 // are 0 or 1 as appropriate. Also check that helperInvocationEXT varies in the quad and
397                                                                                 // is false on non-helper pixels. Demote the pixel if it gets the right values, so the final
398                                                                                 // image should be entirely the clear color. If we don't get the right values, output red.
399                                                                                 // This test case would not work for discard, because derivatives become undefined.
400                                                                                 "  ivec2 f = ivec2(gl_FragCoord.xy);\n"
401                                                                                 "  int lsb = (f.x | f.y)&1;\n"
402                                                                                 "  if (lsb != 0) demote;\n"
403                                                                                 "  bool isHelper = helperInvocationEXT();\n"
404                                                                                 "  highp vec2 dx = dFdx(a_one.xy + gl_FragCoord.xy);\n"
405                                                                                 "  highp vec2 dy = dFdy(a_one.xy + gl_FragCoord.xy);\n"
406                                                                                 "  highp float dh = dFdx(float(isHelper));\n"
407                                                                                 "  bool valid = abs(dx.x-1.0) < 0.01 && dx.y == 0.0 && dy.x == 0.0 && abs(dy.y-1.0) < 0.01 && abs(dh-1.0) < 0.1 && !isHelper;\n"
408                                                                                 "  if (valid) demote;\n"
409                                                                                 "  o_color = vec4(1,0,0,1);\n";
410                                                                                 break;
411                 default:
412                         DE_ASSERT(DE_FALSE);
413                         break;
414         }
415
416         std::string name                = std::string(getTemplateName(tmpl)) + "_" + getModeName(mode);
417         std::string description = std::string(getModeDesc(mode)) + " in " + getTemplateDesc(tmpl);
418
419         return de::MovePtr<ShaderDiscardCase>(new ShaderDiscardCase(testCtx, name.c_str(),
420                                                                                                                                 description.c_str(),
421                                                                                                                                 shaderTemplate.specialize(params).c_str(),
422                                                                                                                                 getEvalFunc(mode),
423                                                                                                                                 mode == DISCARDMODE_TEXTURE,            // usesTexture
424                                                                                                                                 mode != DISCARDMODE_DERIV,                      // fuzzyCompare
425                                                                                                                                 discardStr == "demote"));                       // demote
426 }
427
428 class ShaderDiscardTests : public tcu::TestCaseGroup
429 {
430 public:
431                                                         ShaderDiscardTests              (tcu::TestContext& textCtx, const char *groupName);
432         virtual                                 ~ShaderDiscardTests             (void);
433
434         virtual void                    init                                    (void);
435
436 private:
437                                                         ShaderDiscardTests              (const ShaderDiscardTests&);            // not allowed!
438         ShaderDiscardTests&             operator=                               (const ShaderDiscardTests&);            // not allowed!
439         const std::string               m_groupName;
440 };
441
442 ShaderDiscardTests::ShaderDiscardTests (tcu::TestContext& testCtx, const char *groupName)
443         : TestCaseGroup(testCtx, groupName, "Discard statement tests")
444         , m_groupName(groupName)
445 {
446 }
447
448 ShaderDiscardTests::~ShaderDiscardTests (void)
449 {
450 }
451
452 void ShaderDiscardTests::init (void)
453 {
454         for (int tmpl = 0; tmpl < DISCARDTEMPLATE_LAST; tmpl++)
455         {
456                 for (int mode = 0; mode < DISCARDMODE_LAST; mode++)
457                 {
458                         if (mode == DISCARDMODE_DERIV && m_groupName == "discard")
459                                 continue;
460                         addChild(makeDiscardCase(m_testCtx, (DiscardTemplate)tmpl, (DiscardMode)mode, m_groupName).release());
461                 }
462         }
463 }
464
465 } // anonymous
466
467 tcu::TestCaseGroup* createDiscardTests (tcu::TestContext& testCtx)
468 {
469         return new ShaderDiscardTests(testCtx, "discard");
470 }
471
472 tcu::TestCaseGroup* createDemoteTests (tcu::TestContext& testCtx)
473 {
474         return new ShaderDiscardTests(testCtx, "demote");
475 }
476
477 } // sr
478 } // vkt