CP: Require 'master' config to be supported in Android CTS
[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         VkPhysicalDeviceLimits  limits                  = m_context.getDeviceProperties().limits;
443
444         // Compute coordinates.
445         {
446                 for (vector<Vec3>::iterator coord = coords.begin(); coord != coords.end(); ++coord)
447                 {
448                         coord->x() = rnd.getFloat(-0.9f, 0.9f);
449                         coord->y() = rnd.getFloat(-0.9f, 0.9f);
450                         coord->z() = limits.pointSizeRange[0] + float(rnd.getInt(0, int((limits.pointSizeRange[1] - limits.pointSizeRange[0]) / limits.pointSizeGranularity))) * limits.pointSizeGranularity;
451                 }
452         }
453
454         setup();
455         addAttribute(0u, VK_FORMAT_R32G32B32_SFLOAT, deUint32(sizeof(Vec3)), numPoints, &coords[0]);
456         render(numPoints, 0, DE_NULL, VK_PRIMITIVE_TOPOLOGY_POINT_LIST);
457         copy(resImage.getAccess(), getResultImage().getAccess());
458
459         // Draw reference
460         clear(refImage.getAccess(), m_clearColor);
461         for (vector<Vec3>::const_iterator pointIter = coords.begin(); pointIter != coords.end(); ++pointIter)
462         {
463                 const int       x0              = deRoundFloatToInt32(float(width) *(pointIter->x()*0.5f + 0.5f) - pointIter->z()*0.5f);
464                 const int       y0              = deRoundFloatToInt32(float(height)*(pointIter->y()*0.5f + 0.5f) - pointIter->z()*0.5f);
465                 const int       x1              = deRoundFloatToInt32(float(width) *(pointIter->x()*0.5f + 0.5f) + pointIter->z()*0.5f);
466                 const int       y1              = deRoundFloatToInt32(float(height)*(pointIter->y()*0.5f + 0.5f) + pointIter->z()*0.5f);
467                 const int       w               = x1-x0;
468                 const int       h               = y1-y0;
469
470                 for (int yo = 0; yo < h; yo++)
471                 {
472                         for (int xo = 0; xo < w; xo++)
473                         {
474                                 const float             xf              = (float(xo)+0.5f) / float(w);
475                                 const float             yf              = (float(yo)+0.5f) / float(h);
476                                 const Vec4              color   (xf, yf, 0.0f, 1.0f);
477                                 const int               dx              = x0+xo;
478                                 const int               dy              = y0+yo;
479
480                                 if (de::inBounds(dx, 0, refImage.getWidth()) && de::inBounds(dy, 0, refImage.getHeight()))
481                                         refImage.setPixel(dx, dy, RGBA(color));
482                         }
483                 }
484         }
485
486         compareOk = fuzzyCompare(m_context.getTestContext().getLog(), "Result", "Image comparison result", refImage, resImage, threshold, COMPARE_LOG_RESULT);
487
488         if (compareOk)
489                 return TestStatus::pass("Result image matches reference");
490         else
491                 return TestStatus::fail("Image mismatch");
492 }
493
494 void BuiltinGlPointCoordCaseInstance::setupDefaultInputs (void)
495 {
496 }
497
498 class BuiltinGlPointCoordCase : public TestCase
499 {
500 public:
501                                                                 BuiltinGlPointCoordCase (TestContext& testCtx, const string& name, const string& description);
502         virtual                                         ~BuiltinGlPointCoordCase        (void);
503
504         void                                            initPrograms                            (SourceCollections& dst) const;
505         TestInstance*                           createInstance                          (Context& context) const;
506
507 private:
508                                                                 BuiltinGlPointCoordCase (const BuiltinGlPointCoordCase&);       // not allowed!
509         BuiltinGlPointCoordCase&        operator=                                       (const BuiltinGlPointCoordCase&);       // not allowed!
510 };
511
512 BuiltinGlPointCoordCase::BuiltinGlPointCoordCase (TestContext& testCtx, const string& name, const string& description)
513         : TestCase(testCtx, name, description)
514 {
515 }
516
517 BuiltinGlPointCoordCase::~BuiltinGlPointCoordCase (void)
518 {
519 }
520
521 void BuiltinGlPointCoordCase::initPrograms (SourceCollections& dst) const
522 {
523         dst.glslSources.add("vert") << glu::VertexSource(
524                 "#version 310 es\n"
525                 "layout(location = 0) in highp vec3 a_position;\n"
526                 "void main (void)\n"
527                 "{\n"
528                 "    gl_Position = vec4(a_position.xy, 0.0, 1.0);\n"
529                 "    gl_PointSize = a_position.z;\n"
530                 "}\n");
531
532         dst.glslSources.add("frag") << glu::FragmentSource(
533                 "#version 310 es\n"
534                 "layout(location = 0) out lowp vec4 o_color;\n"
535                 "void main (void)\n"
536                 "{\n"
537                 "    o_color = vec4(gl_PointCoord, 0.0, 1.0);\n"
538                 "}\n");
539 }
540
541 TestInstance* BuiltinGlPointCoordCase::createInstance (Context& context) const
542 {
543         return new BuiltinGlPointCoordCaseInstance(context);
544 }
545
546 enum ShaderInputTypeBits
547 {
548         SHADER_INPUT_BUILTIN_BIT        = 0x01,
549         SHADER_INPUT_VARYING_BIT        = 0x02,
550         SHADER_INPUT_CONSTANT_BIT       = 0x04
551 };
552
553 typedef deUint16 ShaderInputTypes;
554
555 string shaderInputTypeToString (ShaderInputTypes type)
556 {
557         string typeString = "input";
558
559         if (type == 0)
560                 return "input_none";
561
562         if (type & SHADER_INPUT_BUILTIN_BIT)
563                 typeString += "_builtin";
564
565         if (type & SHADER_INPUT_VARYING_BIT)
566                 typeString += "_varying";
567
568         if (type & SHADER_INPUT_CONSTANT_BIT)
569                 typeString += "_constant";
570
571         return typeString;
572 }
573
574 class BuiltinInputVariationsCaseInstance : public ShaderRenderCaseInstance
575 {
576 public:
577                                                         BuiltinInputVariationsCaseInstance      (Context& context, const ShaderInputTypes shaderInputTypes);
578
579         TestStatus                              iterate                                                         (void);
580         virtual void                    setupDefaultInputs                                      (void);
581         virtual void                    updatePushConstants                                     (vk::VkCommandBuffer commandBuffer, vk::VkPipelineLayout pipelineLayout);
582
583 private:
584         const ShaderInputTypes  m_shaderInputTypes;
585         const Vec4                              m_constantColor;
586 };
587
588 BuiltinInputVariationsCaseInstance::BuiltinInputVariationsCaseInstance (Context& context, const ShaderInputTypes shaderInputTypes)
589         : ShaderRenderCaseInstance      (context)
590         , m_shaderInputTypes            (shaderInputTypes)
591         , m_constantColor                       (0.1f, 0.05f, 0.2f, 0.0f)
592 {
593 }
594
595 TestStatus BuiltinInputVariationsCaseInstance::iterate (void)
596 {
597         const UVec2                                     viewportSize    = getViewportSize();
598         const int                                       width                   = viewportSize.x();
599         const int                                       height                  = viewportSize.y();
600         const tcu::RGBA                         threshold               (2, 2, 2, 2);
601         Surface                                         resImage                (width, height);
602         Surface                                         refImage                (width, height);
603         bool                                            compareOk               = false;
604         const VkPushConstantRange       pcRanges                =
605         {
606                 VK_SHADER_STAGE_FRAGMENT_BIT,   // VkShaderStageFlags   stageFlags;
607                 0u,                                                             // deUint32                             offset;
608                 sizeof(Vec4)                                    // deUint32                             size;
609         };
610         const deUint16                          indices[12]             =
611         {
612                 0, 4, 1,
613                 0, 5, 4,
614                 1, 2, 3,
615                 1, 3, 4
616         };
617
618         setup();
619
620         if (m_shaderInputTypes & SHADER_INPUT_CONSTANT_BIT)
621                 setPushConstantRanges(1, &pcRanges);
622
623         render(6, 4, indices);
624         copy(resImage.getAccess(), getResultImage().getAccess());
625
626         // Reference image
627         for (int y = 0; y < refImage.getHeight(); y++)
628         {
629                 for (int x = 0; x < refImage.getWidth(); x++)
630                 {
631                         Vec4 color (0.1f, 0.2f, 0.3f, 1.0f);
632
633                         if (((m_shaderInputTypes & SHADER_INPUT_BUILTIN_BIT) && (x < refImage.getWidth() / 2)) ||
634                                 !(m_shaderInputTypes & SHADER_INPUT_BUILTIN_BIT))
635                         {
636                                 if (m_shaderInputTypes & SHADER_INPUT_VARYING_BIT)
637                                 {
638                                         const float xf = (float(x)+.5f) / float(refImage.getWidth());
639                                         color += Vec4(0.6f * (1 - xf), 0.6f * xf, 0.0f, 0.0f);
640                                 }
641                                 else
642                                         color += Vec4(0.3f, 0.2f, 0.1f, 0.0f);
643                         }
644
645                         if (m_shaderInputTypes & SHADER_INPUT_CONSTANT_BIT)
646                                 color += m_constantColor;
647
648                         refImage.setPixel(x, y, RGBA(color));
649                 }
650         }
651
652         compareOk = pixelThresholdCompare(m_context.getTestContext().getLog(), "Result", "Image comparison result", refImage, resImage, threshold, COMPARE_LOG_RESULT);
653
654         if (compareOk)
655                 return TestStatus::pass("Result image matches reference");
656         else
657                 return TestStatus::fail("Image mismatch");
658 }
659
660 void BuiltinInputVariationsCaseInstance::setupDefaultInputs (void)
661 {
662         const float vertices[] =
663         {
664                 -1.0f, -1.0f, 0.0f, 1.0f,
665                  0.0f, -1.0f, 0.0f, 1.0f,
666                  1.0f, -1.0f, 0.0f, 1.0f,
667                  1.0f,  1.0f, 0.0f, 1.0f,
668                  0.0f,  1.0f, 0.0f, 1.0f,
669                 -1.0f,  1.0f, 0.0f, 1.0f
670         };
671
672         addAttribute(0u, VK_FORMAT_R32G32B32A32_SFLOAT, deUint32(sizeof(float) * 4), 6, vertices);
673
674         if (m_shaderInputTypes & SHADER_INPUT_VARYING_BIT)
675         {
676                 const float colors[] =
677                 {
678                          0.6f,  0.0f, 0.0f, 1.0f,
679                          0.3f,  0.3f, 0.0f, 1.0f,
680                          0.0f,  0.6f, 0.0f, 1.0f,
681                          0.0f,  0.6f, 0.0f, 1.0f,
682                          0.3f,  0.3f, 0.0f, 1.0f,
683                          0.6f,  0.0f, 0.0f, 1.0f
684                 };
685                 addAttribute(1u, VK_FORMAT_R32G32B32A32_SFLOAT, deUint32(sizeof(float) * 4), 6, colors);
686         }
687 }
688
689 void BuiltinInputVariationsCaseInstance::updatePushConstants (vk::VkCommandBuffer commandBuffer, vk::VkPipelineLayout pipelineLayout)
690 {
691         if (m_shaderInputTypes & SHADER_INPUT_CONSTANT_BIT)
692         {
693                 const DeviceInterface& vk = m_context.getDeviceInterface();
694                 vk.cmdPushConstants(commandBuffer, pipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(Vec4), &m_constantColor);
695         }
696 }
697
698 class BuiltinInputVariationsCase : public TestCase
699 {
700 public:
701                                                                 BuiltinInputVariationsCase      (TestContext& testCtx, const string& name, const string& description, const ShaderInputTypes shaderInputTypes);
702         virtual                                         ~BuiltinInputVariationsCase     (void);
703
704         void                                            initPrograms                            (SourceCollections& dst) const;
705         TestInstance*                           createInstance                          (Context& context) const;
706
707 private:
708                                                                 BuiltinInputVariationsCase      (const BuiltinInputVariationsCase&);    // not allowed!
709         BuiltinInputVariationsCase&     operator=                                       (const BuiltinInputVariationsCase&);    // not allowed!
710         const ShaderInputTypes          m_shaderInputTypes;
711 };
712
713 BuiltinInputVariationsCase::BuiltinInputVariationsCase (TestContext& testCtx, const string& name, const string& description, ShaderInputTypes shaderInputTypes)
714         : TestCase                              (testCtx, name, description)
715         , m_shaderInputTypes    (shaderInputTypes)
716 {
717 }
718
719 BuiltinInputVariationsCase::~BuiltinInputVariationsCase (void)
720 {
721 }
722
723 void BuiltinInputVariationsCase::initPrograms (SourceCollections& dst) const
724 {
725         map<string, string>                     vertexParams;
726         map<string, string>                     fragmentParams;
727         const tcu::StringTemplate       vertexCodeTemplate              (
728                 "#version 450\n"
729                 "layout(location = 0) in highp vec4 a_position;\n"
730                 "out gl_PerVertex {\n"
731                 "       vec4 gl_Position;\n"
732                 "};\n"
733                 "${VARYING_DECL}"
734                 "void main (void)\n"
735                 "{\n"
736                 "    gl_Position = a_position;\n"
737                 "    ${VARYING_USAGE}"
738                 "}\n");
739
740         const tcu::StringTemplate       fragmentCodeTemplate    (
741                 "#version 450\n"
742                 "${VARYING_DECL}"
743                 "${CONSTANT_DECL}"
744                 "layout(location = 0) out highp vec4 o_color;\n"
745                 "void main (void)\n"
746                 "{\n"
747                 "    o_color = vec4(0.1, 0.2, 0.3, 1.0);\n"
748                 "    ${BUILTIN_USAGE}"
749                 "    ${VARYING_USAGE}"
750                 "    ${CONSTANT_USAGE}"
751                 "}\n");
752
753         vertexParams["VARYING_DECL"]            =
754                 m_shaderInputTypes & SHADER_INPUT_VARYING_BIT   ? "layout(location = 1) in highp vec4 a_color;\n"
755                                                                                                                   "layout(location = 0) out highp vec4 v_color;\n"
756                                                                                                                 : "";
757
758         vertexParams["VARYING_USAGE"]           =
759                 m_shaderInputTypes & SHADER_INPUT_VARYING_BIT   ? "v_color = a_color;\n"
760                                                                                                                 : "";
761
762         fragmentParams["VARYING_DECL"]          =
763                 m_shaderInputTypes & SHADER_INPUT_VARYING_BIT   ? "layout(location = 0) in highp vec4 a_color;\n"
764                                                                                                                 : "";
765
766         fragmentParams["CONSTANT_DECL"]         =
767                 m_shaderInputTypes & SHADER_INPUT_CONSTANT_BIT  ? "layout(push_constant) uniform PCBlock {\n"
768                                                                                                                   "  vec4 color;\n"
769                                                                                                                   "} pc;\n"
770                                                                                                                 : "";
771
772         fragmentParams["BUILTIN_USAGE"]         =
773                 m_shaderInputTypes & SHADER_INPUT_BUILTIN_BIT   ? "if (gl_FrontFacing)\n"
774                                                                                                                 : "";
775
776         fragmentParams["VARYING_USAGE"]         =
777                 m_shaderInputTypes & SHADER_INPUT_VARYING_BIT   ? "o_color += vec4(a_color.xyz, 0.0);\n"
778                                                                                                                 : "o_color += vec4(0.3, 0.2, 0.1, 0.0);\n";
779
780
781         fragmentParams["CONSTANT_USAGE"]        =
782                 m_shaderInputTypes & SHADER_INPUT_CONSTANT_BIT  ? "o_color += pc.color;\n"
783                                                                                                                 : "";
784
785         dst.glslSources.add("vert") << glu::VertexSource(vertexCodeTemplate.specialize(vertexParams));
786         dst.glslSources.add("frag") << glu::FragmentSource(fragmentCodeTemplate.specialize(fragmentParams));
787 }
788
789 TestInstance* BuiltinInputVariationsCase::createInstance (Context& context) const
790 {
791         return new BuiltinInputVariationsCaseInstance(context, m_shaderInputTypes);
792 }
793
794 } // anonymous
795
796 TestCaseGroup* createBuiltinVarTests (TestContext& testCtx)
797 {
798         de::MovePtr<TestCaseGroup> builtinGroup                 (new TestCaseGroup(testCtx, "builtin_var", "Shader builtin variable tests."));
799         de::MovePtr<TestCaseGroup> simpleGroup                  (new TestCaseGroup(testCtx, "simple", "Simple cases."));
800         de::MovePtr<TestCaseGroup> inputVariationsGroup (new TestCaseGroup(testCtx, "input_variations", "Input type variation tests."));
801
802         simpleGroup->addChild(new BuiltinGlFrontFacingCase(testCtx, "frontfacing", "FrontFacing test"));
803         simpleGroup->addChild(new BuiltinGlFragCoordXYZCase(testCtx, "fragcoord_xyz", "FragCoord xyz test"));
804         simpleGroup->addChild(new BuiltinGlFragCoordWCase(testCtx, "fragcoord_w", "FragCoord w test"));
805         simpleGroup->addChild(new BuiltinGlPointCoordCase(testCtx, "pointcoord", "PointCoord test"));
806
807         builtinGroup->addChild(simpleGroup.release());
808
809         for (deUint16 shaderType = 0; shaderType <= (SHADER_INPUT_BUILTIN_BIT | SHADER_INPUT_VARYING_BIT | SHADER_INPUT_CONSTANT_BIT); ++shaderType)
810         {
811                 inputVariationsGroup->addChild(new BuiltinInputVariationsCase(testCtx, shaderInputTypeToString(shaderType), "Input variation test", shaderType));
812         }
813
814         builtinGroup->addChild(inputVariationsGroup.release());
815         return builtinGroup.release();
816 }
817
818 } // sr
819 } // vkt