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 {
82 {-1.0f, -1.0f},
83 { 1.0f, -1.0f},
84 { 1.0f, 1.0f},
85
86 {-1.0f, 1.0f},
87 { 1.0f, -1.0f},
88 { 1.0f, 1.0f},
89 };
90
createImageRobustnessDevice(Context & context,const vk::VkInstance & instance,const InstanceInterface & vki)91 Move<VkDevice> createImageRobustnessDevice(Context& context, const vk::VkInstance& instance, const InstanceInterface& vki)
92 {
93 const VkPhysicalDevice physicalDevice = chooseDevice(vki, instance, context.getTestContext().getCommandLine());
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 vki.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 instance, vki, 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 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 CaseDef data)205 FSRPixelConsistencyTestCase::FSRPixelConsistencyTestCase(tcu::TestContext& context, const char* name, const CaseDef data)
206 : vkt::TestCase (context, name)
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 const VkInstance instance = m_context.getInstance();
485 const auto& instanceDriver = m_context.getInstanceInterface();
486
487 Move<VkDevice> vkd = createImageRobustnessDevice(m_context, instance, instanceDriver);
488 const VkDevice device = *vkd;
489 #ifndef CTS_USES_VULKANSC
490 de::MovePtr<vk::DeviceDriver> deviceDriver = de::MovePtr<DeviceDriver>(new DeviceDriver(m_context.getPlatformInterface(), m_context.getInstance(), device, m_context.getUsedApiVersion()));
491 #else
492 de::MovePtr<vk::DeviceDriverSC, vk::DeinitDeviceDeleter> deviceDriver = de::MovePtr<DeviceDriverSC, DeinitDeviceDeleter>(new DeviceDriverSC(m_context.getPlatformInterface(), m_context.getInstance(), device, m_context.getTestContext().getCommandLine(), m_context.getResourceInterface(), m_context.getDeviceVulkanSC10Properties(), m_context.getDeviceProperties(), m_context.getUsedApiVersion()), vk::DeinitDeviceDeleter(m_context.getResourceInterface().get(), device));
493 #endif // CTS_USES_VULKANSC
494 const DeviceInterface& vk = *deviceDriver;
495 const VkQueue queue = getDeviceQueue(vk, device, m_context.getUniversalQueueFamilyIndex(), 0);
496 de::MovePtr<Allocator> allocator = de::MovePtr<Allocator>(new SimpleAllocator(vk, device, memoryProperties));
497
498 // Create vertex buffer
499 const VkDeviceSize vertexBufferSize = sizeof(basicTriangles);
500
501 const VkFormat imageFormat = VK_FORMAT_R32G32_UINT;
502
503 de::MovePtr<BufferWithMemory> vertexBuffer;
504 vertexBuffer = de::MovePtr<BufferWithMemory>(new BufferWithMemory(
505 vk, device, *allocator, makeBufferCreateInfo(vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT), MemoryRequirement::HostVisible));
506
507 float* vbuf = (float*)vertexBuffer->getAllocation().getHostPtr();
508
509 deMemcpy(vbuf, basicTriangles, vertexBufferSize);
510
511 flushAlloc(vk, device, vertexBuffer->getAllocation());
512
513 // Create color output buffer
514 const VkDeviceSize colorOutputBufferSize = m_data.framebufferExtent.width * m_data.framebufferExtent.height * tcu::getPixelSize(mapVkFormat(imageFormat));
515
516 de::MovePtr<BufferWithMemory> colorOutputBuffer;
517 colorOutputBuffer = de::MovePtr<BufferWithMemory>(new BufferWithMemory(
518 vk, device, *allocator, makeBufferCreateInfo(colorOutputBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT), MemoryRequirement::HostVisible));
519
520
521 // Create color attachment for subpass 0
522 de::MovePtr<ImageWithMemory> cbImagePass0;
523 Move<VkImageView> cbImagePass0View;
524 {
525 const VkImageUsageFlags cbUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
526 VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT |
527 VK_IMAGE_USAGE_TRANSFER_DST_BIT;
528
529 const VkImageCreateInfo imageCreateInfo =
530 {
531 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
532 DE_NULL, // const void* pNext;
533 (VkImageCreateFlags)0u, // VkImageCreateFlags flags;
534 VK_IMAGE_TYPE_2D, // VkImageType imageType;
535 imageFormat, // VkFormat format;
536 {
537 m_data.framebufferExtent.width, // deUint32 width;
538 m_data.framebufferExtent.height, // deUint32 height;
539 1u // deUint32 depth;
540 }, // VkExtent3D extent;
541 1u, // deUint32 mipLevels;
542 1u, // deUint32 arrayLayers;
543 m_data.samples, // VkSampleCountFlagBits samples;
544 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
545 cbUsage, // VkImageUsageFlags usage;
546 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
547 0u, // deUint32 queueFamilyIndexCount;
548 DE_NULL, // const deUint32* pQueueFamilyIndices;
549 VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout initialLayout;
550 };
551 cbImagePass0 = de::MovePtr<ImageWithMemory>(new ImageWithMemory(
552 vk, device, *allocator, imageCreateInfo, MemoryRequirement::Any));
553
554 VkImageViewCreateInfo imageViewCreateInfo =
555 {
556 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType;
557 DE_NULL, // const void* pNext;
558 (VkImageViewCreateFlags)0u, // VkImageViewCreateFlags flags;
559 **cbImagePass0, // VkImage image;
560 VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType;
561 imageFormat, // VkFormat format;
562 {
563 VK_COMPONENT_SWIZZLE_R, // VkComponentSwizzle r;
564 VK_COMPONENT_SWIZZLE_G, // VkComponentSwizzle g;
565 VK_COMPONENT_SWIZZLE_B, // VkComponentSwizzle b;
566 VK_COMPONENT_SWIZZLE_A // VkComponentSwizzle a;
567 }, // VkComponentMapping components;
568 {
569 VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask;
570 0u, // deUint32 baseMipLevel;
571 1u, // deUint32 levelCount;
572 0u, // deUint32 baseArrayLayer;
573 1u // deUint32 layerCount;
574 } // VkImageSubresourceRange subresourceRange;
575 };
576 cbImagePass0View = createImageView(vk, device, &imageViewCreateInfo, NULL);
577 }
578
579 // Create color attachment for subpass 1
580 de::MovePtr<ImageWithMemory> cbImagePass1;
581 Move<VkImageView> cbImagePass1View;
582 {
583 const VkImageUsageFlags cbUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
584 VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
585 VK_IMAGE_USAGE_TRANSFER_DST_BIT;
586
587 const VkImageCreateInfo imageCreateInfo =
588 {
589 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
590 DE_NULL, // const void* pNext;
591 (VkImageCreateFlags)0u, // VkImageCreateFlags flags;
592 VK_IMAGE_TYPE_2D, // VkImageType imageType;
593 imageFormat, // VkFormat format;
594 {
595 m_data.framebufferExtent.width, // deUint32 width;
596 m_data.framebufferExtent.height, // deUint32 height;
597 1u // deUint32 depth;
598 }, // VkExtent3D extent;
599 1u, // deUint32 mipLevels;
600 1u, // deUint32 arrayLayers;
601 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
602 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
603 cbUsage, // VkImageUsageFlags usage;
604 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
605 0u, // deUint32 queueFamilyIndexCount;
606 DE_NULL, // const deUint32* pQueueFamilyIndices;
607 VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout initialLayout;
608 };
609 cbImagePass1 = de::MovePtr<ImageWithMemory>(new ImageWithMemory(
610 vk, device, *allocator, imageCreateInfo, MemoryRequirement::Any));
611
612 VkImageViewCreateInfo imageViewCreateInfo =
613 {
614 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType;
615 DE_NULL, // const void* pNext;
616 (VkImageViewCreateFlags)0u, // VkImageViewCreateFlags flags;
617 **cbImagePass1, // VkImage image;
618 VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType;
619 imageFormat, // VkFormat format;
620 {
621 VK_COMPONENT_SWIZZLE_R, // VkComponentSwizzle r;
622 VK_COMPONENT_SWIZZLE_G, // VkComponentSwizzle g;
623 VK_COMPONENT_SWIZZLE_B, // VkComponentSwizzle b;
624 VK_COMPONENT_SWIZZLE_A // VkComponentSwizzle a;
625 }, // VkComponentMapping components;
626 {
627 VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask;
628 0u, // deUint32 baseMipLevel;
629 1u, // deUint32 levelCount;
630 0u, // deUint32 baseArrayLayer;
631 1u // deUint32 layerCount;
632 } // VkImageSubresourceRange subresourceRange;
633 };
634 cbImagePass1View = createImageView(vk, device, &imageViewCreateInfo, NULL);
635 }
636
637 // Create render pass
638 Move<VkRenderPass> renderPass;
639 {
640 const vk::VkAttachmentReference colorAttachment0Reference =
641 {
642 0, // attachment
643 vk::VK_IMAGE_LAYOUT_GENERAL, // layout
644 };
645
646 const vk::VkAttachmentReference colorAttachment1Reference =
647 {
648 1, // attachment
649 vk::VK_IMAGE_LAYOUT_GENERAL, // layout
650 };
651
652 std::vector<VkAttachmentDescription> attachmentDescriptions;
653
654 attachmentDescriptions.push_back(
655 {
656 (VkAttachmentDescriptionFlags)0u, // VkAttachmentDescriptionFlags flags;
657 imageFormat, // VkFormat format;
658 m_data.samples, // VkSampleCountFlagBits samples;
659 VK_ATTACHMENT_LOAD_OP_LOAD, // VkAttachmentLoadOp loadOp;
660 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
661 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp;
662 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp;
663 VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout initialLayout;
664 VK_IMAGE_LAYOUT_GENERAL // VkImageLayout finalLayout;
665 }
666 );
667
668 attachmentDescriptions.push_back(
669 {
670 (VkAttachmentDescriptionFlags)0u, // VkAttachmentDescriptionFlags flags;
671 imageFormat, // VkFormat format;
672 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
673 VK_ATTACHMENT_LOAD_OP_LOAD, // VkAttachmentLoadOp loadOp;
674 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
675 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp;
676 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp;
677 VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout initialLayout;
678 VK_IMAGE_LAYOUT_GENERAL // VkImageLayout finalLayout;
679 }
680 );
681
682 const VkSubpassDescription subpassDescs[] =
683 {
684 {
685 (vk::VkSubpassDescriptionFlags)0, // flags
686 vk::VK_PIPELINE_BIND_POINT_GRAPHICS, // pipelineBindPoint
687 0u, // inputCount
688 DE_NULL, // pInputAttachments
689 1u, // colorCount
690 &colorAttachment0Reference, // pColorAttachments
691 DE_NULL, // pResolveAttachments
692 DE_NULL, // depthStencilAttachment
693 0u, // preserveCount
694 DE_NULL, // pPreserveAttachments
695 },
696 {
697 (vk::VkSubpassDescriptionFlags)0, // flags
698 vk::VK_PIPELINE_BIND_POINT_GRAPHICS, // pipelineBindPoint
699 1u, // inputCount
700 &colorAttachment0Reference, // pInputAttachments
701 1u, // colorCount
702 &colorAttachment1Reference, // pColorAttachments
703 DE_NULL, // pResolveAttachments
704 DE_NULL, // depthStencilAttachment
705 0u, // preserveCount
706 DE_NULL, // pPreserveAttachments
707 },
708 };
709
710 const VkSubpassDependency subpassDependency =
711 {
712 0u, // srcSubpass;
713 1u, // dstSubpass;
714 VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, // srcStageMask;
715 VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, // dstStageMask;
716 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // srcAccessMask;
717 VK_ACCESS_INPUT_ATTACHMENT_READ_BIT, // dstAccessMask;
718 0 // dependencyFlags;
719 };
720
721 const VkRenderPassCreateInfo renderPassParams =
722 {
723 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // sType
724 DE_NULL, // pNext
725 (vk::VkRenderPassCreateFlags)0,
726 (deUint32)attachmentDescriptions.size(), // attachmentCount
727 &attachmentDescriptions[0], // pAttachments
728 sizeof(subpassDescs) / sizeof(subpassDescs[0]), // subpassCount
729 subpassDescs, // pSubpasses
730 1u, // dependencyCount
731 &subpassDependency, // pDependencies
732 };
733
734 renderPass = createRenderPass(vk, device, &renderPassParams);
735 }
736
737 // Create framebuffer
738 Move<VkFramebuffer> framebuffer;
739 {
740 std::vector<VkImageView> attachments;
741 attachments.push_back(*cbImagePass0View);
742 attachments.push_back(*cbImagePass1View);
743
744 const vk::VkFramebufferCreateInfo framebufferParams =
745 {
746 vk::VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // sType
747 DE_NULL, // pNext
748 (vk::VkFramebufferCreateFlags)(0), // createFlags
749 *renderPass, // renderPass
750 (deUint32)attachments.size(), // attachmentCount
751 &attachments[0], // pAttachments
752 m_data.framebufferExtent.width, // width
753 m_data.framebufferExtent.height, // height
754 1u, // layers
755 };
756
757 framebuffer = createFramebuffer(vk, device, &framebufferParams);
758 }
759
760
761 // Create vertex attribute
762 const VkVertexInputBindingDescription vertexBinding =
763 {
764 0u, // deUint32 binding;
765 sizeof(Vertex), // deUint32 stride;
766 VK_VERTEX_INPUT_RATE_VERTEX // VkVertexInputRate inputRate;
767 };
768
769 const VkVertexInputAttributeDescription vertexInputAttributeDescription =
770 {
771 0u, // deUint32 location;
772 0u, // deUint32 binding;
773 VK_FORMAT_R32G32_SFLOAT, // VkFormat format;
774 0u // deUint32 offset;
775 };
776
777 const VkPipelineVertexInputStateCreateInfo vertexInputStateCreateInfo =
778 {
779 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
780 DE_NULL, // const void* pNext;
781 (VkPipelineVertexInputStateCreateFlags)0, // VkPipelineVertexInputStateCreateFlags flags;
782 1u, // deUint32 vertexBindingDescriptionCount;
783 &vertexBinding, // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
784 1u, // deUint32 vertexAttributeDescriptionCount;
785 &vertexInputAttributeDescription // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
786 };
787
788 const VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateCreateInfo =
789 {
790 VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType;
791 DE_NULL, // const void* pNext;
792 (VkPipelineInputAssemblyStateCreateFlags)0, // VkPipelineInputAssemblyStateCreateFlags flags;
793 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, // VkPrimitiveTopology topology;
794 VK_FALSE // VkBool32 primitiveRestartEnable;
795 };
796
797 // Create rasterization state
798 const VkPipelineRasterizationStateCreateInfo rasterizationStateCreateInfo =
799 {
800 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType;
801 DE_NULL, // const void* pNext;
802 (VkPipelineRasterizationStateCreateFlags)0, // VkPipelineRasterizationStateCreateFlags flags;
803 VK_FALSE, // VkBool32 depthClampEnable;
804 VK_FALSE, // VkBool32 rasterizerDiscardEnable;
805 VK_POLYGON_MODE_FILL, // VkPolygonMode polygonMode;
806 VK_CULL_MODE_NONE, // VkCullModeFlags cullMode;
807 VK_FRONT_FACE_CLOCKWISE, // VkFrontFace frontFace;
808 VK_FALSE, // VkBool32 depthBiasEnable;
809 0.0f, // float depthBiasConstantFactor;
810 0.0f, // float depthBiasClamp;
811 0.0f, // float depthBiasSlopeFactor;
812 1.0f // float lineWidth;
813 };
814
815 // Create scissor and viewport
816 VkViewport viewport = makeViewport(m_data.framebufferExtent.width, m_data.framebufferExtent.height);
817 VkRect2D scissor = makeRect2D(m_data.framebufferExtent.width, m_data.framebufferExtent.height);
818
819 const VkPipelineViewportStateCreateInfo viewportStateCreateInfo =
820 {
821 VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType
822 DE_NULL, // const void* pNext
823 (VkPipelineViewportStateCreateFlags)0, // VkPipelineViewportStateCreateFlags flags
824 1u, // deUint32 viewportCount
825 &viewport, // const VkViewport* pViewports
826 1u, // deUint32 scissorCount
827 &scissor // const VkRect2D* pScissors
828 };
829
830 const VkPipelineDynamicStateCreateInfo dynamicStateCreateInfo =
831 {
832 VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, // VkStructureType sType;
833 DE_NULL, // const void* pNext;
834 (VkPipelineDynamicStateCreateFlags)0, // VkPipelineDynamicStateCreateFlags flags;
835 0u, // uint32_t dynamicStateCount;
836 DE_NULL, // const VkDynamicState* pDynamicStates;
837 };
838
839 const VkPipelineColorBlendAttachmentState colorBlendAttachmentState[] =
840 {
841 {
842 VK_FALSE, // VkBool32 blendEnable;
843 VK_BLEND_FACTOR_ZERO, // VkBlendFactor srcColorBlendFactor;
844 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstColorBlendFactor;
845 VK_BLEND_OP_ADD, // VkBlendOp colorBlendOp;
846 VK_BLEND_FACTOR_ZERO, // VkBlendFactor srcAlphaBlendFactor;
847 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstAlphaBlendFactor;
848 VK_BLEND_OP_ADD, // VkBlendOp alphaBlendOp;
849 0xf // VkColorComponentFlags colorWriteMask;
850 }
851 };
852
853 const VkPipelineColorBlendStateCreateInfo colorBlendStateCreateInfo =
854 {
855 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType;
856 DE_NULL, // const void* pNext;
857 0u, // VkPipelineColorBlendStateCreateFlags flags;
858 VK_FALSE, // VkBool32 logicOpEnable;
859 VK_LOGIC_OP_COPY, // VkLogicOp logicOp;
860 sizeof(colorBlendAttachmentState) / sizeof(colorBlendAttachmentState[0]), // deUint32 attachmentCount;
861 colorBlendAttachmentState, // const VkPipelineColorBlendAttachmentState* pAttachments;
862 { 1.0f, 1.0f, 1.0f, 1.0f } // float blendConstants[4];
863 };
864
865 VkPipelineDepthStencilStateCreateInfo depthStencilStateParams =
866 {
867 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType;
868 DE_NULL, // const void* pNext;
869 0u, // VkPipelineDepthStencilStateCreateFlags flags;
870 VK_FALSE, // VkBool32 depthTestEnable;
871 VK_FALSE, // VkBool32 depthWriteEnable;
872 VK_COMPARE_OP_ALWAYS, // VkCompareOp depthCompareOp;
873 VK_FALSE, // VkBool32 depthBoundsTestEnable;
874 VK_FALSE, // VkBool32 stencilTestEnable;
875 // VkStencilOpState front;
876 {
877 VK_STENCIL_OP_REPLACE, // VkStencilOp failOp;
878 VK_STENCIL_OP_REPLACE, // VkStencilOp passOp;
879 VK_STENCIL_OP_REPLACE, // VkStencilOp depthFailOp;
880 VK_COMPARE_OP_ALWAYS, // VkCompareOp compareOp;
881 0u, // deUint32 compareMask;
882 0xFFu, // deUint32 writeMask;
883 0xFFu, // deUint32 reference;
884 },
885 // VkStencilOpState back;
886 {
887 VK_STENCIL_OP_REPLACE, // VkStencilOp failOp;
888 VK_STENCIL_OP_REPLACE, // VkStencilOp passOp;
889 VK_STENCIL_OP_REPLACE, // VkStencilOp depthFailOp;
890 VK_COMPARE_OP_ALWAYS, // VkCompareOp compareOp;
891 0u, // deUint32 compareMask;
892 0xFFu, // deUint32 writeMask;
893 0xFFu, // deUint32 reference;
894 },
895 0.0f, // float minDepthBounds;
896 0.0f, // float maxDepthBounds;
897 };
898
899 // Create pipeline for pass 0
900 Move<VkPipeline> pipelinePass0;
901 Move<VkPipelineLayout> pipelineLayoutPass0;
902 {
903 const VkPushConstantRange pushConstantRange =
904 {
905 VK_SHADER_STAGE_FRAGMENT_BIT, // VkShaderStageFlags stageFlags;
906 0u, // deUint32 offset;
907 2 * sizeof(VkExtent2D) // deUint32 size;
908 };
909
910 const VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo =
911 {
912 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // sType
913 DE_NULL, // pNext
914 (VkPipelineLayoutCreateFlags)0,
915 0u, // setLayoutCount
916 DE_NULL, // pSetLayouts
917 1u, // pushConstantRangeCount
918 &pushConstantRange, // pPushConstantRanges
919 };
920
921 pipelineLayoutPass0 = createPipelineLayout(vk, device, &pipelineLayoutCreateInfo, NULL);
922
923 const VkPipelineMultisampleStateCreateInfo multisampleStateCreateInfo =
924 {
925 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType
926 DE_NULL, // const void* pNext
927 0u, // VkPipelineMultisampleStateCreateFlags flags
928 (VkSampleCountFlagBits)m_data.samples, // VkSampleCountFlagBits rasterizationSamples
929 VK_FALSE, // VkBool32 sampleShadingEnable
930 1.0f, // float minSampleShading
931 DE_NULL, // const VkSampleMask* pSampleMask
932 VK_FALSE, // VkBool32 alphaToCoverageEnable
933 VK_FALSE // VkBool32 alphaToOneEnable
934 };
935
936 Move<VkShaderModule> vertShader = createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0);
937 Move<VkShaderModule> fragShader = createShaderModule(vk, device, m_context.getBinaryCollection().get("frag_pass0"), 0);
938
939 const VkPipelineShaderStageCreateInfo shaderCreateInfo[] =
940 {
941 {
942 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
943 DE_NULL,
944 (VkPipelineShaderStageCreateFlags)0,
945 VK_SHADER_STAGE_VERTEX_BIT, // stage
946 *vertShader, // shader
947 "main",
948 DE_NULL, // pSpecializationInfo
949 },
950 {
951 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
952 DE_NULL,
953 (VkPipelineShaderStageCreateFlags)0,
954 VK_SHADER_STAGE_FRAGMENT_BIT, // stage
955 *fragShader, // shader
956 "main",
957 DE_NULL, // pSpecializationInfo
958 }
959 };
960
961 const VkGraphicsPipelineCreateInfo graphicsPipelineCreateInfo =
962 {
963 VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType sType;
964 DE_NULL, // const void* pNext;
965 (VkPipelineCreateFlags)0, // VkPipelineCreateFlags flags;
966 sizeof(shaderCreateInfo) / sizeof(shaderCreateInfo[0]), // deUint32 stageCount;
967 &shaderCreateInfo[0], // const VkPipelineShaderStageCreateInfo* pStages;
968 &vertexInputStateCreateInfo, // const VkPipelineVertexInputStateCreateInfo* pVertexInputState;
969 &inputAssemblyStateCreateInfo, // const VkPipelineInputAssemblyStateCreateInfo* pInputAssemblyState;
970 DE_NULL, // const VkPipelineTessellationStateCreateInfo* pTessellationState;
971 &viewportStateCreateInfo, // const VkPipelineViewportStateCreateInfo* pViewportState;
972 &rasterizationStateCreateInfo, // const VkPipelineRasterizationStateCreateInfo* pRasterizationState;
973 &multisampleStateCreateInfo, // const VkPipelineMultisampleStateCreateInfo* pMultisampleState;
974 &depthStencilStateParams, // const VkPipelineDepthStencilStateCreateInfo* pDepthStencilState;
975 &colorBlendStateCreateInfo, // const VkPipelineColorBlendStateCreateInfo* pColorBlendState;
976 &dynamicStateCreateInfo, // const VkPipelineDynamicStateCreateInfo* pDynamicState;
977 pipelineLayoutPass0.get(), // VkPipelineLayout layout;
978 renderPass.get(), // VkRenderPass renderPass;
979 0u, // deUint32 subpass;
980 DE_NULL, // VkPipeline basePipelineHandle;
981 0 // int basePipelineIndex;
982 };
983
984 pipelinePass0 = createGraphicsPipeline(vk, device, DE_NULL, &graphicsPipelineCreateInfo);
985 }
986
987
988 // Create pipeline for pass 1
989 Move<VkPipeline> pipelinePass1;
990 Move<VkPipelineLayout> pipelineLayoutPass1;
991 Move<vk::VkDescriptorPool> descriptorPool;
992 Move<vk::VkDescriptorSetLayout> descriptorSetLayout;
993 Move<vk::VkDescriptorSet> descriptorSet;
994 {
995 const VkDescriptorSetLayoutBinding bindings[] =
996 {
997 {
998 0u, // binding
999 VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, // descriptorType
1000 1u, // descriptorCount
1001 VK_SHADER_STAGE_FRAGMENT_BIT, // stageFlags
1002 DE_NULL, // pImmutableSamplers
1003 }
1004 };
1005
1006 // Create a layout and allocate a descriptor set for it.
1007 const VkDescriptorSetLayoutCreateInfo setLayoutCreateInfo =
1008 {
1009 vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, // sType
1010 DE_NULL, // pNext
1011 (VkDescriptorSetLayoutCreateFlags)(0), // flags
1012 sizeof(bindings) / sizeof(bindings[0]), // bindingCount
1013 &bindings[0] // pBindings
1014 };
1015
1016 descriptorSetLayout = vk::createDescriptorSetLayout(vk, device, &setLayoutCreateInfo);
1017
1018 vk::DescriptorPoolBuilder poolBuilder;
1019
1020 for (deInt32 i = 0; i < (deInt32)(sizeof(bindings) / sizeof(bindings[0])); ++i)
1021 {
1022 poolBuilder.addType(bindings[i].descriptorType, bindings[i].descriptorCount);
1023 }
1024
1025 descriptorPool = poolBuilder.build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
1026 descriptorSet = makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout);
1027
1028 VkDescriptorImageInfo imageInfo = makeDescriptorImageInfo(DE_NULL, *cbImagePass0View, VK_IMAGE_LAYOUT_GENERAL);
1029
1030 VkWriteDescriptorSet writeDescriptorSet =
1031 {
1032 VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, // sType
1033 DE_NULL, // pNext
1034 *descriptorSet, // dstSet
1035 0u, // dstBinding
1036 0u, // dstArrayElement
1037 1u, // descriptorCount
1038 bindings[0].descriptorType, // descriptorType
1039 &imageInfo, // pImageInfo
1040 DE_NULL, // pBufferInfo
1041 DE_NULL, // pTexelBufferView
1042 };
1043
1044 vk.updateDescriptorSets(device, 1, &writeDescriptorSet, 0, NULL);
1045
1046 const VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo =
1047 {
1048 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // sType
1049 DE_NULL, // pNext
1050 (VkPipelineLayoutCreateFlags)0,
1051 1u, // setLayoutCount
1052 &descriptorSetLayout.get(), // pSetLayouts
1053 0u, // pushConstantRangeCount
1054 DE_NULL, // pPushConstantRanges
1055 };
1056
1057 pipelineLayoutPass1 = createPipelineLayout(vk, device, &pipelineLayoutCreateInfo, NULL);
1058
1059 const VkPipelineMultisampleStateCreateInfo multisampleStateCreateInfo =
1060 {
1061 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType
1062 DE_NULL, // const void* pNext
1063 0u, // VkPipelineMultisampleStateCreateFlags flags
1064 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits rasterizationSamples
1065 VK_FALSE, // VkBool32 sampleShadingEnable
1066 1.0f, // float minSampleShading
1067 DE_NULL, // const VkSampleMask* pSampleMask
1068 VK_FALSE, // VkBool32 alphaToCoverageEnable
1069 VK_FALSE // VkBool32 alphaToOneEnable
1070 };
1071
1072 VkPipelineFragmentShadingRateStateCreateInfoKHR shadingRateStateCreateInfo =
1073 {
1074 VK_STRUCTURE_TYPE_PIPELINE_FRAGMENT_SHADING_RATE_STATE_CREATE_INFO_KHR, // VkStructureType sType;
1075 DE_NULL, // const void* pNext;
1076 m_data.shadingRate, // VkExtent2D fragmentSize;
1077 { VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR, VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR }, // VkFragmentShadingRateCombinerOpKHR combinerOps[2];
1078 };
1079
1080 Move<VkShaderModule> vertShader = createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0);
1081 Move<VkShaderModule> fragShader = createShaderModule(vk, device, m_context.getBinaryCollection().get("frag_pass1"), 0);
1082
1083 const VkPipelineShaderStageCreateInfo shaderCreateInfo[] =
1084 {
1085 {
1086 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
1087 DE_NULL,
1088 (VkPipelineShaderStageCreateFlags)0,
1089 VK_SHADER_STAGE_VERTEX_BIT, // stage
1090 *vertShader, // shader
1091 "main",
1092 DE_NULL, // pSpecializationInfo
1093 },
1094 {
1095 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
1096 DE_NULL,
1097 (VkPipelineShaderStageCreateFlags)0,
1098 VK_SHADER_STAGE_FRAGMENT_BIT, // stage
1099 *fragShader, // shader
1100 "main",
1101 DE_NULL, // pSpecializationInfo
1102 }
1103 };
1104
1105 const VkGraphicsPipelineCreateInfo graphicsPipelineCreateInfo =
1106 {
1107 VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType sType;
1108 &shadingRateStateCreateInfo, // const void* pNext;
1109 (VkPipelineCreateFlags)0, // VkPipelineCreateFlags flags;
1110 sizeof(shaderCreateInfo) / sizeof(shaderCreateInfo[0]), // deUint32 stageCount;
1111 &shaderCreateInfo[0], // const VkPipelineShaderStageCreateInfo* pStages;
1112 &vertexInputStateCreateInfo, // const VkPipelineVertexInputStateCreateInfo* pVertexInputState;
1113 &inputAssemblyStateCreateInfo, // const VkPipelineInputAssemblyStateCreateInfo* pInputAssemblyState;
1114 DE_NULL, // const VkPipelineTessellationStateCreateInfo* pTessellationState;
1115 &viewportStateCreateInfo, // const VkPipelineViewportStateCreateInfo* pViewportState;
1116 &rasterizationStateCreateInfo, // const VkPipelineRasterizationStateCreateInfo* pRasterizationState;
1117 &multisampleStateCreateInfo, // const VkPipelineMultisampleStateCreateInfo* pMultisampleState;
1118 &depthStencilStateParams, // const VkPipelineDepthStencilStateCreateInfo* pDepthStencilState;
1119 &colorBlendStateCreateInfo, // const VkPipelineColorBlendStateCreateInfo* pColorBlendState;
1120 &dynamicStateCreateInfo, // const VkPipelineDynamicStateCreateInfo* pDynamicState;
1121 pipelineLayoutPass1.get(), // VkPipelineLayout layout;
1122 renderPass.get(), // VkRenderPass renderPass;
1123 1u, // deUint32 subpass;
1124 DE_NULL, // VkPipeline basePipelineHandle;
1125 0 // int basePipelineIndex;
1126 };
1127
1128 pipelinePass1 = createGraphicsPipeline(vk, device, DE_NULL, &graphicsPipelineCreateInfo);
1129 }
1130
1131 // Create command buffer
1132 Move<VkCommandPool> cmdPool = createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, m_context.getUniversalQueueFamilyIndex());
1133 Move<VkCommandBuffer> cmdBuffer = allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
1134
1135 VkImageMemoryBarrier preImageBarriers[] =
1136 {
1137 {
1138 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType
1139 DE_NULL, // const void* pNext
1140 0u, // VkAccessFlags srcAccessMask
1141 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags dstAccessMask
1142 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout
1143 VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout newLayout
1144 VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex
1145 VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex
1146 **cbImagePass0, // VkImage image
1147 {
1148 VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask
1149 0u, // uint32_t baseMipLevel
1150 VK_REMAINING_MIP_LEVELS, // uint32_t mipLevels,
1151 0u, // uint32_t baseArray
1152 VK_REMAINING_ARRAY_LAYERS, // uint32_t arraySize
1153 }
1154 },
1155 {
1156 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType
1157 DE_NULL, // const void* pNext
1158 0u, // VkAccessFlags srcAccessMask
1159 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags dstAccessMask
1160 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout
1161 VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout newLayout
1162 VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex
1163 VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex
1164 **cbImagePass1, // VkImage image
1165 {
1166 VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask
1167 0u, // uint32_t baseMipLevel
1168 VK_REMAINING_MIP_LEVELS, // uint32_t mipLevels,
1169 0u, // uint32_t baseArray
1170 VK_REMAINING_ARRAY_LAYERS, // uint32_t arraySize
1171 }
1172 }
1173 };
1174
1175 // Record commands
1176 beginCommandBuffer(vk, *cmdBuffer, 0u);
1177
1178 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
1179 (VkDependencyFlags)0,
1180 0, (const VkMemoryBarrier*)DE_NULL,
1181 0, (const VkBufferMemoryBarrier*)DE_NULL,
1182 sizeof(preImageBarriers) / sizeof(preImageBarriers[0]), preImageBarriers);
1183
1184 // Clear both images to UINT_MAX
1185 VkImageSubresourceRange range = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
1186 VkClearValue clearColor = makeClearValueColorU32(std::numeric_limits<unsigned int>::max(),0,0,0);
1187
1188 vk.cmdClearColorImage(*cmdBuffer, **cbImagePass0, VK_IMAGE_LAYOUT_GENERAL, &clearColor.color, 1, &range);
1189 vk.cmdClearColorImage(*cmdBuffer, **cbImagePass1, VK_IMAGE_LAYOUT_GENERAL, &clearColor.color, 1, &range);
1190
1191 // Barrier between the clear and the rendering
1192 VkImageMemoryBarrier clearColorBarriers[] =
1193 {
1194 {
1195 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType
1196 DE_NULL, // const void* pNext
1197 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask
1198 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags dstAccessMask
1199 VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout oldLayout
1200 VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout newLayout
1201 VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex
1202 VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex
1203 **cbImagePass0, // VkImage image
1204 {
1205 VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask
1206 0u, // uint32_t baseMipLevel
1207 VK_REMAINING_MIP_LEVELS, // uint32_t mipLevels,
1208 0u, // uint32_t baseArray
1209 VK_REMAINING_ARRAY_LAYERS, // uint32_t arraySize
1210 }
1211 },
1212 {
1213 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType
1214 DE_NULL, // const void* pNext
1215 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask
1216 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags dstAccessMask
1217 VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout oldLayout
1218 VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout newLayout
1219 VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex
1220 VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex
1221 **cbImagePass1, // VkImage image
1222 {
1223 VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask
1224 0u, // uint32_t baseMipLevel
1225 VK_REMAINING_MIP_LEVELS, // uint32_t mipLevels,
1226 0u, // uint32_t baseArray
1227 VK_REMAINING_ARRAY_LAYERS, // uint32_t arraySize
1228 }
1229 }
1230 };
1231
1232 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
1233 (VkDependencyFlags)0,
1234 0, (const VkMemoryBarrier*)DE_NULL,
1235 0, (const VkBufferMemoryBarrier*)DE_NULL,
1236 sizeof(clearColorBarriers) / sizeof(clearColorBarriers[0]), clearColorBarriers);
1237
1238 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer,
1239 makeRect2D(m_data.framebufferExtent.width, m_data.framebufferExtent.height),
1240 0, DE_NULL, VK_SUBPASS_CONTENTS_INLINE, DE_NULL);
1241
1242 // Put primitive shading rate in a push constant
1243 if (m_shadingRateClamped.size() == 1)
1244 {
1245 vk.cmdPushConstants(*cmdBuffer, *pipelineLayoutPass0, VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(m_shadingRateClamped[0]), &m_shadingRateClamped[0]);
1246 vk.cmdPushConstants(*cmdBuffer, *pipelineLayoutPass0, VK_SHADER_STAGE_FRAGMENT_BIT, sizeof(m_shadingRateClamped[0]), sizeof(m_shadingRateClamped[0]), &m_shadingRateClamped[0]);
1247 }
1248 else
1249 {
1250 vk.cmdPushConstants(*cmdBuffer, *pipelineLayoutPass0, VK_SHADER_STAGE_FRAGMENT_BIT, 0, static_cast<deUint32>(m_shadingRateClamped.size() * sizeof(m_shadingRateClamped[0])), &m_shadingRateClamped[0]);
1251 }
1252
1253 // Bind vertex buffer
1254 const VkDeviceSize vertexBufferOffset = 0;
1255 VkBuffer vb = **vertexBuffer;
1256 vk.cmdBindVertexBuffers(*cmdBuffer, 0, 1, &vb, &vertexBufferOffset);
1257
1258 // Bind pipeline
1259 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelinePass0);
1260
1261 // Draw triangles
1262 vk.cmdDraw(*cmdBuffer, sizeof(basicTriangles) / sizeof(Vertex), 1u, 0u, 0u);
1263
1264 // Start next subpass
1265 vk.cmdNextSubpass(*cmdBuffer, VK_SUBPASS_CONTENTS_INLINE);
1266
1267 // Bind descriptors
1268 vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayoutPass1, 0, 1, &descriptorSet.get(), 0, DE_NULL);
1269
1270 // Bind vertex buffer
1271 vk.cmdBindVertexBuffers(*cmdBuffer, 0, 1, &vb, &vertexBufferOffset);
1272
1273 // Bind pipeline
1274 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelinePass1);
1275
1276 // Draw triangles
1277 vk.cmdDraw(*cmdBuffer, sizeof(basicTriangles) / sizeof(Vertex), 1u, 0u, 0u);
1278
1279 endRenderPass(vk, *cmdBuffer);
1280
1281 VkImageMemoryBarrier postImageBarrier =
1282 {
1283 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType
1284 DE_NULL, // const void* pNext
1285 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags srcAccessMask
1286 VK_ACCESS_TRANSFER_READ_BIT, // VkAccessFlags dstAccessMask
1287 VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout oldLayout
1288 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // VkImageLayout newLayout
1289 VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex
1290 VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex
1291 **cbImagePass1, // VkImage image
1292 {
1293 VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask
1294 0u, // uint32_t baseMipLevel
1295 VK_REMAINING_MIP_LEVELS, // uint32_t mipLevels,
1296 0u, // uint32_t baseArray
1297 VK_REMAINING_ARRAY_LAYERS, // uint32_t arraySize
1298 }
1299 };
1300
1301 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);
1302
1303 const VkBufferImageCopy copyRegion =
1304 {
1305 0u, // VkDeviceSize bufferOffset;
1306 0u, // deUint32 bufferRowLength;
1307 0u, // deUint32 bufferImageHeight;
1308 {
1309 VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspect;
1310 0u, // deUint32 mipLevel;
1311 0u, // deUint32 baseArrayLayer;
1312 1u, // deUint32 layerCount;
1313 }, // VkImageSubresourceLayers imageSubresource;
1314 { 0, 0, 0 }, // VkOffset3D imageOffset;
1315 {m_data.framebufferExtent.width, m_data.framebufferExtent.height, 1} // VkExtent3D imageExtent;
1316 };
1317
1318 vk.cmdCopyImageToBuffer(*cmdBuffer, **cbImagePass1, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, **colorOutputBuffer, 1u, ©Region);
1319
1320 const VkBufferMemoryBarrier bufferBarrier =
1321 {
1322 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType;
1323 DE_NULL, // const void* pNext;
1324 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask;
1325 VK_ACCESS_HOST_READ_BIT, // VkAccessFlags dstAccessMask;
1326 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
1327 VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex;
1328 **colorOutputBuffer, // VkBuffer buffer;
1329 0ull, // VkDeviceSize offset;
1330 VK_WHOLE_SIZE // VkDeviceSize size;
1331 };
1332
1333 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);
1334
1335 endCommandBuffer(vk, *cmdBuffer);
1336
1337 submitCommandsAndWait(vk, device, queue, cmdBuffer.get());
1338
1339 // Read buffer data
1340 invalidateAlloc(vk, device, colorOutputBuffer->getAllocation());
1341
1342 tcu::ConstPixelBufferAccess resultBuffer = tcu::ConstPixelBufferAccess(
1343 tcu::TextureFormat(tcu::TextureFormat::RG, tcu::TextureFormat::UNSIGNED_INT32),
1344 m_data.framebufferExtent.width, m_data.framebufferExtent.height, 1, (const void *)colorOutputBuffer->getAllocation().getHostPtr());
1345
1346 for (deUint32 i = 0; i < m_shadingRateClamped.size(); i++)
1347 {
1348 tcu::TestStatus result = verifyResult(resultBuffer, i);
1349 if (result.getCode() == QP_TEST_RESULT_PASS)
1350 {
1351 return result;
1352 }
1353 }
1354
1355 return tcu::TestStatus(QP_TEST_RESULT_FAIL, qpGetTestResultName(QP_TEST_RESULT_FAIL));
1356 }
1357
1358 } // anonymous
1359
createPixelConsistencyTests(tcu::TestContext & testCtx,tcu::TestCaseGroup * parentGroup)1360 void createPixelConsistencyTests(tcu::TestContext& testCtx, tcu::TestCaseGroup* parentGroup)
1361 {
1362 typedef struct
1363 {
1364 deUint32 count;
1365 const char* name;
1366 } TestGroupCase;
1367
1368 typedef struct
1369 {
1370 VkExtent2D count;
1371 const char* name;
1372 } TestGroupCase2D;
1373
1374 TestGroupCase2D shadingRateCases[] =
1375 {
1376 { {1, 1}, "rate_1x1"},
1377 { {1, 2}, "rate_1x2"},
1378 { {1, 4}, "rate_1x4"},
1379 { {2, 1}, "rate_2x1"},
1380 { {2, 2}, "rate_2x2"},
1381 { {2, 4}, "rate_2x4",},
1382 { {4, 1}, "rate_4x1",},
1383 { {4, 2}, "rate_4x2",},
1384 { {4, 4}, "rate_4x4",},
1385 };
1386
1387 TestGroupCase sampCases[] =
1388 {
1389 { VK_SAMPLE_COUNT_1_BIT, "samples_1"},
1390 { VK_SAMPLE_COUNT_2_BIT, "samples_2"},
1391 { VK_SAMPLE_COUNT_4_BIT, "samples_4"},
1392 { VK_SAMPLE_COUNT_8_BIT, "samples_8"},
1393 { VK_SAMPLE_COUNT_16_BIT, "samples_16"},
1394 };
1395
1396 TestGroupCase2D extentCases[] =
1397 {
1398 { {1, 1}, "extent_1x1"},
1399 { {4, 4}, "extent_4x4"},
1400 { {33, 35}, "extent_33x35"},
1401 { {151, 431}, "extent_151x431"},
1402 { {256, 256}, "extent_256x256"},
1403 };
1404
1405 de::MovePtr<tcu::TestCaseGroup> pixelGroup(new tcu::TestCaseGroup(testCtx, "pixel_consistency"));
1406
1407 for (int rateNdx = 0; rateNdx < DE_LENGTH_OF_ARRAY(shadingRateCases); rateNdx++)
1408 {
1409 de::MovePtr<tcu::TestCaseGroup> rateGroup(new tcu::TestCaseGroup(testCtx, shadingRateCases[rateNdx].name));
1410
1411 for (int sampNdx = 0; sampNdx < DE_LENGTH_OF_ARRAY(sampCases); sampNdx++)
1412 {
1413 de::MovePtr<tcu::TestCaseGroup> sampleGroup(new tcu::TestCaseGroup(testCtx, sampCases[sampNdx].name));
1414 for (int extNdx = 0; extNdx < DE_LENGTH_OF_ARRAY(extentCases); extNdx++)
1415 {
1416 VkSampleCountFlagBits samples = static_cast<VkSampleCountFlagBits>(sampCases[sampNdx].count);
1417 VkExtent2D framebufferExtent = extentCases[extNdx].count;
1418
1419 CaseDef caseParams{
1420 shadingRateCases[rateNdx].count,
1421 samples,
1422 framebufferExtent,
1423 false};
1424 sampleGroup->addChild(new FSRPixelConsistencyTestCase(testCtx, extentCases[extNdx].name, caseParams));
1425
1426 // test FragCoord.zw but to avoid duplication limit tests to extent_151x431/256x256 and 1 or 4 samples
1427 if ((framebufferExtent.width > 150) && (samples & (VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT)))
1428 {
1429 std::string caseName = std::string(extentCases[extNdx].name) + "_zw_coord";
1430 caseParams.zwCoord = true;
1431 sampleGroup->addChild(new FSRPixelConsistencyTestCase(testCtx, caseName.c_str(), caseParams));
1432 }
1433 }
1434 rateGroup->addChild(sampleGroup.release());
1435 }
1436
1437 pixelGroup->addChild(rateGroup.release());
1438 }
1439
1440 parentGroup->addChild(pixelGroup.release());
1441 }
1442
1443 } // FragmentShadingRage
1444 } // vkt
1445