1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2017-2020 The Khronos Group Inc.
6 * Copyright (c) 2020 AMD
7 *
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 *
20 *//*!
21 * \file
22 * \brief Tests for VK_KHR_fragment_shading_rate
23 *//*--------------------------------------------------------------------*/
24
25 #include "vktFragmentShadingRatePixelConsistency.hpp"
26
27 #include "vkBufferWithMemory.hpp"
28 #include "vkImageWithMemory.hpp"
29 #include "vkQueryUtil.hpp"
30 #include "vkBuilderUtil.hpp"
31 #include "vkCmdUtil.hpp"
32 #include "vkTypeUtil.hpp"
33 #include "vkObjUtil.hpp"
34 #include "vkImageUtil.hpp"
35 #include "vkQueryUtil.hpp"
36 #include "vkPlatform.hpp"
37
38 #include "vktTestGroupUtil.hpp"
39 #include "vktTestCase.hpp"
40 #include "vktCustomInstancesDevices.hpp"
41
42 #include "deDefs.h"
43 #include "deMath.h"
44 #include "deRandom.h"
45 #include "deSharedPtr.hpp"
46 #include "deString.h"
47
48 #include "tcuTestCase.hpp"
49 #include "tcuTestLog.hpp"
50 #include "tcuCommandLine.hpp"
51
52 #include <limits>
53 #include <string>
54 #include <sstream>
55
56 namespace vkt
57 {
58 namespace FragmentShadingRate
59 {
60 namespace
61 {
62 using namespace vk;
63 using namespace std;
64
65 struct CaseDef
66 {
67 VkExtent2D shadingRate;
68 VkSampleCountFlagBits samples;
69 VkExtent2D framebufferExtent;
70 bool zwCoord;
71 };
72
73 struct Vertex
74 {
75 float x;
76 float y;
77 };
78
79 Vertex basicTriangles[6] =
80 {
81 {-1.0f, -1.0f},
82 { 1.0f, -1.0f},
83 { 1.0f, 1.0f},
84
85 {-1.0f, 1.0f},
86 { 1.0f, -1.0f},
87 { 1.0f, 1.0f},
88 };
89
createImageRobustnessDevice(Context & context)90 Move<VkDevice> createImageRobustnessDevice(Context& context)
91 {
92 const InstanceInterface& instance = context.getInstanceInterface();
93 const vk::VkPhysicalDevice physicalDevice = context.getPhysicalDevice();
94 const float queuePriority = 1.0f;
95
96 // Create a universal queue
97 const VkDeviceQueueCreateInfo queueParams =
98 {
99 VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, // VkStructureType sType;
100 DE_NULL, // const void* pNext;
101 0u, // VkDeviceQueueCreateFlags flags;
102 context.getUniversalQueueFamilyIndex(), // deUint32 queueFamilyIndex;
103 1u, // deUint32 queueCount;
104 &queuePriority // const float* pQueuePriorities;
105 };
106
107 // Add image robustness extension if supported
108 std::vector<const char*> deviceExtensions;
109
110 deviceExtensions.push_back("VK_KHR_fragment_shading_rate");
111
112 if (context.isDeviceFunctionalitySupported("VK_EXT_image_robustness"))
113 {
114 deviceExtensions.push_back("VK_EXT_image_robustness");
115 }
116
117 VkPhysicalDeviceFragmentShadingRateFeaturesKHR fsrFeatures =
118 {
119 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_FEATURES_KHR, // VkStructureType sType;
120 DE_NULL, // void* pNext;
121 DE_FALSE, // VkBool32 pipelineFragmentShadingRate;
122 DE_FALSE, // VkBool32 primitiveFragmentShadingRate;
123 DE_FALSE, // VkBool32 attachmentFragmentShadingRate;
124 };
125
126 VkPhysicalDeviceFeatures2 enabledFeatures;
127 enabledFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
128 enabledFeatures.pNext = &fsrFeatures;
129
130 instance.getPhysicalDeviceFeatures2(physicalDevice, &enabledFeatures);
131
132 const VkDeviceCreateInfo deviceParams =
133 {
134 VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, // VkStructureType sType;
135 &enabledFeatures, // const void* pNext;
136 0u, // VkDeviceCreateFlags flags;
137 1u, // deUint32 queueCreateInfoCount;
138 &queueParams, // const VkDeviceQueueCreateInfo* pQueueCreateInfos;
139 0u, // deUint32 enabledLayerCount;
140 DE_NULL, // const char* const* ppEnabledLayerNames;
141 static_cast<deUint32>(deviceExtensions.size()), // deUint32 enabledExtensionCount;
142 deviceExtensions.empty() ? DE_NULL : &deviceExtensions[0], // const char* const* ppEnabledExtensionNames;
143 DE_NULL, // const VkPhysicalDeviceFeatures* pEnabledFeatures;
144 };
145
146 return createCustomDevice(context.getTestContext().getCommandLine().isValidationEnabled(), context.getPlatformInterface(),
147 context.getInstance(), context.getInstanceInterface(), context.getPhysicalDevice(), &deviceParams);
148 }
149
150 class FSRPixelConsistencyInstance : public TestInstance
151 {
152 public:
153 FSRPixelConsistencyInstance (Context& context, const CaseDef& data);
154 ~FSRPixelConsistencyInstance(void);
155 tcu::TestStatus iterate (void);
156
157 private:
158 void clampShadingRate();
159 tcu::TestStatus verifyResult(tcu::ConstPixelBufferAccess& resultBuffer, const deUint32 index);
160
161 CaseDef m_data;
162 vector<VkExtent2D> m_shadingRateClamped;
163
164 deUint32 m_supportedFragmentShadingRateCount;
165 vector<VkPhysicalDeviceFragmentShadingRateKHR> m_supportedFragmentShadingRates;
166 };
167
FSRPixelConsistencyInstance(Context & context,const CaseDef & data)168 FSRPixelConsistencyInstance::FSRPixelConsistencyInstance(Context& context, const CaseDef& data)
169 : vkt::TestInstance (context)
170 , m_data(data)
171 , m_supportedFragmentShadingRateCount(0)
172 {
173 // Fetch information about supported fragment shading rates
174 context.getInstanceInterface().getPhysicalDeviceFragmentShadingRatesKHR(context.getPhysicalDevice(), &m_supportedFragmentShadingRateCount, DE_NULL);
175
176 m_supportedFragmentShadingRates.resize(m_supportedFragmentShadingRateCount);
177 for (deUint32 i = 0; i < m_supportedFragmentShadingRateCount; ++i)
178 {
179 m_supportedFragmentShadingRates[i].sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_KHR;
180 m_supportedFragmentShadingRates[i].pNext = nullptr;
181 }
182 context.getInstanceInterface().getPhysicalDeviceFragmentShadingRatesKHR(context.getPhysicalDevice(), &m_supportedFragmentShadingRateCount, &m_supportedFragmentShadingRates[0]);
183
184 clampShadingRate();
185 }
186
~FSRPixelConsistencyInstance(void)187 FSRPixelConsistencyInstance::~FSRPixelConsistencyInstance(void)
188 {
189 }
190
191 class FSRPixelConsistencyTestCase : public TestCase
192 {
193 public:
194 FSRPixelConsistencyTestCase (tcu::TestContext& context, const char* name, const char* desc, const CaseDef data);
195 ~FSRPixelConsistencyTestCase (void);
196 virtual void initPrograms (SourceCollections& programCollection) const;
197 virtual TestInstance* createInstance (Context& context) const;
198 virtual void checkSupport (Context& context) const;
199
200 private:
201
202 CaseDef m_data;
203 };
204
FSRPixelConsistencyTestCase(tcu::TestContext & context,const char * name,const char * desc,const CaseDef data)205 FSRPixelConsistencyTestCase::FSRPixelConsistencyTestCase(tcu::TestContext& context, const char* name, const char* desc, const CaseDef data)
206 : vkt::TestCase (context, name, desc)
207 , m_data (data)
208 {
209 }
210
~FSRPixelConsistencyTestCase(void)211 FSRPixelConsistencyTestCase::~FSRPixelConsistencyTestCase(void)
212 {
213 }
214
checkSupport(Context & context) const215 void FSRPixelConsistencyTestCase::checkSupport(Context& context) const
216 {
217 const VkImageUsageFlags cbUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
218 VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT |
219 VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
220 VK_IMAGE_USAGE_TRANSFER_DST_BIT;
221
222 context.requireDeviceFunctionality("VK_KHR_fragment_shading_rate");
223
224 if (!context.getFragmentShadingRateFeatures().pipelineFragmentShadingRate)
225 TCU_THROW(NotSupportedError, "pipelineFragmentShadingRate not supported");
226
227 VkImageFormatProperties imageProperties;
228 VkResult result = context.getInstanceInterface().getPhysicalDeviceImageFormatProperties(context.getPhysicalDevice(), VK_FORMAT_R32G32_UINT, VK_IMAGE_TYPE_2D,
229 VK_IMAGE_TILING_OPTIMAL, cbUsage , 0, &imageProperties);
230
231 if (result == VK_ERROR_FORMAT_NOT_SUPPORTED)
232 TCU_THROW(NotSupportedError, "VK_FORMAT_R32G32_UINT not supported");
233
234 if (!(imageProperties.sampleCounts & m_data.samples))
235 TCU_THROW(NotSupportedError, "Image sample count not supported");
236
237 if ((imageProperties.maxExtent.width < m_data.framebufferExtent.width) || (imageProperties.maxExtent.height < m_data.framebufferExtent.height))
238 TCU_THROW(NotSupportedError, "Image max extents are smaller than required");
239 }
240
initPrograms(SourceCollections & programCollection) const241 void FSRPixelConsistencyTestCase::initPrograms (SourceCollections& programCollection) const
242 {
243 std::stringstream vss;
244
245 vss <<
246 "#version 450 core\n"
247 "layout(location = 0) in vec2 position;\n"
248 "out gl_PerVertex\n"
249 "{\n"
250 " vec4 gl_Position;\n"
251 "};\n"
252 "void main()\n"
253 "{\n";
254 if (!m_data.zwCoord)
255 {
256 vss <<
257 " gl_Position = vec4(position, 0, 1);\n";
258 }
259 else
260 {
261 vss <<
262 " gl_Position = vec4(position, position);\n";
263 }
264 vss <<
265 "}\n";
266
267 programCollection.glslSources.add("vert") << glu::VertexSource(vss.str());
268
269 std::stringstream fssPass0;
270
271 fssPass0 <<
272 "#version 450 core\n"
273 "layout(push_constant) uniform PC {\n"
274 " uvec2 shadingRate[2];\n"
275 "} pc;\n"
276 "layout(location = 0) out uvec2 col0;\n"
277 "void main()\n"
278 "{\n";
279 if (!m_data.zwCoord)
280 {
281 fssPass0 <<
282 " col0.x = (uint(gl_FragCoord.x) % pc.shadingRate[0].x) + ((uint(gl_FragCoord.y) % pc.shadingRate[0].y) * pc.shadingRate[0].x);\n"
283 " col0.y = (uint(gl_FragCoord.x) % pc.shadingRate[1].x) + ((uint(gl_FragCoord.y) % pc.shadingRate[1].y) * pc.shadingRate[1].x);\n";
284 }
285 else
286 {
287 fssPass0 <<
288 " col0.x = (uint(gl_FragCoord.z) % pc.shadingRate[0].x) + ((uint(gl_FragCoord.w) % pc.shadingRate[0].y) * pc.shadingRate[0].x);\n"
289 " col0.y = (uint(gl_FragCoord.z) % pc.shadingRate[1].x) + ((uint(gl_FragCoord.w) % pc.shadingRate[1].y) * pc.shadingRate[1].x);\n";
290 }
291 fssPass0 <<
292 "}\n";
293
294 programCollection.glslSources.add("frag_pass0") << glu::FragmentSource(fssPass0.str());
295
296 std::stringstream fssPass1;
297
298 fssPass1 <<
299 "#version 450 core\n";
300
301 if (m_data.samples == VK_SAMPLE_COUNT_1_BIT)
302 {
303 fssPass1 <<
304 "layout(input_attachment_index=0, set=0, binding=0) uniform usubpassInput inputAttachment;\n";
305 }
306 else
307 {
308 fssPass1 <<
309 "layout(input_attachment_index=0, set=0, binding=0) uniform usubpassInputMS inputAttachment;\n";
310 }
311
312 fssPass1 <<
313 "layout(location = 0) out uvec2 col0;\n"
314 "void main()\n"
315 "{\n";
316
317 if (m_data.samples == VK_SAMPLE_COUNT_1_BIT)
318 {
319 fssPass1 <<
320 " col0 = subpassLoad(inputAttachment).xy;\n";
321 }
322 else
323 {
324 fssPass1 <<
325 " col0 = subpassLoad(inputAttachment, 0).xy;\n";
326 }
327
328 fssPass1 <<
329 "}\n";
330
331 programCollection.glslSources.add("frag_pass1") << glu::FragmentSource(fssPass1.str());
332 }
333
createInstance(Context & context) const334 TestInstance* FSRPixelConsistencyTestCase::createInstance (Context& context) const
335 {
336 return new FSRPixelConsistencyInstance(context, m_data);
337 }
338
compareShadingRate(VkExtent2D ext1,VkExtent2D ext2)339 bool compareShadingRate(VkExtent2D ext1, VkExtent2D ext2)
340 {
341 deUint32 ratio1 = std::max(ext1.width, ext1.height) / std::min(ext1.width, ext1.height);
342 deUint32 ratio2 = std::max(ext2.width, ext2.height) / std::min(ext2.width, ext2.height);
343
344 return ratio1 < ratio2;
345 }
346
clampShadingRate()347 void FSRPixelConsistencyInstance::clampShadingRate()
348 {
349 deUint32 desiredSize = m_data.shadingRate.width * m_data.shadingRate.height;
350
351 while (desiredSize > 0)
352 {
353 // Find modes that maximize the area
354 for (deUint32 i = 0; i < m_supportedFragmentShadingRateCount; ++i)
355 {
356 const VkPhysicalDeviceFragmentShadingRateKHR& supportedRate = m_supportedFragmentShadingRates[i];
357
358 if (supportedRate.sampleCounts & VK_SAMPLE_COUNT_1_BIT)
359 {
360 // We found exact match
361 if (supportedRate.fragmentSize.width == m_data.shadingRate.width &&
362 supportedRate.fragmentSize.height == m_data.shadingRate.height)
363 {
364 m_shadingRateClamped.push_back(supportedRate.fragmentSize);
365
366 return;
367 }
368 else
369 {
370 if (supportedRate.fragmentSize.width <= m_data.shadingRate.width &&
371 supportedRate.fragmentSize.height <= m_data.shadingRate.height &&
372 supportedRate.fragmentSize.width * supportedRate.fragmentSize.height == desiredSize)
373 {
374 m_shadingRateClamped.push_back(supportedRate.fragmentSize);
375 }
376 }
377 }
378 }
379 if (!m_shadingRateClamped.empty())
380 {
381 // Sort the modes so that the ones with the smallest aspect ratio are in front
382 std::sort(m_shadingRateClamped.begin(), m_shadingRateClamped.end(), compareShadingRate);
383
384 deUint32 desiredRatio = std::max(m_shadingRateClamped[0].width, m_shadingRateClamped[0].height) /
385 std::min(m_shadingRateClamped[0].width, m_shadingRateClamped[0].height);
386
387 // Leave only entries with the smallest aspect ratio
388 auto it = m_shadingRateClamped.begin();
389 while (it != m_shadingRateClamped.end())
390 {
391 deUint32 ratio = std::max(it->width, it->height) / std::min(it->width, it->height);
392
393 if (ratio < desiredRatio)
394 {
395 it = m_shadingRateClamped.erase(it, m_shadingRateClamped.end());
396 }
397 else
398 {
399 ++it;
400 }
401 }
402
403 return;
404 }
405 else
406 {
407 desiredSize /= 2;
408 }
409 }
410 DE_ASSERT(0);
411
412 return;
413 }
414
verifyResult(tcu::ConstPixelBufferAccess & resultBuffer,const deUint32 index)415 tcu::TestStatus FSRPixelConsistencyInstance::verifyResult(tcu::ConstPixelBufferAccess& resultBuffer, const deUint32 index)
416 {
417 deUint32 pixelIndex = std::numeric_limits<unsigned int>::max();
418 deUint32 pixelOutsideIndex = std::numeric_limits<unsigned int>::max();
419
420 for (int y = 0; y < resultBuffer.getHeight(); y++)
421 {
422 for (int x = 0; x < resultBuffer.getWidth(); x++)
423 {
424 deUint32 pixel = resultBuffer.getPixelUint(x, y)[index];
425
426 // If pixel was not covered by any triangle, we skip it
427 if (pixel == std::numeric_limits<unsigned int>::max())
428 {
429 continue;
430 }
431
432 // We check if pixel is part of fragment area that is partially outside of framebuffer area
433 deBool outsideW = (x / m_shadingRateClamped[index].width + 1) * m_shadingRateClamped[index].width > static_cast<deUint32>(resultBuffer.getWidth());
434 deBool outsideH = (y / m_shadingRateClamped[index].height + 1) * m_shadingRateClamped[index].height > static_cast<deUint32>(resultBuffer.getHeight());
435
436 if (outsideW || outsideH)
437 {
438 // If image robustness is enabled such pixel can have either a value of 0 or one of the values from the area inside framebuffer
439 if (m_context.isDeviceFunctionalitySupported("VK_EXT_image_robustness"))
440 {
441 if (pixelOutsideIndex == std::numeric_limits<unsigned int>::max() || pixelOutsideIndex == 0)
442 {
443 pixelOutsideIndex = pixel;
444 }
445 // If value is non-zero we make sure that all 'corner' pixels have the same value
446 else if ((pixel != 0) && (pixelOutsideIndex != pixel))
447 {
448 return tcu::TestStatus(QP_TEST_RESULT_FAIL, qpGetTestResultName(QP_TEST_RESULT_FAIL));
449 }
450 }
451 // If image robustness is not enabled such pixel can have an undefined value, so we skip it
452 else
453 {
454 continue;
455 }
456 }
457 else
458 {
459 if (pixelIndex == std::numeric_limits<unsigned int>::max())
460 {
461 if (pixel >= m_shadingRateClamped[index].width * m_shadingRateClamped[index].height)
462 {
463 return tcu::TestStatus(QP_TEST_RESULT_FAIL, qpGetTestResultName(QP_TEST_RESULT_FAIL));
464 }
465
466 pixelIndex = pixel;
467 }
468 // If pixel is not part of 'corner' pixels we make sure that is has the same value as other non-'corner' pixels
469 else if (pixelIndex != pixel)
470 {
471 return tcu::TestStatus(QP_TEST_RESULT_FAIL, qpGetTestResultName(QP_TEST_RESULT_FAIL));
472 }
473 }
474 }
475 }
476
477 return tcu::TestStatus(QP_TEST_RESULT_PASS, qpGetTestResultName(QP_TEST_RESULT_PASS));
478 }
479
iterate(void)480 tcu::TestStatus FSRPixelConsistencyInstance::iterate (void)
481 {
482 const VkPhysicalDeviceMemoryProperties memoryProperties = vk::getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice());
483
484 Move<VkDevice> vkd = createImageRobustnessDevice(m_context);
485 const VkDevice device = *vkd;
486 de::MovePtr<DeviceDriver> deviceDriver = de::MovePtr<DeviceDriver>(new DeviceDriver(m_context.getPlatformInterface(), m_context.getInstance(), device));
487 const DeviceInterface& vk = *deviceDriver.get();
488 const VkQueue queue = getDeviceQueue(vk, device, m_context.getUniversalQueueFamilyIndex(), 0);
489 de::MovePtr<Allocator> allocator = de::MovePtr<Allocator>(new SimpleAllocator(vk, device, memoryProperties));
490
491 // Create vertex buffer
492 const VkDeviceSize vertexBufferSize = sizeof(basicTriangles);
493
494 const VkFormat imageFormat = VK_FORMAT_R32G32_UINT;
495
496 de::MovePtr<BufferWithMemory> vertexBuffer;
497 vertexBuffer = de::MovePtr<BufferWithMemory>(new BufferWithMemory(
498 vk, device, *allocator, makeBufferCreateInfo(vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT), MemoryRequirement::HostVisible));
499
500 float* vbuf = (float*)vertexBuffer->getAllocation().getHostPtr();
501
502 deMemcpy(vbuf, basicTriangles, vertexBufferSize);
503
504 flushAlloc(vk, device, vertexBuffer->getAllocation());
505
506 // Create color output buffer
507 const VkDeviceSize colorOutputBufferSize = m_data.framebufferExtent.width * m_data.framebufferExtent.height * tcu::getPixelSize(mapVkFormat(imageFormat));
508
509 de::MovePtr<BufferWithMemory> colorOutputBuffer;
510 colorOutputBuffer = de::MovePtr<BufferWithMemory>(new BufferWithMemory(
511 vk, device, *allocator, makeBufferCreateInfo(colorOutputBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT), MemoryRequirement::HostVisible));
512
513
514 // Create color attachment for subpass 0
515 de::MovePtr<ImageWithMemory> cbImagePass0;
516 Move<VkImageView> cbImagePass0View;
517 {
518 const VkImageUsageFlags cbUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
519 VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT |
520 VK_IMAGE_USAGE_TRANSFER_DST_BIT;
521
522 const VkImageCreateInfo imageCreateInfo =
523 {
524 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
525 DE_NULL, // const void* pNext;
526 (VkImageCreateFlags)0u, // VkImageCreateFlags flags;
527 VK_IMAGE_TYPE_2D, // VkImageType imageType;
528 imageFormat, // VkFormat format;
529 {
530 m_data.framebufferExtent.width, // deUint32 width;
531 m_data.framebufferExtent.height, // deUint32 height;
532 1u // deUint32 depth;
533 }, // VkExtent3D extent;
534 1u, // deUint32 mipLevels;
535 1u, // deUint32 arrayLayers;
536 m_data.samples, // VkSampleCountFlagBits samples;
537 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
538 cbUsage, // VkImageUsageFlags usage;
539 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
540 0u, // deUint32 queueFamilyIndexCount;
541 DE_NULL, // const deUint32* pQueueFamilyIndices;
542 VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout initialLayout;
543 };
544 cbImagePass0 = de::MovePtr<ImageWithMemory>(new ImageWithMemory(
545 vk, device, *allocator, imageCreateInfo, MemoryRequirement::Any));
546
547 VkImageViewCreateInfo imageViewCreateInfo =
548 {
549 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType;
550 DE_NULL, // const void* pNext;
551 (VkImageViewCreateFlags)0u, // VkImageViewCreateFlags flags;
552 **cbImagePass0, // VkImage image;
553 VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType;
554 imageFormat, // VkFormat format;
555 {
556 VK_COMPONENT_SWIZZLE_R, // VkComponentSwizzle r;
557 VK_COMPONENT_SWIZZLE_G, // VkComponentSwizzle g;
558 VK_COMPONENT_SWIZZLE_B, // VkComponentSwizzle b;
559 VK_COMPONENT_SWIZZLE_A // VkComponentSwizzle a;
560 }, // VkComponentMapping components;
561 {
562 VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask;
563 0u, // deUint32 baseMipLevel;
564 1u, // deUint32 levelCount;
565 0u, // deUint32 baseArrayLayer;
566 1u // deUint32 layerCount;
567 } // VkImageSubresourceRange subresourceRange;
568 };
569 cbImagePass0View = createImageView(vk, device, &imageViewCreateInfo, NULL);
570 }
571
572 // Create color attachment for subpass 1
573 de::MovePtr<ImageWithMemory> cbImagePass1;
574 Move<VkImageView> cbImagePass1View;
575 {
576 const VkImageUsageFlags cbUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
577 VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
578 VK_IMAGE_USAGE_TRANSFER_DST_BIT;
579
580 const VkImageCreateInfo imageCreateInfo =
581 {
582 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
583 DE_NULL, // const void* pNext;
584 (VkImageCreateFlags)0u, // VkImageCreateFlags flags;
585 VK_IMAGE_TYPE_2D, // VkImageType imageType;
586 imageFormat, // VkFormat format;
587 {
588 m_data.framebufferExtent.width, // deUint32 width;
589 m_data.framebufferExtent.height, // deUint32 height;
590 1u // deUint32 depth;
591 }, // VkExtent3D extent;
592 1u, // deUint32 mipLevels;
593 1u, // deUint32 arrayLayers;
594 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
595 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
596 cbUsage, // VkImageUsageFlags usage;
597 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
598 0u, // deUint32 queueFamilyIndexCount;
599 DE_NULL, // const deUint32* pQueueFamilyIndices;
600 VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout initialLayout;
601 };
602 cbImagePass1 = de::MovePtr<ImageWithMemory>(new ImageWithMemory(
603 vk, device, *allocator, imageCreateInfo, MemoryRequirement::Any));
604
605 VkImageViewCreateInfo imageViewCreateInfo =
606 {
607 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType;
608 DE_NULL, // const void* pNext;
609 (VkImageViewCreateFlags)0u, // VkImageViewCreateFlags flags;
610 **cbImagePass1, // VkImage image;
611 VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType;
612 imageFormat, // VkFormat format;
613 {
614 VK_COMPONENT_SWIZZLE_R, // VkComponentSwizzle r;
615 VK_COMPONENT_SWIZZLE_G, // VkComponentSwizzle g;
616 VK_COMPONENT_SWIZZLE_B, // VkComponentSwizzle b;
617 VK_COMPONENT_SWIZZLE_A // VkComponentSwizzle a;
618 }, // VkComponentMapping components;
619 {
620 VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask;
621 0u, // deUint32 baseMipLevel;
622 1u, // deUint32 levelCount;
623 0u, // deUint32 baseArrayLayer;
624 1u // deUint32 layerCount;
625 } // VkImageSubresourceRange subresourceRange;
626 };
627 cbImagePass1View = createImageView(vk, device, &imageViewCreateInfo, NULL);
628 }
629
630 // Create render pass
631 Move<VkRenderPass> renderPass;
632 {
633 const vk::VkAttachmentReference colorAttachment0Reference =
634 {
635 0, // attachment
636 vk::VK_IMAGE_LAYOUT_GENERAL, // layout
637 };
638
639 const vk::VkAttachmentReference colorAttachment1Reference =
640 {
641 1, // attachment
642 vk::VK_IMAGE_LAYOUT_GENERAL, // layout
643 };
644
645 std::vector<VkAttachmentDescription> attachmentDescriptions;
646
647 attachmentDescriptions.push_back(
648 {
649 (VkAttachmentDescriptionFlags)0u, // VkAttachmentDescriptionFlags flags;
650 imageFormat, // VkFormat format;
651 m_data.samples, // VkSampleCountFlagBits samples;
652 VK_ATTACHMENT_LOAD_OP_LOAD, // VkAttachmentLoadOp loadOp;
653 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
654 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp;
655 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp;
656 VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout initialLayout;
657 VK_IMAGE_LAYOUT_GENERAL // VkImageLayout finalLayout;
658 }
659 );
660
661 attachmentDescriptions.push_back(
662 {
663 (VkAttachmentDescriptionFlags)0u, // VkAttachmentDescriptionFlags flags;
664 imageFormat, // VkFormat format;
665 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
666 VK_ATTACHMENT_LOAD_OP_LOAD, // VkAttachmentLoadOp loadOp;
667 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
668 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp;
669 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp;
670 VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout initialLayout;
671 VK_IMAGE_LAYOUT_GENERAL // VkImageLayout finalLayout;
672 }
673 );
674
675 const VkSubpassDescription subpassDescs[] =
676 {
677 {
678 (vk::VkSubpassDescriptionFlags)0, // flags
679 vk::VK_PIPELINE_BIND_POINT_GRAPHICS, // pipelineBindPoint
680 0u, // inputCount
681 DE_NULL, // pInputAttachments
682 1u, // colorCount
683 &colorAttachment0Reference, // pColorAttachments
684 DE_NULL, // pResolveAttachments
685 DE_NULL, // depthStencilAttachment
686 0u, // preserveCount
687 DE_NULL, // pPreserveAttachments
688 },
689 {
690 (vk::VkSubpassDescriptionFlags)0, // flags
691 vk::VK_PIPELINE_BIND_POINT_GRAPHICS, // pipelineBindPoint
692 1u, // inputCount
693 &colorAttachment0Reference, // pInputAttachments
694 1u, // colorCount
695 &colorAttachment1Reference, // pColorAttachments
696 DE_NULL, // pResolveAttachments
697 DE_NULL, // depthStencilAttachment
698 0u, // preserveCount
699 DE_NULL, // pPreserveAttachments
700 },
701 };
702
703 const VkSubpassDependency subpassDependency =
704 {
705 0u, // srcSubpass;
706 1u, // dstSubpass;
707 VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, // srcStageMask;
708 VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, // dstStageMask;
709 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // srcAccessMask;
710 VK_ACCESS_INPUT_ATTACHMENT_READ_BIT, // dstAccessMask;
711 0 // dependencyFlags;
712 };
713
714 const VkRenderPassCreateInfo renderPassParams =
715 {
716 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // sType
717 DE_NULL, // pNext
718 (vk::VkRenderPassCreateFlags)0,
719 (deUint32)attachmentDescriptions.size(), // attachmentCount
720 &attachmentDescriptions[0], // pAttachments
721 sizeof(subpassDescs) / sizeof(subpassDescs[0]), // subpassCount
722 subpassDescs, // pSubpasses
723 1u, // dependencyCount
724 &subpassDependency, // pDependencies
725 };
726
727 renderPass = createRenderPass(vk, device, &renderPassParams);
728 }
729
730 // Create framebuffer
731 Move<VkFramebuffer> framebuffer;
732 {
733 std::vector<VkImageView> attachments;
734 attachments.push_back(*cbImagePass0View);
735 attachments.push_back(*cbImagePass1View);
736
737 const vk::VkFramebufferCreateInfo framebufferParams =
738 {
739 vk::VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // sType
740 DE_NULL, // pNext
741 (vk::VkFramebufferCreateFlags)(0), // createFlags
742 *renderPass, // renderPass
743 (deUint32)attachments.size(), // attachmentCount
744 &attachments[0], // pAttachments
745 m_data.framebufferExtent.width, // width
746 m_data.framebufferExtent.height, // height
747 1u, // layers
748 };
749
750 framebuffer = createFramebuffer(vk, device, &framebufferParams);
751 }
752
753
754 // Create vertex attribute
755 const VkVertexInputBindingDescription vertexBinding =
756 {
757 0u, // deUint32 binding;
758 sizeof(Vertex), // deUint32 stride;
759 VK_VERTEX_INPUT_RATE_VERTEX // VkVertexInputRate inputRate;
760 };
761
762 const VkVertexInputAttributeDescription vertexInputAttributeDescription =
763 {
764 0u, // deUint32 location;
765 0u, // deUint32 binding;
766 VK_FORMAT_R32G32_SFLOAT, // VkFormat format;
767 0u // deUint32 offset;
768 };
769
770 const VkPipelineVertexInputStateCreateInfo vertexInputStateCreateInfo =
771 {
772 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
773 DE_NULL, // const void* pNext;
774 (VkPipelineVertexInputStateCreateFlags)0, // VkPipelineVertexInputStateCreateFlags flags;
775 1u, // deUint32 vertexBindingDescriptionCount;
776 &vertexBinding, // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
777 1u, // deUint32 vertexAttributeDescriptionCount;
778 &vertexInputAttributeDescription // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
779 };
780
781 const VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateCreateInfo =
782 {
783 VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType;
784 DE_NULL, // const void* pNext;
785 (VkPipelineInputAssemblyStateCreateFlags)0, // VkPipelineInputAssemblyStateCreateFlags flags;
786 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, // VkPrimitiveTopology topology;
787 VK_FALSE // VkBool32 primitiveRestartEnable;
788 };
789
790 // Create rasterization state
791 const VkPipelineRasterizationStateCreateInfo rasterizationStateCreateInfo =
792 {
793 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType;
794 DE_NULL, // const void* pNext;
795 (VkPipelineRasterizationStateCreateFlags)0, // VkPipelineRasterizationStateCreateFlags flags;
796 VK_FALSE, // VkBool32 depthClampEnable;
797 VK_FALSE, // VkBool32 rasterizerDiscardEnable;
798 VK_POLYGON_MODE_FILL, // VkPolygonMode polygonMode;
799 VK_CULL_MODE_NONE, // VkCullModeFlags cullMode;
800 VK_FRONT_FACE_CLOCKWISE, // VkFrontFace frontFace;
801 VK_FALSE, // VkBool32 depthBiasEnable;
802 0.0f, // float depthBiasConstantFactor;
803 0.0f, // float depthBiasClamp;
804 0.0f, // float depthBiasSlopeFactor;
805 1.0f // float lineWidth;
806 };
807
808 // Create scissor and viewport
809 VkViewport viewport = makeViewport(m_data.framebufferExtent.width, m_data.framebufferExtent.height);
810 VkRect2D scissor = makeRect2D(m_data.framebufferExtent.width, m_data.framebufferExtent.height);
811
812 const VkPipelineViewportStateCreateInfo viewportStateCreateInfo =
813 {
814 VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType
815 DE_NULL, // const void* pNext
816 (VkPipelineViewportStateCreateFlags)0, // VkPipelineViewportStateCreateFlags flags
817 1u, // deUint32 viewportCount
818 &viewport, // const VkViewport* pViewports
819 1u, // deUint32 scissorCount
820 &scissor // const VkRect2D* pScissors
821 };
822
823 const VkPipelineDynamicStateCreateInfo dynamicStateCreateInfo =
824 {
825 VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, // VkStructureType sType;
826 DE_NULL, // const void* pNext;
827 (VkPipelineDynamicStateCreateFlags)0, // VkPipelineDynamicStateCreateFlags flags;
828 0u, // uint32_t dynamicStateCount;
829 DE_NULL, // const VkDynamicState* pDynamicStates;
830 };
831
832 const VkPipelineColorBlendAttachmentState colorBlendAttachmentState[] =
833 {
834 {
835 VK_FALSE, // VkBool32 blendEnable;
836 VK_BLEND_FACTOR_ZERO, // VkBlendFactor srcColorBlendFactor;
837 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstColorBlendFactor;
838 VK_BLEND_OP_ADD, // VkBlendOp colorBlendOp;
839 VK_BLEND_FACTOR_ZERO, // VkBlendFactor srcAlphaBlendFactor;
840 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstAlphaBlendFactor;
841 VK_BLEND_OP_ADD, // VkBlendOp alphaBlendOp;
842 0xf // VkColorComponentFlags colorWriteMask;
843 }
844 };
845
846 const VkPipelineColorBlendStateCreateInfo colorBlendStateCreateInfo =
847 {
848 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType;
849 DE_NULL, // const void* pNext;
850 0u, // VkPipelineColorBlendStateCreateFlags flags;
851 VK_FALSE, // VkBool32 logicOpEnable;
852 VK_LOGIC_OP_COPY, // VkLogicOp logicOp;
853 sizeof(colorBlendAttachmentState) / sizeof(colorBlendAttachmentState[0]), // deUint32 attachmentCount;
854 colorBlendAttachmentState, // const VkPipelineColorBlendAttachmentState* pAttachments;
855 { 1.0f, 1.0f, 1.0f, 1.0f } // float blendConstants[4];
856 };
857
858 VkPipelineDepthStencilStateCreateInfo depthStencilStateParams =
859 {
860 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType;
861 DE_NULL, // const void* pNext;
862 0u, // VkPipelineDepthStencilStateCreateFlags flags;
863 VK_FALSE, // VkBool32 depthTestEnable;
864 VK_FALSE, // VkBool32 depthWriteEnable;
865 VK_COMPARE_OP_ALWAYS, // VkCompareOp depthCompareOp;
866 VK_FALSE, // VkBool32 depthBoundsTestEnable;
867 VK_FALSE, // VkBool32 stencilTestEnable;
868 // VkStencilOpState front;
869 {
870 VK_STENCIL_OP_REPLACE, // VkStencilOp failOp;
871 VK_STENCIL_OP_REPLACE, // VkStencilOp passOp;
872 VK_STENCIL_OP_REPLACE, // VkStencilOp depthFailOp;
873 VK_COMPARE_OP_ALWAYS, // VkCompareOp compareOp;
874 0u, // deUint32 compareMask;
875 0xFFu, // deUint32 writeMask;
876 0xFFu, // deUint32 reference;
877 },
878 // VkStencilOpState back;
879 {
880 VK_STENCIL_OP_REPLACE, // VkStencilOp failOp;
881 VK_STENCIL_OP_REPLACE, // VkStencilOp passOp;
882 VK_STENCIL_OP_REPLACE, // VkStencilOp depthFailOp;
883 VK_COMPARE_OP_ALWAYS, // VkCompareOp compareOp;
884 0u, // deUint32 compareMask;
885 0xFFu, // deUint32 writeMask;
886 0xFFu, // deUint32 reference;
887 },
888 0.0f, // float minDepthBounds;
889 0.0f, // float maxDepthBounds;
890 };
891
892 // Create pipeline for pass 0
893 Move<VkPipeline> pipelinePass0;
894 Move<VkPipelineLayout> pipelineLayoutPass0;
895 {
896 const VkPushConstantRange pushConstantRange =
897 {
898 VK_SHADER_STAGE_FRAGMENT_BIT, // VkShaderStageFlags stageFlags;
899 0u, // deUint32 offset;
900 2 * sizeof(VkExtent2D) // deUint32 size;
901 };
902
903 const VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo =
904 {
905 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // sType
906 DE_NULL, // pNext
907 (VkPipelineLayoutCreateFlags)0,
908 0u, // setLayoutCount
909 DE_NULL, // pSetLayouts
910 1u, // pushConstantRangeCount
911 &pushConstantRange, // pPushConstantRanges
912 };
913
914 pipelineLayoutPass0 = createPipelineLayout(vk, device, &pipelineLayoutCreateInfo, NULL);
915
916 const VkPipelineMultisampleStateCreateInfo multisampleStateCreateInfo =
917 {
918 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType
919 DE_NULL, // const void* pNext
920 0u, // VkPipelineMultisampleStateCreateFlags flags
921 (VkSampleCountFlagBits)m_data.samples, // VkSampleCountFlagBits rasterizationSamples
922 VK_FALSE, // VkBool32 sampleShadingEnable
923 1.0f, // float minSampleShading
924 DE_NULL, // const VkSampleMask* pSampleMask
925 VK_FALSE, // VkBool32 alphaToCoverageEnable
926 VK_FALSE // VkBool32 alphaToOneEnable
927 };
928
929 Move<VkShaderModule> vertShader = createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0);
930 Move<VkShaderModule> fragShader = createShaderModule(vk, device, m_context.getBinaryCollection().get("frag_pass0"), 0);
931
932 const VkPipelineShaderStageCreateInfo shaderCreateInfo[] =
933 {
934 {
935 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
936 DE_NULL,
937 (VkPipelineShaderStageCreateFlags)0,
938 VK_SHADER_STAGE_VERTEX_BIT, // stage
939 *vertShader, // shader
940 "main",
941 DE_NULL, // pSpecializationInfo
942 },
943 {
944 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
945 DE_NULL,
946 (VkPipelineShaderStageCreateFlags)0,
947 VK_SHADER_STAGE_FRAGMENT_BIT, // stage
948 *fragShader, // shader
949 "main",
950 DE_NULL, // pSpecializationInfo
951 }
952 };
953
954 const VkGraphicsPipelineCreateInfo graphicsPipelineCreateInfo =
955 {
956 VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType sType;
957 DE_NULL, // const void* pNext;
958 (VkPipelineCreateFlags)0, // VkPipelineCreateFlags flags;
959 sizeof(shaderCreateInfo) / sizeof(shaderCreateInfo[0]), // deUint32 stageCount;
960 &shaderCreateInfo[0], // const VkPipelineShaderStageCreateInfo* pStages;
961 &vertexInputStateCreateInfo, // const VkPipelineVertexInputStateCreateInfo* pVertexInputState;
962 &inputAssemblyStateCreateInfo, // const VkPipelineInputAssemblyStateCreateInfo* pInputAssemblyState;
963 DE_NULL, // const VkPipelineTessellationStateCreateInfo* pTessellationState;
964 &viewportStateCreateInfo, // const VkPipelineViewportStateCreateInfo* pViewportState;
965 &rasterizationStateCreateInfo, // const VkPipelineRasterizationStateCreateInfo* pRasterizationState;
966 &multisampleStateCreateInfo, // const VkPipelineMultisampleStateCreateInfo* pMultisampleState;
967 &depthStencilStateParams, // const VkPipelineDepthStencilStateCreateInfo* pDepthStencilState;
968 &colorBlendStateCreateInfo, // const VkPipelineColorBlendStateCreateInfo* pColorBlendState;
969 &dynamicStateCreateInfo, // const VkPipelineDynamicStateCreateInfo* pDynamicState;
970 pipelineLayoutPass0.get(), // VkPipelineLayout layout;
971 renderPass.get(), // VkRenderPass renderPass;
972 0u, // deUint32 subpass;
973 DE_NULL, // VkPipeline basePipelineHandle;
974 0 // int basePipelineIndex;
975 };
976
977 pipelinePass0 = createGraphicsPipeline(vk, device, DE_NULL, &graphicsPipelineCreateInfo);
978 }
979
980
981 // Create pipeline for pass 1
982 Move<VkPipeline> pipelinePass1;
983 Move<VkPipelineLayout> pipelineLayoutPass1;
984 Move<vk::VkDescriptorPool> descriptorPool;
985 Move<vk::VkDescriptorSetLayout> descriptorSetLayout;
986 Move<vk::VkDescriptorSet> descriptorSet;
987 {
988 const VkDescriptorSetLayoutBinding bindings[] =
989 {
990 {
991 0u, // binding
992 VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, // descriptorType
993 1u, // descriptorCount
994 VK_SHADER_STAGE_FRAGMENT_BIT, // stageFlags
995 DE_NULL, // pImmutableSamplers
996 }
997 };
998
999 // Create a layout and allocate a descriptor set for it.
1000 const VkDescriptorSetLayoutCreateInfo setLayoutCreateInfo =
1001 {
1002 vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, // sType
1003 DE_NULL, // pNext
1004 (VkDescriptorSetLayoutCreateFlags)(0), // flags
1005 sizeof(bindings) / sizeof(bindings[0]), // bindingCount
1006 &bindings[0] // pBindings
1007 };
1008
1009 descriptorSetLayout = vk::createDescriptorSetLayout(vk, device, &setLayoutCreateInfo);
1010
1011 vk::DescriptorPoolBuilder poolBuilder;
1012
1013 for (deInt32 i = 0; i < (deInt32)(sizeof(bindings) / sizeof(bindings[0])); ++i)
1014 {
1015 poolBuilder.addType(bindings[i].descriptorType, bindings[i].descriptorCount);
1016 }
1017
1018 descriptorPool = poolBuilder.build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
1019 descriptorSet = makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout);
1020
1021 VkDescriptorImageInfo imageInfo = makeDescriptorImageInfo(DE_NULL, *cbImagePass0View, VK_IMAGE_LAYOUT_GENERAL);
1022
1023 VkWriteDescriptorSet writeDescriptorSet =
1024 {
1025 VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, // sType
1026 DE_NULL, // pNext
1027 *descriptorSet, // dstSet
1028 0u, // dstBinding
1029 0u, // dstArrayElement
1030 1u, // descriptorCount
1031 bindings[0].descriptorType, // descriptorType
1032 &imageInfo, // pImageInfo
1033 DE_NULL, // pBufferInfo
1034 DE_NULL, // pTexelBufferView
1035 };
1036
1037 vk.updateDescriptorSets(device, 1, &writeDescriptorSet, 0, NULL);
1038
1039 const VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo =
1040 {
1041 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // sType
1042 DE_NULL, // pNext
1043 (VkPipelineLayoutCreateFlags)0,
1044 1u, // setLayoutCount
1045 &descriptorSetLayout.get(), // pSetLayouts
1046 0u, // pushConstantRangeCount
1047 DE_NULL, // pPushConstantRanges
1048 };
1049
1050 pipelineLayoutPass1 = createPipelineLayout(vk, device, &pipelineLayoutCreateInfo, NULL);
1051
1052 const VkPipelineMultisampleStateCreateInfo multisampleStateCreateInfo =
1053 {
1054 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType
1055 DE_NULL, // const void* pNext
1056 0u, // VkPipelineMultisampleStateCreateFlags flags
1057 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits rasterizationSamples
1058 VK_FALSE, // VkBool32 sampleShadingEnable
1059 1.0f, // float minSampleShading
1060 DE_NULL, // const VkSampleMask* pSampleMask
1061 VK_FALSE, // VkBool32 alphaToCoverageEnable
1062 VK_FALSE // VkBool32 alphaToOneEnable
1063 };
1064
1065 VkPipelineFragmentShadingRateStateCreateInfoKHR shadingRateStateCreateInfo =
1066 {
1067 VK_STRUCTURE_TYPE_PIPELINE_FRAGMENT_SHADING_RATE_STATE_CREATE_INFO_KHR, // VkStructureType sType;
1068 DE_NULL, // const void* pNext;
1069 m_data.shadingRate, // VkExtent2D fragmentSize;
1070 { VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR, VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR }, // VkFragmentShadingRateCombinerOpKHR combinerOps[2];
1071 };
1072
1073 Move<VkShaderModule> vertShader = createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0);
1074 Move<VkShaderModule> fragShader = createShaderModule(vk, device, m_context.getBinaryCollection().get("frag_pass1"), 0);
1075
1076 const VkPipelineShaderStageCreateInfo shaderCreateInfo[] =
1077 {
1078 {
1079 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
1080 DE_NULL,
1081 (VkPipelineShaderStageCreateFlags)0,
1082 VK_SHADER_STAGE_VERTEX_BIT, // stage
1083 *vertShader, // shader
1084 "main",
1085 DE_NULL, // pSpecializationInfo
1086 },
1087 {
1088 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
1089 DE_NULL,
1090 (VkPipelineShaderStageCreateFlags)0,
1091 VK_SHADER_STAGE_FRAGMENT_BIT, // stage
1092 *fragShader, // shader
1093 "main",
1094 DE_NULL, // pSpecializationInfo
1095 }
1096 };
1097
1098 const VkGraphicsPipelineCreateInfo graphicsPipelineCreateInfo =
1099 {
1100 VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType sType;
1101 &shadingRateStateCreateInfo, // const void* pNext;
1102 (VkPipelineCreateFlags)0, // VkPipelineCreateFlags flags;
1103 sizeof(shaderCreateInfo) / sizeof(shaderCreateInfo[0]), // deUint32 stageCount;
1104 &shaderCreateInfo[0], // const VkPipelineShaderStageCreateInfo* pStages;
1105 &vertexInputStateCreateInfo, // const VkPipelineVertexInputStateCreateInfo* pVertexInputState;
1106 &inputAssemblyStateCreateInfo, // const VkPipelineInputAssemblyStateCreateInfo* pInputAssemblyState;
1107 DE_NULL, // const VkPipelineTessellationStateCreateInfo* pTessellationState;
1108 &viewportStateCreateInfo, // const VkPipelineViewportStateCreateInfo* pViewportState;
1109 &rasterizationStateCreateInfo, // const VkPipelineRasterizationStateCreateInfo* pRasterizationState;
1110 &multisampleStateCreateInfo, // const VkPipelineMultisampleStateCreateInfo* pMultisampleState;
1111 &depthStencilStateParams, // const VkPipelineDepthStencilStateCreateInfo* pDepthStencilState;
1112 &colorBlendStateCreateInfo, // const VkPipelineColorBlendStateCreateInfo* pColorBlendState;
1113 &dynamicStateCreateInfo, // const VkPipelineDynamicStateCreateInfo* pDynamicState;
1114 pipelineLayoutPass1.get(), // VkPipelineLayout layout;
1115 renderPass.get(), // VkRenderPass renderPass;
1116 1u, // deUint32 subpass;
1117 DE_NULL, // VkPipeline basePipelineHandle;
1118 0 // int basePipelineIndex;
1119 };
1120
1121 pipelinePass1 = createGraphicsPipeline(vk, device, DE_NULL, &graphicsPipelineCreateInfo);
1122 }
1123
1124 // Create command buffer
1125 Move<VkCommandPool> cmdPool = createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, m_context.getUniversalQueueFamilyIndex());
1126 Move<VkCommandBuffer> cmdBuffer = allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
1127
1128 VkImageMemoryBarrier preImageBarriers[] =
1129 {
1130 {
1131 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType
1132 DE_NULL, // const void* pNext
1133 0u, // VkAccessFlags srcAccessMask
1134 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags dstAccessMask
1135 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout
1136 VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout newLayout
1137 VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex
1138 VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex
1139 **cbImagePass0, // VkImage image
1140 {
1141 VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask
1142 0u, // uint32_t baseMipLevel
1143 VK_REMAINING_MIP_LEVELS, // uint32_t mipLevels,
1144 0u, // uint32_t baseArray
1145 VK_REMAINING_ARRAY_LAYERS, // uint32_t arraySize
1146 }
1147 },
1148 {
1149 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType
1150 DE_NULL, // const void* pNext
1151 0u, // VkAccessFlags srcAccessMask
1152 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags dstAccessMask
1153 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout
1154 VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout newLayout
1155 VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex
1156 VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex
1157 **cbImagePass1, // VkImage image
1158 {
1159 VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask
1160 0u, // uint32_t baseMipLevel
1161 VK_REMAINING_MIP_LEVELS, // uint32_t mipLevels,
1162 0u, // uint32_t baseArray
1163 VK_REMAINING_ARRAY_LAYERS, // uint32_t arraySize
1164 }
1165 }
1166 };
1167
1168 // Record commands
1169 beginCommandBuffer(vk, *cmdBuffer, 0u);
1170
1171 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
1172 (VkDependencyFlags)0,
1173 0, (const VkMemoryBarrier*)DE_NULL,
1174 0, (const VkBufferMemoryBarrier*)DE_NULL,
1175 sizeof(preImageBarriers) / sizeof(preImageBarriers[0]), preImageBarriers);
1176
1177 // Clear both images to UINT_MAX
1178 VkImageSubresourceRange range = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
1179 VkClearValue clearColor = makeClearValueColorU32(std::numeric_limits<unsigned int>::max(),0,0,0);
1180
1181 vk.cmdClearColorImage(*cmdBuffer, **cbImagePass0, VK_IMAGE_LAYOUT_GENERAL, &clearColor.color, 1, &range);
1182 vk.cmdClearColorImage(*cmdBuffer, **cbImagePass1, VK_IMAGE_LAYOUT_GENERAL, &clearColor.color, 1, &range);
1183
1184 // Barrier between the clear and the rendering
1185 VkImageMemoryBarrier clearColorBarriers[] =
1186 {
1187 {
1188 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType
1189 DE_NULL, // const void* pNext
1190 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask
1191 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags dstAccessMask
1192 VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout oldLayout
1193 VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout newLayout
1194 VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex
1195 VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex
1196 **cbImagePass0, // VkImage image
1197 {
1198 VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask
1199 0u, // uint32_t baseMipLevel
1200 VK_REMAINING_MIP_LEVELS, // uint32_t mipLevels,
1201 0u, // uint32_t baseArray
1202 VK_REMAINING_ARRAY_LAYERS, // uint32_t arraySize
1203 }
1204 },
1205 {
1206 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType
1207 DE_NULL, // const void* pNext
1208 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask
1209 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags dstAccessMask
1210 VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout oldLayout
1211 VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout newLayout
1212 VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex
1213 VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex
1214 **cbImagePass1, // VkImage image
1215 {
1216 VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask
1217 0u, // uint32_t baseMipLevel
1218 VK_REMAINING_MIP_LEVELS, // uint32_t mipLevels,
1219 0u, // uint32_t baseArray
1220 VK_REMAINING_ARRAY_LAYERS, // uint32_t arraySize
1221 }
1222 }
1223 };
1224
1225 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
1226 (VkDependencyFlags)0,
1227 0, (const VkMemoryBarrier*)DE_NULL,
1228 0, (const VkBufferMemoryBarrier*)DE_NULL,
1229 sizeof(clearColorBarriers) / sizeof(clearColorBarriers[0]), clearColorBarriers);
1230
1231 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer,
1232 makeRect2D(m_data.framebufferExtent.width, m_data.framebufferExtent.height),
1233 0, DE_NULL, VK_SUBPASS_CONTENTS_INLINE, DE_NULL);
1234
1235 // Put primitive shading rate in a push constant
1236 if (m_shadingRateClamped.size() == 1)
1237 {
1238 vk.cmdPushConstants(*cmdBuffer, *pipelineLayoutPass0, VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(m_shadingRateClamped[0]), &m_shadingRateClamped[0]);
1239 vk.cmdPushConstants(*cmdBuffer, *pipelineLayoutPass0, VK_SHADER_STAGE_FRAGMENT_BIT, sizeof(m_shadingRateClamped[0]), sizeof(m_shadingRateClamped[0]), &m_shadingRateClamped[0]);
1240 }
1241 else
1242 {
1243 vk.cmdPushConstants(*cmdBuffer, *pipelineLayoutPass0, VK_SHADER_STAGE_FRAGMENT_BIT, 0, static_cast<deUint32>(m_shadingRateClamped.size() * sizeof(m_shadingRateClamped[0])), &m_shadingRateClamped[0]);
1244 }
1245
1246 // Bind vertex buffer
1247 const VkDeviceSize vertexBufferOffset = 0;
1248 VkBuffer vb = **vertexBuffer;
1249 vk.cmdBindVertexBuffers(*cmdBuffer, 0, 1, &vb, &vertexBufferOffset);
1250
1251 // Bind pipeline
1252 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelinePass0);
1253
1254 // Draw triangles
1255 vk.cmdDraw(*cmdBuffer, sizeof(basicTriangles) / sizeof(Vertex), 1u, 0u, 0u);
1256
1257 // Start next subpass
1258 vk.cmdNextSubpass(*cmdBuffer, VK_SUBPASS_CONTENTS_INLINE);
1259
1260 // Bind descriptors
1261 vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayoutPass1, 0, 1, &descriptorSet.get(), 0, DE_NULL);
1262
1263 // Bind vertex buffer
1264 vk.cmdBindVertexBuffers(*cmdBuffer, 0, 1, &vb, &vertexBufferOffset);
1265
1266 // Bind pipeline
1267 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelinePass1);
1268
1269 // Draw triangles
1270 vk.cmdDraw(*cmdBuffer, sizeof(basicTriangles) / sizeof(Vertex), 1u, 0u, 0u);
1271
1272 endRenderPass(vk, *cmdBuffer);
1273
1274 VkImageMemoryBarrier postImageBarrier =
1275 {
1276 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType
1277 DE_NULL, // const void* pNext
1278 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags srcAccessMask
1279 VK_ACCESS_TRANSFER_READ_BIT, // VkAccessFlags dstAccessMask
1280 VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout oldLayout
1281 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // VkImageLayout newLayout
1282 VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex
1283 VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex
1284 **cbImagePass1, // VkImage image
1285 {
1286 VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask
1287 0u, // uint32_t baseMipLevel
1288 VK_REMAINING_MIP_LEVELS, // uint32_t mipLevels,
1289 0u, // uint32_t baseArray
1290 VK_REMAINING_ARRAY_LAYERS, // uint32_t arraySize
1291 }
1292 };
1293
1294 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &postImageBarrier);
1295
1296 const VkBufferImageCopy copyRegion =
1297 {
1298 0u, // VkDeviceSize bufferOffset;
1299 0u, // deUint32 bufferRowLength;
1300 0u, // deUint32 bufferImageHeight;
1301 {
1302 VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspect;
1303 0u, // deUint32 mipLevel;
1304 0u, // deUint32 baseArrayLayer;
1305 1u, // deUint32 layerCount;
1306 }, // VkImageSubresourceLayers imageSubresource;
1307 { 0, 0, 0 }, // VkOffset3D imageOffset;
1308 {m_data.framebufferExtent.width, m_data.framebufferExtent.height, 1} // VkExtent3D imageExtent;
1309 };
1310
1311 vk.cmdCopyImageToBuffer(*cmdBuffer, **cbImagePass1, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, **colorOutputBuffer, 1u, ©Region);
1312
1313 const VkBufferMemoryBarrier bufferBarrier =
1314 {
1315 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType;
1316 DE_NULL, // const void* pNext;
1317 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask;
1318 VK_ACCESS_HOST_READ_BIT, // VkAccessFlags dstAccessMask;
1319 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
1320 VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex;
1321 **colorOutputBuffer, // VkBuffer buffer;
1322 0ull, // VkDeviceSize offset;
1323 VK_WHOLE_SIZE // VkDeviceSize size;
1324 };
1325
1326 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, &bufferBarrier, 0, (const VkImageMemoryBarrier*)DE_NULL);
1327
1328 endCommandBuffer(vk, *cmdBuffer);
1329
1330 submitCommandsAndWait(vk, device, queue, cmdBuffer.get());
1331
1332 // Read buffer data
1333 invalidateAlloc(vk, device, colorOutputBuffer->getAllocation());
1334
1335 tcu::ConstPixelBufferAccess resultBuffer = tcu::ConstPixelBufferAccess(
1336 tcu::TextureFormat(tcu::TextureFormat::RG, tcu::TextureFormat::UNSIGNED_INT32),
1337 m_data.framebufferExtent.width, m_data.framebufferExtent.height, 1, (const void *)colorOutputBuffer->getAllocation().getHostPtr());
1338
1339 for (deUint32 i = 0; i < m_shadingRateClamped.size(); i++)
1340 {
1341 tcu::TestStatus result = verifyResult(resultBuffer, i);
1342 if (result.getCode() == QP_TEST_RESULT_PASS)
1343 {
1344 return result;
1345 }
1346 }
1347
1348 return tcu::TestStatus(QP_TEST_RESULT_FAIL, qpGetTestResultName(QP_TEST_RESULT_FAIL));
1349 }
1350
1351 } // anonymous
1352
createPixelConsistencyTests(tcu::TestContext & testCtx,tcu::TestCaseGroup * parentGroup)1353 void createPixelConsistencyTests(tcu::TestContext& testCtx, tcu::TestCaseGroup* parentGroup)
1354 {
1355 typedef struct
1356 {
1357 deUint32 count;
1358 const char* name;
1359 const char* description;
1360 } TestGroupCase;
1361
1362 typedef struct
1363 {
1364 VkExtent2D count;
1365 const char* name;
1366 const char* description;
1367 } TestGroupCase2D;
1368
1369 TestGroupCase2D shadingRateCases[] =
1370 {
1371 { {1, 1}, "rate_1x1", "1x1 shading rate" },
1372 { {1, 2}, "rate_1x2", "1x2 shading rate" },
1373 { {1, 4}, "rate_1x4", "1x4 shading rate" },
1374 { {2, 1}, "rate_2x1", "2x1 shading rate" },
1375 { {2, 2}, "rate_2x2", "2x2 shading rate" },
1376 { {2, 4}, "rate_2x4", "2x4 shading rate" },
1377 { {4, 1}, "rate_4x1", "4x1 shading rate" },
1378 { {4, 2}, "rate_4x2", "4x2 shading rate" },
1379 { {4, 4}, "rate_4x4", "4x4 shading rate" },
1380 };
1381
1382 TestGroupCase sampCases[] =
1383 {
1384 { VK_SAMPLE_COUNT_1_BIT, "samples_1", "1 raster sample" },
1385 { VK_SAMPLE_COUNT_2_BIT, "samples_2", "2 raster samples" },
1386 { VK_SAMPLE_COUNT_4_BIT, "samples_4", "4 raster samples" },
1387 { VK_SAMPLE_COUNT_8_BIT, "samples_8", "8 raster samples" },
1388 { VK_SAMPLE_COUNT_16_BIT, "samples_16", "16 raster samples" },
1389 };
1390
1391 TestGroupCase2D extentCases[] =
1392 {
1393 { {1, 1}, "extent_1x1", "framebuffer size 1x1" },
1394 { {4, 4}, "extent_4x4", "framebuffer size 4x4" },
1395 { {33, 35}, "extent_33x35", "framebuffer size 33x35" },
1396 { {151, 431}, "extent_151x431", "framebuffer size 151x431" },
1397 { {256, 256}, "extent_256x256", "framebuffer size 256x256" },
1398 };
1399
1400 de::MovePtr<tcu::TestCaseGroup> pixelGroup(new tcu::TestCaseGroup(testCtx, "pixel_consistency", "Pixel selection consistency"));
1401
1402 for (int rateNdx = 0; rateNdx < DE_LENGTH_OF_ARRAY(shadingRateCases); rateNdx++)
1403 {
1404 de::MovePtr<tcu::TestCaseGroup> rateGroup(new tcu::TestCaseGroup(testCtx, shadingRateCases[rateNdx].name, shadingRateCases[rateNdx].description));
1405
1406 for (int sampNdx = 0; sampNdx < DE_LENGTH_OF_ARRAY(sampCases); sampNdx++)
1407 {
1408 de::MovePtr<tcu::TestCaseGroup> sampleGroup(new tcu::TestCaseGroup(testCtx, sampCases[sampNdx].name, sampCases[sampNdx].description));
1409 for (int extNdx = 0; extNdx < DE_LENGTH_OF_ARRAY(extentCases); extNdx++)
1410 {
1411 VkSampleCountFlagBits samples = static_cast<VkSampleCountFlagBits>(sampCases[sampNdx].count);
1412 VkExtent2D framebufferExtent = extentCases[extNdx].count;
1413
1414 CaseDef caseParams{
1415 shadingRateCases[rateNdx].count,
1416 samples,
1417 framebufferExtent,
1418 false};
1419 sampleGroup->addChild(new FSRPixelConsistencyTestCase(testCtx, extentCases[extNdx].name, extentCases[extNdx].description, caseParams));
1420
1421 // test FragCoord.zw but to avoid duplication limit tests to extent_151x431/256x256 and 1 or 4 samples
1422 if ((framebufferExtent.width > 150) && (samples & (VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT)))
1423 {
1424 std::string caseName = std::string(extentCases[extNdx].name) + "_zw_coord";
1425 caseParams.zwCoord = true;
1426 sampleGroup->addChild(new FSRPixelConsistencyTestCase(testCtx, caseName.c_str(), extentCases[extNdx].description, caseParams));
1427 }
1428 }
1429 rateGroup->addChild(sampleGroup.release());
1430 }
1431
1432 pixelGroup->addChild(rateGroup.release());
1433 }
1434
1435 parentGroup->addChild(pixelGroup.release());
1436 }
1437
1438 } // FragmentShadingRage
1439 } // vkt
1440