Merge vk-gl-cts/vulkan-cts-1.0.1 into vk-gl-cts/vulkan-cts-1.0.2
[platform/upstream/VK-GL-CTS.git] / external / vulkancts / modules / vulkan / shaderrender / vktShaderRenderBuiltinVarTests.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 builtin variable tests.
24  *//*--------------------------------------------------------------------*/
25
26 #include "vktShaderRenderBuiltinVarTests.hpp"
27 #include "vktShaderRender.hpp"
28 #include "gluShaderUtil.hpp"
29 #include "tcuImageCompare.hpp"
30 #include "tcuStringTemplate.hpp"
31 #include "tcuTextureUtil.hpp"
32
33 #include "deMath.h"
34 #include "deRandom.hpp"
35
36 #include <map>
37
38 using namespace std;
39 using namespace tcu;
40 using namespace vk;
41
42 namespace vkt
43 {
44 namespace sr
45 {
46
47 namespace
48 {
49
50 class BuiltinGlFrontFacingCaseInstance : public ShaderRenderCaseInstance
51 {
52 public:
53                                         BuiltinGlFrontFacingCaseInstance        (Context& context);
54
55         TestStatus              iterate                                                         (void);
56         virtual void    setupDefaultInputs                                      (void);
57 };
58
59 BuiltinGlFrontFacingCaseInstance::BuiltinGlFrontFacingCaseInstance (Context& context)
60         : ShaderRenderCaseInstance      (context)
61 {
62 }
63
64 TestStatus BuiltinGlFrontFacingCaseInstance::iterate (void)
65 {
66         const UVec2             viewportSize    = getViewportSize();
67         const int               width                   = viewportSize.x();
68         const int               height                  = viewportSize.y();
69         const RGBA              threshold               (2, 2, 2, 2);
70         Surface                 resImage                (width, height);
71         Surface                 refImage                (width, height);
72         bool                    compareOk               = false;
73         const deUint16  indices[12]             =
74         {
75                 0, 4, 1,
76                 0, 5, 4,
77                 1, 2, 3,
78                 1, 3, 4
79         };
80
81         setup();
82         render(6, 4, indices);
83         copy(resImage.getAccess(), getResultImage().getAccess());
84
85         for (int y = 0; y < refImage.getHeight(); y++)
86         {
87                 for (int x = 0; x < refImage.getWidth()/2; x++)
88                         refImage.setPixel(x, y, RGBA::green());
89
90                 for (int x = refImage.getWidth()/2; x < refImage.getWidth(); x++)
91                         refImage.setPixel(x, y, RGBA::blue());
92         }
93
94         compareOk = pixelThresholdCompare(m_context.getTestContext().getLog(), "Result", "Image comparison result", refImage, resImage, threshold, COMPARE_LOG_RESULT);
95
96         if (compareOk)
97                 return TestStatus::pass("Result image matches reference");
98         else
99                 return TestStatus::fail("Image mismatch");
100 }
101
102 void BuiltinGlFrontFacingCaseInstance::setupDefaultInputs (void)
103 {
104         const float vertices[] =
105         {
106                 -1.0f, -1.0f, 0.0f, 1.0f,
107                  0.0f, -1.0f, 0.0f, 1.0f,
108                  1.0f, -1.0f, 0.0f, 1.0f,
109                  1.0f,  1.0f, 0.0f, 1.0f,
110                  0.0f,  1.0f, 0.0f, 1.0f,
111                 -1.0f,  1.0f, 0.0f, 1.0f
112         };
113
114         addAttribute(0u, VK_FORMAT_R32G32B32A32_SFLOAT, deUint32(sizeof(float) * 4), 6, vertices);
115 }
116
117 class BuiltinGlFrontFacingCase : public TestCase
118 {
119 public:
120                                                                 BuiltinGlFrontFacingCase        (TestContext& testCtx, const string& name, const string& description);
121         virtual                                         ~BuiltinGlFrontFacingCase       (void);
122
123         void                                            initPrograms                            (SourceCollections& dst) const;
124         TestInstance*                           createInstance                          (Context& context) const;
125
126 private:
127                                                                 BuiltinGlFrontFacingCase        (const BuiltinGlFrontFacingCase&);      // not allowed!
128         BuiltinGlFrontFacingCase&       operator=                                       (const BuiltinGlFrontFacingCase&);      // not allowed!
129 };
130
131 BuiltinGlFrontFacingCase::BuiltinGlFrontFacingCase (TestContext& testCtx, const string& name, const string& description)
132         : TestCase(testCtx, name, description)
133 {
134 }
135
136 BuiltinGlFrontFacingCase::~BuiltinGlFrontFacingCase (void)
137 {
138 }
139
140 void BuiltinGlFrontFacingCase::initPrograms (SourceCollections& dst) const
141 {
142         dst.glslSources.add("vert") << glu::VertexSource(
143                 "#version 310 es\n"
144                 "layout(location = 0) in highp vec4 a_position;\n"
145                 "void main (void)\n"
146                 "{\n"
147                 "       gl_Position = a_position;\n"
148                 "}\n");
149
150         dst.glslSources.add("frag") << glu::FragmentSource(
151                 "#version 310 es\n"
152                 "layout(location = 0) out lowp vec4 o_color;\n"
153                 "void main (void)\n"
154                 "{\n"
155                 "       if (gl_FrontFacing)\n"
156                 "               o_color = vec4(0.0, 1.0, 0.0, 1.0);\n"
157                 "       else\n"
158                 "               o_color = vec4(0.0, 0.0, 1.0, 1.0);\n"
159                 "}\n");
160 }
161
162 TestInstance* BuiltinGlFrontFacingCase::createInstance (Context& context) const
163 {
164         return new BuiltinGlFrontFacingCaseInstance(context);
165 }
166
167 class BuiltinGlFragCoordXYZCaseInstance : public ShaderRenderCaseInstance
168 {
169 public:
170                                         BuiltinGlFragCoordXYZCaseInstance       (Context& context);
171
172         TestStatus              iterate                                                         (void);
173         virtual void    setupDefaultInputs                                      (void);
174 };
175
176 BuiltinGlFragCoordXYZCaseInstance::BuiltinGlFragCoordXYZCaseInstance (Context& context)
177         : ShaderRenderCaseInstance      (context)
178 {
179 }
180
181 TestStatus BuiltinGlFragCoordXYZCaseInstance::iterate (void)
182 {
183         const UVec2             viewportSize    = getViewportSize();
184         const int               width                   = viewportSize.x();
185         const int               height                  = viewportSize.y();
186         const tcu::Vec3 scale                   (1.f / float(width), 1.f / float(height), 1.0f);
187         const tcu::RGBA threshold               (2, 2, 2, 2);
188         Surface                 resImage                (width, height);
189         Surface                 refImage                (width, height);
190         bool                    compareOk               = false;
191         const deUint16  indices[6]              =
192         {
193                 2, 1, 3,
194                 0, 1, 2,
195         };
196
197         setup();
198         addUniform(0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, scale);
199
200         render(4, 2, indices);
201         copy(resImage.getAccess(), getResultImage().getAccess());
202
203         // Reference image
204         for (int y = 0; y < refImage.getHeight(); y++)
205         {
206                 for (int x = 0; x < refImage.getWidth(); x++)
207                 {
208                         const float     xf                      = (float(x)+.5f) / float(refImage.getWidth());
209                         const float     yf                      = (float(refImage.getHeight()-y-1)+.5f) / float(refImage.getHeight());
210                         const float     z                       = (xf + yf) / 2.0f;
211                         const Vec3      fragCoord       (float(x)+.5f, float(y)+.5f, z);
212                         const Vec3      scaledFC        = fragCoord*scale;
213                         const Vec4      color           (scaledFC.x(), scaledFC.y(), scaledFC.z(), 1.0f);
214
215                         refImage.setPixel(x, y, RGBA(color));
216                 }
217         }
218
219         compareOk = pixelThresholdCompare(m_context.getTestContext().getLog(), "Result", "Image comparison result", refImage, resImage, threshold, COMPARE_LOG_RESULT);
220
221         if (compareOk)
222                 return TestStatus::pass("Result image matches reference");
223         else
224                 return TestStatus::fail("Image mismatch");
225 }
226
227 void BuiltinGlFragCoordXYZCaseInstance::setupDefaultInputs (void)
228 {
229         const float             vertices[]              =
230         {
231                 -1.0f,  1.0f,  0.0f, 1.0f,
232                 -1.0f, -1.0f,  0.5f, 1.0f,
233                  1.0f,  1.0f,  0.5f, 1.0f,
234                  1.0f, -1.0f,  1.0f, 1.0f,
235         };
236
237         addAttribute(0u, VK_FORMAT_R32G32B32A32_SFLOAT, deUint32(sizeof(float) * 4), 4, vertices);
238 }
239
240 class BuiltinGlFragCoordXYZCase : public TestCase
241 {
242 public:
243                                                                 BuiltinGlFragCoordXYZCase       (TestContext& testCtx, const string& name, const string& description);
244         virtual                                         ~BuiltinGlFragCoordXYZCase      (void);
245
246         void                                            initPrograms                            (SourceCollections& dst) const;
247         TestInstance*                           createInstance                          (Context& context) const;
248
249 private:
250                                                                 BuiltinGlFragCoordXYZCase       (const BuiltinGlFragCoordXYZCase&);     // not allowed!
251         BuiltinGlFragCoordXYZCase&      operator=                                       (const BuiltinGlFragCoordXYZCase&);     // not allowed!
252 };
253
254 BuiltinGlFragCoordXYZCase::BuiltinGlFragCoordXYZCase (TestContext& testCtx, const string& name, const string& description)
255         : TestCase(testCtx, name, description)
256 {
257 }
258
259 BuiltinGlFragCoordXYZCase::~BuiltinGlFragCoordXYZCase (void)
260 {
261 }
262
263 void BuiltinGlFragCoordXYZCase::initPrograms (SourceCollections& dst) const
264 {
265         dst.glslSources.add("vert") << glu::VertexSource(
266                 "#version 310 es\n"
267                 "layout(location = 0) in highp vec4 a_position;\n"
268                 "void main (void)\n"
269                 "{\n"
270                 "       gl_Position = a_position;\n"
271                 "}\n");
272
273         dst.glslSources.add("frag") << glu::FragmentSource(
274                 "#version 310 es\n"
275                 "layout(set=0, binding=0) uniform Scale { highp vec3 u_scale; };\n"
276                 "layout(location = 0) out highp vec4 o_color;\n"
277                 "void main (void)\n"
278                 "{\n"
279                 "       o_color = vec4(gl_FragCoord.xyz * u_scale, 1.0);\n"
280                 "}\n");
281 }
282
283 TestInstance* BuiltinGlFragCoordXYZCase::createInstance (Context& context) const
284 {
285         return new BuiltinGlFragCoordXYZCaseInstance(context);
286 }
287
288 inline float projectedTriInterpolate (const Vec3& s, const Vec3& w, float nx, float ny)
289 {
290         return (s[0]*(1.0f-nx-ny)/w[0] + s[1]*ny/w[1] + s[2]*nx/w[2]) / ((1.0f-nx-ny)/w[0] + ny/w[1] + nx/w[2]);
291 }
292
293 class BuiltinGlFragCoordWCaseInstance : public ShaderRenderCaseInstance
294 {
295 public:
296                                         BuiltinGlFragCoordWCaseInstance (Context& context);
297
298         TestStatus              iterate                                                 (void);
299         virtual void    setupDefaultInputs                              (void);
300
301 private:
302
303         const Vec4              m_w;
304
305 };
306
307 BuiltinGlFragCoordWCaseInstance::BuiltinGlFragCoordWCaseInstance (Context& context)
308         : ShaderRenderCaseInstance      (context)
309         , m_w                                           (1.7f, 2.0f, 1.2f, 1.0f)
310 {
311 }
312
313 TestStatus BuiltinGlFragCoordWCaseInstance::iterate (void)
314 {
315         const UVec2             viewportSize    = getViewportSize();
316         const int               width                   = viewportSize.x();
317         const int               height                  = viewportSize.y();
318         const tcu::RGBA threshold               (2, 2, 2, 2);
319         Surface                 resImage                (width, height);
320         Surface                 refImage                (width, height);
321         bool                    compareOk               = false;
322         const deUint16  indices[6]              =
323         {
324                 2, 1, 3,
325                 0, 1, 2,
326         };
327
328         setup();
329         render(4, 2, indices);
330         copy(resImage.getAccess(), getResultImage().getAccess());
331
332         // Reference image
333         for (int y = 0; y < refImage.getHeight(); y++)
334         {
335                 for (int x = 0; x < refImage.getWidth(); x++)
336                 {
337                         const float     xf                      = (float(x)+.5f) / float(refImage.getWidth());
338                         const float     yf                      = (float(refImage.getHeight()-y-1)+.5f) / float(refImage.getHeight());
339                         const float     oow                     = ((xf + yf) < 1.0f)
340                                                                                 ? projectedTriInterpolate(Vec3(m_w[0], m_w[1], m_w[2]), Vec3(m_w[0], m_w[1], m_w[2]), xf, yf)
341                                                                                 : projectedTriInterpolate(Vec3(m_w[3], m_w[2], m_w[1]), Vec3(m_w[3], m_w[2], m_w[1]), 1.0f-xf, 1.0f-yf);
342                         const Vec4      color           (0.0f, oow - 1.0f, 0.0f, 1.0f);
343
344                         refImage.setPixel(x, y, RGBA(color));
345                 }
346         }
347
348         compareOk = pixelThresholdCompare(m_context.getTestContext().getLog(), "Result", "Image comparison result", refImage, resImage, threshold, COMPARE_LOG_RESULT);
349
350         if (compareOk)
351                 return TestStatus::pass("Result image matches reference");
352         else
353                 return TestStatus::fail("Image mismatch");
354 }
355
356 void BuiltinGlFragCoordWCaseInstance::setupDefaultInputs (void)
357 {
358         const float vertices[] =
359         {
360                 -m_w[0],  m_w[0], 0.0f, m_w[0],
361                 -m_w[1], -m_w[1], 0.0f, m_w[1],
362                  m_w[2],  m_w[2], 0.0f, m_w[2],
363                  m_w[3], -m_w[3], 0.0f, m_w[3]
364         };
365
366         addAttribute(0u, VK_FORMAT_R32G32B32A32_SFLOAT, deUint32(sizeof(float) * 4), 4, vertices);
367 }
368
369 class BuiltinGlFragCoordWCase : public TestCase
370 {
371 public:
372                                                                 BuiltinGlFragCoordWCase         (TestContext& testCtx, const string& name, const string& description);
373         virtual                                         ~BuiltinGlFragCoordWCase        (void);
374
375         void                                            initPrograms                            (SourceCollections& dst) const;
376         TestInstance*                           createInstance                          (Context& context) const;
377
378 private:
379                                                                 BuiltinGlFragCoordWCase         (const BuiltinGlFragCoordWCase&);       // not allowed!
380         BuiltinGlFragCoordWCase&        operator=                                       (const BuiltinGlFragCoordWCase&);       // not allowed!
381 };
382
383 BuiltinGlFragCoordWCase::BuiltinGlFragCoordWCase (TestContext& testCtx, const string& name, const string& description)
384         : TestCase(testCtx, name, description)
385 {
386 }
387
388 BuiltinGlFragCoordWCase::~BuiltinGlFragCoordWCase (void)
389 {
390 }
391
392 void BuiltinGlFragCoordWCase::initPrograms (SourceCollections& dst) const
393 {
394         dst.glslSources.add("vert") << glu::VertexSource(
395                 "#version 310 es\n"
396                 "layout(location = 0) in highp vec4 a_position;\n"
397                 "void main (void)\n"
398                 "{\n"
399                 "       gl_Position = a_position;\n"
400                 "}\n");
401
402         dst.glslSources.add("frag") << glu::FragmentSource(
403                 "#version 310 es\n"
404                 "layout(location = 0) out highp vec4 o_color;\n"
405                 "void main (void)\n"
406                 "{\n"
407                 "       o_color = vec4(0.0, 1.0 / gl_FragCoord.w - 1.0, 0.0, 1.0);\n"
408                 "}\n");
409 }
410
411 TestInstance* BuiltinGlFragCoordWCase::createInstance (Context& context) const
412 {
413         return new BuiltinGlFragCoordWCaseInstance(context);
414 }
415
416 class BuiltinGlPointCoordCaseInstance : public ShaderRenderCaseInstance
417 {
418 public:
419                                         BuiltinGlPointCoordCaseInstance (Context& context);
420
421         TestStatus              iterate                                                         (void);
422         virtual void    setupDefaultInputs                                      (void);
423 };
424
425 BuiltinGlPointCoordCaseInstance::BuiltinGlPointCoordCaseInstance (Context& context)
426         : ShaderRenderCaseInstance      (context)
427 {
428 }
429
430 TestStatus BuiltinGlPointCoordCaseInstance::iterate (void)
431 {
432         const UVec2                             viewportSize    = getViewportSize();
433         const int                               width                   = viewportSize.x();
434         const int                               height                  = viewportSize.y();
435         const float                             threshold               = 0.02f;
436         const int                               numPoints               = 16;
437         vector<Vec3>                    coords                  (numPoints);
438         de::Random                              rnd                             (0x145fa);
439         Surface                                 resImage                (width, height);
440         Surface                                 refImage                (width, height);
441         bool                                    compareOk               = false;
442
443         // Compute coordinates.
444         {
445                 const VkPhysicalDeviceLimits&   limits                                  = m_context.getDeviceProperties().limits;
446                 const float                                             minPointSize                    = limits.pointSizeRange[0];
447                 const float                                             maxPointSize                    = limits.pointSizeRange[1];
448                 const int                                               pointSizeDeltaMultiples = de::max(1, deCeilFloatToInt32((maxPointSize - minPointSize) / limits.pointSizeGranularity));
449
450                 TCU_CHECK(minPointSize <= maxPointSize);
451
452                 for (vector<Vec3>::iterator coord = coords.begin(); coord != coords.end(); ++coord)
453                 {
454                         coord->x() = rnd.getFloat(-0.9f, 0.9f);
455                         coord->y() = rnd.getFloat(-0.9f, 0.9f);
456                         coord->z() = de::min(maxPointSize, minPointSize + float(rnd.getInt(0, pointSizeDeltaMultiples)) * limits.pointSizeGranularity);
457                 }
458         }
459
460         setup();
461         addAttribute(0u, VK_FORMAT_R32G32B32_SFLOAT, deUint32(sizeof(Vec3)), numPoints, &coords[0]);
462         render(numPoints, 0, DE_NULL, VK_PRIMITIVE_TOPOLOGY_POINT_LIST);
463         copy(resImage.getAccess(), getResultImage().getAccess());
464
465         // Draw reference
466         clear(refImage.getAccess(), m_clearColor);
467
468         for (vector<Vec3>::const_iterator pointIter = coords.begin(); pointIter != coords.end(); ++pointIter)
469         {
470                 const float     centerX = float(width) *(pointIter->x()*0.5f + 0.5f);
471                 const float     centerY = float(height)*(pointIter->y()*0.5f + 0.5f);
472                 const float     size    = pointIter->z();
473                 const int       x0              = deRoundFloatToInt32(centerX - size*0.5f);
474                 const int       y0              = deRoundFloatToInt32(centerY - size*0.5f);
475                 const int       x1              = deRoundFloatToInt32(centerX + size*0.5f);
476                 const int       y1              = deRoundFloatToInt32(centerY + size*0.5f);
477                 const int       w               = x1-x0;
478                 const int       h               = y1-y0;
479
480                 for (int yo = 0; yo < h; yo++)
481                 {
482                         for (int xo = 0; xo < w; xo++)
483                         {
484                                 const int               dx              = x0+xo;
485                                 const int               dy              = y0+yo;
486                                 const float             fragX   = float(dx) + 0.5f;
487                                 const float             fragY   = float(dy) + 0.5f;
488                                 const float             s               = 0.5f + (fragX - centerX) / size;
489                                 const float             t               = 0.5f + (fragY - centerY) / size;
490                                 const Vec4              color   (s, t, 0.0f, 1.0f);
491
492                                 if (de::inBounds(dx, 0, refImage.getWidth()) && de::inBounds(dy, 0, refImage.getHeight()))
493                                         refImage.setPixel(dx, dy, RGBA(color));
494                         }
495                 }
496         }
497
498         compareOk = fuzzyCompare(m_context.getTestContext().getLog(), "Result", "Image comparison result", refImage, resImage, threshold, COMPARE_LOG_RESULT);
499
500         if (compareOk)
501                 return TestStatus::pass("Result image matches reference");
502         else
503                 return TestStatus::fail("Image mismatch");
504 }
505
506 void BuiltinGlPointCoordCaseInstance::setupDefaultInputs (void)
507 {
508 }
509
510 class BuiltinGlPointCoordCase : public TestCase
511 {
512 public:
513                                                                 BuiltinGlPointCoordCase (TestContext& testCtx, const string& name, const string& description);
514         virtual                                         ~BuiltinGlPointCoordCase        (void);
515
516         void                                            initPrograms                            (SourceCollections& dst) const;
517         TestInstance*                           createInstance                          (Context& context) const;
518
519 private:
520                                                                 BuiltinGlPointCoordCase (const BuiltinGlPointCoordCase&);       // not allowed!
521         BuiltinGlPointCoordCase&        operator=                                       (const BuiltinGlPointCoordCase&);       // not allowed!
522 };
523
524 BuiltinGlPointCoordCase::BuiltinGlPointCoordCase (TestContext& testCtx, const string& name, const string& description)
525         : TestCase(testCtx, name, description)
526 {
527 }
528
529 BuiltinGlPointCoordCase::~BuiltinGlPointCoordCase (void)
530 {
531 }
532
533 void BuiltinGlPointCoordCase::initPrograms (SourceCollections& dst) const
534 {
535         dst.glslSources.add("vert") << glu::VertexSource(
536                 "#version 310 es\n"
537                 "layout(location = 0) in highp vec3 a_position;\n"
538                 "void main (void)\n"
539                 "{\n"
540                 "    gl_Position = vec4(a_position.xy, 0.0, 1.0);\n"
541                 "    gl_PointSize = a_position.z;\n"
542                 "}\n");
543
544         dst.glslSources.add("frag") << glu::FragmentSource(
545                 "#version 310 es\n"
546                 "layout(location = 0) out lowp vec4 o_color;\n"
547                 "void main (void)\n"
548                 "{\n"
549                 "    o_color = vec4(gl_PointCoord, 0.0, 1.0);\n"
550                 "}\n");
551 }
552
553 TestInstance* BuiltinGlPointCoordCase::createInstance (Context& context) const
554 {
555         return new BuiltinGlPointCoordCaseInstance(context);
556 }
557
558 enum ShaderInputTypeBits
559 {
560         SHADER_INPUT_BUILTIN_BIT        = 0x01,
561         SHADER_INPUT_VARYING_BIT        = 0x02,
562         SHADER_INPUT_CONSTANT_BIT       = 0x04
563 };
564
565 typedef deUint16 ShaderInputTypes;
566
567 string shaderInputTypeToString (ShaderInputTypes type)
568 {
569         string typeString = "input";
570
571         if (type == 0)
572                 return "input_none";
573
574         if (type & SHADER_INPUT_BUILTIN_BIT)
575                 typeString += "_builtin";
576
577         if (type & SHADER_INPUT_VARYING_BIT)
578                 typeString += "_varying";
579
580         if (type & SHADER_INPUT_CONSTANT_BIT)
581                 typeString += "_constant";
582
583         return typeString;
584 }
585
586 class BuiltinInputVariationsCaseInstance : public ShaderRenderCaseInstance
587 {
588 public:
589                                                         BuiltinInputVariationsCaseInstance      (Context& context, const ShaderInputTypes shaderInputTypes);
590
591         TestStatus                              iterate                                                         (void);
592         virtual void                    setupDefaultInputs                                      (void);
593         virtual void                    updatePushConstants                                     (vk::VkCommandBuffer commandBuffer, vk::VkPipelineLayout pipelineLayout);
594
595 private:
596         const ShaderInputTypes  m_shaderInputTypes;
597         const Vec4                              m_constantColor;
598 };
599
600 BuiltinInputVariationsCaseInstance::BuiltinInputVariationsCaseInstance (Context& context, const ShaderInputTypes shaderInputTypes)
601         : ShaderRenderCaseInstance      (context)
602         , m_shaderInputTypes            (shaderInputTypes)
603         , m_constantColor                       (0.1f, 0.05f, 0.2f, 0.0f)
604 {
605 }
606
607 TestStatus BuiltinInputVariationsCaseInstance::iterate (void)
608 {
609         const UVec2                                     viewportSize    = getViewportSize();
610         const int                                       width                   = viewportSize.x();
611         const int                                       height                  = viewportSize.y();
612         const tcu::RGBA                         threshold               (2, 2, 2, 2);
613         Surface                                         resImage                (width, height);
614         Surface                                         refImage                (width, height);
615         bool                                            compareOk               = false;
616         const VkPushConstantRange       pcRanges                =
617         {
618                 VK_SHADER_STAGE_FRAGMENT_BIT,   // VkShaderStageFlags   stageFlags;
619                 0u,                                                             // deUint32                             offset;
620                 sizeof(Vec4)                                    // deUint32                             size;
621         };
622         const deUint16                          indices[12]             =
623         {
624                 0, 4, 1,
625                 0, 5, 4,
626                 1, 2, 3,
627                 1, 3, 4
628         };
629
630         setup();
631
632         if (m_shaderInputTypes & SHADER_INPUT_CONSTANT_BIT)
633                 setPushConstantRanges(1, &pcRanges);
634
635         render(6, 4, indices);
636         copy(resImage.getAccess(), getResultImage().getAccess());
637
638         // Reference image
639         for (int y = 0; y < refImage.getHeight(); y++)
640         {
641                 for (int x = 0; x < refImage.getWidth(); x++)
642                 {
643                         Vec4 color (0.1f, 0.2f, 0.3f, 1.0f);
644
645                         if (((m_shaderInputTypes & SHADER_INPUT_BUILTIN_BIT) && (x < refImage.getWidth() / 2)) ||
646                                 !(m_shaderInputTypes & SHADER_INPUT_BUILTIN_BIT))
647                         {
648                                 if (m_shaderInputTypes & SHADER_INPUT_VARYING_BIT)
649                                 {
650                                         const float xf = (float(x)+.5f) / float(refImage.getWidth());
651                                         color += Vec4(0.6f * (1 - xf), 0.6f * xf, 0.0f, 0.0f);
652                                 }
653                                 else
654                                         color += Vec4(0.3f, 0.2f, 0.1f, 0.0f);
655                         }
656
657                         if (m_shaderInputTypes & SHADER_INPUT_CONSTANT_BIT)
658                                 color += m_constantColor;
659
660                         refImage.setPixel(x, y, RGBA(color));
661                 }
662         }
663
664         compareOk = pixelThresholdCompare(m_context.getTestContext().getLog(), "Result", "Image comparison result", refImage, resImage, threshold, COMPARE_LOG_RESULT);
665
666         if (compareOk)
667                 return TestStatus::pass("Result image matches reference");
668         else
669                 return TestStatus::fail("Image mismatch");
670 }
671
672 void BuiltinInputVariationsCaseInstance::setupDefaultInputs (void)
673 {
674         const float vertices[] =
675         {
676                 -1.0f, -1.0f, 0.0f, 1.0f,
677                  0.0f, -1.0f, 0.0f, 1.0f,
678                  1.0f, -1.0f, 0.0f, 1.0f,
679                  1.0f,  1.0f, 0.0f, 1.0f,
680                  0.0f,  1.0f, 0.0f, 1.0f,
681                 -1.0f,  1.0f, 0.0f, 1.0f
682         };
683
684         addAttribute(0u, VK_FORMAT_R32G32B32A32_SFLOAT, deUint32(sizeof(float) * 4), 6, vertices);
685
686         if (m_shaderInputTypes & SHADER_INPUT_VARYING_BIT)
687         {
688                 const float colors[] =
689                 {
690                          0.6f,  0.0f, 0.0f, 1.0f,
691                          0.3f,  0.3f, 0.0f, 1.0f,
692                          0.0f,  0.6f, 0.0f, 1.0f,
693                          0.0f,  0.6f, 0.0f, 1.0f,
694                          0.3f,  0.3f, 0.0f, 1.0f,
695                          0.6f,  0.0f, 0.0f, 1.0f
696                 };
697                 addAttribute(1u, VK_FORMAT_R32G32B32A32_SFLOAT, deUint32(sizeof(float) * 4), 6, colors);
698         }
699 }
700
701 void BuiltinInputVariationsCaseInstance::updatePushConstants (vk::VkCommandBuffer commandBuffer, vk::VkPipelineLayout pipelineLayout)
702 {
703         if (m_shaderInputTypes & SHADER_INPUT_CONSTANT_BIT)
704         {
705                 const DeviceInterface& vk = m_context.getDeviceInterface();
706                 vk.cmdPushConstants(commandBuffer, pipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(Vec4), &m_constantColor);
707         }
708 }
709
710 class BuiltinInputVariationsCase : public TestCase
711 {
712 public:
713                                                                 BuiltinInputVariationsCase      (TestContext& testCtx, const string& name, const string& description, const ShaderInputTypes shaderInputTypes);
714         virtual                                         ~BuiltinInputVariationsCase     (void);
715
716         void                                            initPrograms                            (SourceCollections& dst) const;
717         TestInstance*                           createInstance                          (Context& context) const;
718
719 private:
720                                                                 BuiltinInputVariationsCase      (const BuiltinInputVariationsCase&);    // not allowed!
721         BuiltinInputVariationsCase&     operator=                                       (const BuiltinInputVariationsCase&);    // not allowed!
722         const ShaderInputTypes          m_shaderInputTypes;
723 };
724
725 BuiltinInputVariationsCase::BuiltinInputVariationsCase (TestContext& testCtx, const string& name, const string& description, ShaderInputTypes shaderInputTypes)
726         : TestCase                              (testCtx, name, description)
727         , m_shaderInputTypes    (shaderInputTypes)
728 {
729 }
730
731 BuiltinInputVariationsCase::~BuiltinInputVariationsCase (void)
732 {
733 }
734
735 void BuiltinInputVariationsCase::initPrograms (SourceCollections& dst) const
736 {
737         map<string, string>                     vertexParams;
738         map<string, string>                     fragmentParams;
739         const tcu::StringTemplate       vertexCodeTemplate              (
740                 "#version 450\n"
741                 "layout(location = 0) in highp vec4 a_position;\n"
742                 "out gl_PerVertex {\n"
743                 "       vec4 gl_Position;\n"
744                 "};\n"
745                 "${VARYING_DECL}"
746                 "void main (void)\n"
747                 "{\n"
748                 "    gl_Position = a_position;\n"
749                 "    ${VARYING_USAGE}"
750                 "}\n");
751
752         const tcu::StringTemplate       fragmentCodeTemplate    (
753                 "#version 450\n"
754                 "${VARYING_DECL}"
755                 "${CONSTANT_DECL}"
756                 "layout(location = 0) out highp vec4 o_color;\n"
757                 "void main (void)\n"
758                 "{\n"
759                 "    o_color = vec4(0.1, 0.2, 0.3, 1.0);\n"
760                 "    ${BUILTIN_USAGE}"
761                 "    ${VARYING_USAGE}"
762                 "    ${CONSTANT_USAGE}"
763                 "}\n");
764
765         vertexParams["VARYING_DECL"]            =
766                 m_shaderInputTypes & SHADER_INPUT_VARYING_BIT   ? "layout(location = 1) in highp vec4 a_color;\n"
767                                                                                                                   "layout(location = 0) out highp vec4 v_color;\n"
768                                                                                                                 : "";
769
770         vertexParams["VARYING_USAGE"]           =
771                 m_shaderInputTypes & SHADER_INPUT_VARYING_BIT   ? "v_color = a_color;\n"
772                                                                                                                 : "";
773
774         fragmentParams["VARYING_DECL"]          =
775                 m_shaderInputTypes & SHADER_INPUT_VARYING_BIT   ? "layout(location = 0) in highp vec4 a_color;\n"
776                                                                                                                 : "";
777
778         fragmentParams["CONSTANT_DECL"]         =
779                 m_shaderInputTypes & SHADER_INPUT_CONSTANT_BIT  ? "layout(push_constant) uniform PCBlock {\n"
780                                                                                                                   "  vec4 color;\n"
781                                                                                                                   "} pc;\n"
782                                                                                                                 : "";
783
784         fragmentParams["BUILTIN_USAGE"]         =
785                 m_shaderInputTypes & SHADER_INPUT_BUILTIN_BIT   ? "if (gl_FrontFacing)\n"
786                                                                                                                 : "";
787
788         fragmentParams["VARYING_USAGE"]         =
789                 m_shaderInputTypes & SHADER_INPUT_VARYING_BIT   ? "o_color += vec4(a_color.xyz, 0.0);\n"
790                                                                                                                 : "o_color += vec4(0.3, 0.2, 0.1, 0.0);\n";
791
792
793         fragmentParams["CONSTANT_USAGE"]        =
794                 m_shaderInputTypes & SHADER_INPUT_CONSTANT_BIT  ? "o_color += pc.color;\n"
795                                                                                                                 : "";
796
797         dst.glslSources.add("vert") << glu::VertexSource(vertexCodeTemplate.specialize(vertexParams));
798         dst.glslSources.add("frag") << glu::FragmentSource(fragmentCodeTemplate.specialize(fragmentParams));
799 }
800
801 TestInstance* BuiltinInputVariationsCase::createInstance (Context& context) const
802 {
803         return new BuiltinInputVariationsCaseInstance(context, m_shaderInputTypes);
804 }
805
806 } // anonymous
807
808 TestCaseGroup* createBuiltinVarTests (TestContext& testCtx)
809 {
810         de::MovePtr<TestCaseGroup> builtinGroup                 (new TestCaseGroup(testCtx, "builtin_var", "Shader builtin variable tests."));
811         de::MovePtr<TestCaseGroup> simpleGroup                  (new TestCaseGroup(testCtx, "simple", "Simple cases."));
812         de::MovePtr<TestCaseGroup> inputVariationsGroup (new TestCaseGroup(testCtx, "input_variations", "Input type variation tests."));
813
814         simpleGroup->addChild(new BuiltinGlFrontFacingCase(testCtx, "frontfacing", "FrontFacing test"));
815         simpleGroup->addChild(new BuiltinGlFragCoordXYZCase(testCtx, "fragcoord_xyz", "FragCoord xyz test"));
816         simpleGroup->addChild(new BuiltinGlFragCoordWCase(testCtx, "fragcoord_w", "FragCoord w test"));
817         simpleGroup->addChild(new BuiltinGlPointCoordCase(testCtx, "pointcoord", "PointCoord test"));
818
819         builtinGroup->addChild(simpleGroup.release());
820
821         for (deUint16 shaderType = 0; shaderType <= (SHADER_INPUT_BUILTIN_BIT | SHADER_INPUT_VARYING_BIT | SHADER_INPUT_CONSTANT_BIT); ++shaderType)
822         {
823                 inputVariationsGroup->addChild(new BuiltinInputVariationsCase(testCtx, shaderInputTypeToString(shaderType), "Input variation test", shaderType));
824         }
825
826         builtinGroup->addChild(inputVariationsGroup.release());
827         return builtinGroup.release();
828 }
829
830 } // sr
831 } // vkt