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
BuiltinGlFrontFacingCaseInstance(Context & context)59 BuiltinGlFrontFacingCaseInstance::BuiltinGlFrontFacingCaseInstance (Context& context)
60 : ShaderRenderCaseInstance (context)
61 {
62 }
63
iterate(void)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
setupDefaultInputs(void)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
BuiltinGlFrontFacingCase(TestContext & testCtx,const string & name,const string & description)131 BuiltinGlFrontFacingCase::BuiltinGlFrontFacingCase (TestContext& testCtx, const string& name, const string& description)
132 : TestCase(testCtx, name, description)
133 {
134 }
135
~BuiltinGlFrontFacingCase(void)136 BuiltinGlFrontFacingCase::~BuiltinGlFrontFacingCase (void)
137 {
138 }
139
initPrograms(SourceCollections & dst) const140 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
createInstance(Context & context) const162 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
BuiltinGlFragCoordXYZCaseInstance(Context & context)176 BuiltinGlFragCoordXYZCaseInstance::BuiltinGlFragCoordXYZCaseInstance (Context& context)
177 : ShaderRenderCaseInstance (context)
178 {
179 }
180
iterate(void)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
setupDefaultInputs(void)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
BuiltinGlFragCoordXYZCase(TestContext & testCtx,const string & name,const string & description)254 BuiltinGlFragCoordXYZCase::BuiltinGlFragCoordXYZCase (TestContext& testCtx, const string& name, const string& description)
255 : TestCase(testCtx, name, description)
256 {
257 }
258
~BuiltinGlFragCoordXYZCase(void)259 BuiltinGlFragCoordXYZCase::~BuiltinGlFragCoordXYZCase (void)
260 {
261 }
262
initPrograms(SourceCollections & dst) const263 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
createInstance(Context & context) const283 TestInstance* BuiltinGlFragCoordXYZCase::createInstance (Context& context) const
284 {
285 return new BuiltinGlFragCoordXYZCaseInstance(context);
286 }
287
projectedTriInterpolate(const Vec3 & s,const Vec3 & w,float nx,float ny)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
BuiltinGlFragCoordWCaseInstance(Context & context)307 BuiltinGlFragCoordWCaseInstance::BuiltinGlFragCoordWCaseInstance (Context& context)
308 : ShaderRenderCaseInstance (context)
309 , m_w (1.7f, 2.0f, 1.2f, 1.0f)
310 {
311 }
312
iterate(void)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
setupDefaultInputs(void)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
BuiltinGlFragCoordWCase(TestContext & testCtx,const string & name,const string & description)383 BuiltinGlFragCoordWCase::BuiltinGlFragCoordWCase (TestContext& testCtx, const string& name, const string& description)
384 : TestCase(testCtx, name, description)
385 {
386 }
387
~BuiltinGlFragCoordWCase(void)388 BuiltinGlFragCoordWCase::~BuiltinGlFragCoordWCase (void)
389 {
390 }
391
initPrograms(SourceCollections & dst) const392 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
createInstance(Context & context) const411 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
BuiltinGlPointCoordCaseInstance(Context & context)425 BuiltinGlPointCoordCaseInstance::BuiltinGlPointCoordCaseInstance (Context& context)
426 : ShaderRenderCaseInstance (context)
427 {
428 }
429
iterate(void)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
setupDefaultInputs(void)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
BuiltinGlPointCoordCase(TestContext & testCtx,const string & name,const string & description)524 BuiltinGlPointCoordCase::BuiltinGlPointCoordCase (TestContext& testCtx, const string& name, const string& description)
525 : TestCase(testCtx, name, description)
526 {
527 }
528
~BuiltinGlPointCoordCase(void)529 BuiltinGlPointCoordCase::~BuiltinGlPointCoordCase (void)
530 {
531 }
532
initPrograms(SourceCollections & dst) const533 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
createInstance(Context & context) const553 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
shaderInputTypeToString(ShaderInputTypes type)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
BuiltinInputVariationsCaseInstance(Context & context,const ShaderInputTypes shaderInputTypes)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
iterate(void)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
setupDefaultInputs(void)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
updatePushConstants(vk::VkCommandBuffer commandBuffer,vk::VkPipelineLayout pipelineLayout)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
BuiltinInputVariationsCase(TestContext & testCtx,const string & name,const string & description,ShaderInputTypes shaderInputTypes)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
~BuiltinInputVariationsCase(void)731 BuiltinInputVariationsCase::~BuiltinInputVariationsCase (void)
732 {
733 }
734
initPrograms(SourceCollections & dst) const735 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
createInstance(Context & context) const801 TestInstance* BuiltinInputVariationsCase::createInstance (Context& context) const
802 {
803 return new BuiltinInputVariationsCaseInstance(context, m_shaderInputTypes);
804 }
805
806 } // anonymous
807
createBuiltinVarTests(TestContext & testCtx)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
832