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