1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2021 The Khronos Group Inc.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  *//*!
20  * \file
21  * \brief Tests for VK_KHR_fragment_shading_rate
22  *//*--------------------------------------------------------------------*/
23 
24 #include "vktAttachmentRateTests.hpp"
25 
26 #include "vkBufferWithMemory.hpp"
27 #include "vkImageWithMemory.hpp"
28 #include "vkQueryUtil.hpp"
29 #include "vkBarrierUtil.hpp"
30 #include "vkCmdUtil.hpp"
31 #include "vkTypeUtil.hpp"
32 #include "vkObjUtil.hpp"
33 #include "vkImageUtil.hpp"
34 #include "vkQueryUtil.hpp"
35 #include "vkPlatform.hpp"
36 #include "vkBuilderUtil.hpp"
37 
38 #include "vktTestGroupUtil.hpp"
39 #include "vktTestCase.hpp"
40 #include "vktCustomInstancesDevices.hpp"
41 
42 #include "deDefs.h"
43 #include "deMath.h"
44 #include "deSharedPtr.hpp"
45 #include "deString.h"
46 #include "deSTLUtil.hpp"
47 
48 #include "tcuTestCase.hpp"
49 #include "tcuTestLog.hpp"
50 #include "tcuTextureUtil.hpp"
51 #include "tcuStringTemplate.hpp"
52 
53 #include <string>
54 #include <vector>
55 #include <limits>
56 #include <map>
57 
58 namespace vkt
59 {
60 namespace FragmentShadingRate
61 {
62 namespace
63 {
64 
65 using namespace vk;
66 
67 // flag used to test TM_SETUP_RATE_WITH_ATOMICS_IN_COMPUTE_SHADER;
68 // when it is 1 instead of using atomic operations to fill image
69 // plain store will be used as it is always supported
70 #define DEBUG_USE_STORE_INSTEAD_OF_ATOMICS 0
71 
72 enum TestMode
73 {
74     TM_SETUP_RATE_WITH_ATOMICS_IN_COMPUTE_SHADER = 0,
75     TM_SETUP_RATE_WITH_FRAGMENT_SHADER,
76     TM_SETUP_RATE_WITH_COPYING_FROM_OTHER_IMAGE,
77     TM_SETUP_RATE_WITH_COPYING_FROM_EXCLUSIVE_IMAGE_USING_TRANSFER_QUEUE,
78     TM_SETUP_RATE_WITH_COPYING_FROM_CONCURENT_IMAGE_USING_TRANSFER_QUEUE,
79     TM_SETUP_RATE_WITH_LINEAR_TILED_IMAGE,
80 
81     TM_TWO_SUBPASS,
82     TM_MEMORY_ACCESS,
83     TM_MAINTENANCE_5
84 };
85 
86 struct DepthStencilParams
87 {
88     const VkFormat format;
89     const VkImageLayout layout;
90 
DepthStencilParamsvkt::FragmentShadingRate::__anonb7408abd0111::DepthStencilParams91     DepthStencilParams(VkFormat format_, VkImageLayout layout_) : format(format_), layout(layout_)
92     {
93         DE_ASSERT(format != VK_FORMAT_UNDEFINED);
94     }
95 };
96 
97 using OptDSParams = tcu::Maybe<DepthStencilParams>;
98 
99 struct TestParams
100 {
101     TestMode mode;
102 
103     VkFormat srFormat;
104     VkExtent2D srRate;
105 
106     bool useDynamicRendering;
107     bool useImagelessFramebuffer;
108     bool useNullShadingRateImage;
109     OptDSParams dsParams;
110 
useDepthStencilvkt::FragmentShadingRate::__anonb7408abd0111::TestParams111     bool useDepthStencil(void) const
112     {
113         return (hasDSParams() && dsParams->format != VK_FORMAT_UNDEFINED);
114     }
115 
116     // Returns depth/stencil format, or VK_FORMAT_UNDEFINED if not present.
getDSFormatvkt::FragmentShadingRate::__anonb7408abd0111::TestParams117     VkFormat getDSFormat(void) const
118     {
119         return (hasDSParams() ? dsParams->format : VK_FORMAT_UNDEFINED);
120     }
121 
122     // Returns depth/stencil layout, or VK_IMAGE_LAYOUT_UNDEFINED if not present.
getDSLayoutvkt::FragmentShadingRate::__anonb7408abd0111::TestParams123     VkImageLayout getDSLayout(void) const
124     {
125         return (hasDSParams() ? dsParams->layout : VK_IMAGE_LAYOUT_UNDEFINED);
126     }
127 
128 private:
hasDSParamsvkt::FragmentShadingRate::__anonb7408abd0111::TestParams129     inline bool hasDSParams(void) const
130     {
131         return static_cast<bool>(dsParams);
132     }
133 };
134 
135 constexpr VkImageUsageFlags kDSUsage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
136 
getFormatAspectFlags(const VkFormat format)137 VkImageAspectFlags getFormatAspectFlags(const VkFormat format)
138 {
139     if (format == VK_FORMAT_UNDEFINED)
140         return 0u;
141 
142     const auto order = mapVkFormat(format).order;
143 
144     switch (order)
145     {
146     case tcu::TextureFormat::DS:
147         return (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT);
148     case tcu::TextureFormat::D:
149         return VK_IMAGE_ASPECT_DEPTH_BIT;
150     case tcu::TextureFormat::S:
151         return VK_IMAGE_ASPECT_STENCIL_BIT;
152     default:
153         return VK_IMAGE_ASPECT_COLOR_BIT;
154     }
155 
156     DE_ASSERT(false);
157     return 0u;
158 }
159 
calculateRate(uint32_t rateWidth,uint32_t rateHeight)160 uint32_t calculateRate(uint32_t rateWidth, uint32_t rateHeight)
161 {
162     return (deCtz32(rateWidth) << 2u) | deCtz32(rateHeight);
163 }
164 
165 class DeviceHolder
166 {
167 public:
168     DeviceHolder(Move<VkDevice> device, de::MovePtr<DeviceDriver> vk, de::MovePtr<Allocator> allocator);
169 
170 private:
171     Move<VkDevice> m_device;
172     de::MovePtr<DeviceDriver> m_vk;
173     de::MovePtr<Allocator> m_allocator;
174 };
175 
DeviceHolder(Move<VkDevice> device,de::MovePtr<DeviceDriver> vk,de::MovePtr<Allocator> allocator)176 DeviceHolder::DeviceHolder(Move<VkDevice> device, de::MovePtr<DeviceDriver> vk, de::MovePtr<Allocator> allocator)
177     : m_device(device)
178     , m_vk(vk)
179     , m_allocator(allocator)
180 {
181 }
182 
183 class AttachmentRateInstance : public TestInstance
184 {
185 public:
186     AttachmentRateInstance(Context &context, const de::SharedPtr<TestParams> params);
187     tcu::TestStatus iterate(void);
188 
189 private:
190     // Helper structure used by buildFramebuffer method.
191     // It is used to build regular or imageless framebuffer.
192     struct FBAttachmentInfo
193     {
194         VkFormat format;
195         VkImageUsageFlags usage;
196         uint32_t width;
197         uint32_t height;
198         VkImageView view;
199     };
200 
201 private:
202     de::MovePtr<ImageWithMemory> buildImageWithMemory(VkDevice device, const DeviceInterface &vk,
203                                                       vk::Allocator &allocator, VkFormat format, uint32_t width,
204                                                       uint32_t height, VkImageUsageFlags usage,
205                                                       VkImageTiling tiling                = VK_IMAGE_TILING_OPTIMAL,
206                                                       std::vector<uint32_t> queueFamilies = std::vector<uint32_t>());
207     de::MovePtr<BufferWithMemory> buildBufferWithMemory(VkDevice device, const DeviceInterface &vk,
208                                                         vk::Allocator &allocator, uint32_t size,
209                                                         VkBufferUsageFlags usage);
210     Move<VkImageView> buildImageView(VkDevice device, const DeviceInterface &vk, VkFormat format, VkImage image);
211 
212     void buildColorBufferObjects(VkDevice device, const DeviceInterface &vk, vk::Allocator &allocator,
213                                  uint32_t cbIindex, VkImageUsageFlags cbUsage);
214     void buildShadingRateObjects(VkDevice device, const DeviceInterface &vk, vk::Allocator &allocator, uint32_t srIndex,
215                                  uint32_t width, uint32_t height, VkImageUsageFlags srUsage,
216                                  VkImageTiling srTiling = VK_IMAGE_TILING_OPTIMAL);
217     void buildCounterBufferObjects(VkDevice device, const DeviceInterface &vk, vk::Allocator &allocator);
218 
219     Move<VkRenderPass> buildRenderPass(VkDevice device, const DeviceInterface &vk, VkFormat cbFormat, VkFormat dsFormat,
220                                        uint32_t sr1TileWidth = 0, uint32_t sr1TileHeight = 0, uint32_t sr2TileWidth = 0,
221                                        uint32_t sr2TileHeight = 0) const;
222     Move<VkFramebuffer> buildFramebuffer(VkDevice device, const DeviceInterface &vk, VkRenderPass renderPass,
223                                          const std::vector<FBAttachmentInfo> &attachmentInfo) const;
224     Move<VkPipelineLayout> buildPipelineLayout(VkDevice device, const DeviceInterface &vk,
225                                                const VkDescriptorSetLayout *setLayouts = DE_NULL) const;
226     Move<VkPipeline> buildGraphicsPipeline(VkDevice device, const DeviceInterface &vk, uint32_t subpass,
227                                            VkRenderPass renderPass, VkFormat cbFormat, VkFormat dsFormat,
228                                            VkPipelineLayout layout, VkShaderModule vertShader,
229                                            VkShaderModule fragShader, bool useShadingRate = VK_TRUE) const;
230     Move<VkPipeline> buildComputePipeline(VkDevice device, const DeviceInterface &vk, VkShaderModule compShader,
231                                           VkPipelineLayout pipelineLayout) const;
232     VkDescriptorSetAllocateInfo makeDescriptorSetAllocInfo(VkDescriptorPool descriptorPool,
233                                                            const VkDescriptorSetLayout *pSetLayouts) const;
234 
235     void startRendering(const VkCommandBuffer commandBuffer, const VkRenderPass renderPass,
236                         const VkFramebuffer framebuffer, const VkRect2D &renderArea,
237                         const std::vector<FBAttachmentInfo> &attachmentInfo, const uint32_t srTileWidth = 0,
238                         const uint32_t srTileHeight = 0, const DeviceInterface *customDevice = nullptr) const;
239     void finishRendering(const VkCommandBuffer commandBuffer) const;
240 
241     bool verifyUsingAtomicChecks(uint32_t tileWidth, uint32_t tileHeight, uint32_t rateWidth, uint32_t rateHeight,
242                                  uint32_t *outBufferPtr) const;
243 
244     bool runComputeShaderMode(void);
245     bool runFragmentShaderMode(void);
246     bool runCopyMode(void);
247     bool runCopyModeOnTransferQueue(void);
248     bool runFillLinearTiledImage(void);
249     bool runTwoSubpassMode(void);
250 
251 private:
252     // A custom device is by tests from runCopyModeOnTransferQueue.
253     // In this test the device is passed to various utils, that create
254     // Vulkan objects later assigned to various members below. To guarantee
255     // proper destruction order, below variable acts as an owner of this custom device
256     // - however, it is not to be used (the device is not accessible directly from this object
257     //   to avoid misusages of the framework device vs custom device).
258     de::MovePtr<DeviceHolder> m_customDeviceHolder;
259 
260     const de::SharedPtr<TestParams> m_params;
261     const uint32_t m_cbWidth;
262     const uint32_t m_cbHeight;
263     VkFormat m_cbFormat;
264     VkImageUsageFlags m_cbUsage;
265     VkImageUsageFlags m_srUsage;
266 
267     // structures commonly used by most of tests
268     const VkImageSubresourceLayers m_defaultImageSubresourceLayers;
269     const VkImageSubresourceRange m_defaultImageSubresourceRange;
270     const VkImageSubresourceRange m_dsImageSubresourceRange;
271     const VkBufferImageCopy m_defaultBufferImageCopy;
272 
273     // objects commonly used by most of tests
274     de::MovePtr<ImageWithMemory> m_cbImage[2];
275     Move<VkImageView> m_cbImageView[2];
276     de::MovePtr<BufferWithMemory> m_cbReadBuffer[2];
277 
278     de::MovePtr<ImageWithMemory> m_dsImage;
279     Move<VkImageView> m_dsImageView;
280 
281     de::MovePtr<ImageWithMemory> m_srImage[2];
282     Move<VkImageView> m_srImageView[2];
283 
284     Move<VkDescriptorSetLayout> m_counterBufferDescriptorSetLayout;
285     Move<VkDescriptorPool> m_counterBufferDescriptorPool;
286     Move<VkDescriptorSet> m_counterBufferDescriptorSet;
287     de::MovePtr<BufferWithMemory> m_counterBuffer;
288 
289     // properties commonly used by most of tests
290     VkExtent2D m_minTileSize;
291     VkExtent2D m_maxTileSize;
292     uint32_t m_maxAspectRatio;
293 };
294 
AttachmentRateInstance(Context & context,const de::SharedPtr<TestParams> params)295 AttachmentRateInstance::AttachmentRateInstance(Context &context, const de::SharedPtr<TestParams> params)
296     : vkt::TestInstance(context)
297     , m_params(params)
298     , m_cbWidth(60)
299     , m_cbHeight(60)
300     , m_cbFormat(VK_FORMAT_R32G32B32A32_UINT)
301     , m_cbUsage(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT)
302     , m_srUsage(VK_IMAGE_USAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR | VK_IMAGE_USAGE_TRANSFER_DST_BIT)
303     , m_defaultImageSubresourceLayers(makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u))
304     , m_defaultImageSubresourceRange(makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0, 1u))
305     , m_dsImageSubresourceRange(makeImageSubresourceRange(getFormatAspectFlags(m_params->getDSFormat()), 0u, 1u, 0, 1u))
306     , m_defaultBufferImageCopy(makeBufferImageCopy({m_cbWidth, m_cbHeight, 1u}, m_defaultImageSubresourceLayers))
307 {
308     // prepare data needed to calculate tile sizes
309     const auto &srProperties = m_context.getFragmentShadingRateProperties();
310     m_minTileSize            = srProperties.minFragmentShadingRateAttachmentTexelSize;
311     m_maxTileSize            = srProperties.maxFragmentShadingRateAttachmentTexelSize;
312     m_maxAspectRatio         = srProperties.maxFragmentShadingRateAttachmentTexelSizeAspectRatio;
313 }
314 
buildImageWithMemory(VkDevice device,const DeviceInterface & vk,vk::Allocator & allocator,VkFormat format,uint32_t width,uint32_t height,VkImageUsageFlags usage,VkImageTiling tiling,std::vector<uint32_t> queueFamilies)315 de::MovePtr<ImageWithMemory> AttachmentRateInstance::buildImageWithMemory(VkDevice device, const DeviceInterface &vk,
316                                                                           vk::Allocator &allocator, VkFormat format,
317                                                                           uint32_t width, uint32_t height,
318                                                                           VkImageUsageFlags usage, VkImageTiling tiling,
319                                                                           std::vector<uint32_t> queueFamilies)
320 {
321     VkImageCreateInfo imageCreateInfo{
322         VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
323         DE_NULL,                             // const void* pNext;
324         (VkImageCreateFlags)0u,              // VkImageCreateFlags flags;
325         VK_IMAGE_TYPE_2D,                    // VkImageType imageType;
326         format,                              // VkFormat format;
327         {
328             width,             // uint32_t width;
329             height,            // uint32_t height;
330             1u                 // uint32_t depth;
331         },                     // VkExtent3D extent;
332         1u,                    // uint32_t mipLevels;
333         1u,                    // uint32_t arrayLayers;
334         VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
335         tiling,                // VkImageTiling tiling;
336         usage,                 // VkImageUsageFlags usage;
337         queueFamilies.empty() ? VK_SHARING_MODE_EXCLUSIVE : VK_SHARING_MODE_CONCURRENT, // VkSharingMode sharingMode;
338         (uint32_t)queueFamilies.size(), // uint32_t queueFamilyIndexCount;
339         queueFamilies.data(),           // const uint32_t* pQueueFamilyIndices;
340         VK_IMAGE_LAYOUT_UNDEFINED       // VkImageLayout initialLayout;
341     };
342 
343     vk::MemoryRequirement memoryRequirement =
344         (tiling == VK_IMAGE_TILING_LINEAR) ? MemoryRequirement::HostVisible : MemoryRequirement::Any;
345     return de::MovePtr<ImageWithMemory>(new ImageWithMemory(vk, device, allocator, imageCreateInfo, memoryRequirement));
346 }
347 
buildBufferWithMemory(VkDevice device,const DeviceInterface & vk,vk::Allocator & allocator,uint32_t size,VkBufferUsageFlags usage)348 de::MovePtr<BufferWithMemory> AttachmentRateInstance::buildBufferWithMemory(VkDevice device, const DeviceInterface &vk,
349                                                                             vk::Allocator &allocator, uint32_t size,
350                                                                             VkBufferUsageFlags usage)
351 {
352     const VkBufferCreateInfo readBufferInfo = makeBufferCreateInfo(size, usage);
353 
354     return de::MovePtr<BufferWithMemory>(
355         new BufferWithMemory(vk, device, allocator, readBufferInfo, MemoryRequirement::HostVisible));
356 }
357 
buildImageView(VkDevice device,const DeviceInterface & vk,VkFormat format,VkImage image)358 Move<VkImageView> AttachmentRateInstance::buildImageView(VkDevice device, const DeviceInterface &vk, VkFormat format,
359                                                          VkImage image)
360 {
361     const auto aspect           = getFormatAspectFlags(format);
362     const auto subresourceRange = makeImageSubresourceRange(aspect, 0u, 1u, 0u, 1u);
363 
364     return makeImageView(vk, device, image, VK_IMAGE_VIEW_TYPE_2D, format, subresourceRange);
365 };
366 
buildColorBufferObjects(VkDevice device,const DeviceInterface & vk,vk::Allocator & allocator,uint32_t cbIndex,VkImageUsageFlags cbUsage)367 void AttachmentRateInstance::buildColorBufferObjects(VkDevice device, const DeviceInterface &vk,
368                                                      vk::Allocator &allocator, uint32_t cbIndex,
369                                                      VkImageUsageFlags cbUsage)
370 {
371     DE_ASSERT(cbIndex < 2);
372 
373     m_cbImage[cbIndex]      = buildImageWithMemory(device, vk, allocator, m_cbFormat, m_cbWidth, m_cbHeight, cbUsage);
374     m_cbImageView[cbIndex]  = buildImageView(device, vk, m_cbFormat, m_cbImage[cbIndex]->get());
375     m_cbReadBuffer[cbIndex] = buildBufferWithMemory(
376         device, vk, allocator, m_cbWidth * m_cbHeight * uint32_t(sizeof(int)) * 4u, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
377 
378     if (m_params->useDepthStencil() && m_dsImage.get() == nullptr)
379     {
380         const auto dsFormat = m_params->getDSFormat();
381         m_dsImage           = buildImageWithMemory(device, vk, allocator, dsFormat, m_cbWidth, m_cbHeight, kDSUsage);
382         m_dsImageView       = buildImageView(device, vk, dsFormat, m_dsImage->get());
383     }
384 }
385 
buildShadingRateObjects(VkDevice device,const DeviceInterface & vk,vk::Allocator & allocator,uint32_t srIndex,uint32_t width,uint32_t height,VkImageUsageFlags srUsage,VkImageTiling srTiling)386 void AttachmentRateInstance::buildShadingRateObjects(VkDevice device, const DeviceInterface &vk,
387                                                      vk::Allocator &allocator, uint32_t srIndex, uint32_t width,
388                                                      uint32_t height, VkImageUsageFlags srUsage, VkImageTiling srTiling)
389 {
390     DE_ASSERT(srIndex < 2);
391 
392     m_srImage[srIndex] =
393         buildImageWithMemory(device, vk, allocator, m_params->srFormat, width, height, srUsage, srTiling);
394     m_srImageView[srIndex] = buildImageView(device, vk, m_params->srFormat, m_srImage[srIndex]->get());
395 }
396 
buildCounterBufferObjects(VkDevice device,const vk::DeviceInterface & vk,vk::Allocator & allocator)397 void AttachmentRateInstance::buildCounterBufferObjects(VkDevice device, const vk::DeviceInterface &vk,
398                                                        vk::Allocator &allocator)
399 {
400     m_counterBufferDescriptorPool = DescriptorPoolBuilder()
401                                         .addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1u)
402                                         .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
403     m_counterBufferDescriptorSetLayout =
404         DescriptorSetLayoutBuilder()
405             .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT)
406             .build(vk, device);
407 
408     const VkDescriptorSetAllocateInfo descriptorSetAllocInfo =
409         makeDescriptorSetAllocInfo(*m_counterBufferDescriptorPool, &(*m_counterBufferDescriptorSetLayout));
410     m_counterBufferDescriptorSet = allocateDescriptorSet(vk, device, &descriptorSetAllocInfo);
411 
412     // create ssbo buffer for atomic counter
413     uint32_t ssboSize = uint32_t(sizeof(uint32_t));
414     m_counterBuffer   = buildBufferWithMemory(device, vk, allocator, ssboSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
415 
416     const VkDescriptorBufferInfo descriptorInfo = makeDescriptorBufferInfo(**m_counterBuffer, 0, ssboSize);
417     DescriptorSetUpdateBuilder()
418         .writeSingle(*m_counterBufferDescriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u),
419                      VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &descriptorInfo)
420         .update(vk, device);
421 
422     // reset counter
423     *((uint32_t *)m_counterBuffer->getAllocation().getHostPtr()) = 0u;
424     flushAlloc(vk, device, m_counterBuffer->getAllocation());
425 }
426 
buildRenderPass(VkDevice device,const vk::DeviceInterface & vk,VkFormat cbFormat,VkFormat dsFormat,uint32_t sr0TileWidth,uint32_t sr0TileHeight,uint32_t sr1TileWidth,uint32_t sr1TileHeight) const427 Move<VkRenderPass> AttachmentRateInstance::buildRenderPass(VkDevice device, const vk::DeviceInterface &vk,
428                                                            VkFormat cbFormat, VkFormat dsFormat, uint32_t sr0TileWidth,
429                                                            uint32_t sr0TileHeight, uint32_t sr1TileWidth,
430                                                            uint32_t sr1TileHeight) const
431 {
432     if (m_params->useDynamicRendering)
433         return Move<VkRenderPass>();
434 
435     const bool useShadingRate0 = (sr0TileWidth * sr0TileHeight > 0);
436     const bool useShadingRate1 = (sr1TileWidth * sr1TileHeight > 0);
437 
438     uint32_t attachmentCount    = 1;
439     const uint32_t subpassCount = 1 + useShadingRate1;
440 
441     std::vector<VkAttachmentReference2> colorAttachmentReferences(
442         subpassCount, {
443                           VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2, // VkStructureType sType;
444                           DE_NULL,                                  // const void* pNext;
445                           0,                                        // uint32_t attachment;
446                           VK_IMAGE_LAYOUT_GENERAL,                  // VkImageLayout layout;
447                           0,                                        // VkImageAspectFlags aspectMask;
448                       });
449 
450     std::vector<VkAttachmentReference2> fragmentShadingRateAttachments(
451         subpassCount,
452         {
453             VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2,                     // VkStructureType sType;
454             DE_NULL,                                                      // const void* pNext;
455             1,                                                            // uint32_t attachment;
456             VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR, // VkImageLayout layout;
457             0,                                                            // VkImageAspectFlags aspectMask;
458         });
459 
460     std::vector<VkFragmentShadingRateAttachmentInfoKHR> shadingRateAttachmentInfos(
461         subpassCount,
462         {
463             VK_STRUCTURE_TYPE_FRAGMENT_SHADING_RATE_ATTACHMENT_INFO_KHR, // VkStructureType sType;
464             DE_NULL,                                                     // const void* pNext;
465             &fragmentShadingRateAttachments[0], // const VkAttachmentReference2* pFragmentShadingRateAttachment;
466             {sr0TileWidth, sr0TileHeight},      // VkExtent2D shadingRateAttachmentTexelSize;
467         });
468 
469     std::vector<VkSubpassDescription2> subpassDescriptions(
470         subpassCount, {
471                           VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2, // VkStructureType sType;
472                           DE_NULL,                                 // const void* pNext;
473                           (vk::VkSubpassDescriptionFlags)0,        // VkSubpassDescriptionFlags flags;
474                           vk::VK_PIPELINE_BIND_POINT_GRAPHICS,     // VkPipelineBindPoint pipelineBindPoint;
475                           0u,                                      // uint32_t viewMask;
476                           0u,                                      // uint32_t inputAttachmentCount;
477                           DE_NULL,                                 // const VkAttachmentReference2* pInputAttachments;
478                           1,                                       // uint32_t colorAttachmentCount;
479                           &colorAttachmentReferences[0],           // const VkAttachmentReference2* pColorAttachments;
480                           DE_NULL,                                 // const VkAttachmentReference2* pResolveAttachments;
481                           DE_NULL, // const VkAttachmentReference2* pDepthStencilAttachment;
482                           0u,      // uint32_t preserveAttachmentCount;
483                           DE_NULL, // const uint32_t* pPreserveAttachments;
484                       });
485 
486     std::vector<VkAttachmentDescription2> attachmentDescriptions(
487         2 * subpassCount, {
488                               VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2, // VkStructureType sType;
489                               DE_NULL,                                    // const void* pNext;
490                               (VkAttachmentDescriptionFlags)0u,           // VkAttachmentDescriptionFlags flags;
491                               cbFormat,                                   // VkFormat format;
492                               VK_SAMPLE_COUNT_1_BIT,                      // VkSampleCountFlagBits samples;
493                               VK_ATTACHMENT_LOAD_OP_CLEAR,                // VkAttachmentLoadOp loadOp;
494                               VK_ATTACHMENT_STORE_OP_STORE,               // VkAttachmentStoreOp storeOp;
495                               VK_ATTACHMENT_LOAD_OP_DONT_CARE,            // VkAttachmentLoadOp stencilLoadOp;
496                               VK_ATTACHMENT_STORE_OP_DONT_CARE,           // VkAttachmentStoreOp stencilStoreOp;
497                               VK_IMAGE_LAYOUT_GENERAL,                    // VkImageLayout initialLayout;
498                               VK_IMAGE_LAYOUT_GENERAL                     // VkImageLayout finalLayout;
499                           });
500 
501     if (useShadingRate0)
502     {
503         attachmentCount                         = 2;
504         subpassDescriptions[0].pNext            = &shadingRateAttachmentInfos[0];
505         attachmentDescriptions[1].format        = m_params->srFormat;
506         attachmentDescriptions[1].loadOp        = VK_ATTACHMENT_LOAD_OP_LOAD;
507         attachmentDescriptions[1].storeOp       = VK_ATTACHMENT_STORE_OP_DONT_CARE;
508         attachmentDescriptions[1].initialLayout = VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR;
509     }
510 
511     if (useShadingRate1)
512     {
513         attachmentCount                                              = 4;
514         colorAttachmentReferences[1].attachment                      = 2;
515         fragmentShadingRateAttachments[1].attachment                 = 3;
516         shadingRateAttachmentInfos[1].pFragmentShadingRateAttachment = &fragmentShadingRateAttachments[1];
517         shadingRateAttachmentInfos[1].shadingRateAttachmentTexelSize = {sr1TileWidth, sr1TileHeight};
518         subpassDescriptions[1].pNext                                 = &shadingRateAttachmentInfos[1];
519         subpassDescriptions[1].pColorAttachments                     = &colorAttachmentReferences[1];
520 
521         attachmentDescriptions[3].format        = m_params->srFormat;
522         attachmentDescriptions[3].loadOp        = VK_ATTACHMENT_LOAD_OP_LOAD;
523         attachmentDescriptions[3].storeOp       = VK_ATTACHMENT_STORE_OP_DONT_CARE;
524         attachmentDescriptions[3].initialLayout = VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR;
525     }
526 
527     std::vector<VkAttachmentReference2> dsAttachmentReferences;
528 
529     if (dsFormat != VK_FORMAT_UNDEFINED)
530     {
531         const auto dsLayout       = m_params->getDSLayout();
532         const auto dsAspects      = getFormatAspectFlags(dsFormat);
533         const auto hasDepth       = ((dsAspects & VK_IMAGE_ASPECT_DEPTH_BIT) != 0);
534         const auto hasStencil     = ((dsAspects & VK_IMAGE_ASPECT_STENCIL_BIT) != 0);
535         const auto depthLoadOp    = (hasDepth ? VK_ATTACHMENT_LOAD_OP_LOAD : VK_ATTACHMENT_LOAD_OP_DONT_CARE);
536         const auto depthStoreOp   = (hasDepth ? VK_ATTACHMENT_STORE_OP_STORE : VK_ATTACHMENT_STORE_OP_DONT_CARE);
537         const auto stencilLoadOp  = (hasStencil ? VK_ATTACHMENT_LOAD_OP_LOAD : VK_ATTACHMENT_LOAD_OP_DONT_CARE);
538         const auto stencilStoreOp = (hasStencil ? VK_ATTACHMENT_STORE_OP_STORE : VK_ATTACHMENT_STORE_OP_DONT_CARE);
539 
540         ++attachmentCount;
541         attachmentDescriptions.push_back(VkAttachmentDescription2{
542             VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2, // VkStructureType sType;
543             nullptr,                                    // const void* pNext;
544             0u,                                         // VkAttachmentDescriptionFlags flags;
545             dsFormat,                                   // VkFormat format;
546             VK_SAMPLE_COUNT_1_BIT,                      // VkSampleCountFlagBits samples;
547             depthLoadOp,                                // VkAttachmentLoadOp loadOp;
548             depthStoreOp,                               // VkAttachmentStoreOp storeOp;
549             stencilLoadOp,                              // VkAttachmentLoadOp stencilLoadOp;
550             stencilStoreOp,                             // VkAttachmentStoreOp stencilStoreOp;
551             dsLayout,                                   // VkImageLayout initialLayout;
552             dsLayout,                                   // VkImageLayout finalLayout;
553         });
554 
555         dsAttachmentReferences.push_back(VkAttachmentReference2{
556             VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2, // VkStructureType sType;
557             nullptr,                                  // const void* pNext;
558             attachmentCount - 1u,                     // uint32_t attachment;
559             dsLayout,                                 // VkImageLayout layout;
560             0u,                                       // VkImageAspectFlags aspectMask;
561         });
562 
563         for (auto &desc : subpassDescriptions)
564             desc.pDepthStencilAttachment = &dsAttachmentReferences.back();
565     }
566 
567     const VkRenderPassCreateInfo2 renderPassParams{
568         VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2, // VkStructureType sType;
569         nullptr,                                     // const void* pNext;
570         (vk::VkRenderPassCreateFlags)0,              // VkRenderPassCreateFlags flags;
571         attachmentCount,                             // uint32_t attachmentCount;
572         attachmentDescriptions.data(),               // const VkAttachmentDescription2* pAttachments;
573         subpassCount,                                // uint32_t subpassCount;
574         subpassDescriptions.data(),                  // const VkSubpassDescription2* pSubpasses;
575         0u,                                          // uint32_t dependencyCount;
576         nullptr,                                     // const VkSubpassDependency2* pDependencies;
577         0u,                                          // uint32_t correlatedViewMaskCount;
578         nullptr,                                     // const uint32_t* pCorrelatedViewMasks;
579     };
580 
581     return createRenderPass2(vk, device, &renderPassParams);
582 }
583 
buildFramebuffer(VkDevice device,const vk::DeviceInterface & vk,VkRenderPass renderPass,const std::vector<FBAttachmentInfo> & attachmentInfo) const584 Move<VkFramebuffer> AttachmentRateInstance::buildFramebuffer(VkDevice device, const vk::DeviceInterface &vk,
585                                                              VkRenderPass renderPass,
586                                                              const std::vector<FBAttachmentInfo> &attachmentInfo) const
587 {
588     if (m_params->useDynamicRendering)
589         return Move<VkFramebuffer>();
590 
591     VkFramebufferCreateInfo framebufferParams{
592         vk::VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType;
593         DE_NULL,                                       // const void* pNext;
594         (vk::VkFramebufferCreateFlags)0u,              // VkFramebufferCreateFlags flags;
595         renderPass,                                    // VkRenderPass renderPass;
596         (uint32_t)attachmentInfo.size(),               // uint32_t attachmentCount;
597         DE_NULL,                                       // const VkImageView* pAttachments;
598         attachmentInfo[0].width,                       // uint32_t width;
599         attachmentInfo[0].height,                      // uint32_t height;
600         1u,                                            // uint32_t layers;
601     };
602 
603     if (m_params->useImagelessFramebuffer)
604     {
605         std::vector<VkFramebufferAttachmentImageInfo> framebufferAttachmentImageInfo(
606             attachmentInfo.size(),
607             {
608                 VK_STRUCTURE_TYPE_FRAMEBUFFER_ATTACHMENT_IMAGE_INFO, // VkStructureType sType;
609                 DE_NULL,                                             // const void* pNext;
610                 (VkImageCreateFlags)0u,                              // VkImageCreateFlags flags;
611                 0u,                                                  // VkImageUsageFlags usage;
612                 0u,                                                  // uint32_t width;
613                 0u,                                                  // uint32_t height;
614                 1u,                                                  // uint32_t layerCount;
615                 1u,                                                  // uint32_t viewFormatCount;
616                 DE_NULL                                              // const VkFormat* pViewFormats;
617             });
618 
619         for (uint32_t i = 0; i < (uint32_t)attachmentInfo.size(); ++i)
620         {
621             const auto &src = attachmentInfo[i];
622             auto &dst       = framebufferAttachmentImageInfo[i];
623 
624             dst.usage        = src.usage;
625             dst.width        = src.width;
626             dst.height       = src.height;
627             dst.pViewFormats = &src.format;
628         }
629 
630         VkFramebufferAttachmentsCreateInfo framebufferAttachmentsCreateInfo{
631             VK_STRUCTURE_TYPE_FRAMEBUFFER_ATTACHMENTS_CREATE_INFO, // VkStructureType sType;
632             DE_NULL,                                               // const void* pNext;
633             (uint32_t)framebufferAttachmentImageInfo.size(),       // uint32_t attachmentImageInfoCount;
634             framebufferAttachmentImageInfo.data() // const VkFramebufferAttachmentImageInfo* pAttachmentImageInfos;
635         };
636 
637         framebufferParams.pNext = &framebufferAttachmentsCreateInfo;
638         framebufferParams.flags = VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT;
639 
640         return createFramebuffer(vk, device, &framebufferParams);
641     }
642 
643     // create array containing just attachment views
644     std::vector<VkImageView> attachments(attachmentInfo.size(), 0);
645     for (uint32_t i = 0; i < (uint32_t)attachmentInfo.size(); ++i)
646         attachments[i] = attachmentInfo[i].view;
647 
648     framebufferParams.pAttachments = attachments.data();
649 
650     return createFramebuffer(vk, device, &framebufferParams);
651 }
652 
buildPipelineLayout(VkDevice device,const vk::DeviceInterface & vk,const VkDescriptorSetLayout * setLayouts) const653 Move<VkPipelineLayout> AttachmentRateInstance::buildPipelineLayout(VkDevice device, const vk::DeviceInterface &vk,
654                                                                    const VkDescriptorSetLayout *setLayouts) const
655 {
656     const VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo{
657         VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType;
658         DE_NULL,                                       // const void* pNext;
659         (VkPipelineLayoutCreateFlags)0,                // VkPipelineLayoutCreateFlags flags;
660         (setLayouts != DE_NULL),                       // uint32_t setLayoutCount;
661         setLayouts,                                    // const VkDescriptorSetLayout* pSetLayouts;
662         0u,                                            // uint32_t pushConstantRangeCount;
663         DE_NULL,                                       // const VkPushConstantRange* pPushConstantRanges;
664     };
665 
666     return createPipelineLayout(vk, device, &pipelineLayoutCreateInfo, NULL);
667 }
668 
buildGraphicsPipeline(VkDevice device,const vk::DeviceInterface & vk,uint32_t subpass,VkRenderPass renderPass,VkFormat cbFormat,VkFormat dsFormat,VkPipelineLayout pipelineLayout,VkShaderModule vertShader,VkShaderModule fragShader,bool useShadingRate) const669 Move<VkPipeline> AttachmentRateInstance::buildGraphicsPipeline(VkDevice device, const vk::DeviceInterface &vk,
670                                                                uint32_t subpass, VkRenderPass renderPass,
671                                                                VkFormat cbFormat, VkFormat dsFormat,
672                                                                VkPipelineLayout pipelineLayout,
673                                                                VkShaderModule vertShader, VkShaderModule fragShader,
674                                                                bool useShadingRate) const
675 {
676     const auto dsAspects        = getFormatAspectFlags(dsFormat);
677     const auto hasDepth         = ((dsAspects & VK_IMAGE_ASPECT_DEPTH_BIT) != 0);
678     const auto hasStencil       = ((dsAspects & VK_IMAGE_ASPECT_STENCIL_BIT) != 0);
679     const auto depthCompareOp   = (hasDepth ? VK_COMPARE_OP_ALWAYS : VK_COMPARE_OP_LESS_OR_EQUAL);
680     const auto stencilCompareOp = (hasStencil ? VK_COMPARE_OP_ALWAYS : VK_COMPARE_OP_NEVER);
681 
682     std::vector<VkPipelineShaderStageCreateInfo> pipelineShaderStageParams(
683         2,
684         {
685             VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType                                sType
686             DE_NULL,                                             // const void*                                    pNext
687             0u,                         // VkPipelineShaderStageCreateFlags                flags
688             VK_SHADER_STAGE_VERTEX_BIT, // VkShaderStageFlagBits                        stage
689             vertShader,                 // VkShaderModule                                module
690             "main",                     // const char*                                    pName
691             DE_NULL                     // const VkSpecializationInfo*                    pSpecializationInfo
692         });
693 
694     pipelineShaderStageParams[1].stage  = VK_SHADER_STAGE_FRAGMENT_BIT;
695     pipelineShaderStageParams[1].module = fragShader;
696 
697     const VkPipelineVertexInputStateCreateInfo vertexInputStateCreateInfo{
698         VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType                                sType
699         DE_NULL,                                  // const void*                                    pNext
700         (VkPipelineVertexInputStateCreateFlags)0, // VkPipelineVertexInputStateCreateFlags        flags
701         0u,      // uint32_t                                        vertexBindingDescriptionCount
702         DE_NULL, // const VkVertexInputBindingDescription*        pVertexBindingDescriptions
703         0u,      // uint32_t                                        vertexAttributeDescriptionCount
704         DE_NULL  // const VkVertexInputAttributeDescription*        pVertexAttributeDescriptions
705     };
706 
707     const VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateCreateInfo{
708         VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType                                sType
709         DE_NULL,                              // const void*                                    pNext
710         0u,                                   // VkPipelineInputAssemblyStateCreateFlags        flags
711         VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, // VkPrimitiveTopology                            topology
712         VK_FALSE                              // VkBool32                                        primitiveRestartEnable
713     };
714 
715     tcu::UVec2 size(m_cbWidth, m_cbHeight);
716     VkViewport viewport = makeViewport(size);
717     VkRect2D scissor    = makeRect2D(size);
718 
719     const VkPipelineViewportStateCreateInfo viewportStateCreateInfo{
720         VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType                                sType
721         DE_NULL,                                               // const void*                                    pNext
722         (VkPipelineViewportStateCreateFlags)0,                 // VkPipelineViewportStateCreateFlags            flags
723         1u,        // uint32_t                                        viewportCount
724         &viewport, // const VkViewport*                            pViewports
725         1u,        // uint32_t                                        scissorCount
726         &scissor   // const VkRect2D*                                pScissors
727     };
728 
729     const VkPipelineRasterizationStateCreateInfo rasterizationStateCreateInfo{
730         VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType                                sType
731         DE_NULL,                         // const void*                                    pNext
732         0u,                              // VkPipelineRasterizationStateCreateFlags        flags
733         VK_FALSE,                        // VkBool32                                        depthClampEnable
734         VK_FALSE,                        // VkBool32                                        rasterizerDiscardEnable
735         VK_POLYGON_MODE_FILL,            // VkPolygonMode                                polygonMode
736         VK_CULL_MODE_NONE,               // VkCullModeFlags                                cullMode
737         VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace                                    frontFace
738         VK_FALSE,                        // VkBool32                                        depthBiasEnable
739         0.0f,                            // float                                        depthBiasConstantFactor
740         0.0f,                            // float                                        depthBiasClamp
741         0.0f,                            // float                                        depthBiasSlopeFactor
742         1.0f                             // float                                        lineWidth
743     };
744 
745     const VkPipelineMultisampleStateCreateInfo multisampleStateCreateInfo{
746         VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType                                sType
747         DE_NULL,               // const void*                                    pNext
748         0u,                    // VkPipelineMultisampleStateCreateFlags        flags
749         VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits                        rasterizationSamples
750         VK_FALSE,              // VkBool32                                        sampleShadingEnable
751         1.0f,                  // float                                        minSampleShading
752         DE_NULL,               // const VkSampleMask*                            pSampleMask
753         VK_FALSE,              // VkBool32                                        alphaToCoverageEnable
754         VK_FALSE               // VkBool32                                        alphaToOneEnable
755     };
756 
757     const VkStencilOpState stencilOpState{
758         VK_STENCIL_OP_KEEP, // VkStencilOp                                    failOp
759         VK_STENCIL_OP_KEEP, // VkStencilOp                                    passOp
760         VK_STENCIL_OP_KEEP, // VkStencilOp                                    depthFailOp
761         stencilCompareOp,   // VkCompareOp                                    compareOp
762         0,                  // uint32_t                                        compareMask
763         0,                  // uint32_t                                        writeMask
764         0                   // uint32_t                                        reference
765     };
766 
767     const VkPipelineDepthStencilStateCreateInfo depthStencilStateCreateInfo{
768         VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType                                sType
769         DE_NULL,        // const void*                                    pNext
770         0u,             // VkPipelineDepthStencilStateCreateFlags        flags
771         hasDepth,       // VkBool32                                        depthTestEnable
772         VK_FALSE,       // VkBool32                                        depthWriteEnable
773         depthCompareOp, // VkCompareOp                                    depthCompareOp
774         VK_FALSE,       // VkBool32                                        depthBoundsTestEnable
775         hasStencil,     // VkBool32                                        stencilTestEnable
776         stencilOpState, // VkStencilOpState                                front
777         stencilOpState, // VkStencilOpState                                back
778         0.0f,           // float                                        minDepthBounds
779         1.0f,           // float                                        maxDepthBounds
780     };
781 
782     const VkPipelineColorBlendAttachmentState colorBlendAttachmentState{
783         VK_FALSE,                // VkBool32                                        blendEnable
784         VK_BLEND_FACTOR_ZERO,    // VkBlendFactor                                srcColorBlendFactor
785         VK_BLEND_FACTOR_ZERO,    // VkBlendFactor                                dstColorBlendFactor
786         VK_BLEND_OP_ADD,         // VkBlendOp                                    colorBlendOp
787         VK_BLEND_FACTOR_ZERO,    // VkBlendFactor                                srcAlphaBlendFactor
788         VK_BLEND_FACTOR_ZERO,    // VkBlendFactor                                dstAlphaBlendFactor
789         VK_BLEND_OP_ADD,         // VkBlendOp                                    alphaBlendOp
790         VK_COLOR_COMPONENT_R_BIT // VkColorComponentFlags                        colorWriteMask
791             | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT};
792 
793     const VkPipelineColorBlendStateCreateInfo colorBlendStateCreateInfo{
794         VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType                                sType
795         DE_NULL,                    // const void*                                    pNext
796         0u,                         // VkPipelineColorBlendStateCreateFlags            flags
797         VK_FALSE,                   // VkBool32                                        logicOpEnable
798         VK_LOGIC_OP_CLEAR,          // VkLogicOp                                    logicOp
799         1u,                         // uint32_t                                        attachmentCount
800         &colorBlendAttachmentState, // const VkPipelineColorBlendAttachmentState*    pAttachments
801         {0.0f, 0.0f, 0.0f, 0.0f}    // float                                        blendConstants[4]
802     };
803 
804     const VkPipelineDynamicStateCreateInfo dynamicStateCreateInfo{
805         VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, // VkStructureType                                sType
806         DE_NULL,                                              // const void*                                    pNext
807         0u,                                                   // VkPipelineDynamicStateCreateFlags            flags
808         0u,     // uint32_t                                        dynamicStateCount
809         DE_NULL // const VkDynamicState*                        pDynamicStates
810     };
811 
812     VkPipelineFragmentShadingRateStateCreateInfoKHR shadingRateStateCreateInfo{
813         VK_STRUCTURE_TYPE_PIPELINE_FRAGMENT_SHADING_RATE_STATE_CREATE_INFO_KHR, // VkStructureType sType;
814         DE_NULL,                                                                // const void* pNext;
815         {1, 1},                                                                 // VkExtent2D fragmentSize;
816         {VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR,
817          VK_FRAGMENT_SHADING_RATE_COMBINER_OP_REPLACE_KHR} // VkFragmentShadingRateCombinerOpKHR combinerOps[2];
818     };
819 
820     void *pNext = useShadingRate ? &shadingRateStateCreateInfo : DE_NULL;
821 #ifndef CTS_USES_VULKANSC
822     VkPipelineRenderingCreateInfoKHR renderingCreateInfo{
823         VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR, pNext, 0u, 1u, &cbFormat, dsFormat, VK_FORMAT_UNDEFINED};
824 
825     if (m_params->useDynamicRendering)
826         pNext = &renderingCreateInfo;
827 #else
828     DE_UNREF(cbFormat);
829 #endif // CTS_USES_VULKANSC
830 
831     VkGraphicsPipelineCreateInfo pipelineCreateInfo{
832         VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType                                    sType
833         pNext,                                           // const void*                                        pNext
834         0u,                                              // VkPipelineCreateFlags                            flags
835         (uint32_t)pipelineShaderStageParams.size(), // uint32_t                                            stageCount
836         &pipelineShaderStageParams[0],              // const VkPipelineShaderStageCreateInfo*            pStages
837         &vertexInputStateCreateInfo,   // const VkPipelineVertexInputStateCreateInfo*        pVertexInputState
838         &inputAssemblyStateCreateInfo, // const VkPipelineInputAssemblyStateCreateInfo*    pInputAssemblyState
839         DE_NULL,                       // const VkPipelineTessellationStateCreateInfo*        pTessellationState
840         &viewportStateCreateInfo,      // const VkPipelineViewportStateCreateInfo*            pViewportState
841         &rasterizationStateCreateInfo, // const VkPipelineRasterizationStateCreateInfo*    pRasterizationState
842         &multisampleStateCreateInfo,   // const VkPipelineMultisampleStateCreateInfo*        pMultisampleState
843         &depthStencilStateCreateInfo,  // const VkPipelineDepthStencilStateCreateInfo*        pDepthStencilState
844         &colorBlendStateCreateInfo,    // const VkPipelineColorBlendStateCreateInfo*        pColorBlendState
845         &dynamicStateCreateInfo,       // const VkPipelineDynamicStateCreateInfo*            pDynamicState
846         pipelineLayout,                // VkPipelineLayout                                    layout
847         renderPass,                    // VkRenderPass                                        renderPass
848         subpass,                       // uint32_t                                            subpass
849         DE_NULL,                       // VkPipeline                                        basePipelineHandle
850         0                              // int32_t basePipelineIndex;
851     };
852 
853 #ifndef CTS_USES_VULKANSC
854     VkPipelineCreateFlags2CreateInfoKHR pipelineFlags2CreateInfo = initVulkanStructure(pNext);
855     if (useShadingRate && m_params->useDynamicRendering)
856     {
857         if (m_params->mode == TM_MAINTENANCE_5)
858         {
859             pipelineFlags2CreateInfo.flags = VK_PIPELINE_CREATE_2_RENDERING_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR;
860             pipelineCreateInfo.pNext       = &pipelineFlags2CreateInfo;
861         }
862         else
863             pipelineCreateInfo.flags |= VK_PIPELINE_CREATE_RENDERING_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR;
864     }
865 #endif // CTS_USES_VULKANSC
866 
867     return createGraphicsPipeline(vk, device, DE_NULL, &pipelineCreateInfo);
868 }
869 
buildComputePipeline(VkDevice device,const vk::DeviceInterface & vk,VkShaderModule compShader,VkPipelineLayout pipelineLayout) const870 Move<VkPipeline> AttachmentRateInstance::buildComputePipeline(VkDevice device, const vk::DeviceInterface &vk,
871                                                               VkShaderModule compShader,
872                                                               VkPipelineLayout pipelineLayout) const
873 {
874     const VkPipelineShaderStageCreateInfo stageCreateInfo{
875         VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
876         DE_NULL,                                             // const void* pNext;
877         0u,                                                  // VkPipelineShaderStageCreateFlags flags;
878         VK_SHADER_STAGE_COMPUTE_BIT,                         // VkShaderStageFlagBits stage;
879         compShader,                                          // VkShaderModule module;
880         "main",                                              // const char* pName;
881         DE_NULL                                              // const VkSpecializationInfo* pSpecializationInfo;
882     };
883 
884     const VkComputePipelineCreateInfo createInfo{
885         VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, // VkStructureType sType;
886         DE_NULL,                                        // const void* pNext;
887         0u,                                             // VkPipelineCreateFlags flags;
888         stageCreateInfo,                                // VkPipelineShaderStageCreateInfo stage;
889         pipelineLayout,                                 // VkPipelineLayout layout;
890         (VkPipeline)0,                                  // VkPipeline basePipelineHandle;
891         0u,                                             // int32_t basePipelineIndex;
892     };
893 
894     return createComputePipeline(vk, device, (vk::VkPipelineCache)0u, &createInfo);
895 }
896 
makeDescriptorSetAllocInfo(VkDescriptorPool descriptorPool,const VkDescriptorSetLayout * pSetLayouts) const897 VkDescriptorSetAllocateInfo AttachmentRateInstance::makeDescriptorSetAllocInfo(
898     VkDescriptorPool descriptorPool, const VkDescriptorSetLayout *pSetLayouts) const
899 {
900     return {
901         VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, // VkStructureType sType;
902         DE_NULL,                                        // const void* pNext;
903         descriptorPool,                                 // VkDescriptorPool descriptorPool;
904         1u,                                             // uint32_t setLayoutCount;
905         pSetLayouts,                                    // const VkDescriptorSetLayout* pSetLayouts;
906     };
907 }
908 
startRendering(const VkCommandBuffer commandBuffer,const VkRenderPass renderPass,const VkFramebuffer framebuffer,const VkRect2D & renderArea,const std::vector<FBAttachmentInfo> & attachmentInfo,const uint32_t srTileWidth,const uint32_t srTileHeight,const DeviceInterface * customDevice) const909 void AttachmentRateInstance::startRendering(const VkCommandBuffer commandBuffer, const VkRenderPass renderPass,
910                                             const VkFramebuffer framebuffer, const VkRect2D &renderArea,
911                                             const std::vector<FBAttachmentInfo> &attachmentInfo,
912                                             const uint32_t srTileWidth, const uint32_t srTileHeight,
913                                             const DeviceInterface *customDevice) const
914 {
915     const DeviceInterface &vk = (customDevice != nullptr) ? *customDevice : m_context.getDeviceInterface();
916     std::vector<VkClearValue> clearColor(attachmentInfo.size(), makeClearValueColorU32(0, 0, 0, 0));
917 
918 #ifndef CTS_USES_VULKANSC
919     if (m_params->useDynamicRendering)
920     {
921         VkRenderingFragmentShadingRateAttachmentInfoKHR shadingRateAttachmentInfo{
922             VK_STRUCTURE_TYPE_RENDERING_FRAGMENT_SHADING_RATE_ATTACHMENT_INFO_KHR, // VkStructureType sType;
923             DE_NULL,                                                               // const void* pNext;
924             DE_NULL,                                                               // VkImageView imageView;
925             VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR,          // VkImageLayout imageLayout;
926             {0, 0} // VkExtent2D shadingRateAttachmentTexelSize;
927         };
928 
929         VkRenderingAttachmentInfoKHR colorAttachment{
930             vk::VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR, // VkStructureType sType;
931             DE_NULL,                                             // const void* pNext;
932             attachmentInfo[0].view,                              // VkImageView imageView;
933             VK_IMAGE_LAYOUT_GENERAL,                             // VkImageLayout imageLayout;
934             VK_RESOLVE_MODE_NONE,                                // VkResolveModeFlagBits resolveMode;
935             DE_NULL,                                             // VkImageView resolveImageView;
936             VK_IMAGE_LAYOUT_UNDEFINED,                           // VkImageLayout resolveImageLayout;
937             VK_ATTACHMENT_LOAD_OP_CLEAR,                         // VkAttachmentLoadOp loadOp;
938             VK_ATTACHMENT_STORE_OP_STORE,                        // VkAttachmentStoreOp storeOp;
939             clearColor[0]                                        // VkClearValue clearValue;
940         };
941 
942         VkRenderingInfoKHR renderingInfo{
943             vk::VK_STRUCTURE_TYPE_RENDERING_INFO_KHR,
944             DE_NULL,
945             0,                // VkRenderingFlagsKHR flags;
946             renderArea,       // VkRect2D renderArea;
947             1u,               // uint32_t layerCount;
948             0u,               // uint32_t viewMask;
949             1u,               // uint32_t colorAttachmentCount;
950             &colorAttachment, // const VkRenderingAttachmentInfoKHR* pColorAttachments;
951             DE_NULL,          // const VkRenderingAttachmentInfoKHR* pDepthAttachment;
952             DE_NULL,          // const VkRenderingAttachmentInfoKHR* pStencilAttachment;
953         };
954 
955         // when shading rate is used it is defined as a second entry in attachmentInfo
956         if ((attachmentInfo.size() == 2) &&
957             (attachmentInfo[1].usage & VK_IMAGE_USAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR))
958         {
959             if (!m_params->useNullShadingRateImage)
960             {
961                 shadingRateAttachmentInfo.imageView = attachmentInfo[1].view;
962             }
963 
964             shadingRateAttachmentInfo.shadingRateAttachmentTexelSize = {srTileWidth, srTileHeight};
965             renderingInfo.pNext                                      = &shadingRateAttachmentInfo;
966         }
967 
968         vk.cmdBeginRendering(commandBuffer, &renderingInfo);
969 
970         return;
971     }
972 #else
973     DE_UNREF(srTileWidth);
974     DE_UNREF(srTileHeight);
975 #endif // CTS_USES_VULKANSC
976 
977     std::vector<VkImageView> attachments(attachmentInfo.size(), 0);
978     VkRenderPassAttachmentBeginInfo renderPassAttachmentBeginInfo;
979     void *pNext(DE_NULL);
980 
981     if (m_params->useImagelessFramebuffer)
982     {
983         // create array containing attachment views
984         for (uint32_t i = 0; i < (uint32_t)attachmentInfo.size(); ++i)
985             attachments[i] = attachmentInfo[i].view;
986 
987         renderPassAttachmentBeginInfo = {
988             VK_STRUCTURE_TYPE_RENDER_PASS_ATTACHMENT_BEGIN_INFO, // VkStructureType sType;
989             DE_NULL,                                             // const void* pNext;
990             (uint32_t)attachments.size(),                        // uint32_t attachmentCount;
991             attachments.data()                                   // const VkImageView* pAttachments;
992         };
993 
994         pNext = &renderPassAttachmentBeginInfo;
995     }
996 
997     beginRenderPass(vk, commandBuffer, renderPass, framebuffer, renderArea, (uint32_t)clearColor.size(),
998                     clearColor.data(), VK_SUBPASS_CONTENTS_INLINE, pNext);
999 }
1000 
finishRendering(const VkCommandBuffer commandBuffer) const1001 void AttachmentRateInstance::finishRendering(const VkCommandBuffer commandBuffer) const
1002 {
1003     const DeviceInterface &vk = m_context.getDeviceInterface();
1004 
1005 #ifndef CTS_USES_VULKANSC
1006     if (m_params->useDynamicRendering)
1007         endRendering(vk, commandBuffer);
1008     else
1009 #endif // CTS_USES_VULKANSC
1010         endRenderPass(vk, commandBuffer);
1011 }
1012 
iterate(void)1013 tcu::TestStatus AttachmentRateInstance::iterate(void)
1014 {
1015     // instead of creating many classes that derive from large common class
1016     // each test mode is defined in separate run* method, those methods
1017     // then use same helper methods defined in this class
1018 
1019     typedef bool (AttachmentRateInstance::*MethodPtr)();
1020     const std::map<TestMode, MethodPtr> modeFuncMap{
1021         {TM_SETUP_RATE_WITH_ATOMICS_IN_COMPUTE_SHADER, &AttachmentRateInstance::runComputeShaderMode},
1022         {TM_SETUP_RATE_WITH_FRAGMENT_SHADER, &AttachmentRateInstance::runFragmentShaderMode},
1023         {TM_SETUP_RATE_WITH_COPYING_FROM_OTHER_IMAGE, &AttachmentRateInstance::runCopyMode},
1024         {TM_SETUP_RATE_WITH_COPYING_FROM_EXCLUSIVE_IMAGE_USING_TRANSFER_QUEUE,
1025          &AttachmentRateInstance::runCopyModeOnTransferQueue},
1026         {TM_SETUP_RATE_WITH_COPYING_FROM_CONCURENT_IMAGE_USING_TRANSFER_QUEUE,
1027          &AttachmentRateInstance::runCopyModeOnTransferQueue},
1028         {TM_SETUP_RATE_WITH_LINEAR_TILED_IMAGE, &AttachmentRateInstance::runFillLinearTiledImage},
1029         {TM_TWO_SUBPASS, &AttachmentRateInstance::runTwoSubpassMode},
1030         {TM_MEMORY_ACCESS, &AttachmentRateInstance::runFragmentShaderMode},
1031         {TM_MAINTENANCE_5, &AttachmentRateInstance::runFragmentShaderMode},
1032     };
1033 
1034     if ((this->*modeFuncMap.at(m_params->mode))())
1035         return tcu::TestStatus::pass("Pass");
1036 
1037     return tcu::TestStatus::fail("Fail");
1038 }
1039 
verifyUsingAtomicChecks(uint32_t tileWidth,uint32_t tileHeight,uint32_t rateWidth,uint32_t rateHeight,uint32_t * outBufferPtr) const1040 bool AttachmentRateInstance::verifyUsingAtomicChecks(uint32_t tileWidth, uint32_t tileHeight, uint32_t rateWidth,
1041                                                      uint32_t rateHeight, uint32_t *outBufferPtr) const
1042 {
1043     tcu::TestLog &log(m_context.getTestContext().getLog());
1044     tcu::TextureLevel errorMaskStorage(tcu::TextureFormat(tcu::TextureFormat::RGB, tcu::TextureFormat::UNORM_INT8),
1045                                        m_cbWidth, m_cbHeight, 1u);
1046     tcu::PixelBufferAccess errorMaskAccess(errorMaskStorage.getAccess());
1047 
1048     uint32_t wrongFragments                          = 0;
1049     const uint32_t fragmentsWithSameAtomicValueCount = rateWidth * rateHeight;
1050 
1051     // map that uses atomic value as a kay and maps it to all fragments sharing same atomic
1052     std::map<uint32_t, std::vector<tcu::UVec2>> fragmentsWithSameAtomicValueMap;
1053 
1054     // this method asumes that top and left edge of triangle are parallel to axes
1055     // and we can store just single coordinate for those edges
1056     uint32_t triangleLeftEdgeX = 0;
1057     uint32_t triangleTopEdgeY  = 0;
1058 
1059     // this method assumes that greatest angle in the triangle points to the top-left corner of FB;
1060     // these vectors will then store fragments on the right and bottom edges of triangle respectively;
1061     // for the right edge vector, the index represents y coordinate and value is x;
1062     // for the bottom edge vector, the index represents x coordinate and value is y
1063     std::vector<uint32_t> fragmentsOnTheRightTriangleEdgeVect(m_cbHeight, 0);
1064     std::vector<uint32_t> fragmentsOnTheBottomTriangleEdgeVect(m_cbWidth, 0);
1065 
1066     tcu::clear(errorMaskAccess, tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0));
1067 
1068     // loop over all fragments and validate the output
1069     for (uint32_t cbFragmentY = 0; cbFragmentY < m_cbHeight; ++cbFragmentY)
1070         for (uint32_t cbFragmentX = 0; cbFragmentX < m_cbWidth; ++cbFragmentX)
1071         {
1072             uint32_t *fragmentColor = &outBufferPtr[4 * (cbFragmentY * m_cbWidth + cbFragmentX)];
1073 
1074             // fragment not covered by primitive, skip it
1075             if (fragmentColor[2] == 0)
1076                 continue;
1077 
1078             // first fragment we hit will define top and left triangle edges
1079             if ((triangleTopEdgeY + triangleLeftEdgeX) == 0)
1080             {
1081                 triangleLeftEdgeX = cbFragmentX;
1082                 triangleTopEdgeY  = cbFragmentY;
1083             }
1084 
1085             // constantly overwrite coordinate on right edge so that we are left with the farthest one
1086             fragmentsOnTheRightTriangleEdgeVect[cbFragmentY] = cbFragmentX;
1087 
1088             // constantly overwrite coordinate on bottom edge so that we are left with the farthest one
1089             fragmentsOnTheBottomTriangleEdgeVect[cbFragmentX] = cbFragmentY;
1090 
1091             // make sure that fragment g and a components are 0
1092             if ((fragmentColor[1] != 0) || (fragmentColor[3] != 0))
1093             {
1094                 ++wrongFragments;
1095                 continue;
1096             }
1097 
1098             uint32_t rate          = fragmentColor[0];
1099             uint32_t fragmentRateX = 1 << ((rate / 4) & 3);
1100             uint32_t fragmentRateY = 1 << (rate & 3);
1101 
1102             // check if proper rate was used for fragment
1103             if ((fragmentRateX != rateWidth) || (fragmentRateY != rateHeight))
1104             {
1105                 ++wrongFragments;
1106                 errorMaskAccess.setPixel(tcu::Vec4(1.0f, 0.5f, 0.0f, 1.0f), cbFragmentX, cbFragmentY, 0u);
1107                 continue;
1108             }
1109 
1110             // mark correct fragments using few green shades so rates are visible
1111             uint32_t atomicValue = fragmentColor[2];
1112             errorMaskAccess.setPixel(tcu::Vec4(0.0f, 1.0f - float(atomicValue % 7) * 0.1f, 0.0f, 1.0f), cbFragmentX,
1113                                      cbFragmentY, 0u);
1114 
1115             // find proper set in map and add value to it after doing verification with existing items
1116             auto fragmentsSetMapIt = fragmentsWithSameAtomicValueMap.find(atomicValue);
1117             if (fragmentsSetMapIt == fragmentsWithSameAtomicValueMap.end())
1118             {
1119                 fragmentsWithSameAtomicValueMap[atomicValue] = {tcu::UVec2(cbFragmentX, cbFragmentY)};
1120                 fragmentsWithSameAtomicValueMap[atomicValue].reserve(fragmentsWithSameAtomicValueCount);
1121             }
1122             else
1123             {
1124                 // make sure that fragments added to set are near the top-left fragment
1125                 auto &fragmentsSet = fragmentsSetMapIt->second;
1126                 if (((cbFragmentX - fragmentsSet[0].x()) > rateWidth) ||
1127                     ((cbFragmentY - fragmentsSet[0].y()) > rateHeight))
1128                 {
1129                     ++wrongFragments;
1130                     errorMaskAccess.setPixel(tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f), cbFragmentX, cbFragmentY, 0u);
1131                 }
1132 
1133                 fragmentsWithSameAtomicValueMap[atomicValue].emplace_back(cbFragmentX, cbFragmentY);
1134             }
1135         }
1136 
1137     // check if there are no valid fragmenst at all
1138     if ((triangleTopEdgeY + triangleLeftEdgeX) == 0)
1139     {
1140         log << tcu::TestLog::Message << "No valid fragments." << tcu::TestLog::EndMessage;
1141         return false;
1142     }
1143 
1144     // if checks failed skip checking other tile sizes
1145     if (wrongFragments)
1146     {
1147         log << tcu::TestLog::Message << "Failed " << wrongFragments << " fragments for tileWidth: " << tileWidth
1148             << ", tileHeight: " << tileHeight << tcu::TestLog::EndMessage
1149             << tcu::TestLog::Image("ErrorMask", "Error mask", errorMaskAccess);
1150         return false;
1151     }
1152 
1153     // do additional checks
1154     tcu::Vec4 fragmentColor(0.0f, 1.0f, 0.0f, 1.0f);
1155 
1156     tcu::clear(errorMaskAccess, tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0));
1157 
1158     // make sure that there is same number of fragments that share same atomic value
1159     for (auto &fragmentsSetMapIt : fragmentsWithSameAtomicValueMap)
1160     {
1161         // mark correct fragments using few green shades so rates are visible
1162         fragmentColor = tcu::Vec4(0.0f, 1.0f - float(fragmentsSetMapIt.first % 7) * 0.1f, 0.0f, 1.0f);
1163 
1164         const auto &fragmentSet = fragmentsSetMapIt.second;
1165         ;
1166         if (fragmentSet.size() != fragmentsWithSameAtomicValueCount)
1167         {
1168             const auto &topLeftFragment  = fragmentSet[0];
1169             uint32_t triangleRightEdgeX  = fragmentsOnTheRightTriangleEdgeVect[topLeftFragment.y()];
1170             uint32_t triangleBottomEdgeY = fragmentsOnTheBottomTriangleEdgeVect[topLeftFragment.x()];
1171 
1172             // we can only count this as an error if set is fully inside of triangle, sets on
1173             // edges may not have same number of fragments as sets fully located in the triangle
1174             if ((topLeftFragment.y() > (triangleTopEdgeY)) && (topLeftFragment.x() > (triangleLeftEdgeX)) &&
1175                 (topLeftFragment.x() < (triangleRightEdgeX - rateWidth)) &&
1176                 (topLeftFragment.y() < (triangleBottomEdgeY - rateHeight)))
1177             {
1178                 wrongFragments += (uint32_t)fragmentSet.size();
1179                 fragmentColor = tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f);
1180             }
1181         }
1182 
1183         // mark all fragmens from set with proper color
1184         for (auto &fragment : fragmentSet)
1185             errorMaskAccess.setPixel(fragmentColor, fragment.x(), fragment.y(), 0u);
1186     }
1187 
1188     if (wrongFragments)
1189     {
1190         log << tcu::TestLog::Message << "Wrong number of fragments with same atomic value (" << wrongFragments
1191             << ") for tileWidth: " << tileWidth << ", tileHeight: " << tileHeight << tcu::TestLog::EndMessage
1192             << tcu::TestLog::Image("ErrorMask", "Error mask", errorMaskAccess);
1193         return false;
1194     }
1195 
1196     return true;
1197 }
1198 
runComputeShaderMode(void)1199 bool AttachmentRateInstance::runComputeShaderMode(void)
1200 {
1201     // clear the shading rate attachment, then using a compute shader, set the shading rate attachment
1202     // values to the desired rate using various atomic operations, then use it to draw a basic triangle
1203     // and do basic checks
1204 
1205     const DeviceInterface &vk = m_context.getDeviceInterface();
1206     VkDevice device           = m_context.getDevice();
1207     uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
1208     VkMemoryBarrier memoryBarrier{VK_STRUCTURE_TYPE_MEMORY_BARRIER, DE_NULL, 0u, 0u};
1209 
1210     Move<VkShaderModule> compShader = createShaderModule(vk, device, m_context.getBinaryCollection().get("comp"), 0);
1211     Move<VkShaderModule> vertShader = createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0);
1212     Move<VkShaderModule> fragShader = createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0);
1213 
1214     Move<VkCommandPool> cmdPool =
1215         createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex);
1216     Move<VkCommandBuffer> cmdBuffer = allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
1217 
1218     // setup descriptor set with storage image for compute pipeline
1219     Move<VkDescriptorSetLayout> computeDescriptorSetLayout =
1220         DescriptorSetLayoutBuilder()
1221             .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
1222             .build(vk, device);
1223     Move<VkDescriptorPool> computeDescriptorPool =
1224         DescriptorPoolBuilder()
1225             .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1u)
1226             .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
1227     const VkDescriptorSetAllocateInfo computeDescriptorSetAllocInfo =
1228         makeDescriptorSetAllocInfo(*computeDescriptorPool, &(*computeDescriptorSetLayout));
1229     Move<VkDescriptorSet> computeDescriptorSet = allocateDescriptorSet(vk, device, &computeDescriptorSetAllocInfo);
1230 
1231     m_srUsage |= VK_IMAGE_USAGE_STORAGE_BIT;
1232 
1233     buildCounterBufferObjects(device, vk, m_context.getDefaultAllocator());
1234     buildColorBufferObjects(device, vk, m_context.getDefaultAllocator(), 0, m_cbUsage);
1235 
1236     // iterate over all possible tile sizes
1237     for (uint32_t tileWidth = m_minTileSize.width; tileWidth <= m_maxTileSize.width; tileWidth *= 2)
1238         for (uint32_t tileHeight = m_minTileSize.height; tileHeight <= m_maxTileSize.height; tileHeight *= 2)
1239         {
1240             // skip tile sizes that have unsuported aspect ratio
1241             uint32_t aspectRatio = (tileHeight > tileWidth) ? (tileHeight / tileWidth) : (tileWidth / tileHeight);
1242             if (aspectRatio > m_maxAspectRatio)
1243                 continue;
1244 
1245             // calculate size of shading rate attachment
1246             uint32_t srWidth  = (m_cbWidth + tileWidth - 1) / tileWidth;
1247             uint32_t srHeight = (m_cbHeight + tileHeight - 1) / tileHeight;
1248 
1249             buildShadingRateObjects(device, vk, m_context.getDefaultAllocator(), 0, srWidth, srHeight, m_srUsage);
1250 
1251             const VkDescriptorImageInfo computeDescriptorInfo =
1252                 makeDescriptorImageInfo(DE_NULL, *m_srImageView[0], VK_IMAGE_LAYOUT_GENERAL);
1253             DescriptorSetUpdateBuilder()
1254                 .writeSingle(*computeDescriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u),
1255                              VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &computeDescriptorInfo)
1256                 .update(vk, device);
1257 
1258             const auto dsFormat = m_params->getDSFormat();
1259             Move<VkPipelineLayout> computePipelineLayout =
1260                 buildPipelineLayout(device, vk, &(*computeDescriptorSetLayout));
1261             Move<VkPipelineLayout> graphicsPipelineLayout =
1262                 buildPipelineLayout(device, vk, &(*m_counterBufferDescriptorSetLayout));
1263             Move<VkPipeline> computePipeline = buildComputePipeline(device, vk, *compShader, *computePipelineLayout);
1264             Move<VkRenderPass> renderPass    = buildRenderPass(device, vk, m_cbFormat, dsFormat, tileWidth, tileHeight);
1265             Move<VkPipeline> graphicsPipeline = buildGraphicsPipeline(
1266                 device, vk, 0, *renderPass, m_cbFormat, dsFormat, *graphicsPipelineLayout, *vertShader, *fragShader);
1267 
1268             std::vector<FBAttachmentInfo> attachmentInfo{
1269                 {m_cbFormat, m_cbUsage, m_cbWidth, m_cbHeight, *m_cbImageView[0]},
1270                 {m_params->srFormat, m_srUsage, srWidth, srHeight, *m_srImageView[0]},
1271             };
1272             // This would need an additional attachment with m_dsImageView and a barrier to transition the DS layout.
1273             // See runFragmentShaderMode for more details.
1274             DE_ASSERT(!m_params->useDepthStencil());
1275 
1276             Move<VkFramebuffer> framebuffer = buildFramebuffer(device, vk, *renderPass, attachmentInfo);
1277 
1278             beginCommandBuffer(vk, *cmdBuffer, 0u);
1279 
1280             // wait till sr image layout is changed
1281             VkPipelineStageFlags srcStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
1282             VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
1283             VkImageMemoryBarrier srImageBarrierGeneral =
1284                 makeImageMemoryBarrier(VK_ACCESS_NONE_KHR, VK_ACCESS_NONE_KHR, VK_IMAGE_LAYOUT_UNDEFINED,
1285                                        VK_IMAGE_LAYOUT_GENERAL, **m_srImage[0], m_defaultImageSubresourceRange);
1286             vk.cmdPipelineBarrier(*cmdBuffer, srcStageMask, dstStageMask, 0, 0, DE_NULL, 0, DE_NULL, 1,
1287                                   &srImageBarrierGeneral);
1288 
1289             // fill sr image using compute shader
1290             vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *computePipeline);
1291             vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *computePipelineLayout, 0, 1,
1292                                      &(*computeDescriptorSet), 0, DE_NULL);
1293             vk.cmdDispatch(*cmdBuffer, srWidth, srHeight, 1);
1294 
1295             // wait till sr image is ready and change sr images layout
1296             srcStageMask                                   = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
1297             dstStageMask                                   = VK_PIPELINE_STAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR;
1298             memoryBarrier.srcAccessMask                    = VK_ACCESS_SHADER_WRITE_BIT;
1299             memoryBarrier.dstAccessMask                    = VK_ACCESS_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR;
1300             VkImageMemoryBarrier srImageBarrierShadingRate = makeImageMemoryBarrier(
1301                 VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR,
1302                 VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR, **m_srImage[0],
1303                 m_defaultImageSubresourceRange);
1304             vk.cmdPipelineBarrier(*cmdBuffer, srcStageMask, dstStageMask, 0, 1, &memoryBarrier, 0, DE_NULL, 1,
1305                                   &srImageBarrierShadingRate);
1306 
1307             // wait till cb image layout is changed
1308             srcStageMask                        = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
1309             dstStageMask                        = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
1310             VkImageMemoryBarrier cbImageBarrier = makeImageMemoryBarrier(
1311                 VK_ACCESS_NONE_KHR, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
1312                 VK_IMAGE_LAYOUT_GENERAL, **m_cbImage[0], m_defaultImageSubresourceRange);
1313             vk.cmdPipelineBarrier(*cmdBuffer, srcStageMask, dstStageMask, 0, 0, DE_NULL, 0, DE_NULL, 1,
1314                                   &cbImageBarrier);
1315 
1316             startRendering(*cmdBuffer, *renderPass, *framebuffer, makeRect2D(m_cbWidth, m_cbHeight), attachmentInfo,
1317                            tileWidth, tileHeight);
1318 
1319             // draw single triangle to cb
1320             vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *graphicsPipelineLayout, 0, 1,
1321                                      &(*m_counterBufferDescriptorSet), 0, DE_NULL);
1322             vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *graphicsPipeline);
1323             vk.cmdDraw(*cmdBuffer, 3u, 1, 0u, 0u);
1324 
1325             finishRendering(*cmdBuffer);
1326 
1327             // wait till color attachment is fully written
1328             srcStageMask                = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
1329             dstStageMask                = VK_PIPELINE_STAGE_TRANSFER_BIT;
1330             memoryBarrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
1331             memoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
1332             vk.cmdPipelineBarrier(*cmdBuffer, srcStageMask, dstStageMask, 0, 1, &memoryBarrier, 0, DE_NULL, 0, DE_NULL);
1333 
1334             // read back color buffer image
1335             vk.cmdCopyImageToBuffer(*cmdBuffer, **m_cbImage[0], VK_IMAGE_LAYOUT_GENERAL, **m_cbReadBuffer[0], 1u,
1336                                     &m_defaultBufferImageCopy);
1337 
1338             endCommandBuffer(vk, *cmdBuffer);
1339 
1340             // submit commands and wait
1341             const VkQueue queue = m_context.getUniversalQueue();
1342             submitCommandsAndWait(vk, device, queue, cmdBuffer.get());
1343 
1344             invalidateAlloc(vk, device, m_cbReadBuffer[0]->getAllocation());
1345             if (!verifyUsingAtomicChecks(tileWidth, tileHeight, m_params->srRate.width, m_params->srRate.height,
1346                                          (uint32_t *)m_cbReadBuffer[0]->getAllocation().getHostPtr()))
1347                 return false;
1348 
1349         } // iterate over all possible tile sizes
1350 
1351     return true;
1352 }
1353 
runFragmentShaderMode(void)1354 bool AttachmentRateInstance::runFragmentShaderMode(void)
1355 {
1356     // Set up the image as a color attachment, and render rate to it,
1357     // then use it to draw a basic triangle and do basic checks
1358 
1359     const DeviceInterface &vk = m_context.getDeviceInterface();
1360     VkDevice device           = m_context.getDevice();
1361     uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
1362     VkMemoryBarrier memoryBarrier{VK_STRUCTURE_TYPE_MEMORY_BARRIER, DE_NULL, 0u, 0u};
1363     const bool useMemoryAccess = (m_params->mode == TM_MEMORY_ACCESS);
1364 
1365     Move<VkShaderModule> vertSetupShader =
1366         createShaderModule(vk, device, m_context.getBinaryCollection().get("vert_setup"), 0);
1367     Move<VkShaderModule> fragSetupShader =
1368         createShaderModule(vk, device, m_context.getBinaryCollection().get("frag_setup"), 0);
1369     Move<VkShaderModule> vertShader = createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0);
1370     Move<VkShaderModule> fragShader = createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0);
1371 
1372     Move<VkCommandPool> cmdPool =
1373         createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex);
1374     Move<VkCommandBuffer> cmdBuffer = allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
1375 
1376     m_srUsage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
1377 
1378     buildCounterBufferObjects(device, vk, m_context.getDefaultAllocator());
1379     buildColorBufferObjects(device, vk, m_context.getDefaultAllocator(), 0, m_cbUsage);
1380 
1381     // iterate over all possible tile sizes
1382     for (uint32_t tileWidth = m_minTileSize.width; tileWidth <= m_maxTileSize.width; tileWidth *= 2)
1383         for (uint32_t tileHeight = m_minTileSize.height; tileHeight <= m_maxTileSize.height; tileHeight *= 2)
1384         {
1385             // skip tile sizes that have unsuported aspect ratio
1386             uint32_t aspectRatio = (tileHeight > tileWidth) ? (tileHeight / tileWidth) : (tileWidth / tileHeight);
1387             if (aspectRatio > m_maxAspectRatio)
1388                 continue;
1389 
1390             // calculate size of shading rate attachment
1391             uint32_t srWidth  = (m_cbWidth + tileWidth - 1) / tileWidth;
1392             uint32_t srHeight = (m_cbHeight + tileHeight - 1) / tileHeight;
1393 
1394             buildShadingRateObjects(device, vk, m_context.getDefaultAllocator(), 0, srWidth, srHeight, m_srUsage);
1395 
1396             const auto dsFormat                        = m_params->getDSFormat();
1397             Move<VkPipelineLayout> setupPipelineLayout = buildPipelineLayout(device, vk);
1398             Move<VkPipelineLayout> ratePipelineLayout =
1399                 buildPipelineLayout(device, vk, &(*m_counterBufferDescriptorSetLayout));
1400             Move<VkRenderPass> setupRenderPass = buildRenderPass(device, vk, m_params->srFormat, VK_FORMAT_UNDEFINED);
1401             Move<VkRenderPass> rateRenderPass =
1402                 buildRenderPass(device, vk, m_cbFormat, dsFormat, tileWidth, tileHeight);
1403             Move<VkPipeline> setupPipeline =
1404                 buildGraphicsPipeline(device, vk, 0, *setupRenderPass, m_params->srFormat, VK_FORMAT_UNDEFINED,
1405                                       *setupPipelineLayout, *vertSetupShader, *fragSetupShader, false);
1406             Move<VkPipeline> ratePipeline = buildGraphicsPipeline(device, vk, 0, *rateRenderPass, m_cbFormat, dsFormat,
1407                                                                   *ratePipelineLayout, *vertShader, *fragShader);
1408 
1409             std::vector<FBAttachmentInfo> setupAttachmentInfo{
1410                 {m_params->srFormat, m_srUsage, srWidth, srHeight, *m_srImageView[0]}};
1411             std::vector<FBAttachmentInfo> rateAttachmentInfo{
1412                 {m_cbFormat, m_cbUsage, m_cbWidth, m_cbHeight, *m_cbImageView[0]},
1413                 {m_params->srFormat, m_srUsage, srWidth, srHeight, *m_srImageView[0]},
1414             };
1415             if (m_params->useDepthStencil())
1416                 rateAttachmentInfo.push_back(
1417                     FBAttachmentInfo{dsFormat, kDSUsage, m_cbWidth, m_cbHeight, *m_dsImageView});
1418 
1419             Move<VkFramebuffer> setupFramebuffer = buildFramebuffer(device, vk, *setupRenderPass, setupAttachmentInfo);
1420             Move<VkFramebuffer> rateFramebuffer  = buildFramebuffer(device, vk, *rateRenderPass, rateAttachmentInfo);
1421 
1422             beginCommandBuffer(vk, *cmdBuffer, 0u);
1423 
1424             // wait till sr image layout is changed
1425             VkPipelineStageFlags srcStageMask          = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
1426             VkPipelineStageFlags dstStageMask          = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
1427             VkImageMemoryBarrier srImageBarrierGeneral = makeImageMemoryBarrier(
1428                 VK_ACCESS_NONE_KHR, useMemoryAccess ? VK_ACCESS_MEMORY_WRITE_BIT : VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
1429                 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, **m_srImage[0], m_defaultImageSubresourceRange);
1430             vk.cmdPipelineBarrier(*cmdBuffer, srcStageMask, dstStageMask, 0, 0, DE_NULL, 0, DE_NULL, 1,
1431                                   &srImageBarrierGeneral);
1432 
1433             if (m_params->useDepthStencil())
1434             {
1435                 const VkPipelineStageFlags srcStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
1436                 const VkPipelineStageFlags dstStage =
1437                     (VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT);
1438                 VkImageMemoryBarrier depthImageReadOnlyBarrier = makeImageMemoryBarrier(
1439                     VK_ACCESS_NONE_KHR, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
1440                     m_params->getDSLayout(), **m_dsImage, m_dsImageSubresourceRange);
1441                 vk.cmdPipelineBarrier(*cmdBuffer, srcStage, dstStage, 0, 0, nullptr, 0, nullptr, 1,
1442                                       &depthImageReadOnlyBarrier);
1443             }
1444 
1445             // render rate to sr image
1446             startRendering(*cmdBuffer, *setupRenderPass, *setupFramebuffer, makeRect2D(srWidth, srHeight),
1447                            setupAttachmentInfo);
1448 
1449             // draw single triangle to cb
1450             vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *setupPipeline);
1451             vk.cmdDraw(*cmdBuffer, 3u, 1, 0u, 0u);
1452 
1453             finishRendering(*cmdBuffer);
1454 
1455             // wait till sr image is ready and change sr images layout
1456             srcStageMask                                   = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
1457             dstStageMask                                   = VK_PIPELINE_STAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR;
1458             VkImageMemoryBarrier srImageBarrierShadingRate = makeImageMemoryBarrier(
1459                 useMemoryAccess ? VK_ACCESS_MEMORY_WRITE_BIT : VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
1460                 useMemoryAccess ? VK_ACCESS_MEMORY_READ_BIT : VK_ACCESS_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR,
1461                 VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR, **m_srImage[0],
1462                 m_defaultImageSubresourceRange);
1463             vk.cmdPipelineBarrier(*cmdBuffer, srcStageMask, dstStageMask, 0, 0, DE_NULL, 0, DE_NULL, 1,
1464                                   &srImageBarrierShadingRate);
1465 
1466             // wait till cb image layout is changed
1467             srcStageMask                        = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
1468             dstStageMask                        = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
1469             VkImageMemoryBarrier cbImageBarrier = makeImageMemoryBarrier(
1470                 VK_ACCESS_NONE_KHR, useMemoryAccess ? VK_ACCESS_MEMORY_WRITE_BIT : VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
1471                 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, **m_cbImage[0], m_defaultImageSubresourceRange);
1472             vk.cmdPipelineBarrier(*cmdBuffer, srcStageMask, dstStageMask, 0, 0, DE_NULL, 0, DE_NULL, 1,
1473                                   &cbImageBarrier);
1474 
1475             startRendering(*cmdBuffer, *rateRenderPass, *rateFramebuffer, makeRect2D(m_cbWidth, m_cbHeight),
1476                            rateAttachmentInfo, tileWidth, tileHeight);
1477 
1478             // draw single triangle to cb
1479             vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *ratePipelineLayout, 0, 1,
1480                                      &(*m_counterBufferDescriptorSet), 0, DE_NULL);
1481             vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *ratePipeline);
1482             vk.cmdDraw(*cmdBuffer, 3u, 1, 0u, 0u);
1483 
1484             finishRendering(*cmdBuffer);
1485 
1486             // wait till color attachment is fully written
1487             srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
1488             dstStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
1489             memoryBarrier.srcAccessMask =
1490                 useMemoryAccess ? VK_ACCESS_MEMORY_WRITE_BIT : VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
1491             memoryBarrier.dstAccessMask = useMemoryAccess ? VK_ACCESS_MEMORY_READ_BIT : VK_ACCESS_TRANSFER_READ_BIT;
1492             vk.cmdPipelineBarrier(*cmdBuffer, srcStageMask, dstStageMask, 0, 1, &memoryBarrier, 0, DE_NULL, 0, DE_NULL);
1493 
1494             // read back color buffer image
1495             vk.cmdCopyImageToBuffer(*cmdBuffer, **m_cbImage[0], VK_IMAGE_LAYOUT_GENERAL, **m_cbReadBuffer[0], 1u,
1496                                     &m_defaultBufferImageCopy);
1497 
1498             endCommandBuffer(vk, *cmdBuffer);
1499 
1500             // submit commands and wait
1501             const VkQueue queue = m_context.getUniversalQueue();
1502             submitCommandsAndWait(vk, device, queue, cmdBuffer.get());
1503 
1504             invalidateAlloc(vk, device, m_cbReadBuffer[0]->getAllocation());
1505             if (!verifyUsingAtomicChecks(tileWidth, tileHeight, m_params->srRate.width, m_params->srRate.height,
1506                                          (uint32_t *)m_cbReadBuffer[0]->getAllocation().getHostPtr()))
1507                 return false;
1508 
1509         } // iterate over all possible tile sizes
1510 
1511     return true;
1512 }
1513 
runCopyMode(void)1514 bool AttachmentRateInstance::runCopyMode(void)
1515 {
1516     // Clear a separate image of the same format to that rate, copy it to
1517     // the shading rate image, then use it to draw a basic triangle and do basic checks
1518 
1519     const DeviceInterface &vk = m_context.getDeviceInterface();
1520     VkDevice device           = m_context.getDevice();
1521     uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
1522     VkMemoryBarrier memoryBarrier{VK_STRUCTURE_TYPE_MEMORY_BARRIER, DE_NULL, 0u, 0u};
1523 
1524     Move<VkShaderModule> vertShader = createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0);
1525     Move<VkShaderModule> fragShader = createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0);
1526 
1527     Move<VkCommandPool> cmdPool =
1528         createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex);
1529     Move<VkCommandBuffer> cmdBuffer = allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
1530 
1531     buildCounterBufferObjects(device, vk, m_context.getDefaultAllocator());
1532     buildColorBufferObjects(device, vk, m_context.getDefaultAllocator(), 0, m_cbUsage);
1533 
1534     // iterate over all possible tile sizes
1535     for (uint32_t tileWidth = m_minTileSize.width; tileWidth <= m_maxTileSize.width; tileWidth *= 2)
1536         for (uint32_t tileHeight = m_minTileSize.height; tileHeight <= m_maxTileSize.height; tileHeight *= 2)
1537         {
1538             // skip tile sizes that have unsuported aspect ratio
1539             uint32_t aspectRatio = (tileHeight > tileWidth) ? (tileHeight / tileWidth) : (tileWidth / tileHeight);
1540             if (aspectRatio > m_maxAspectRatio)
1541                 continue;
1542 
1543             // calculate size of shading rate attachment
1544             uint32_t srWidth  = (m_cbWidth + tileWidth - 1) / tileWidth;
1545             uint32_t srHeight = (m_cbHeight + tileHeight - 1) / tileHeight;
1546 
1547             buildShadingRateObjects(device, vk, m_context.getDefaultAllocator(), 0, srWidth, srHeight, m_srUsage);
1548 
1549             // create image that will be source for shading rate image
1550             de::MovePtr<ImageWithMemory> srSrcImage =
1551                 buildImageWithMemory(device, vk, m_context.getDefaultAllocator(), m_params->srFormat, srWidth, srHeight,
1552                                      VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
1553 
1554             const auto dsFormat = m_params->getDSFormat();
1555             Move<VkPipelineLayout> graphicsPipelineLayout =
1556                 buildPipelineLayout(device, vk, &(*m_counterBufferDescriptorSetLayout));
1557             Move<VkRenderPass> renderPass = buildRenderPass(device, vk, m_cbFormat, dsFormat, tileWidth, tileHeight);
1558             Move<VkPipeline> graphicsPipeline = buildGraphicsPipeline(
1559                 device, vk, 0, *renderPass, m_cbFormat, dsFormat, *graphicsPipelineLayout, *vertShader, *fragShader);
1560 
1561             std::vector<FBAttachmentInfo> attachmentInfo{
1562                 {m_cbFormat, m_cbUsage, m_cbWidth, m_cbHeight, *m_cbImageView[0]},
1563                 {m_params->srFormat, m_srUsage, srWidth, srHeight, *m_srImageView[0]},
1564             };
1565             // This would need an additional attachment with m_dsImageView and a barrier to transition the DS layout.
1566             // See runFragmentShaderMode for more details.
1567             DE_ASSERT(!m_params->useDepthStencil());
1568 
1569             Move<VkFramebuffer> framebuffer = buildFramebuffer(device, vk, *renderPass, attachmentInfo);
1570 
1571             beginCommandBuffer(vk, *cmdBuffer, 0u);
1572 
1573             // wait till sr images layout are changed
1574             VkPipelineStageFlags srcStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
1575             VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
1576             std::vector<VkImageMemoryBarrier> srImageBarrierGeneral(
1577                 2,
1578                 makeImageMemoryBarrier(VK_ACCESS_NONE_KHR, (VK_ACCESS_TRANSFER_WRITE_BIT | VK_ACCESS_TRANSFER_READ_BIT),
1579                                        VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, **m_srImage[0],
1580                                        m_defaultImageSubresourceRange));
1581             srImageBarrierGeneral[1].image = **srSrcImage;
1582             vk.cmdPipelineBarrier(*cmdBuffer, srcStageMask, dstStageMask, 0, 0, DE_NULL, 0, DE_NULL, 2,
1583                                   srImageBarrierGeneral.data());
1584 
1585             // clear source sr image with proper rate
1586             VkClearColorValue clearValue = {{0, 0, 0, 0}};
1587             clearValue.uint32[0]         = calculateRate(m_params->srRate.width, m_params->srRate.height);
1588             vk.cmdClearColorImage(*cmdBuffer, **srSrcImage, VK_IMAGE_LAYOUT_GENERAL, &clearValue, 1,
1589                                   &m_defaultImageSubresourceRange);
1590 
1591             // wait till sr source image is ready
1592             srcStageMask                = VK_PIPELINE_STAGE_TRANSFER_BIT;
1593             dstStageMask                = VK_PIPELINE_STAGE_TRANSFER_BIT;
1594             memoryBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
1595             memoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
1596             vk.cmdPipelineBarrier(*cmdBuffer, srcStageMask, dstStageMask, 0, 1, &memoryBarrier, 0, DE_NULL, 0, DE_NULL);
1597 
1598             // copy sr source image to sr image used during rendering
1599             VkImageCopy imageCopyRegion{
1600                 m_defaultImageSubresourceLayers, // VkImageSubresourceLayers srcSubresource;
1601                 {0, 0, 0},                       // VkOffset3D srcOffset;
1602                 m_defaultImageSubresourceLayers, // VkImageSubresourceLayers dstSubresource;
1603                 {0, 0, 0},                       // VkOffset3D dstOffset;
1604                 {srWidth, srHeight, 1u}          // VkExtent3D extent;
1605             };
1606             vk.cmdCopyImage(*cmdBuffer, **srSrcImage, VK_IMAGE_LAYOUT_GENERAL, **m_srImage[0], VK_IMAGE_LAYOUT_GENERAL,
1607                             1, &imageCopyRegion);
1608 
1609             // wait till sr image is ready and change sr images layout
1610             srcStageMask                                   = VK_PIPELINE_STAGE_TRANSFER_BIT;
1611             dstStageMask                                   = VK_PIPELINE_STAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR;
1612             memoryBarrier.srcAccessMask                    = VK_ACCESS_TRANSFER_WRITE_BIT;
1613             memoryBarrier.dstAccessMask                    = VK_ACCESS_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR;
1614             VkImageMemoryBarrier srImageBarrierShadingRate = makeImageMemoryBarrier(
1615                 VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR,
1616                 VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR, **m_srImage[0],
1617                 m_defaultImageSubresourceRange);
1618             vk.cmdPipelineBarrier(*cmdBuffer, srcStageMask, dstStageMask, 0, 1, &memoryBarrier, 0, DE_NULL, 1,
1619                                   &srImageBarrierShadingRate);
1620 
1621             // wait till cb image layout is changed
1622             srcStageMask                        = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
1623             dstStageMask                        = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
1624             VkImageMemoryBarrier cbImageBarrier = makeImageMemoryBarrier(
1625                 VK_ACCESS_NONE_KHR, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
1626                 VK_IMAGE_LAYOUT_GENERAL, **m_cbImage[0], m_defaultImageSubresourceRange);
1627             vk.cmdPipelineBarrier(*cmdBuffer, srcStageMask, dstStageMask, 0, 0, DE_NULL, 0, DE_NULL, 1,
1628                                   &cbImageBarrier);
1629 
1630             startRendering(*cmdBuffer, *renderPass, *framebuffer, makeRect2D(m_cbWidth, m_cbHeight), attachmentInfo,
1631                            tileWidth, tileHeight);
1632 
1633             // draw single triangle to cb
1634             vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *graphicsPipelineLayout, 0, 1,
1635                                      &(*m_counterBufferDescriptorSet), 0, DE_NULL);
1636             vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *graphicsPipeline);
1637             vk.cmdDraw(*cmdBuffer, 3u, 1, 0u, 0u);
1638 
1639             finishRendering(*cmdBuffer);
1640 
1641             // wait till color attachment is fully written
1642             srcStageMask                = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
1643             dstStageMask                = VK_PIPELINE_STAGE_TRANSFER_BIT;
1644             memoryBarrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
1645             memoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
1646             vk.cmdPipelineBarrier(*cmdBuffer, srcStageMask, dstStageMask, 0, 1, &memoryBarrier, 0, DE_NULL, 0, DE_NULL);
1647 
1648             // read back color buffer image
1649             vk.cmdCopyImageToBuffer(*cmdBuffer, **m_cbImage[0], VK_IMAGE_LAYOUT_GENERAL, **m_cbReadBuffer[0], 1u,
1650                                     &m_defaultBufferImageCopy);
1651 
1652             endCommandBuffer(vk, *cmdBuffer);
1653 
1654             // submit commands and wait
1655             const VkQueue queue = m_context.getUniversalQueue();
1656             submitCommandsAndWait(vk, device, queue, cmdBuffer.get());
1657 
1658             invalidateAlloc(vk, device, m_cbReadBuffer[0]->getAllocation());
1659             if (!verifyUsingAtomicChecks(tileWidth, tileHeight, m_params->srRate.width, m_params->srRate.height,
1660                                          (uint32_t *)m_cbReadBuffer[0]->getAllocation().getHostPtr()))
1661                 return false;
1662 
1663         } // iterate over all possible tile sizes
1664 
1665     return true;
1666 }
1667 
runCopyModeOnTransferQueue(void)1668 bool AttachmentRateInstance::runCopyModeOnTransferQueue(void)
1669 {
1670     // Clear a separate image of the same format to that rate, copy it to
1671     // the shading rate image on separate transfer queue and then use copied
1672     // image to draw a basic triangle and do basic checks
1673 
1674     const PlatformInterface &vkp      = m_context.getPlatformInterface();
1675     const InstanceInterface &vki      = m_context.getInstanceInterface();
1676     VkPhysicalDevice pd               = m_context.getPhysicalDevice();
1677     uint32_t transferQueueFamilyIndex = std::numeric_limits<uint32_t>::max();
1678     uint32_t graphicsQueueFamilyIndex = std::numeric_limits<uint32_t>::max();
1679     VkMemoryBarrier memoryBarrier{VK_STRUCTURE_TYPE_MEMORY_BARRIER, DE_NULL, 0u, 0u};
1680     std::vector<VkQueueFamilyProperties> queueFamilyProperties = getPhysicalDeviceQueueFamilyProperties(vki, pd);
1681 
1682     // find graphics and transfer queue families
1683     for (uint32_t queueNdx = 0; queueNdx < queueFamilyProperties.size(); queueNdx++)
1684     {
1685         VkQueueFlags queueFlags = queueFamilyProperties[queueNdx].queueFlags;
1686         if ((graphicsQueueFamilyIndex == std::numeric_limits<uint32_t>::max()) && (queueFlags & VK_QUEUE_GRAPHICS_BIT))
1687             graphicsQueueFamilyIndex = queueNdx;
1688         else if ((queueNdx != graphicsQueueFamilyIndex) && (queueFlags & VK_QUEUE_TRANSFER_BIT))
1689             transferQueueFamilyIndex = queueNdx;
1690     }
1691     if (transferQueueFamilyIndex == std::numeric_limits<uint32_t>::max())
1692         TCU_THROW(NotSupportedError, "No separate transfer queue");
1693 
1694     if (graphicsQueueFamilyIndex == std::numeric_limits<uint32_t>::max())
1695         TCU_THROW(NotSupportedError, "No separate graphics queue");
1696     // using queueFamilies vector to determine if sr image uses exclusiv or concurrent sharing
1697     std::vector<uint32_t> queueFamilies;
1698     if (m_params->mode == TM_SETUP_RATE_WITH_COPYING_FROM_CONCURENT_IMAGE_USING_TRANSFER_QUEUE)
1699         queueFamilies = {graphicsQueueFamilyIndex, transferQueueFamilyIndex};
1700 
1701     // create custom device
1702     VkDevice device;
1703     DeviceInterface *driver;
1704     Allocator *allocator;
1705 
1706     {
1707         const float queuePriorities = 1.0f;
1708         std::vector<VkDeviceQueueCreateInfo> queueInfo(
1709             2,
1710             {
1711                 VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, // VkStructureType sType;
1712                 DE_NULL,                                    // const void* pNext;
1713                 (VkDeviceQueueCreateFlags)0u,               // VkDeviceQueueCreateFlags flags;
1714                 transferQueueFamilyIndex,                   // uint32_t queueFamilyIndex;
1715                 1u,                                         // uint32_t queueCount;
1716                 &queuePriorities                            // const float* pQueuePriorities;
1717             });
1718         queueInfo[1].queueFamilyIndex = graphicsQueueFamilyIndex;
1719 
1720         VkPhysicalDeviceFeatures deviceFeatures;
1721         vki.getPhysicalDeviceFeatures(pd, &deviceFeatures);
1722 
1723         VkPhysicalDeviceFragmentShadingRateFeaturesKHR fsrFeatures{
1724             VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_FEATURES_KHR, DE_NULL, false, false, true};
1725 #ifndef CTS_USES_VULKANSC
1726         VkPhysicalDeviceDynamicRenderingFeaturesKHR drFeatures{
1727             VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DYNAMIC_RENDERING_FEATURES_KHR, DE_NULL, true};
1728 #endif // CTS_USES_VULKANSC
1729         VkPhysicalDeviceImagelessFramebufferFeatures ifbFeatures{
1730             VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGELESS_FRAMEBUFFER_FEATURES, DE_NULL, true};
1731         VkPhysicalDeviceFeatures2 createPhysicalFeature{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2, &fsrFeatures,
1732                                                         deviceFeatures};
1733 
1734         void *pNext                                 = DE_NULL;
1735         std::vector<const char *> enabledExtensions = {"VK_KHR_fragment_shading_rate"};
1736 #ifndef CTS_USES_VULKANSC
1737         if (m_params->useDynamicRendering)
1738         {
1739             pNext = &drFeatures;
1740         }
1741 #endif // CTS_USES_VULKANSC
1742         if (m_params->useImagelessFramebuffer)
1743         {
1744             enabledExtensions.push_back("VK_KHR_imageless_framebuffer");
1745             ifbFeatures.pNext = pNext;
1746             pNext             = &ifbFeatures;
1747         }
1748         fsrFeatures.pNext = pNext;
1749 
1750         std::vector<const char *> enabledLayers = getValidationLayers(vki, pd);
1751         VkDeviceCreateInfo deviceInfo{
1752             VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,            // VkStructureType sType;
1753             &createPhysicalFeature,                          // const void* pNext;
1754             (VkDeviceCreateFlags)0u,                         // VkDeviceCreateFlags flags;
1755             2u,                                              // uint32_t queueCreateInfoCount;
1756             queueInfo.data(),                                // const VkDeviceQueueCreateInfo* pQueueCreateInfos;
1757             static_cast<uint32_t>(enabledLayers.size()),     // uint32_t enabledLayerCount;
1758             de::dataOrNull(enabledLayers),                   // const char* const* ppEnabledLayerNames;
1759             static_cast<uint32_t>(enabledExtensions.size()), // uint32_t enabledExtensionCount;
1760             enabledExtensions.data(),                        // const char* const* ppEnabledExtensionNames;
1761             DE_NULL                                          // const VkPhysicalDeviceFeatures* pEnabledFeatures;
1762         };
1763 
1764         vk::Move<VkDevice> customDevice        = createDevice(vkp, m_context.getInstance(), vki, pd, &deviceInfo);
1765         de::MovePtr<DeviceDriver> customDriver = de::MovePtr<DeviceDriver>(
1766             new DeviceDriver(vkp, m_context.getInstance(), *customDevice, m_context.getUsedApiVersion(),
1767                              m_context.getTestContext().getCommandLine()));
1768         de::MovePtr<Allocator> customAllocator = de::MovePtr<Allocator>(
1769             new SimpleAllocator(*customDriver, *customDevice, getPhysicalDeviceMemoryProperties(vki, pd)));
1770 
1771         device    = *customDevice;
1772         driver    = &*customDriver;
1773         allocator = &*customAllocator;
1774 
1775         m_customDeviceHolder = de::MovePtr<DeviceHolder>(new DeviceHolder(customDevice, customDriver, customAllocator));
1776     }
1777 
1778     DeviceInterface &vk = *driver;
1779 
1780     VkQueue transferQueue;
1781     vk.getDeviceQueue(device, transferQueueFamilyIndex, 0u, &transferQueue);
1782     VkQueue graphicsQueue;
1783     vk.getDeviceQueue(device, graphicsQueueFamilyIndex, 0u, &graphicsQueue);
1784 
1785     // create transfer and graphics command buffers
1786     Move<VkCommandPool> transferCmdPool =
1787         createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, transferQueueFamilyIndex);
1788     Move<VkCommandBuffer> transferCmdBuffer =
1789         allocateCommandBuffer(vk, device, *transferCmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
1790     Move<VkCommandPool> graphicsCmdPool =
1791         createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, graphicsQueueFamilyIndex);
1792     Move<VkCommandBuffer> graphicsCmdBuffer =
1793         allocateCommandBuffer(vk, device, *graphicsCmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
1794 
1795     Move<VkShaderModule> vertShader = createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0);
1796     Move<VkShaderModule> fragShader = createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0);
1797 
1798     buildColorBufferObjects(device, vk, *allocator, 0, m_cbUsage);
1799     buildCounterBufferObjects(device, vk, *allocator);
1800 
1801     // iterate over all possible tile sizes
1802     for (uint32_t tileWidth = m_minTileSize.width; tileWidth <= m_maxTileSize.width; tileWidth *= 2)
1803         for (uint32_t tileHeight = m_minTileSize.height; tileHeight <= m_maxTileSize.height; tileHeight *= 2)
1804         {
1805             // skip tile sizes that have unsuported aspect ratio
1806             uint32_t aspectRatio = (tileHeight > tileWidth) ? (tileHeight / tileWidth) : (tileWidth / tileHeight);
1807             if (aspectRatio > m_maxAspectRatio)
1808                 continue;
1809 
1810             // calculate size of shading rate attachment
1811             uint32_t srWidth  = (m_cbWidth + tileWidth - 1) / tileWidth;
1812             uint32_t srHeight = (m_cbHeight + tileHeight - 1) / tileHeight;
1813 
1814             // create image that will be source for shading rate image
1815             de::MovePtr<ImageWithMemory> srSrcImage =
1816                 buildImageWithMemory(device, vk, *allocator, m_params->srFormat, srWidth, srHeight,
1817                                      VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
1818 
1819             // create buffer that will contain shading rate source data
1820             tcu::TextureFormat srTextureFormat = mapVkFormat(m_params->srFormat);
1821             uint32_t srWriteBufferSize =
1822                 srWidth * srHeight * getNumUsedChannels(srTextureFormat.order) * getChannelSize(srTextureFormat.type);
1823             de::MovePtr<BufferWithMemory> srSrcBuffer =
1824                 buildBufferWithMemory(device, vk, *allocator, srWriteBufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
1825 
1826             // fill buffer with tested shading rate
1827             uint8_t *srWriteBufferHostPtr = (uint8_t *)srSrcBuffer->getAllocation().getHostPtr();
1828             uint8_t value                 = (uint8_t)calculateRate(m_params->srRate.width, m_params->srRate.height);
1829             deMemset(srWriteBufferHostPtr, value, (size_t)srWriteBufferSize);
1830             flushAlloc(vk, device, srSrcBuffer->getAllocation());
1831 
1832             // create shading rate iamge
1833             m_srImage[0]     = buildImageWithMemory(device, vk, *allocator, m_params->srFormat, srWidth, srHeight,
1834                                                     VK_IMAGE_USAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR |
1835                                                         VK_IMAGE_USAGE_TRANSFER_DST_BIT,
1836                                                     VK_IMAGE_TILING_OPTIMAL, queueFamilies);
1837             m_srImageView[0] = buildImageView(device, vk, m_params->srFormat, m_srImage[0]->get());
1838 
1839             const auto dsFormat = m_params->getDSFormat();
1840             Move<VkPipelineLayout> graphicsPipelineLayout =
1841                 buildPipelineLayout(device, vk, &(*m_counterBufferDescriptorSetLayout));
1842             Move<VkRenderPass> renderPass = buildRenderPass(device, vk, m_cbFormat, dsFormat, tileWidth, tileHeight);
1843             Move<VkPipeline> graphicsPipeline = buildGraphicsPipeline(
1844                 device, vk, 0, *renderPass, m_cbFormat, dsFormat, *graphicsPipelineLayout, *vertShader, *fragShader);
1845 
1846             std::vector<FBAttachmentInfo> attachmentInfo{
1847                 {m_cbFormat, m_cbUsage, m_cbWidth, m_cbHeight, *m_cbImageView[0]},
1848                 {m_params->srFormat, m_srUsage, srWidth, srHeight, *m_srImageView[0]},
1849             };
1850             // This would need an additional attachment with m_dsImageView and a barrier to transition the DS layout.
1851             // See runFragmentShaderMode for more details.
1852             DE_ASSERT(!m_params->useDepthStencil());
1853 
1854             Move<VkFramebuffer> framebuffer = buildFramebuffer(device, vk, *renderPass, attachmentInfo);
1855 
1856             beginCommandBuffer(vk, *transferCmdBuffer, 0u);
1857 
1858             // wait till sr data is ready in buffer and change sr image layouts to general
1859             VkPipelineStageFlags srcStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
1860             VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
1861             std::vector<VkImageMemoryBarrier> srImageBarrierGeneral(
1862                 2,
1863                 makeImageMemoryBarrier(VK_ACCESS_NONE_KHR, (VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_TRANSFER_WRITE_BIT),
1864                                        VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, **m_srImage[0],
1865                                        m_defaultImageSubresourceRange));
1866             srImageBarrierGeneral[1].image = **srSrcImage;
1867             vk.cmdPipelineBarrier(*transferCmdBuffer, srcStageMask, dstStageMask, 0, 0, nullptr, 0, DE_NULL, 2,
1868                                   srImageBarrierGeneral.data());
1869 
1870             // copy sr data to images
1871             const VkBufferImageCopy srCopyBuffer =
1872                 makeBufferImageCopy({srWidth, srHeight, 1u}, m_defaultImageSubresourceLayers);
1873             vk.cmdCopyBufferToImage(*transferCmdBuffer, **srSrcBuffer, **srSrcImage, VK_IMAGE_LAYOUT_GENERAL, 1,
1874                                     &srCopyBuffer);
1875 
1876             // wait till sr source image is ready
1877             srcStageMask                = VK_PIPELINE_STAGE_TRANSFER_BIT;
1878             dstStageMask                = VK_PIPELINE_STAGE_TRANSFER_BIT;
1879             memoryBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
1880             memoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
1881             vk.cmdPipelineBarrier(*transferCmdBuffer, srcStageMask, dstStageMask, 0, 1, &memoryBarrier, 0, DE_NULL, 0,
1882                                   DE_NULL);
1883 
1884             // copy sr source image to sr image used during rendering
1885             VkImageCopy imageCopyRegion{
1886                 m_defaultImageSubresourceLayers, // VkImageSubresourceLayers srcSubresource;
1887                 {0, 0, 0},                       // VkOffset3D srcOffset;
1888                 m_defaultImageSubresourceLayers, // VkImageSubresourceLayers dstSubresource;
1889                 {0, 0, 0},                       // VkOffset3D dstOffset;
1890                 {srWidth, srHeight, 1u}          // VkExtent3D extent;
1891             };
1892             vk.cmdCopyImage(*transferCmdBuffer, **srSrcImage, VK_IMAGE_LAYOUT_GENERAL, **m_srImage[0],
1893                             VK_IMAGE_LAYOUT_GENERAL, 1, &imageCopyRegion);
1894 
1895             // release exclusive ownership from the transfer queue family
1896             srcStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
1897             dstStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
1898             VkImageMemoryBarrier srImageBarrierOwnershipTransfer =
1899                 makeImageMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_NONE_KHR, VK_IMAGE_LAYOUT_GENERAL,
1900                                        VK_IMAGE_LAYOUT_GENERAL, **m_srImage[0], m_defaultImageSubresourceRange);
1901             if (m_params->mode == TM_SETUP_RATE_WITH_COPYING_FROM_EXCLUSIVE_IMAGE_USING_TRANSFER_QUEUE)
1902             {
1903                 srImageBarrierOwnershipTransfer.srcQueueFamilyIndex = transferQueueFamilyIndex;
1904                 srImageBarrierOwnershipTransfer.dstQueueFamilyIndex = graphicsQueueFamilyIndex;
1905             }
1906             vk.cmdPipelineBarrier(*transferCmdBuffer, srcStageMask, dstStageMask, 0, 0, DE_NULL, 0, DE_NULL, 1,
1907                                   &srImageBarrierOwnershipTransfer);
1908 
1909             endCommandBuffer(vk, *transferCmdBuffer);
1910 
1911             beginCommandBuffer(vk, *graphicsCmdBuffer, 0u);
1912 
1913             // acquire exclusive ownership for the graphics queue family - while changing sr images layout
1914             vk.cmdPipelineBarrier(*graphicsCmdBuffer, srcStageMask, dstStageMask, 0, 0, DE_NULL, 0, DE_NULL, 1,
1915                                   &srImageBarrierOwnershipTransfer);
1916 
1917             // wait till sr image layout is changed
1918             srcStageMask                                   = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
1919             dstStageMask                                   = VK_PIPELINE_STAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR;
1920             VkImageMemoryBarrier srImageBarrierShadingRate = makeImageMemoryBarrier(
1921                 VK_ACCESS_NONE_KHR, VK_ACCESS_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR, VK_IMAGE_LAYOUT_GENERAL,
1922                 VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR, **m_srImage[0],
1923                 m_defaultImageSubresourceRange);
1924             vk.cmdPipelineBarrier(*graphicsCmdBuffer, srcStageMask, dstStageMask, 0, 0, DE_NULL, 0, DE_NULL, 1,
1925                                   &srImageBarrierShadingRate);
1926 
1927             // wait till cb image layout is changed
1928             srcStageMask                        = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
1929             dstStageMask                        = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
1930             VkImageMemoryBarrier cbImageBarrier = makeImageMemoryBarrier(
1931                 VK_ACCESS_NONE_KHR, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
1932                 VK_IMAGE_LAYOUT_GENERAL, **m_cbImage[0], m_defaultImageSubresourceRange);
1933             vk.cmdPipelineBarrier(*graphicsCmdBuffer, srcStageMask, dstStageMask, 0, 0, DE_NULL, 0, DE_NULL, 1,
1934                                   &cbImageBarrier);
1935 
1936             startRendering(*graphicsCmdBuffer, *renderPass, *framebuffer, makeRect2D(m_cbWidth, m_cbHeight),
1937                            attachmentInfo, tileWidth, tileHeight, driver);
1938 
1939             // draw single triangle to cb
1940             vk.cmdBindDescriptorSets(*graphicsCmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *graphicsPipelineLayout, 0, 1,
1941                                      &(*m_counterBufferDescriptorSet), 0, DE_NULL);
1942             vk.cmdBindPipeline(*graphicsCmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *graphicsPipeline);
1943             vk.cmdDraw(*graphicsCmdBuffer, 3u, 1, 0u, 0u);
1944 
1945             finishRendering(*graphicsCmdBuffer);
1946 
1947             // wait till color attachment is fully written
1948             srcStageMask                = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
1949             dstStageMask                = VK_PIPELINE_STAGE_TRANSFER_BIT;
1950             memoryBarrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
1951             memoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
1952             vk.cmdPipelineBarrier(*graphicsCmdBuffer, srcStageMask, dstStageMask, 0, 1, &memoryBarrier, 0, DE_NULL, 0,
1953                                   DE_NULL);
1954 
1955             // read back color buffer image
1956             vk.cmdCopyImageToBuffer(*graphicsCmdBuffer, **m_cbImage[0], VK_IMAGE_LAYOUT_GENERAL, **m_cbReadBuffer[0],
1957                                     1u, &m_defaultBufferImageCopy);
1958 
1959             endCommandBuffer(vk, *graphicsCmdBuffer);
1960 
1961             // create synchronization objects
1962             Move<VkSemaphore> semaphore = createSemaphore(vk, device);
1963             Move<VkFence> transferFence = createFence(vk, device);
1964             Move<VkFence> graphicsFence = createFence(vk, device);
1965 
1966             const VkSubmitInfo transferSubmitInfo{
1967                 VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType;
1968                 DE_NULL,                       // const void* pNext;
1969                 0u,                            // uint32_t waitSemaphoreCount;
1970                 DE_NULL,                       // const VkSemaphore* pWaitSemaphores;
1971                 DE_NULL,                       // const VkPipelineStageFlags* pWaitDstStageMask;
1972                 1u,                            // uint32_t commandBufferCount;
1973                 &*transferCmdBuffer,           // const VkCommandBuffer* pCommandBuffers;
1974                 1u,                            // uint32_t signalSemaphoreCount;
1975                 &*semaphore,                   // const VkSemaphore* pSignalSemaphores;
1976             };
1977             const VkPipelineStageFlags waitDstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
1978             const VkSubmitInfo graphicsSubmitInfo{
1979                 VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType;
1980                 DE_NULL,                       // const void* pNext;
1981                 1u,                            // uint32_t waitSemaphoreCount;
1982                 &*semaphore,                   // const VkSemaphore* pWaitSemaphores;
1983                 &waitDstStageMask,             // const VkPipelineStageFlags* pWaitDstStageMask;
1984                 1u,                            // uint32_t commandBufferCount;
1985                 &*graphicsCmdBuffer,           // const VkCommandBuffer* pCommandBuffers;
1986                 0u,                            // uint32_t signalSemaphoreCount;
1987                 DE_NULL,                       // const VkSemaphore* pSignalSemaphores;
1988             };
1989 
1990             // submit commands to both queues
1991             VK_CHECK(vk.queueSubmit(transferQueue, 1u, &transferSubmitInfo, *transferFence));
1992             VK_CHECK(vk.queueSubmit(graphicsQueue, 1u, &graphicsSubmitInfo, *graphicsFence));
1993 
1994             VkFence fences[] = {*graphicsFence, *transferFence};
1995             VK_CHECK(vk.waitForFences(device, 2u, fences, true, ~0ull));
1996 
1997             invalidateAlloc(vk, device, m_cbReadBuffer[0]->getAllocation());
1998             if (!verifyUsingAtomicChecks(tileWidth, tileHeight, m_params->srRate.width, m_params->srRate.height,
1999                                          (uint32_t *)m_cbReadBuffer[0]->getAllocation().getHostPtr()))
2000                 return false;
2001 
2002         } // iterate over all possible tile sizes
2003 
2004     return true;
2005 }
2006 
runFillLinearTiledImage(void)2007 bool AttachmentRateInstance::runFillLinearTiledImage(void)
2008 {
2009     // Create a linear tiled fragment shading rate attachment image and set
2010     // its data on the host, then draw a basic triangle and do basic checks
2011 
2012     const DeviceInterface &vk           = m_context.getDeviceInterface();
2013     VkDevice device                     = m_context.getDevice();
2014     uint32_t queueFamilyIndex           = m_context.getUniversalQueueFamilyIndex();
2015     VkImageSubresource imageSubresource = makeImageSubresource(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u);
2016     VkMemoryBarrier memoryBarrier{VK_STRUCTURE_TYPE_MEMORY_BARRIER, DE_NULL, 0u, 0u};
2017     VkSubresourceLayout srImageLayout;
2018 
2019     Move<VkShaderModule> vertShader = createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0);
2020     Move<VkShaderModule> fragShader = createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0);
2021 
2022     Move<VkCommandPool> cmdPool =
2023         createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex);
2024     Move<VkCommandBuffer> cmdBuffer = allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
2025 
2026     buildCounterBufferObjects(device, vk, m_context.getDefaultAllocator());
2027     buildColorBufferObjects(device, vk, m_context.getDefaultAllocator(), 0, m_cbUsage);
2028 
2029     // iterate over all possible tile sizes
2030     for (uint32_t tileWidth = m_minTileSize.width; tileWidth <= m_maxTileSize.width; tileWidth *= 2)
2031         for (uint32_t tileHeight = m_minTileSize.height; tileHeight <= m_maxTileSize.height; tileHeight *= 2)
2032         {
2033             // skip tile sizes that have unsuported aspect ratio
2034             uint32_t aspectRatio = (tileHeight > tileWidth) ? (tileHeight / tileWidth) : (tileWidth / tileHeight);
2035             if (aspectRatio > m_maxAspectRatio)
2036                 continue;
2037 
2038             // calculate size of shading rate attachment
2039             uint32_t srWidth  = (m_cbWidth + tileWidth - 1) / tileWidth;
2040             uint32_t srHeight = (m_cbHeight + tileHeight - 1) / tileHeight;
2041 
2042             buildShadingRateObjects(device, vk, m_context.getDefaultAllocator(), 0, srWidth, srHeight, m_srUsage,
2043                                     VK_IMAGE_TILING_LINEAR);
2044 
2045             uint8_t *imagePtr = reinterpret_cast<uint8_t *>(m_srImage[0]->getAllocation().getHostPtr());
2046             uint8_t value     = (uint8_t)calculateRate(m_params->srRate.width, m_params->srRate.height);
2047 
2048             // fill sr image on the host row by row
2049             vk.getImageSubresourceLayout(device, **m_srImage[0], &imageSubresource, &srImageLayout);
2050             for (uint32_t srTexelRow = 0; srTexelRow < srHeight; srTexelRow++)
2051             {
2052                 uint8_t *rowDst = imagePtr + srImageLayout.offset + srImageLayout.rowPitch * srTexelRow;
2053                 deMemset(rowDst, value, (size_t)srWidth);
2054             }
2055 
2056             const auto dsFormat = m_params->getDSFormat();
2057             Move<VkPipelineLayout> graphicsPipelineLayout =
2058                 buildPipelineLayout(device, vk, &(*m_counterBufferDescriptorSetLayout));
2059             Move<VkRenderPass> renderPass = buildRenderPass(device, vk, m_cbFormat, dsFormat, tileWidth, tileHeight);
2060             Move<VkPipeline> graphicsPipeline = buildGraphicsPipeline(
2061                 device, vk, 0, *renderPass, m_cbFormat, dsFormat, *graphicsPipelineLayout, *vertShader, *fragShader);
2062 
2063             std::vector<FBAttachmentInfo> attachmentInfo{
2064                 {m_cbFormat, m_cbUsage, m_cbWidth, m_cbHeight, *m_cbImageView[0]},
2065                 {m_params->srFormat, m_srUsage, srWidth, srHeight, *m_srImageView[0]},
2066             };
2067             // This would need an additional attachment with m_dsImageView and a barrier to transition the DS layout.
2068             // See runFragmentShaderMode for more details.
2069             DE_ASSERT(!m_params->useDepthStencil());
2070 
2071             Move<VkFramebuffer> framebuffer = buildFramebuffer(device, vk, *renderPass, attachmentInfo);
2072 
2073             beginCommandBuffer(vk, *cmdBuffer, 0u);
2074 
2075             // wait till sr image layout is changed
2076             VkPipelineStageFlags srcStageMask             = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
2077             VkPipelineStageFlags dstStageMask             = VK_PIPELINE_STAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR;
2078             VkImageMemoryBarrier srImageBarrierAttachment = makeImageMemoryBarrier(
2079                 VK_ACCESS_NONE_KHR, VK_ACCESS_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR, VK_IMAGE_LAYOUT_UNDEFINED,
2080                 VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR, **m_srImage[0],
2081                 m_defaultImageSubresourceRange);
2082             vk.cmdPipelineBarrier(*cmdBuffer, srcStageMask, dstStageMask, 0, 0, DE_NULL, 0, DE_NULL, 1,
2083                                   &srImageBarrierAttachment);
2084 
2085             // wait till cb image layout is changed
2086             srcStageMask                        = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
2087             dstStageMask                        = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
2088             VkImageMemoryBarrier cbImageBarrier = makeImageMemoryBarrier(
2089                 VK_ACCESS_NONE_KHR, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
2090                 VK_IMAGE_LAYOUT_GENERAL, **m_cbImage[0], m_defaultImageSubresourceRange);
2091             vk.cmdPipelineBarrier(*cmdBuffer, srcStageMask, dstStageMask, 0, 0, DE_NULL, 0, DE_NULL, 1,
2092                                   &cbImageBarrier);
2093 
2094             startRendering(*cmdBuffer, *renderPass, *framebuffer, makeRect2D(m_cbWidth, m_cbHeight), attachmentInfo,
2095                            tileWidth, tileHeight);
2096 
2097             // draw single triangle to cb
2098             vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *graphicsPipelineLayout, 0, 1,
2099                                      &(*m_counterBufferDescriptorSet), 0, DE_NULL);
2100             vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *graphicsPipeline);
2101             vk.cmdDraw(*cmdBuffer, 3u, 1, 0u, 0u);
2102 
2103             finishRendering(*cmdBuffer);
2104 
2105             // wait till color attachment is fully written
2106             srcStageMask                = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
2107             dstStageMask                = VK_PIPELINE_STAGE_TRANSFER_BIT;
2108             memoryBarrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
2109             memoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
2110             vk.cmdPipelineBarrier(*cmdBuffer, srcStageMask, dstStageMask, 0, 1, &memoryBarrier, 0, DE_NULL, 0, DE_NULL);
2111 
2112             // read back color buffer image
2113             vk.cmdCopyImageToBuffer(*cmdBuffer, **m_cbImage[0], VK_IMAGE_LAYOUT_GENERAL, **m_cbReadBuffer[0], 1u,
2114                                     &m_defaultBufferImageCopy);
2115 
2116             endCommandBuffer(vk, *cmdBuffer);
2117 
2118             // submit commands and wait
2119             const VkQueue queue = m_context.getUniversalQueue();
2120             submitCommandsAndWait(vk, device, queue, cmdBuffer.get());
2121 
2122             invalidateAlloc(vk, device, m_cbReadBuffer[0]->getAllocation());
2123             if (!verifyUsingAtomicChecks(tileWidth, tileHeight, m_params->srRate.width, m_params->srRate.height,
2124                                          (uint32_t *)m_cbReadBuffer[0]->getAllocation().getHostPtr()))
2125                 return false;
2126 
2127         } // iterate over all possible tile sizes
2128 
2129     return true;
2130 }
2131 
runTwoSubpassMode(void)2132 bool AttachmentRateInstance::runTwoSubpassMode(void)
2133 {
2134     // Set up a two-subpass render pass with different shading rate attachments used in each subpass.
2135     // Then draw a basic triangle in each subpass and do basic checks.
2136 
2137     const InstanceInterface &vki = m_context.getInstanceInterface();
2138     const DeviceInterface &vk    = m_context.getDeviceInterface();
2139     VkPhysicalDevice pd          = m_context.getPhysicalDevice();
2140     VkDevice device              = m_context.getDevice();
2141     uint32_t queueFamilyIndex    = m_context.getUniversalQueueFamilyIndex();
2142     VkMemoryBarrier memoryBarrier{VK_STRUCTURE_TYPE_MEMORY_BARRIER, DE_NULL, 0u, 0u};
2143 
2144     Move<VkShaderModule> vertShader0 = createShaderModule(vk, device, m_context.getBinaryCollection().get("vert0"), 0);
2145     Move<VkShaderModule> vertShader1 = createShaderModule(vk, device, m_context.getBinaryCollection().get("vert1"), 0);
2146     Move<VkShaderModule> fragShader  = createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0);
2147 
2148     Move<VkCommandPool> cmdPool =
2149         createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex);
2150     Move<VkCommandBuffer> cmdBuffer = allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
2151 
2152     // fetch information about supported rates
2153     uint32_t supportedFragmentShadingRateCount;
2154     std::vector<VkPhysicalDeviceFragmentShadingRateKHR> supportedFragmentShadingRates;
2155     vki.getPhysicalDeviceFragmentShadingRatesKHR(pd, &supportedFragmentShadingRateCount, DE_NULL);
2156     supportedFragmentShadingRates.resize(
2157         supportedFragmentShadingRateCount,
2158         {
2159             VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_KHR, // VkStructureType sType;
2160             DE_NULL,                                                     // void* pNext;
2161             VK_SAMPLE_COUNT_1_BIT,                                       // VkSampleCountFlags sampleCounts;
2162             {0, 0}                                                       // VkExtent2D fragmentSize;
2163         });
2164     vki.getPhysicalDeviceFragmentShadingRatesKHR(pd, &supportedFragmentShadingRateCount,
2165                                                  &supportedFragmentShadingRates[0]);
2166 
2167     // grab min and max tile sieze and biggest and smallest rate
2168     uint32_t sr0Width      = (m_cbWidth + m_minTileSize.width - 1) / m_minTileSize.width;
2169     uint32_t sr0Height     = (m_cbHeight + m_minTileSize.height - 1) / m_minTileSize.height;
2170     uint32_t sr1Width      = (m_cbWidth + m_maxTileSize.width - 1) / m_maxTileSize.width;
2171     uint32_t sr1Height     = (m_cbHeight + m_maxTileSize.height - 1) / m_maxTileSize.height;
2172     uint32_t sr0RateWidth  = supportedFragmentShadingRates[0].fragmentSize.width; // bigets supported rate
2173     uint32_t sr0RateHeight = supportedFragmentShadingRates[0].fragmentSize.height;
2174     uint32_t sr1RateWidth  = supportedFragmentShadingRates[supportedFragmentShadingRateCount - 2]
2175                                 .fragmentSize.width; // smallest supported rate excluding {1, 1}
2176     uint32_t sr1RateHeight = supportedFragmentShadingRates[supportedFragmentShadingRateCount - 2].fragmentSize.height;
2177 
2178     buildColorBufferObjects(device, vk, m_context.getDefaultAllocator(), 0, m_cbUsage);
2179     buildColorBufferObjects(device, vk, m_context.getDefaultAllocator(), 1, m_cbUsage);
2180     buildShadingRateObjects(device, vk, m_context.getDefaultAllocator(), 0, sr0Width, sr0Height, m_srUsage);
2181     buildShadingRateObjects(device, vk, m_context.getDefaultAllocator(), 1, sr1Width, sr1Height, m_srUsage);
2182     buildCounterBufferObjects(device, vk, m_context.getDefaultAllocator());
2183 
2184     const auto dsFormat                   = m_params->getDSFormat();
2185     Move<VkRenderPass> renderPass         = buildRenderPass(device, vk, m_cbFormat, dsFormat, m_minTileSize.width,
2186                                                             m_minTileSize.height, m_maxTileSize.width, m_maxTileSize.height);
2187     Move<VkPipelineLayout> pipelineLayout = buildPipelineLayout(device, vk, &(*m_counterBufferDescriptorSetLayout));
2188     Move<VkPipeline> graphicsPipeline0    = buildGraphicsPipeline(device, vk, 0, *renderPass, m_cbFormat, dsFormat,
2189                                                                   *pipelineLayout, *vertShader0, *fragShader);
2190     Move<VkPipeline> graphicsPipeline1    = buildGraphicsPipeline(device, vk, 1, *renderPass, m_cbFormat, dsFormat,
2191                                                                   *pipelineLayout, *vertShader1, *fragShader);
2192 
2193     std::vector<FBAttachmentInfo> attachmentInfo{
2194         {m_cbFormat, m_cbUsage, m_cbWidth, m_cbHeight, *m_cbImageView[0]},
2195         {m_params->srFormat, m_srUsage, sr0Width, sr0Height, *m_srImageView[0]},
2196         {m_cbFormat, m_cbUsage, m_cbWidth, m_cbHeight, *m_cbImageView[1]},
2197         {m_params->srFormat, m_srUsage, sr1Width, sr1Height, *m_srImageView[1]},
2198     };
2199     // This would need an additional attachment with m_dsImageView and a barrier to transition the DS layout.
2200     // See runFragmentShaderMode for more details.
2201     DE_ASSERT(!m_params->useDepthStencil());
2202 
2203     Move<VkFramebuffer> framebuffer = buildFramebuffer(device, vk, *renderPass, attachmentInfo);
2204 
2205     beginCommandBuffer(vk, *cmdBuffer, 0u);
2206 
2207     // change sr image layouts to general
2208     VkPipelineStageFlags srcStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
2209     VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
2210     std::vector<VkImageMemoryBarrier> srImageBarrierGeneral(
2211         2, makeImageMemoryBarrier(VK_ACCESS_NONE_KHR, (VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_TRANSFER_WRITE_BIT),
2212                                   VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, **m_srImage[0],
2213                                   m_defaultImageSubresourceRange));
2214     srImageBarrierGeneral[1].image = **m_srImage[1];
2215     vk.cmdPipelineBarrier(*cmdBuffer, srcStageMask, dstStageMask, 0, 0, DE_NULL, 0, DE_NULL, 2,
2216                           srImageBarrierGeneral.data());
2217 
2218     VkClearColorValue clearValues[2] = {{{0, 0, 0, 0}}, {{0, 0, 0, 0}}};
2219     clearValues[0].uint32[0]         = calculateRate(sr0RateWidth, sr0RateHeight);
2220     clearValues[1].uint32[0]         = calculateRate(sr1RateWidth, sr1RateHeight);
2221     vk.cmdClearColorImage(*cmdBuffer, **m_srImage[0], VK_IMAGE_LAYOUT_GENERAL, &clearValues[0], 1,
2222                           &m_defaultImageSubresourceRange);
2223     vk.cmdClearColorImage(*cmdBuffer, **m_srImage[1], VK_IMAGE_LAYOUT_GENERAL, &clearValues[1], 1,
2224                           &m_defaultImageSubresourceRange);
2225 
2226     // wait till sr data is ready and change sr images layout
2227     srcStageMask                = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
2228     dstStageMask                = VK_PIPELINE_STAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR;
2229     memoryBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
2230     memoryBarrier.dstAccessMask = VK_ACCESS_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR;
2231     std::vector<VkImageMemoryBarrier> srImageBarrierShadingRate(
2232         2, makeImageMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR,
2233                                   VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR,
2234                                   **m_srImage[0], m_defaultImageSubresourceRange));
2235     srImageBarrierShadingRate[1].image = **m_srImage[1];
2236     vk.cmdPipelineBarrier(*cmdBuffer, srcStageMask, dstStageMask, 0, 1, &memoryBarrier, 0, DE_NULL, 2,
2237                           srImageBarrierShadingRate.data());
2238 
2239     // wait till cb image layouts are changed
2240     srcStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
2241     dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
2242     std::vector<VkImageMemoryBarrier> cbImageBarrier(
2243         2, makeImageMemoryBarrier(VK_ACCESS_NONE_KHR, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
2244                                   VK_IMAGE_LAYOUT_GENERAL, **m_cbImage[0], m_defaultImageSubresourceRange));
2245     cbImageBarrier[1].image = **m_cbImage[1];
2246     vk.cmdPipelineBarrier(*cmdBuffer, srcStageMask, dstStageMask, 0, 0, DE_NULL, 0, DE_NULL, 2, cbImageBarrier.data());
2247 
2248     startRendering(*cmdBuffer, *renderPass, *framebuffer, makeRect2D(m_cbWidth, m_cbHeight), attachmentInfo);
2249 
2250     // draw single triangle to first cb
2251     vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0, 1,
2252                              &(*m_counterBufferDescriptorSet), 0, DE_NULL);
2253     vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *graphicsPipeline0);
2254     vk.cmdDraw(*cmdBuffer, 3u, 1, 0u, 0u);
2255 
2256     vk.cmdNextSubpass(*cmdBuffer, VK_SUBPASS_CONTENTS_INLINE);
2257 
2258     // draw single triangle to second cb
2259     vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *graphicsPipeline1);
2260     vk.cmdDraw(*cmdBuffer, 3u, 1, 0u, 0u);
2261 
2262     finishRendering(*cmdBuffer);
2263 
2264     // wait till color attachments are fully written
2265     srcStageMask                = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
2266     dstStageMask                = VK_PIPELINE_STAGE_TRANSFER_BIT;
2267     memoryBarrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
2268     memoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
2269     vk.cmdPipelineBarrier(*cmdBuffer, srcStageMask, dstStageMask, 0, 1, &memoryBarrier, 0, DE_NULL, 0, DE_NULL);
2270 
2271     // read back color buffer images
2272     vk.cmdCopyImageToBuffer(*cmdBuffer, **m_cbImage[0], VK_IMAGE_LAYOUT_GENERAL, **m_cbReadBuffer[0], 1u,
2273                             &m_defaultBufferImageCopy);
2274     vk.cmdCopyImageToBuffer(*cmdBuffer, **m_cbImage[1], VK_IMAGE_LAYOUT_GENERAL, **m_cbReadBuffer[1], 1u,
2275                             &m_defaultBufferImageCopy);
2276 
2277     endCommandBuffer(vk, *cmdBuffer);
2278 
2279     // submit commands and wait
2280     const VkQueue queue = m_context.getUniversalQueue();
2281     submitCommandsAndWait(vk, device, queue, cmdBuffer.get());
2282 
2283     // read back buffer with color attachment 1 data
2284     Allocation &cb0BuffAlloc = m_cbReadBuffer[0]->getAllocation();
2285     invalidateAlloc(vk, device, cb0BuffAlloc);
2286 
2287     // read back buffer with color attachment 2 data
2288     Allocation &cb1BuffAlloc = m_cbReadBuffer[1]->getAllocation();
2289     invalidateAlloc(vk, device, cb1BuffAlloc);
2290 
2291     // validate both attachemtns triangle
2292     return (verifyUsingAtomicChecks(m_minTileSize.width, m_minTileSize.height, sr0RateWidth, sr0RateHeight,
2293                                     (uint32_t *)m_cbReadBuffer[0]->getAllocation().getHostPtr()) &&
2294             verifyUsingAtomicChecks(m_maxTileSize.width, m_maxTileSize.height, sr1RateWidth, sr1RateHeight,
2295                                     (uint32_t *)m_cbReadBuffer[1]->getAllocation().getHostPtr()));
2296 }
2297 
2298 class AttachmentRateTestCase : public TestCase
2299 {
2300 public:
2301     AttachmentRateTestCase(tcu::TestContext &context, const char *name, de::SharedPtr<TestParams> params);
2302     ~AttachmentRateTestCase(void) = default;
2303 
2304     void initPrograms(SourceCollections &programCollection) const override;
2305     TestInstance *createInstance(Context &context) const override;
2306     void checkSupport(Context &context) const override;
2307 
2308 private:
2309     const de::SharedPtr<TestParams> m_params;
2310 };
2311 
AttachmentRateTestCase(tcu::TestContext & context,const char * name,de::SharedPtr<TestParams> params)2312 AttachmentRateTestCase::AttachmentRateTestCase(tcu::TestContext &context, const char *name,
2313                                                de::SharedPtr<TestParams> params)
2314     : vkt::TestCase(context, name)
2315     , m_params(params)
2316 {
2317 }
2318 
checkSupport(Context & context) const2319 void AttachmentRateTestCase::checkSupport(Context &context) const
2320 {
2321     context.requireDeviceFunctionality("VK_KHR_fragment_shading_rate");
2322 
2323     if (m_params->useDynamicRendering)
2324         context.requireDeviceFunctionality("VK_KHR_dynamic_rendering");
2325     if (m_params->useImagelessFramebuffer)
2326         context.requireDeviceFunctionality("VK_KHR_imageless_framebuffer");
2327 
2328     if (!context.getFragmentShadingRateFeatures().attachmentFragmentShadingRate)
2329         TCU_THROW(NotSupportedError, "attachmentFragmentShadingRate not supported");
2330 
2331     const vk::InstanceInterface &vk = context.getInstanceInterface();
2332     const vk::VkPhysicalDevice pd   = context.getPhysicalDevice();
2333 
2334     VkImageFormatProperties imageProperties;
2335     VkImageUsageFlags srUsage =
2336         VK_IMAGE_USAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
2337 
2338     VkResult result = vk.getPhysicalDeviceImageFormatProperties(pd, m_params->srFormat, VK_IMAGE_TYPE_2D,
2339                                                                 VK_IMAGE_TILING_OPTIMAL, srUsage, 0, &imageProperties);
2340     if (result == VK_ERROR_FORMAT_NOT_SUPPORTED)
2341         TCU_THROW(NotSupportedError, "Format not supported");
2342 
2343     if (m_params->mode != TM_TWO_SUBPASS)
2344     {
2345         uint32_t supportedFragmentShadingRateCount;
2346         VkExtent2D testedRate = m_params->srRate;
2347         std::vector<VkPhysicalDeviceFragmentShadingRateKHR> supportedFragmentShadingRates;
2348 
2349         // fetch information about supported rates
2350         vk.getPhysicalDeviceFragmentShadingRatesKHR(pd, &supportedFragmentShadingRateCount, DE_NULL);
2351         supportedFragmentShadingRates.resize(
2352             supportedFragmentShadingRateCount,
2353             {
2354                 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_KHR, // VkStructureType sType;
2355                 DE_NULL,                                                     // void* pNext;
2356                 VK_SAMPLE_COUNT_1_BIT,                                       // VkSampleCountFlags sampleCounts;
2357                 {0, 0}                                                       // VkExtent2D fragmentSize;
2358             });
2359         vk.getPhysicalDeviceFragmentShadingRatesKHR(pd, &supportedFragmentShadingRateCount,
2360                                                     &supportedFragmentShadingRates[0]);
2361 
2362         // check if rate required by test is not supported
2363         if (std::none_of(supportedFragmentShadingRates.begin(), supportedFragmentShadingRates.end(),
2364                          [&testedRate](const VkPhysicalDeviceFragmentShadingRateKHR &r) {
2365                              return (r.fragmentSize.width == testedRate.width &&
2366                                      r.fragmentSize.height == testedRate.height);
2367                          }))
2368         {
2369             TCU_THROW(NotSupportedError, "Rate not supported");
2370         }
2371     }
2372 
2373     if (m_params->mode == TM_MAINTENANCE_5)
2374         context.requireDeviceFunctionality("VK_KHR_maintenance5");
2375 
2376     VkFormatFeatureFlags requiredFeatures = 0;
2377     if (m_params->mode == TM_SETUP_RATE_WITH_ATOMICS_IN_COMPUTE_SHADER)
2378         requiredFeatures =
2379             VK_FORMAT_FEATURE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR | VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT;
2380     else if ((m_params->mode == TM_SETUP_RATE_WITH_COPYING_FROM_OTHER_IMAGE) ||
2381              (m_params->mode == TM_SETUP_RATE_WITH_COPYING_FROM_EXCLUSIVE_IMAGE_USING_TRANSFER_QUEUE) ||
2382              (m_params->mode == TM_SETUP_RATE_WITH_COPYING_FROM_CONCURENT_IMAGE_USING_TRANSFER_QUEUE) ||
2383              (m_params->mode == TM_SETUP_RATE_WITH_LINEAR_TILED_IMAGE))
2384         requiredFeatures = VK_FORMAT_FEATURE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR;
2385     else if (m_params->mode == TM_SETUP_RATE_WITH_FRAGMENT_SHADER)
2386         requiredFeatures =
2387             VK_FORMAT_FEATURE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT;
2388 
2389 #if DEBUG_USE_STORE_INSTEAD_OF_ATOMICS == 1
2390     if (m_params->mode == TM_SETUP_RATE_WITH_ATOMICS_IN_COMPUTE_SHADER)
2391         requiredFeatures =
2392             VK_FORMAT_FEATURE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT;
2393 #endif
2394 
2395     if (requiredFeatures)
2396     {
2397         const VkFormatProperties formatProperties = getPhysicalDeviceFormatProperties(vk, pd, m_params->srFormat);
2398 
2399         if (m_params->mode == TM_SETUP_RATE_WITH_LINEAR_TILED_IMAGE)
2400         {
2401             if ((formatProperties.linearTilingFeatures & requiredFeatures) != requiredFeatures)
2402                 TCU_THROW(NotSupportedError, "Required format feature bits not supported");
2403         }
2404         else if ((formatProperties.optimalTilingFeatures & requiredFeatures) != requiredFeatures)
2405             TCU_THROW(NotSupportedError, "Required format feature bits not supported");
2406     }
2407 
2408     if (m_params->useDepthStencil())
2409     {
2410         const auto dsFormat                         = m_params->getDSFormat();
2411         const VkFormatProperties dsFormatProperties = getPhysicalDeviceFormatProperties(vk, pd, dsFormat);
2412 
2413         if ((dsFormatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) == 0)
2414         {
2415             std::ostringstream msg;
2416             msg << dsFormat << " not supported";
2417             TCU_THROW(NotSupportedError, msg.str());
2418         }
2419     }
2420 }
2421 
initPrograms(SourceCollections & programCollection) const2422 void AttachmentRateTestCase::initPrograms(SourceCollections &programCollection) const
2423 {
2424     uint32_t rateValue = calculateRate(m_params->srRate.width, m_params->srRate.height);
2425 
2426     if (m_params->mode == TM_SETUP_RATE_WITH_ATOMICS_IN_COMPUTE_SHADER)
2427     {
2428         std::stringstream compStream;
2429         compStream << "#version 450\n"
2430                       "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
2431                       "layout(r32ui, binding = 0) coherent uniform highp uimage2D srImage;\n"
2432                       "void main (void)\n"
2433                       "{\n"
2434 #if DEBUG_USE_STORE_INSTEAD_OF_ATOMICS == 1
2435                       "  imageStore(srImage, ivec2(gl_GlobalInvocationID.xy), uvec4("
2436                    << rateValue
2437                    << "));\n"
2438 #else
2439                       "  imageAtomicAdd(srImage, ivec2(gl_GlobalInvocationID.xy), "
2440                    << rateValue
2441                    << ");\n"
2442 #endif
2443                       "}\n";
2444 
2445         programCollection.glslSources.add("comp") << glu::ComputeSource(compStream.str());
2446     }
2447 
2448     tcu::StringTemplate vertTemplate(
2449         "#version 450 core\n"
2450         "out gl_PerVertex\n"
2451         "{\n"
2452         "  vec4 gl_Position;\n"
2453         "};\n"
2454         "void main()\n"
2455         "{\n"
2456         "  gl_Position = vec4(float(1.0 - 2.0 * int(gl_VertexIndex != 1)) * ${SCALE} + ${TRANSLATE},\n"
2457         "                     float(1.0 - 2.0 * int(gl_VertexIndex > 0))  * ${SCALE} + ${TRANSLATE}, 0.0, 1.0);\n"
2458         "}\n");
2459 
2460     std::map<std::string, std::string> specializationMap{
2461         {"SCALE", "0.8"},
2462         {"TRANSLATE", "0.0"},
2463     };
2464 
2465     if (m_params->mode == TM_TWO_SUBPASS)
2466     {
2467         specializationMap["SCALE"]     = "0.4";
2468         specializationMap["TRANSLATE"] = "-0.5";
2469         programCollection.glslSources.add("vert0") << glu::VertexSource(vertTemplate.specialize(specializationMap));
2470 
2471         specializationMap["SCALE"]     = "0.4";
2472         specializationMap["TRANSLATE"] = "0.5";
2473         programCollection.glslSources.add("vert1") << glu::VertexSource(vertTemplate.specialize(specializationMap));
2474     }
2475     else
2476     {
2477         programCollection.glslSources.add("vert") << glu::VertexSource(vertTemplate.specialize(specializationMap));
2478     }
2479 
2480     if ((m_params->mode == TM_SETUP_RATE_WITH_FRAGMENT_SHADER) || (m_params->mode == TM_MEMORY_ACCESS) ||
2481         (m_params->mode == TM_MAINTENANCE_5))
2482     {
2483         // use large triangle that will cover whole color buffer
2484         specializationMap["SCALE"]     = "9.0";
2485         specializationMap["TRANSLATE"] = "0.0";
2486         programCollection.glslSources.add("vert_setup")
2487             << glu::VertexSource(vertTemplate.specialize(specializationMap));
2488 
2489         std::stringstream fragStream;
2490         fragStream << "#version 450 core\n"
2491                       "layout(location = 0) out uint outColor;\n"
2492                       "void main()\n"
2493                       "{\n"
2494                       "  outColor.x = "
2495                    << rateValue
2496                    << ";\n"
2497                       "}\n";
2498         programCollection.glslSources.add("frag_setup") << glu::FragmentSource(fragStream.str());
2499     }
2500 
2501     std::string frag = "#version 450 core\n"
2502                        "#extension GL_EXT_fragment_shading_rate : enable\n"
2503                        "layout(set = 0, binding = 0) buffer Block { uint counter; } buf;\n"
2504                        "layout(location = 0) out uvec4 outColor;\n"
2505                        "void main()\n"
2506                        "{\n"
2507                        "  outColor.x = gl_ShadingRateEXT;\n"
2508                        "  outColor.y = 0;\n"
2509                        "  outColor.z = atomicAdd(buf.counter, 1);\n"
2510                        "  outColor.w = 0;\n"
2511                        "}\n";
2512     programCollection.glslSources.add("frag") << glu::FragmentSource(frag);
2513 }
2514 
createInstance(Context & context) const2515 TestInstance *AttachmentRateTestCase::createInstance(Context &context) const
2516 {
2517     return new AttachmentRateInstance(context, m_params);
2518 }
2519 
2520 } // namespace
2521 
createAttachmentRateTests(tcu::TestContext & testCtx,tcu::TestCaseGroup * parentGroup,SharedGroupParams groupParams)2522 void createAttachmentRateTests(tcu::TestContext &testCtx, tcu::TestCaseGroup *parentGroup,
2523                                SharedGroupParams groupParams)
2524 {
2525     struct SRFormat
2526     {
2527         VkFormat format;
2528         const char *name;
2529     };
2530 
2531     const std::vector<SRFormat> srFormats{
2532         {VK_FORMAT_R8_UINT, "r8_uint"},
2533         {VK_FORMAT_R8G8_UINT, "r8g8_uint"},
2534         {VK_FORMAT_R8G8B8_UINT, "r8g8b8_uint"},
2535         {VK_FORMAT_R8G8B8A8_UINT, "r8g8b8a8_uint"},
2536         {VK_FORMAT_R16_UINT, "r16_uint"},
2537         {VK_FORMAT_R16G16_UINT, "r16g16_uint"},
2538         {VK_FORMAT_R16G16B16_UINT, "r16g16b16_uint"},
2539         {VK_FORMAT_R16G16B16A16_UINT, "r16g16b16a16_uint"},
2540         {VK_FORMAT_R32_UINT, "r32_uint"},
2541         {VK_FORMAT_R32G32_UINT, "r32g32_uint"},
2542         {VK_FORMAT_R32G32B32_UINT, "r32g32b32_uint"},
2543         {VK_FORMAT_R32G32B32A32_UINT, "r32g32b32a32_uint"},
2544         {VK_FORMAT_R64_UINT, "r64_uint"},
2545         {VK_FORMAT_R64G64_UINT, "r64g64_uint"},
2546         {VK_FORMAT_R64G64B64_UINT, "r64g64b64_uint"},
2547         {VK_FORMAT_R64G64B64A64_UINT, "r64g64b64a64_uint"},
2548     };
2549 
2550     struct SRRate
2551     {
2552         VkExtent2D count;
2553         const char *name;
2554     };
2555 
2556     const std::vector<SRRate> srRates{
2557         {{1, 1}, "rate_1x1"}, {{1, 2}, "rate_1x2"}, {{1, 4}, "rate_1x4"}, {{2, 1}, "rate_2x1"}, {{2, 2}, "rate_2x2"},
2558         {{2, 4}, "rate_2x4"}, {{4, 1}, "rate_4x1"}, {{4, 2}, "rate_4x2"}, {{4, 4}, "rate_4x4"},
2559     };
2560 
2561     struct TestModeParam
2562     {
2563         TestMode mode;
2564         const char *name;
2565     };
2566 
2567     const std::vector<TestModeParam> testModeParams{
2568         {TM_SETUP_RATE_WITH_ATOMICS_IN_COMPUTE_SHADER, "setup_with_atomics"},
2569         {TM_SETUP_RATE_WITH_FRAGMENT_SHADER, "setup_with_fragment"},
2570         {TM_SETUP_RATE_WITH_COPYING_FROM_OTHER_IMAGE, "setup_with_copying"},
2571         {TM_SETUP_RATE_WITH_COPYING_FROM_CONCURENT_IMAGE_USING_TRANSFER_QUEUE,
2572          "setup_with_copying_using_transfer_queue_concurent"},
2573         {TM_SETUP_RATE_WITH_COPYING_FROM_EXCLUSIVE_IMAGE_USING_TRANSFER_QUEUE,
2574          "setup_with_copying_using_transfer_queue_exclusive"},
2575         {TM_SETUP_RATE_WITH_LINEAR_TILED_IMAGE, "setup_with_linear_tiled_image"},
2576     };
2577 
2578     de::MovePtr<tcu::TestCaseGroup> mainGroup(new tcu::TestCaseGroup(testCtx, "attachment_rate"));
2579 
2580     for (const auto &testModeParam : testModeParams)
2581     {
2582         de::MovePtr<tcu::TestCaseGroup> testModeGroup(new tcu::TestCaseGroup(testCtx, testModeParam.name));
2583 
2584         for (const auto &srFormat : srFormats)
2585         {
2586             de::MovePtr<tcu::TestCaseGroup> formatGroup(new tcu::TestCaseGroup(testCtx, srFormat.name));
2587             for (const auto &srRate : srRates)
2588             {
2589                 formatGroup->addChild(
2590                     new AttachmentRateTestCase(testCtx, srRate.name,
2591                                                de::SharedPtr<TestParams>(new TestParams{
2592                                                    testModeParam.mode,               // TestMode mode;
2593                                                    srFormat.format,                  // VkFormat srFormat;
2594                                                    srRate.count,                     // VkExtent2D srRate;
2595                                                    groupParams->useDynamicRendering, // bool useDynamicRendering;
2596                                                    false,                            // bool useImagelessFramebuffer;
2597                                                    false,                            // bool useNullShadingRateImage;
2598                                                    tcu::Nothing,                     // OptDSParams dsParams;
2599                                                })));
2600 
2601                 if (groupParams->useDynamicRendering)
2602                 {
2603                     // Duplicate all tests using dynamic rendering for NULL shading image.
2604                     std::string nullShadingName = std::string(srRate.name) + "_null_shading";
2605                     formatGroup->addChild(new AttachmentRateTestCase(testCtx, nullShadingName.c_str(),
2606                                                                      de::SharedPtr<TestParams>(new TestParams{
2607                                                                          testModeParam.mode, // TestMode mode;
2608                                                                          srFormat.format,    // VkFormat srFormat;
2609                                                                          srRate.count,       // VkExtent2D srRate;
2610                                                                          false,        // bool useDynamicRendering;
2611                                                                          false,        // bool useImagelessFramebuffer;
2612                                                                          true,         // bool useNullShadingRateImage;
2613                                                                          tcu::Nothing, // OptDSParams dsParams;
2614                                                                      })));
2615                 }
2616 
2617                 if (!groupParams->useDynamicRendering)
2618                 {
2619                     // duplicate all tests for imageless framebuffer
2620                     std::string imagelessName = std::string(srRate.name) + "_imageless";
2621                     formatGroup->addChild(new AttachmentRateTestCase(testCtx, imagelessName.c_str(),
2622                                                                      de::SharedPtr<TestParams>(new TestParams{
2623                                                                          testModeParam.mode, // TestMode mode;
2624                                                                          srFormat.format,    // VkFormat srFormat;
2625                                                                          srRate.count,       // VkExtent2D srRate;
2626                                                                          false,        // bool useDynamicRendering;
2627                                                                          true,         // bool useImagelessFramebuffer;
2628                                                                          false,        // bool useNullShadingRateImage;
2629                                                                          tcu::Nothing, // OptDSParams dsParams;
2630                                                                      })));
2631                 }
2632             }
2633 
2634             testModeGroup->addChild(formatGroup.release());
2635         }
2636 
2637         mainGroup->addChild(testModeGroup.release());
2638     }
2639 
2640     de::MovePtr<tcu::TestCaseGroup> miscGroup(new tcu::TestCaseGroup(testCtx, "misc"));
2641     if (!groupParams->useDynamicRendering)
2642     {
2643         miscGroup->addChild(new AttachmentRateTestCase(
2644             testCtx, "two_subpass",
2645             de::SharedPtr<TestParams>(new TestParams{
2646                 TM_TWO_SUBPASS,    // TestMode mode;
2647                 VK_FORMAT_R8_UINT, // VkFormat srFormat;
2648                 {0, 0},            // VkExtent2D        srRate;                    // not used in TM_TWO_SUBPASS
2649                 false,             // bool useDynamicRendering;
2650                 false,             // bool useImagelessFramebuffer;
2651                 false,             // bool useNullShadingRateImage;
2652                 tcu::Nothing,      // OptDSParams dsParams;
2653             })));
2654         miscGroup->addChild(new AttachmentRateTestCase(testCtx, "memory_access",
2655                                                        de::SharedPtr<TestParams>(new TestParams{
2656                                                            TM_MEMORY_ACCESS,  // TestMode mode;
2657                                                            VK_FORMAT_R8_UINT, // VkFormat srFormat;
2658                                                            {1, 1},            // VkExtent2D srRate;
2659                                                            false,             // bool useDynamicRendering;
2660                                                            false,             // bool useImagelessFramebuffer;
2661                                                            false,             // bool useNullShadingRateImage;
2662                                                            tcu::Nothing,      // OptDSParams dsParams;
2663                                                        })));
2664         {
2665             const VkImageLayout testedLayouts[] = {
2666                 VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL_KHR,
2667                 VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL,
2668                 VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL,
2669                 VK_IMAGE_LAYOUT_GENERAL,
2670             };
2671 
2672             const auto skip = strlen("VK_IMAGE_LAYOUT_");
2673 
2674             for (const auto &layout : testedLayouts)
2675             {
2676                 const auto dsFormat =
2677                     ((layout == VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL) ? VK_FORMAT_S8_UINT : VK_FORMAT_D16_UNORM);
2678                 const std::string layoutName = de::toLower(de::toString(layout).substr(skip));
2679                 const std::string testName   = "ro_ds_" + layoutName;
2680 
2681                 miscGroup->addChild(
2682                     new AttachmentRateTestCase(testCtx, testName.c_str(),
2683                                                de::SharedPtr<TestParams>(new TestParams{
2684                                                    TM_MEMORY_ACCESS,  // TestMode mode;
2685                                                    VK_FORMAT_R8_UINT, // VkFormat srFormat;
2686                                                    {2, 2},            // VkExtent2D srRate;
2687                                                    false,             // bool useDynamicRendering;
2688                                                    false,             // bool useImagelessFramebuffer;
2689                                                    false,             // bool useNullShadingRateImage;
2690                                                    DepthStencilParams{dsFormat, layout}, // OptDSParams dsParams;
2691                                                })));
2692             }
2693         }
2694     }
2695     else
2696     {
2697 #ifndef CTS_USES_VULKANSC
2698         miscGroup->addChild(new AttachmentRateTestCase(testCtx, "maintenance5",
2699                                                        de::SharedPtr<TestParams>(new TestParams{
2700                                                            TM_MAINTENANCE_5,  // TestMode mode;
2701                                                            VK_FORMAT_R8_UINT, // VkFormat srFormat;
2702                                                            {1, 1},            // VkExtent2D srRate;
2703                                                            true,              // bool useDynamicRendering;
2704                                                            false,             // bool useImagelessFramebuffer;
2705                                                            false,             // bool useNullShadingRateImage;
2706                                                            tcu::Nothing       // OptDSParams dsParams;
2707                                                        })));
2708 #endif
2709     }
2710     if (!miscGroup->empty())
2711         mainGroup->addChild(miscGroup.release());
2712 
2713     parentGroup->addChild(mainGroup.release());
2714 }
2715 
2716 } // namespace FragmentShadingRate
2717 } // namespace vkt
2718