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