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::__anon16891c1b0111::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::__anon16891c1b0111::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::__anon16891c1b0111::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::__anon16891c1b0111::TestParams123 VkImageLayout getDSLayout(void) const
124 {
125 return (hasDSParams() ? dsParams->layout : VK_IMAGE_LAYOUT_UNDEFINED);
126 }
127
128 private:
hasDSParamsvkt::FragmentShadingRate::__anon16891c1b0111::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;
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) 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) const
913 {
914 const DeviceInterface &vk(m_context.getDeviceInterface());
915 std::vector<VkClearValue> clearColor(attachmentInfo.size(), makeClearValueColorU32(0, 0, 0, 0));
916
917 #ifndef CTS_USES_VULKANSC
918 if (m_params->useDynamicRendering)
919 {
920 VkRenderingFragmentShadingRateAttachmentInfoKHR shadingRateAttachmentInfo{
921 VK_STRUCTURE_TYPE_RENDERING_FRAGMENT_SHADING_RATE_ATTACHMENT_INFO_KHR, // VkStructureType sType;
922 DE_NULL, // const void* pNext;
923 DE_NULL, // VkImageView imageView;
924 VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR, // VkImageLayout imageLayout;
925 {0, 0} // VkExtent2D shadingRateAttachmentTexelSize;
926 };
927
928 VkRenderingAttachmentInfoKHR colorAttachment{
929 vk::VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR, // VkStructureType sType;
930 DE_NULL, // const void* pNext;
931 attachmentInfo[0].view, // VkImageView imageView;
932 VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout imageLayout;
933 VK_RESOLVE_MODE_NONE, // VkResolveModeFlagBits resolveMode;
934 DE_NULL, // VkImageView resolveImageView;
935 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout resolveImageLayout;
936 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp;
937 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
938 clearColor[0] // VkClearValue clearValue;
939 };
940
941 VkRenderingInfoKHR renderingInfo{
942 vk::VK_STRUCTURE_TYPE_RENDERING_INFO_KHR,
943 DE_NULL,
944 0, // VkRenderingFlagsKHR flags;
945 renderArea, // VkRect2D renderArea;
946 1u, // uint32_t layerCount;
947 0u, // uint32_t viewMask;
948 1u, // uint32_t colorAttachmentCount;
949 &colorAttachment, // const VkRenderingAttachmentInfoKHR* pColorAttachments;
950 DE_NULL, // const VkRenderingAttachmentInfoKHR* pDepthAttachment;
951 DE_NULL, // const VkRenderingAttachmentInfoKHR* pStencilAttachment;
952 };
953
954 // when shading rate is used it is defined as a second entry in attachmentInfo
955 if ((attachmentInfo.size() == 2) &&
956 (attachmentInfo[1].usage & VK_IMAGE_USAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR))
957 {
958 if (!m_params->useNullShadingRateImage)
959 {
960 shadingRateAttachmentInfo.imageView = attachmentInfo[1].view;
961 }
962
963 shadingRateAttachmentInfo.shadingRateAttachmentTexelSize = {srTileWidth, srTileHeight};
964 renderingInfo.pNext = &shadingRateAttachmentInfo;
965 }
966
967 vk.cmdBeginRendering(commandBuffer, &renderingInfo);
968
969 return;
970 }
971 #else
972 DE_UNREF(srTileWidth);
973 DE_UNREF(srTileHeight);
974 #endif // CTS_USES_VULKANSC
975
976 std::vector<VkImageView> attachments(attachmentInfo.size(), 0);
977 VkRenderPassAttachmentBeginInfo renderPassAttachmentBeginInfo;
978 void *pNext(DE_NULL);
979
980 if (m_params->useImagelessFramebuffer)
981 {
982 // create array containing attachment views
983 for (uint32_t i = 0; i < (uint32_t)attachmentInfo.size(); ++i)
984 attachments[i] = attachmentInfo[i].view;
985
986 renderPassAttachmentBeginInfo = {
987 VK_STRUCTURE_TYPE_RENDER_PASS_ATTACHMENT_BEGIN_INFO, // VkStructureType sType;
988 DE_NULL, // const void* pNext;
989 (uint32_t)attachments.size(), // uint32_t attachmentCount;
990 attachments.data() // const VkImageView* pAttachments;
991 };
992
993 pNext = &renderPassAttachmentBeginInfo;
994 }
995
996 beginRenderPass(vk, commandBuffer, renderPass, framebuffer, renderArea, (uint32_t)clearColor.size(),
997 clearColor.data(), VK_SUBPASS_CONTENTS_INLINE, pNext);
998 }
999
finishRendering(const VkCommandBuffer commandBuffer) const1000 void AttachmentRateInstance::finishRendering(const VkCommandBuffer commandBuffer) const
1001 {
1002 const DeviceInterface &vk = m_context.getDeviceInterface();
1003
1004 #ifndef CTS_USES_VULKANSC
1005 if (m_params->useDynamicRendering)
1006 endRendering(vk, commandBuffer);
1007 else
1008 #endif // CTS_USES_VULKANSC
1009 endRenderPass(vk, commandBuffer);
1010 }
1011
iterate(void)1012 tcu::TestStatus AttachmentRateInstance::iterate(void)
1013 {
1014 // instead of creating many classes that derive from large common class
1015 // each test mode is defined in separate run* method, those methods
1016 // then use same helper methods defined in this class
1017
1018 typedef bool (AttachmentRateInstance::*MethodPtr)();
1019 const std::map<TestMode, MethodPtr> modeFuncMap{
1020 {TM_SETUP_RATE_WITH_ATOMICS_IN_COMPUTE_SHADER, &AttachmentRateInstance::runComputeShaderMode},
1021 {TM_SETUP_RATE_WITH_FRAGMENT_SHADER, &AttachmentRateInstance::runFragmentShaderMode},
1022 {TM_SETUP_RATE_WITH_COPYING_FROM_OTHER_IMAGE, &AttachmentRateInstance::runCopyMode},
1023 {TM_SETUP_RATE_WITH_COPYING_FROM_EXCLUSIVE_IMAGE_USING_TRANSFER_QUEUE,
1024 &AttachmentRateInstance::runCopyModeOnTransferQueue},
1025 {TM_SETUP_RATE_WITH_COPYING_FROM_CONCURENT_IMAGE_USING_TRANSFER_QUEUE,
1026 &AttachmentRateInstance::runCopyModeOnTransferQueue},
1027 {TM_SETUP_RATE_WITH_LINEAR_TILED_IMAGE, &AttachmentRateInstance::runFillLinearTiledImage},
1028 {TM_TWO_SUBPASS, &AttachmentRateInstance::runTwoSubpassMode},
1029 {TM_MEMORY_ACCESS, &AttachmentRateInstance::runFragmentShaderMode},
1030 {TM_MAINTENANCE_5, &AttachmentRateInstance::runFragmentShaderMode},
1031 };
1032
1033 if ((this->*modeFuncMap.at(m_params->mode))())
1034 return tcu::TestStatus::pass("Pass");
1035
1036 return tcu::TestStatus::fail("Fail");
1037 }
1038
verifyUsingAtomicChecks(uint32_t tileWidth,uint32_t tileHeight,uint32_t rateWidth,uint32_t rateHeight,uint32_t * outBufferPtr) const1039 bool AttachmentRateInstance::verifyUsingAtomicChecks(uint32_t tileWidth, uint32_t tileHeight, uint32_t rateWidth,
1040 uint32_t rateHeight, uint32_t *outBufferPtr) const
1041 {
1042 tcu::TestLog &log(m_context.getTestContext().getLog());
1043 tcu::TextureLevel errorMaskStorage(tcu::TextureFormat(tcu::TextureFormat::RGB, tcu::TextureFormat::UNORM_INT8),
1044 m_cbWidth, m_cbHeight, 1u);
1045 tcu::PixelBufferAccess errorMaskAccess(errorMaskStorage.getAccess());
1046
1047 uint32_t wrongFragments = 0;
1048 const uint32_t fragmentsWithSameAtomicValueCount = rateWidth * rateHeight;
1049
1050 // map that uses atomic value as a kay and maps it to all fragments sharing same atomic
1051 std::map<uint32_t, std::vector<tcu::UVec2>> fragmentsWithSameAtomicValueMap;
1052
1053 // this method asumes that top and left edge of triangle are parallel to axes
1054 // and we can store just single coordinate for those edges
1055 uint32_t triangleLeftEdgeX = 0;
1056 uint32_t triangleTopEdgeY = 0;
1057
1058 // this method assumes that greatest angle in the triangle points to the top-left corner of FB;
1059 // these vectors will then store fragments on the right and bottom edges of triangle respectively;
1060 // for the right edge vector, the index represents y coordinate and value is x;
1061 // for the bottom edge vector, the index represents x coordinate and value is y
1062 std::vector<uint32_t> fragmentsOnTheRightTriangleEdgeVect(m_cbHeight, 0);
1063 std::vector<uint32_t> fragmentsOnTheBottomTriangleEdgeVect(m_cbWidth, 0);
1064
1065 tcu::clear(errorMaskAccess, tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0));
1066
1067 // loop over all fragments and validate the output
1068 for (uint32_t cbFragmentY = 0; cbFragmentY < m_cbHeight; ++cbFragmentY)
1069 for (uint32_t cbFragmentX = 0; cbFragmentX < m_cbWidth; ++cbFragmentX)
1070 {
1071 uint32_t *fragmentColor = &outBufferPtr[4 * (cbFragmentY * m_cbWidth + cbFragmentX)];
1072
1073 // fragment not covered by primitive, skip it
1074 if (fragmentColor[2] == 0)
1075 continue;
1076
1077 // first fragment we hit will define top and left triangle edges
1078 if ((triangleTopEdgeY + triangleLeftEdgeX) == 0)
1079 {
1080 triangleLeftEdgeX = cbFragmentX;
1081 triangleTopEdgeY = cbFragmentY;
1082 }
1083
1084 // constantly overwrite coordinate on right edge so that we are left with the farthest one
1085 fragmentsOnTheRightTriangleEdgeVect[cbFragmentY] = cbFragmentX;
1086
1087 // constantly overwrite coordinate on bottom edge so that we are left with the farthest one
1088 fragmentsOnTheBottomTriangleEdgeVect[cbFragmentX] = cbFragmentY;
1089
1090 // make sure that fragment g and a components are 0
1091 if ((fragmentColor[1] != 0) || (fragmentColor[3] != 0))
1092 {
1093 ++wrongFragments;
1094 continue;
1095 }
1096
1097 uint32_t rate = fragmentColor[0];
1098 uint32_t fragmentRateX = 1 << ((rate / 4) & 3);
1099 uint32_t fragmentRateY = 1 << (rate & 3);
1100
1101 // check if proper rate was used for fragment
1102 if ((fragmentRateX != rateWidth) || (fragmentRateY != rateHeight))
1103 {
1104 ++wrongFragments;
1105 errorMaskAccess.setPixel(tcu::Vec4(1.0f, 0.5f, 0.0f, 1.0f), cbFragmentX, cbFragmentY, 0u);
1106 continue;
1107 }
1108
1109 // mark correct fragments using few green shades so rates are visible
1110 uint32_t atomicValue = fragmentColor[2];
1111 errorMaskAccess.setPixel(tcu::Vec4(0.0f, 1.0f - float(atomicValue % 7) * 0.1f, 0.0f, 1.0f), cbFragmentX,
1112 cbFragmentY, 0u);
1113
1114 // find proper set in map and add value to it after doing verification with existing items
1115 auto fragmentsSetMapIt = fragmentsWithSameAtomicValueMap.find(atomicValue);
1116 if (fragmentsSetMapIt == fragmentsWithSameAtomicValueMap.end())
1117 {
1118 fragmentsWithSameAtomicValueMap[atomicValue] = {tcu::UVec2(cbFragmentX, cbFragmentY)};
1119 fragmentsWithSameAtomicValueMap[atomicValue].reserve(fragmentsWithSameAtomicValueCount);
1120 }
1121 else
1122 {
1123 // make sure that fragments added to set are near the top-left fragment
1124 auto &fragmentsSet = fragmentsSetMapIt->second;
1125 if (((cbFragmentX - fragmentsSet[0].x()) > rateWidth) ||
1126 ((cbFragmentY - fragmentsSet[0].y()) > rateHeight))
1127 {
1128 ++wrongFragments;
1129 errorMaskAccess.setPixel(tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f), cbFragmentX, cbFragmentY, 0u);
1130 }
1131
1132 fragmentsWithSameAtomicValueMap[atomicValue].emplace_back(cbFragmentX, cbFragmentY);
1133 }
1134 }
1135
1136 // check if there are no valid fragmenst at all
1137 if ((triangleTopEdgeY + triangleLeftEdgeX) == 0)
1138 {
1139 log << tcu::TestLog::Message << "No valid fragments." << tcu::TestLog::EndMessage;
1140 return false;
1141 }
1142
1143 // if checks failed skip checking other tile sizes
1144 if (wrongFragments)
1145 {
1146 log << tcu::TestLog::Message << "Failed " << wrongFragments << " fragments for tileWidth: " << tileWidth
1147 << ", tileHeight: " << tileHeight << tcu::TestLog::EndMessage
1148 << tcu::TestLog::Image("ErrorMask", "Error mask", errorMaskAccess);
1149 return false;
1150 }
1151
1152 // do additional checks
1153 tcu::Vec4 fragmentColor(0.0f, 1.0f, 0.0f, 1.0f);
1154
1155 tcu::clear(errorMaskAccess, tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0));
1156
1157 // make sure that there is same number of fragments that share same atomic value
1158 for (auto &fragmentsSetMapIt : fragmentsWithSameAtomicValueMap)
1159 {
1160 // mark correct fragments using few green shades so rates are visible
1161 fragmentColor = tcu::Vec4(0.0f, 1.0f - float(fragmentsSetMapIt.first % 7) * 0.1f, 0.0f, 1.0f);
1162
1163 const auto &fragmentSet = fragmentsSetMapIt.second;
1164 ;
1165 if (fragmentSet.size() != fragmentsWithSameAtomicValueCount)
1166 {
1167 const auto &topLeftFragment = fragmentSet[0];
1168 uint32_t triangleRightEdgeX = fragmentsOnTheRightTriangleEdgeVect[topLeftFragment.y()];
1169 uint32_t triangleBottomEdgeY = fragmentsOnTheBottomTriangleEdgeVect[topLeftFragment.x()];
1170
1171 // we can only count this as an error if set is fully inside of triangle, sets on
1172 // edges may not have same number of fragments as sets fully located in the triangle
1173 if ((topLeftFragment.y() > (triangleTopEdgeY)) && (topLeftFragment.x() > (triangleLeftEdgeX)) &&
1174 (topLeftFragment.x() < (triangleRightEdgeX - rateWidth)) &&
1175 (topLeftFragment.y() < (triangleBottomEdgeY - rateHeight)))
1176 {
1177 wrongFragments += (uint32_t)fragmentSet.size();
1178 fragmentColor = tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f);
1179 }
1180 }
1181
1182 // mark all fragmens from set with proper color
1183 for (auto &fragment : fragmentSet)
1184 errorMaskAccess.setPixel(fragmentColor, fragment.x(), fragment.y(), 0u);
1185 }
1186
1187 if (wrongFragments)
1188 {
1189 log << tcu::TestLog::Message << "Wrong number of fragments with same atomic value (" << wrongFragments
1190 << ") for tileWidth: " << tileWidth << ", tileHeight: " << tileHeight << tcu::TestLog::EndMessage
1191 << tcu::TestLog::Image("ErrorMask", "Error mask", errorMaskAccess);
1192 return false;
1193 }
1194
1195 return true;
1196 }
1197
runComputeShaderMode(void)1198 bool AttachmentRateInstance::runComputeShaderMode(void)
1199 {
1200 // clear the shading rate attachment, then using a compute shader, set the shading rate attachment
1201 // values to the desired rate using various atomic operations, then use it to draw a basic triangle
1202 // and do basic checks
1203
1204 const DeviceInterface &vk = m_context.getDeviceInterface();
1205 VkDevice device = m_context.getDevice();
1206 uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
1207 VkMemoryBarrier memoryBarrier{VK_STRUCTURE_TYPE_MEMORY_BARRIER, DE_NULL, 0u, 0u};
1208
1209 Move<VkShaderModule> compShader = createShaderModule(vk, device, m_context.getBinaryCollection().get("comp"), 0);
1210 Move<VkShaderModule> vertShader = createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0);
1211 Move<VkShaderModule> fragShader = createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0);
1212
1213 Move<VkCommandPool> cmdPool =
1214 createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex);
1215 Move<VkCommandBuffer> cmdBuffer = allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
1216
1217 // setup descriptor set with storage image for compute pipeline
1218 Move<VkDescriptorSetLayout> computeDescriptorSetLayout =
1219 DescriptorSetLayoutBuilder()
1220 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
1221 .build(vk, device);
1222 Move<VkDescriptorPool> computeDescriptorPool =
1223 DescriptorPoolBuilder()
1224 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1u)
1225 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
1226 const VkDescriptorSetAllocateInfo computeDescriptorSetAllocInfo =
1227 makeDescriptorSetAllocInfo(*computeDescriptorPool, &(*computeDescriptorSetLayout));
1228 Move<VkDescriptorSet> computeDescriptorSet = allocateDescriptorSet(vk, device, &computeDescriptorSetAllocInfo);
1229
1230 m_srUsage |= VK_IMAGE_USAGE_STORAGE_BIT;
1231
1232 buildCounterBufferObjects(device, vk, m_context.getDefaultAllocator());
1233 buildColorBufferObjects(device, vk, m_context.getDefaultAllocator(), 0, m_cbUsage);
1234
1235 // iterate over all possible tile sizes
1236 for (uint32_t tileWidth = m_minTileSize.width; tileWidth <= m_maxTileSize.width; tileWidth *= 2)
1237 for (uint32_t tileHeight = m_minTileSize.height; tileHeight <= m_maxTileSize.height; tileHeight *= 2)
1238 {
1239 // skip tile sizes that have unsuported aspect ratio
1240 uint32_t aspectRatio = (tileHeight > tileWidth) ? (tileHeight / tileWidth) : (tileWidth / tileHeight);
1241 if (aspectRatio > m_maxAspectRatio)
1242 continue;
1243
1244 // calculate size of shading rate attachment
1245 uint32_t srWidth = (m_cbWidth + tileWidth - 1) / tileWidth;
1246 uint32_t srHeight = (m_cbHeight + tileHeight - 1) / tileHeight;
1247
1248 buildShadingRateObjects(device, vk, m_context.getDefaultAllocator(), 0, srWidth, srHeight, m_srUsage);
1249
1250 const VkDescriptorImageInfo computeDescriptorInfo =
1251 makeDescriptorImageInfo(DE_NULL, *m_srImageView[0], VK_IMAGE_LAYOUT_GENERAL);
1252 DescriptorSetUpdateBuilder()
1253 .writeSingle(*computeDescriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u),
1254 VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &computeDescriptorInfo)
1255 .update(vk, device);
1256
1257 const auto dsFormat = m_params->getDSFormat();
1258 Move<VkPipelineLayout> computePipelineLayout =
1259 buildPipelineLayout(device, vk, &(*computeDescriptorSetLayout));
1260 Move<VkPipelineLayout> graphicsPipelineLayout =
1261 buildPipelineLayout(device, vk, &(*m_counterBufferDescriptorSetLayout));
1262 Move<VkPipeline> computePipeline = buildComputePipeline(device, vk, *compShader, *computePipelineLayout);
1263 Move<VkRenderPass> renderPass = buildRenderPass(device, vk, m_cbFormat, dsFormat, tileWidth, tileHeight);
1264 Move<VkPipeline> graphicsPipeline = buildGraphicsPipeline(
1265 device, vk, 0, *renderPass, m_cbFormat, dsFormat, *graphicsPipelineLayout, *vertShader, *fragShader);
1266
1267 std::vector<FBAttachmentInfo> attachmentInfo{
1268 {m_cbFormat, m_cbUsage, m_cbWidth, m_cbHeight, *m_cbImageView[0]},
1269 {m_params->srFormat, m_srUsage, srWidth, srHeight, *m_srImageView[0]},
1270 };
1271 // This would need an additional attachment with m_dsImageView and a barrier to transition the DS layout.
1272 // See runFragmentShaderMode for more details.
1273 DE_ASSERT(!m_params->useDepthStencil());
1274
1275 Move<VkFramebuffer> framebuffer = buildFramebuffer(device, vk, *renderPass, attachmentInfo);
1276
1277 beginCommandBuffer(vk, *cmdBuffer, 0u);
1278
1279 // wait till sr image layout is changed
1280 VkPipelineStageFlags srcStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
1281 VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
1282 VkImageMemoryBarrier srImageBarrierGeneral =
1283 makeImageMemoryBarrier(VK_ACCESS_NONE_KHR, VK_ACCESS_NONE_KHR, VK_IMAGE_LAYOUT_UNDEFINED,
1284 VK_IMAGE_LAYOUT_GENERAL, **m_srImage[0], m_defaultImageSubresourceRange);
1285 vk.cmdPipelineBarrier(*cmdBuffer, srcStageMask, dstStageMask, 0, 0, DE_NULL, 0, DE_NULL, 1,
1286 &srImageBarrierGeneral);
1287
1288 // fill sr image using compute shader
1289 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *computePipeline);
1290 vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *computePipelineLayout, 0, 1,
1291 &(*computeDescriptorSet), 0, DE_NULL);
1292 vk.cmdDispatch(*cmdBuffer, srWidth, srHeight, 1);
1293
1294 // wait till sr image is ready and change sr images layout
1295 srcStageMask = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
1296 dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR;
1297 memoryBarrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
1298 memoryBarrier.dstAccessMask = VK_ACCESS_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR;
1299 VkImageMemoryBarrier srImageBarrierShadingRate = makeImageMemoryBarrier(
1300 VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR,
1301 VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR, **m_srImage[0],
1302 m_defaultImageSubresourceRange);
1303 vk.cmdPipelineBarrier(*cmdBuffer, srcStageMask, dstStageMask, 0, 1, &memoryBarrier, 0, DE_NULL, 1,
1304 &srImageBarrierShadingRate);
1305
1306 // wait till cb image layout is changed
1307 srcStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
1308 dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
1309 VkImageMemoryBarrier cbImageBarrier = makeImageMemoryBarrier(
1310 VK_ACCESS_NONE_KHR, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
1311 VK_IMAGE_LAYOUT_GENERAL, **m_cbImage[0], m_defaultImageSubresourceRange);
1312 vk.cmdPipelineBarrier(*cmdBuffer, srcStageMask, dstStageMask, 0, 0, DE_NULL, 0, DE_NULL, 1,
1313 &cbImageBarrier);
1314
1315 startRendering(*cmdBuffer, *renderPass, *framebuffer, makeRect2D(m_cbWidth, m_cbHeight), attachmentInfo,
1316 tileWidth, tileHeight);
1317
1318 // draw single triangle to cb
1319 vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *graphicsPipelineLayout, 0, 1,
1320 &(*m_counterBufferDescriptorSet), 0, DE_NULL);
1321 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *graphicsPipeline);
1322 vk.cmdDraw(*cmdBuffer, 3u, 1, 0u, 0u);
1323
1324 finishRendering(*cmdBuffer);
1325
1326 // wait till color attachment is fully written
1327 srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
1328 dstStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
1329 memoryBarrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
1330 memoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
1331 vk.cmdPipelineBarrier(*cmdBuffer, srcStageMask, dstStageMask, 0, 1, &memoryBarrier, 0, DE_NULL, 0, DE_NULL);
1332
1333 // read back color buffer image
1334 vk.cmdCopyImageToBuffer(*cmdBuffer, **m_cbImage[0], VK_IMAGE_LAYOUT_GENERAL, **m_cbReadBuffer[0], 1u,
1335 &m_defaultBufferImageCopy);
1336
1337 endCommandBuffer(vk, *cmdBuffer);
1338
1339 // submit commands and wait
1340 const VkQueue queue = m_context.getUniversalQueue();
1341 submitCommandsAndWait(vk, device, queue, cmdBuffer.get());
1342
1343 invalidateAlloc(vk, device, m_cbReadBuffer[0]->getAllocation());
1344 if (!verifyUsingAtomicChecks(tileWidth, tileHeight, m_params->srRate.width, m_params->srRate.height,
1345 (uint32_t *)m_cbReadBuffer[0]->getAllocation().getHostPtr()))
1346 return false;
1347
1348 } // iterate over all possible tile sizes
1349
1350 return true;
1351 }
1352
runFragmentShaderMode(void)1353 bool AttachmentRateInstance::runFragmentShaderMode(void)
1354 {
1355 // Set up the image as a color attachment, and render rate to it,
1356 // then use it to draw a basic triangle and do basic checks
1357
1358 const DeviceInterface &vk = m_context.getDeviceInterface();
1359 VkDevice device = m_context.getDevice();
1360 uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
1361 VkMemoryBarrier memoryBarrier{VK_STRUCTURE_TYPE_MEMORY_BARRIER, DE_NULL, 0u, 0u};
1362 const bool useMemoryAccess = (m_params->mode == TM_MEMORY_ACCESS);
1363
1364 Move<VkShaderModule> vertSetupShader =
1365 createShaderModule(vk, device, m_context.getBinaryCollection().get("vert_setup"), 0);
1366 Move<VkShaderModule> fragSetupShader =
1367 createShaderModule(vk, device, m_context.getBinaryCollection().get("frag_setup"), 0);
1368 Move<VkShaderModule> vertShader = createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0);
1369 Move<VkShaderModule> fragShader = createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0);
1370
1371 Move<VkCommandPool> cmdPool =
1372 createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex);
1373 Move<VkCommandBuffer> cmdBuffer = allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
1374
1375 m_srUsage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
1376
1377 buildCounterBufferObjects(device, vk, m_context.getDefaultAllocator());
1378 buildColorBufferObjects(device, vk, m_context.getDefaultAllocator(), 0, m_cbUsage);
1379
1380 // iterate over all possible tile sizes
1381 for (uint32_t tileWidth = m_minTileSize.width; tileWidth <= m_maxTileSize.width; tileWidth *= 2)
1382 for (uint32_t tileHeight = m_minTileSize.height; tileHeight <= m_maxTileSize.height; tileHeight *= 2)
1383 {
1384 // skip tile sizes that have unsuported aspect ratio
1385 uint32_t aspectRatio = (tileHeight > tileWidth) ? (tileHeight / tileWidth) : (tileWidth / tileHeight);
1386 if (aspectRatio > m_maxAspectRatio)
1387 continue;
1388
1389 // calculate size of shading rate attachment
1390 uint32_t srWidth = (m_cbWidth + tileWidth - 1) / tileWidth;
1391 uint32_t srHeight = (m_cbHeight + tileHeight - 1) / tileHeight;
1392
1393 buildShadingRateObjects(device, vk, m_context.getDefaultAllocator(), 0, srWidth, srHeight, m_srUsage);
1394
1395 const auto dsFormat = m_params->getDSFormat();
1396 Move<VkPipelineLayout> setupPipelineLayout = buildPipelineLayout(device, vk);
1397 Move<VkPipelineLayout> ratePipelineLayout =
1398 buildPipelineLayout(device, vk, &(*m_counterBufferDescriptorSetLayout));
1399 Move<VkRenderPass> setupRenderPass = buildRenderPass(device, vk, m_params->srFormat, VK_FORMAT_UNDEFINED);
1400 Move<VkRenderPass> rateRenderPass =
1401 buildRenderPass(device, vk, m_cbFormat, dsFormat, tileWidth, tileHeight);
1402 Move<VkPipeline> setupPipeline =
1403 buildGraphicsPipeline(device, vk, 0, *setupRenderPass, m_params->srFormat, VK_FORMAT_UNDEFINED,
1404 *setupPipelineLayout, *vertSetupShader, *fragSetupShader, false);
1405 Move<VkPipeline> ratePipeline = buildGraphicsPipeline(device, vk, 0, *rateRenderPass, m_cbFormat, dsFormat,
1406 *ratePipelineLayout, *vertShader, *fragShader);
1407
1408 std::vector<FBAttachmentInfo> setupAttachmentInfo{
1409 {m_params->srFormat, m_srUsage, srWidth, srHeight, *m_srImageView[0]}};
1410 std::vector<FBAttachmentInfo> rateAttachmentInfo{
1411 {m_cbFormat, m_cbUsage, m_cbWidth, m_cbHeight, *m_cbImageView[0]},
1412 {m_params->srFormat, m_srUsage, srWidth, srHeight, *m_srImageView[0]},
1413 };
1414 if (m_params->useDepthStencil())
1415 rateAttachmentInfo.push_back(
1416 FBAttachmentInfo{dsFormat, kDSUsage, m_cbWidth, m_cbHeight, *m_dsImageView});
1417
1418 Move<VkFramebuffer> setupFramebuffer = buildFramebuffer(device, vk, *setupRenderPass, setupAttachmentInfo);
1419 Move<VkFramebuffer> rateFramebuffer = buildFramebuffer(device, vk, *rateRenderPass, rateAttachmentInfo);
1420
1421 beginCommandBuffer(vk, *cmdBuffer, 0u);
1422
1423 // wait till sr image layout is changed
1424 VkPipelineStageFlags srcStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
1425 VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
1426 VkImageMemoryBarrier srImageBarrierGeneral = makeImageMemoryBarrier(
1427 VK_ACCESS_NONE_KHR, useMemoryAccess ? VK_ACCESS_MEMORY_WRITE_BIT : VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
1428 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, **m_srImage[0], m_defaultImageSubresourceRange);
1429 vk.cmdPipelineBarrier(*cmdBuffer, srcStageMask, dstStageMask, 0, 0, DE_NULL, 0, DE_NULL, 1,
1430 &srImageBarrierGeneral);
1431
1432 if (m_params->useDepthStencil())
1433 {
1434 const VkPipelineStageFlags srcStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
1435 const VkPipelineStageFlags dstStage =
1436 (VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT);
1437 VkImageMemoryBarrier depthImageReadOnlyBarrier = makeImageMemoryBarrier(
1438 VK_ACCESS_NONE_KHR, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
1439 m_params->getDSLayout(), **m_dsImage, m_dsImageSubresourceRange);
1440 vk.cmdPipelineBarrier(*cmdBuffer, srcStage, dstStage, 0, 0, nullptr, 0, nullptr, 1,
1441 &depthImageReadOnlyBarrier);
1442 }
1443
1444 // render rate to sr image
1445 startRendering(*cmdBuffer, *setupRenderPass, *setupFramebuffer, makeRect2D(srWidth, srHeight),
1446 setupAttachmentInfo);
1447
1448 // draw single triangle to cb
1449 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *setupPipeline);
1450 vk.cmdDraw(*cmdBuffer, 3u, 1, 0u, 0u);
1451
1452 finishRendering(*cmdBuffer);
1453
1454 // wait till sr image is ready and change sr images layout
1455 srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
1456 dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR;
1457 VkImageMemoryBarrier srImageBarrierShadingRate = makeImageMemoryBarrier(
1458 useMemoryAccess ? VK_ACCESS_MEMORY_WRITE_BIT : VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
1459 useMemoryAccess ? VK_ACCESS_MEMORY_READ_BIT : VK_ACCESS_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR,
1460 VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR, **m_srImage[0],
1461 m_defaultImageSubresourceRange);
1462 vk.cmdPipelineBarrier(*cmdBuffer, srcStageMask, dstStageMask, 0, 0, DE_NULL, 0, DE_NULL, 1,
1463 &srImageBarrierShadingRate);
1464
1465 // wait till cb image layout is changed
1466 srcStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
1467 dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
1468 VkImageMemoryBarrier cbImageBarrier = makeImageMemoryBarrier(
1469 VK_ACCESS_NONE_KHR, useMemoryAccess ? VK_ACCESS_MEMORY_WRITE_BIT : VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
1470 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, **m_cbImage[0], m_defaultImageSubresourceRange);
1471 vk.cmdPipelineBarrier(*cmdBuffer, srcStageMask, dstStageMask, 0, 0, DE_NULL, 0, DE_NULL, 1,
1472 &cbImageBarrier);
1473
1474 startRendering(*cmdBuffer, *rateRenderPass, *rateFramebuffer, makeRect2D(m_cbWidth, m_cbHeight),
1475 rateAttachmentInfo, tileWidth, tileHeight);
1476
1477 // draw single triangle to cb
1478 vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *ratePipelineLayout, 0, 1,
1479 &(*m_counterBufferDescriptorSet), 0, DE_NULL);
1480 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *ratePipeline);
1481 vk.cmdDraw(*cmdBuffer, 3u, 1, 0u, 0u);
1482
1483 finishRendering(*cmdBuffer);
1484
1485 // wait till color attachment is fully written
1486 srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
1487 dstStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
1488 memoryBarrier.srcAccessMask =
1489 useMemoryAccess ? VK_ACCESS_MEMORY_WRITE_BIT : VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
1490 memoryBarrier.dstAccessMask = useMemoryAccess ? VK_ACCESS_MEMORY_READ_BIT : VK_ACCESS_TRANSFER_READ_BIT;
1491 vk.cmdPipelineBarrier(*cmdBuffer, srcStageMask, dstStageMask, 0, 1, &memoryBarrier, 0, DE_NULL, 0, DE_NULL);
1492
1493 // read back color buffer image
1494 vk.cmdCopyImageToBuffer(*cmdBuffer, **m_cbImage[0], VK_IMAGE_LAYOUT_GENERAL, **m_cbReadBuffer[0], 1u,
1495 &m_defaultBufferImageCopy);
1496
1497 endCommandBuffer(vk, *cmdBuffer);
1498
1499 // submit commands and wait
1500 const VkQueue queue = m_context.getUniversalQueue();
1501 submitCommandsAndWait(vk, device, queue, cmdBuffer.get());
1502
1503 invalidateAlloc(vk, device, m_cbReadBuffer[0]->getAllocation());
1504 if (!verifyUsingAtomicChecks(tileWidth, tileHeight, m_params->srRate.width, m_params->srRate.height,
1505 (uint32_t *)m_cbReadBuffer[0]->getAllocation().getHostPtr()))
1506 return false;
1507
1508 } // iterate over all possible tile sizes
1509
1510 return true;
1511 }
1512
runCopyMode(void)1513 bool AttachmentRateInstance::runCopyMode(void)
1514 {
1515 // Clear a separate image of the same format to that rate, copy it to
1516 // the shading rate image, then use it to draw a basic triangle and do basic checks
1517
1518 const DeviceInterface &vk = m_context.getDeviceInterface();
1519 VkDevice device = m_context.getDevice();
1520 uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
1521 VkMemoryBarrier memoryBarrier{VK_STRUCTURE_TYPE_MEMORY_BARRIER, DE_NULL, 0u, 0u};
1522
1523 Move<VkShaderModule> vertShader = createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0);
1524 Move<VkShaderModule> fragShader = createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0);
1525
1526 Move<VkCommandPool> cmdPool =
1527 createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex);
1528 Move<VkCommandBuffer> cmdBuffer = allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
1529
1530 buildCounterBufferObjects(device, vk, m_context.getDefaultAllocator());
1531 buildColorBufferObjects(device, vk, m_context.getDefaultAllocator(), 0, m_cbUsage);
1532
1533 // iterate over all possible tile sizes
1534 for (uint32_t tileWidth = m_minTileSize.width; tileWidth <= m_maxTileSize.width; tileWidth *= 2)
1535 for (uint32_t tileHeight = m_minTileSize.height; tileHeight <= m_maxTileSize.height; tileHeight *= 2)
1536 {
1537 // skip tile sizes that have unsuported aspect ratio
1538 uint32_t aspectRatio = (tileHeight > tileWidth) ? (tileHeight / tileWidth) : (tileWidth / tileHeight);
1539 if (aspectRatio > m_maxAspectRatio)
1540 continue;
1541
1542 // calculate size of shading rate attachment
1543 uint32_t srWidth = (m_cbWidth + tileWidth - 1) / tileWidth;
1544 uint32_t srHeight = (m_cbHeight + tileHeight - 1) / tileHeight;
1545
1546 buildShadingRateObjects(device, vk, m_context.getDefaultAllocator(), 0, srWidth, srHeight, m_srUsage);
1547
1548 // create image that will be source for shading rate image
1549 de::MovePtr<ImageWithMemory> srSrcImage =
1550 buildImageWithMemory(device, vk, m_context.getDefaultAllocator(), m_params->srFormat, srWidth, srHeight,
1551 VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
1552
1553 const auto dsFormat = m_params->getDSFormat();
1554 Move<VkPipelineLayout> graphicsPipelineLayout =
1555 buildPipelineLayout(device, vk, &(*m_counterBufferDescriptorSetLayout));
1556 Move<VkRenderPass> renderPass = buildRenderPass(device, vk, m_cbFormat, dsFormat, tileWidth, tileHeight);
1557 Move<VkPipeline> graphicsPipeline = buildGraphicsPipeline(
1558 device, vk, 0, *renderPass, m_cbFormat, dsFormat, *graphicsPipelineLayout, *vertShader, *fragShader);
1559
1560 std::vector<FBAttachmentInfo> attachmentInfo{
1561 {m_cbFormat, m_cbUsage, m_cbWidth, m_cbHeight, *m_cbImageView[0]},
1562 {m_params->srFormat, m_srUsage, srWidth, srHeight, *m_srImageView[0]},
1563 };
1564 // This would need an additional attachment with m_dsImageView and a barrier to transition the DS layout.
1565 // See runFragmentShaderMode for more details.
1566 DE_ASSERT(!m_params->useDepthStencil());
1567
1568 Move<VkFramebuffer> framebuffer = buildFramebuffer(device, vk, *renderPass, attachmentInfo);
1569
1570 beginCommandBuffer(vk, *cmdBuffer, 0u);
1571
1572 // wait till sr images layout are changed
1573 VkPipelineStageFlags srcStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
1574 VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
1575 std::vector<VkImageMemoryBarrier> srImageBarrierGeneral(
1576 2,
1577 makeImageMemoryBarrier(VK_ACCESS_NONE_KHR, (VK_ACCESS_TRANSFER_WRITE_BIT | VK_ACCESS_TRANSFER_READ_BIT),
1578 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, **m_srImage[0],
1579 m_defaultImageSubresourceRange));
1580 srImageBarrierGeneral[1].image = **srSrcImage;
1581 vk.cmdPipelineBarrier(*cmdBuffer, srcStageMask, dstStageMask, 0, 0, DE_NULL, 0, DE_NULL, 2,
1582 srImageBarrierGeneral.data());
1583
1584 // clear source sr image with proper rate
1585 VkClearColorValue clearValue = {{0, 0, 0, 0}};
1586 clearValue.uint32[0] = calculateRate(m_params->srRate.width, m_params->srRate.height);
1587 vk.cmdClearColorImage(*cmdBuffer, **srSrcImage, VK_IMAGE_LAYOUT_GENERAL, &clearValue, 1,
1588 &m_defaultImageSubresourceRange);
1589
1590 // wait till sr source image is ready
1591 srcStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
1592 dstStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
1593 memoryBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
1594 memoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
1595 vk.cmdPipelineBarrier(*cmdBuffer, srcStageMask, dstStageMask, 0, 1, &memoryBarrier, 0, DE_NULL, 0, DE_NULL);
1596
1597 // copy sr source image to sr image used during rendering
1598 VkImageCopy imageCopyRegion{
1599 m_defaultImageSubresourceLayers, // VkImageSubresourceLayers srcSubresource;
1600 {0, 0, 0}, // VkOffset3D srcOffset;
1601 m_defaultImageSubresourceLayers, // VkImageSubresourceLayers dstSubresource;
1602 {0, 0, 0}, // VkOffset3D dstOffset;
1603 {srWidth, srHeight, 1u} // VkExtent3D extent;
1604 };
1605 vk.cmdCopyImage(*cmdBuffer, **srSrcImage, VK_IMAGE_LAYOUT_GENERAL, **m_srImage[0], VK_IMAGE_LAYOUT_GENERAL,
1606 1, &imageCopyRegion);
1607
1608 // wait till sr image is ready and change sr images layout
1609 srcStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
1610 dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR;
1611 memoryBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
1612 memoryBarrier.dstAccessMask = VK_ACCESS_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR;
1613 VkImageMemoryBarrier srImageBarrierShadingRate = makeImageMemoryBarrier(
1614 VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR,
1615 VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR, **m_srImage[0],
1616 m_defaultImageSubresourceRange);
1617 vk.cmdPipelineBarrier(*cmdBuffer, srcStageMask, dstStageMask, 0, 1, &memoryBarrier, 0, DE_NULL, 1,
1618 &srImageBarrierShadingRate);
1619
1620 // wait till cb image layout is changed
1621 srcStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
1622 dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
1623 VkImageMemoryBarrier cbImageBarrier = makeImageMemoryBarrier(
1624 VK_ACCESS_NONE_KHR, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
1625 VK_IMAGE_LAYOUT_GENERAL, **m_cbImage[0], m_defaultImageSubresourceRange);
1626 vk.cmdPipelineBarrier(*cmdBuffer, srcStageMask, dstStageMask, 0, 0, DE_NULL, 0, DE_NULL, 1,
1627 &cbImageBarrier);
1628
1629 startRendering(*cmdBuffer, *renderPass, *framebuffer, makeRect2D(m_cbWidth, m_cbHeight), attachmentInfo,
1630 tileWidth, tileHeight);
1631
1632 // draw single triangle to cb
1633 vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *graphicsPipelineLayout, 0, 1,
1634 &(*m_counterBufferDescriptorSet), 0, DE_NULL);
1635 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *graphicsPipeline);
1636 vk.cmdDraw(*cmdBuffer, 3u, 1, 0u, 0u);
1637
1638 finishRendering(*cmdBuffer);
1639
1640 // wait till color attachment is fully written
1641 srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
1642 dstStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
1643 memoryBarrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
1644 memoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
1645 vk.cmdPipelineBarrier(*cmdBuffer, srcStageMask, dstStageMask, 0, 1, &memoryBarrier, 0, DE_NULL, 0, DE_NULL);
1646
1647 // read back color buffer image
1648 vk.cmdCopyImageToBuffer(*cmdBuffer, **m_cbImage[0], VK_IMAGE_LAYOUT_GENERAL, **m_cbReadBuffer[0], 1u,
1649 &m_defaultBufferImageCopy);
1650
1651 endCommandBuffer(vk, *cmdBuffer);
1652
1653 // submit commands and wait
1654 const VkQueue queue = m_context.getUniversalQueue();
1655 submitCommandsAndWait(vk, device, queue, cmdBuffer.get());
1656
1657 invalidateAlloc(vk, device, m_cbReadBuffer[0]->getAllocation());
1658 if (!verifyUsingAtomicChecks(tileWidth, tileHeight, m_params->srRate.width, m_params->srRate.height,
1659 (uint32_t *)m_cbReadBuffer[0]->getAllocation().getHostPtr()))
1660 return false;
1661
1662 } // iterate over all possible tile sizes
1663
1664 return true;
1665 }
1666
runCopyModeOnTransferQueue(void)1667 bool AttachmentRateInstance::runCopyModeOnTransferQueue(void)
1668 {
1669 // Clear a separate image of the same format to that rate, copy it to
1670 // the shading rate image on separate transfer queue and then use copied
1671 // image to draw a basic triangle and do basic checks
1672
1673 const PlatformInterface &vkp = m_context.getPlatformInterface();
1674 const InstanceInterface &vki = m_context.getInstanceInterface();
1675 VkPhysicalDevice pd = m_context.getPhysicalDevice();
1676 uint32_t transferQueueFamilyIndex = std::numeric_limits<uint32_t>::max();
1677 uint32_t graphicsQueueFamilyIndex = std::numeric_limits<uint32_t>::max();
1678 VkMemoryBarrier memoryBarrier{VK_STRUCTURE_TYPE_MEMORY_BARRIER, DE_NULL, 0u, 0u};
1679 std::vector<VkQueueFamilyProperties> queueFamilyProperties = getPhysicalDeviceQueueFamilyProperties(vki, pd);
1680
1681 // find graphics and transfer queue families
1682 for (uint32_t queueNdx = 0; queueNdx < queueFamilyProperties.size(); queueNdx++)
1683 {
1684 VkQueueFlags queueFlags = queueFamilyProperties[queueNdx].queueFlags;
1685 if ((graphicsQueueFamilyIndex == std::numeric_limits<uint32_t>::max()) && (queueFlags & VK_QUEUE_GRAPHICS_BIT))
1686 graphicsQueueFamilyIndex = queueNdx;
1687 else if ((queueNdx != graphicsQueueFamilyIndex) && (queueFlags & VK_QUEUE_TRANSFER_BIT))
1688 transferQueueFamilyIndex = queueNdx;
1689 }
1690 if (transferQueueFamilyIndex == std::numeric_limits<uint32_t>::max())
1691 TCU_THROW(NotSupportedError, "No separate transfer queue");
1692
1693 if (graphicsQueueFamilyIndex == std::numeric_limits<uint32_t>::max())
1694 TCU_THROW(NotSupportedError, "No separate graphics queue");
1695 // using queueFamilies vector to determine if sr image uses exclusiv or concurrent sharing
1696 std::vector<uint32_t> queueFamilies;
1697 if (m_params->mode == TM_SETUP_RATE_WITH_COPYING_FROM_CONCURENT_IMAGE_USING_TRANSFER_QUEUE)
1698 queueFamilies = {graphicsQueueFamilyIndex, transferQueueFamilyIndex};
1699
1700 // create custom device
1701 VkDevice device;
1702 DeviceInterface *driver;
1703 Allocator *allocator;
1704
1705 {
1706 const float queuePriorities = 1.0f;
1707 std::vector<VkDeviceQueueCreateInfo> queueInfo(
1708 2,
1709 {
1710 VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, // VkStructureType sType;
1711 DE_NULL, // const void* pNext;
1712 (VkDeviceQueueCreateFlags)0u, // VkDeviceQueueCreateFlags flags;
1713 transferQueueFamilyIndex, // uint32_t queueFamilyIndex;
1714 1u, // uint32_t queueCount;
1715 &queuePriorities // const float* pQueuePriorities;
1716 });
1717 queueInfo[1].queueFamilyIndex = graphicsQueueFamilyIndex;
1718
1719 VkPhysicalDeviceFeatures deviceFeatures;
1720 vki.getPhysicalDeviceFeatures(pd, &deviceFeatures);
1721
1722 VkPhysicalDeviceFragmentShadingRateFeaturesKHR fsrFeatures{
1723 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_FEATURES_KHR, DE_NULL, false, false, true};
1724 #ifndef CTS_USES_VULKANSC
1725 VkPhysicalDeviceDynamicRenderingFeaturesKHR drFeatures{
1726 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DYNAMIC_RENDERING_FEATURES_KHR, DE_NULL, true};
1727 #endif // CTS_USES_VULKANSC
1728 VkPhysicalDeviceImagelessFramebufferFeatures ifbFeatures{
1729 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGELESS_FRAMEBUFFER_FEATURES, DE_NULL, true};
1730 VkPhysicalDeviceFeatures2 createPhysicalFeature{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2, &fsrFeatures,
1731 deviceFeatures};
1732
1733 void *pNext = DE_NULL;
1734 std::vector<const char *> enabledExtensions = {"VK_KHR_fragment_shading_rate"};
1735 #ifndef CTS_USES_VULKANSC
1736 if (m_params->useDynamicRendering)
1737 {
1738 pNext = &drFeatures;
1739 }
1740 #endif // CTS_USES_VULKANSC
1741 if (m_params->useImagelessFramebuffer)
1742 {
1743 enabledExtensions.push_back("VK_KHR_imageless_framebuffer");
1744 ifbFeatures.pNext = pNext;
1745 pNext = &ifbFeatures;
1746 }
1747 fsrFeatures.pNext = pNext;
1748
1749 std::vector<const char *> enabledLayers = getValidationLayers(vki, pd);
1750 VkDeviceCreateInfo deviceInfo{
1751 VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, // VkStructureType sType;
1752 &createPhysicalFeature, // const void* pNext;
1753 (VkDeviceCreateFlags)0u, // VkDeviceCreateFlags flags;
1754 2u, // uint32_t queueCreateInfoCount;
1755 queueInfo.data(), // const VkDeviceQueueCreateInfo* pQueueCreateInfos;
1756 static_cast<uint32_t>(enabledLayers.size()), // uint32_t enabledLayerCount;
1757 de::dataOrNull(enabledLayers), // const char* const* ppEnabledLayerNames;
1758 static_cast<uint32_t>(enabledExtensions.size()), // uint32_t enabledExtensionCount;
1759 enabledExtensions.data(), // const char* const* ppEnabledExtensionNames;
1760 DE_NULL // const VkPhysicalDeviceFeatures* pEnabledFeatures;
1761 };
1762
1763 vk::Move<VkDevice> customDevice = createDevice(vkp, m_context.getInstance(), vki, pd, &deviceInfo);
1764 de::MovePtr<DeviceDriver> customDriver = de::MovePtr<DeviceDriver>(
1765 new DeviceDriver(vkp, m_context.getInstance(), *customDevice, m_context.getUsedApiVersion(),
1766 m_context.getTestContext().getCommandLine()));
1767 de::MovePtr<Allocator> customAllocator = de::MovePtr<Allocator>(
1768 new SimpleAllocator(*customDriver, *customDevice, getPhysicalDeviceMemoryProperties(vki, pd)));
1769
1770 device = *customDevice;
1771 driver = &*customDriver;
1772 allocator = &*customAllocator;
1773
1774 m_customDeviceHolder = de::MovePtr<DeviceHolder>(new DeviceHolder(customDevice, customDriver, customAllocator));
1775 }
1776
1777 DeviceInterface &vk = *driver;
1778
1779 VkQueue transferQueue;
1780 vk.getDeviceQueue(device, transferQueueFamilyIndex, 0u, &transferQueue);
1781 VkQueue graphicsQueue;
1782 vk.getDeviceQueue(device, graphicsQueueFamilyIndex, 0u, &graphicsQueue);
1783
1784 // create transfer and graphics command buffers
1785 Move<VkCommandPool> transferCmdPool =
1786 createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, transferQueueFamilyIndex);
1787 Move<VkCommandBuffer> transferCmdBuffer =
1788 allocateCommandBuffer(vk, device, *transferCmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
1789 Move<VkCommandPool> graphicsCmdPool =
1790 createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, graphicsQueueFamilyIndex);
1791 Move<VkCommandBuffer> graphicsCmdBuffer =
1792 allocateCommandBuffer(vk, device, *graphicsCmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
1793
1794 Move<VkShaderModule> vertShader = createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0);
1795 Move<VkShaderModule> fragShader = createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0);
1796
1797 buildColorBufferObjects(device, vk, *allocator, 0, m_cbUsage);
1798 buildCounterBufferObjects(device, vk, *allocator);
1799
1800 // iterate over all possible tile sizes
1801 for (uint32_t tileWidth = m_minTileSize.width; tileWidth <= m_maxTileSize.width; tileWidth *= 2)
1802 for (uint32_t tileHeight = m_minTileSize.height; tileHeight <= m_maxTileSize.height; tileHeight *= 2)
1803 {
1804 // skip tile sizes that have unsuported aspect ratio
1805 uint32_t aspectRatio = (tileHeight > tileWidth) ? (tileHeight / tileWidth) : (tileWidth / tileHeight);
1806 if (aspectRatio > m_maxAspectRatio)
1807 continue;
1808
1809 // calculate size of shading rate attachment
1810 uint32_t srWidth = (m_cbWidth + tileWidth - 1) / tileWidth;
1811 uint32_t srHeight = (m_cbHeight + tileHeight - 1) / tileHeight;
1812
1813 // create image that will be source for shading rate image
1814 de::MovePtr<ImageWithMemory> srSrcImage =
1815 buildImageWithMemory(device, vk, *allocator, m_params->srFormat, srWidth, srHeight,
1816 VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
1817
1818 // create buffer that will contain shading rate source data
1819 tcu::TextureFormat srTextureFormat = mapVkFormat(m_params->srFormat);
1820 uint32_t srWriteBufferSize =
1821 srWidth * srHeight * getNumUsedChannels(srTextureFormat.order) * getChannelSize(srTextureFormat.type);
1822 de::MovePtr<BufferWithMemory> srSrcBuffer =
1823 buildBufferWithMemory(device, vk, *allocator, srWriteBufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
1824
1825 // fill buffer with tested shading rate
1826 uint8_t *srWriteBufferHostPtr = (uint8_t *)srSrcBuffer->getAllocation().getHostPtr();
1827 uint8_t value = (uint8_t)calculateRate(m_params->srRate.width, m_params->srRate.height);
1828 deMemset(srWriteBufferHostPtr, value, (size_t)srWriteBufferSize);
1829 flushAlloc(vk, device, srSrcBuffer->getAllocation());
1830
1831 // create shading rate iamge
1832 m_srImage[0] = buildImageWithMemory(device, vk, *allocator, m_params->srFormat, srWidth, srHeight,
1833 VK_IMAGE_USAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR |
1834 VK_IMAGE_USAGE_TRANSFER_DST_BIT,
1835 VK_IMAGE_TILING_OPTIMAL, queueFamilies);
1836 m_srImageView[0] = buildImageView(device, vk, m_params->srFormat, m_srImage[0]->get());
1837
1838 const auto dsFormat = m_params->getDSFormat();
1839 Move<VkPipelineLayout> graphicsPipelineLayout =
1840 buildPipelineLayout(device, vk, &(*m_counterBufferDescriptorSetLayout));
1841 Move<VkRenderPass> renderPass = buildRenderPass(device, vk, m_cbFormat, dsFormat, tileWidth, tileHeight);
1842 Move<VkPipeline> graphicsPipeline = buildGraphicsPipeline(
1843 device, vk, 0, *renderPass, m_cbFormat, dsFormat, *graphicsPipelineLayout, *vertShader, *fragShader);
1844
1845 std::vector<FBAttachmentInfo> attachmentInfo{
1846 {m_cbFormat, m_cbUsage, m_cbWidth, m_cbHeight, *m_cbImageView[0]},
1847 {m_params->srFormat, m_srUsage, srWidth, srHeight, *m_srImageView[0]},
1848 };
1849 // This would need an additional attachment with m_dsImageView and a barrier to transition the DS layout.
1850 // See runFragmentShaderMode for more details.
1851 DE_ASSERT(!m_params->useDepthStencil());
1852
1853 Move<VkFramebuffer> framebuffer = buildFramebuffer(device, vk, *renderPass, attachmentInfo);
1854
1855 beginCommandBuffer(vk, *transferCmdBuffer, 0u);
1856
1857 // wait till sr data is ready in buffer and change sr image layouts to general
1858 VkPipelineStageFlags srcStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
1859 VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
1860 std::vector<VkImageMemoryBarrier> srImageBarrierGeneral(
1861 2,
1862 makeImageMemoryBarrier(VK_ACCESS_NONE_KHR, (VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_TRANSFER_WRITE_BIT),
1863 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, **m_srImage[0],
1864 m_defaultImageSubresourceRange));
1865 srImageBarrierGeneral[1].image = **srSrcImage;
1866 vk.cmdPipelineBarrier(*transferCmdBuffer, srcStageMask, dstStageMask, 0, 0, nullptr, 0, DE_NULL, 2,
1867 srImageBarrierGeneral.data());
1868
1869 // copy sr data to images
1870 const VkBufferImageCopy srCopyBuffer =
1871 makeBufferImageCopy({srWidth, srHeight, 1u}, m_defaultImageSubresourceLayers);
1872 vk.cmdCopyBufferToImage(*transferCmdBuffer, **srSrcBuffer, **srSrcImage, VK_IMAGE_LAYOUT_GENERAL, 1,
1873 &srCopyBuffer);
1874
1875 // wait till sr source image is ready
1876 srcStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
1877 dstStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
1878 memoryBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
1879 memoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
1880 vk.cmdPipelineBarrier(*transferCmdBuffer, srcStageMask, dstStageMask, 0, 1, &memoryBarrier, 0, DE_NULL, 0,
1881 DE_NULL);
1882
1883 // copy sr source image to sr image used during rendering
1884 VkImageCopy imageCopyRegion{
1885 m_defaultImageSubresourceLayers, // VkImageSubresourceLayers srcSubresource;
1886 {0, 0, 0}, // VkOffset3D srcOffset;
1887 m_defaultImageSubresourceLayers, // VkImageSubresourceLayers dstSubresource;
1888 {0, 0, 0}, // VkOffset3D dstOffset;
1889 {srWidth, srHeight, 1u} // VkExtent3D extent;
1890 };
1891 vk.cmdCopyImage(*transferCmdBuffer, **srSrcImage, VK_IMAGE_LAYOUT_GENERAL, **m_srImage[0],
1892 VK_IMAGE_LAYOUT_GENERAL, 1, &imageCopyRegion);
1893
1894 // release exclusive ownership from the transfer queue family
1895 srcStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
1896 dstStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
1897 VkImageMemoryBarrier srImageBarrierOwnershipTransfer =
1898 makeImageMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_NONE_KHR, VK_IMAGE_LAYOUT_GENERAL,
1899 VK_IMAGE_LAYOUT_GENERAL, **m_srImage[0], m_defaultImageSubresourceRange);
1900 if (m_params->mode == TM_SETUP_RATE_WITH_COPYING_FROM_EXCLUSIVE_IMAGE_USING_TRANSFER_QUEUE)
1901 {
1902 srImageBarrierOwnershipTransfer.srcQueueFamilyIndex = transferQueueFamilyIndex;
1903 srImageBarrierOwnershipTransfer.dstQueueFamilyIndex = graphicsQueueFamilyIndex;
1904 }
1905 vk.cmdPipelineBarrier(*transferCmdBuffer, srcStageMask, dstStageMask, 0, 0, DE_NULL, 0, DE_NULL, 1,
1906 &srImageBarrierOwnershipTransfer);
1907
1908 endCommandBuffer(vk, *transferCmdBuffer);
1909
1910 beginCommandBuffer(vk, *graphicsCmdBuffer, 0u);
1911
1912 // acquire exclusive ownership for the graphics queue family - while changing sr images layout
1913 vk.cmdPipelineBarrier(*graphicsCmdBuffer, srcStageMask, dstStageMask, 0, 0, DE_NULL, 0, DE_NULL, 1,
1914 &srImageBarrierOwnershipTransfer);
1915
1916 // wait till sr image layout is changed
1917 srcStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
1918 dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR;
1919 VkImageMemoryBarrier srImageBarrierShadingRate = makeImageMemoryBarrier(
1920 VK_ACCESS_NONE_KHR, VK_ACCESS_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR, VK_IMAGE_LAYOUT_GENERAL,
1921 VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR, **m_srImage[0],
1922 m_defaultImageSubresourceRange);
1923 vk.cmdPipelineBarrier(*graphicsCmdBuffer, srcStageMask, dstStageMask, 0, 0, DE_NULL, 0, DE_NULL, 1,
1924 &srImageBarrierShadingRate);
1925
1926 // wait till cb image layout is changed
1927 srcStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
1928 dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
1929 VkImageMemoryBarrier cbImageBarrier = makeImageMemoryBarrier(
1930 VK_ACCESS_NONE_KHR, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
1931 VK_IMAGE_LAYOUT_GENERAL, **m_cbImage[0], m_defaultImageSubresourceRange);
1932 vk.cmdPipelineBarrier(*graphicsCmdBuffer, srcStageMask, dstStageMask, 0, 0, DE_NULL, 0, DE_NULL, 1,
1933 &cbImageBarrier);
1934
1935 startRendering(*graphicsCmdBuffer, *renderPass, *framebuffer, makeRect2D(m_cbWidth, m_cbHeight),
1936 attachmentInfo, tileWidth, tileHeight);
1937
1938 // draw single triangle to cb
1939 vk.cmdBindDescriptorSets(*graphicsCmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *graphicsPipelineLayout, 0, 1,
1940 &(*m_counterBufferDescriptorSet), 0, DE_NULL);
1941 vk.cmdBindPipeline(*graphicsCmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *graphicsPipeline);
1942 vk.cmdDraw(*graphicsCmdBuffer, 3u, 1, 0u, 0u);
1943
1944 finishRendering(*graphicsCmdBuffer);
1945
1946 // wait till color attachment is fully written
1947 srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
1948 dstStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
1949 memoryBarrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
1950 memoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
1951 vk.cmdPipelineBarrier(*graphicsCmdBuffer, srcStageMask, dstStageMask, 0, 1, &memoryBarrier, 0, DE_NULL, 0,
1952 DE_NULL);
1953
1954 // read back color buffer image
1955 vk.cmdCopyImageToBuffer(*graphicsCmdBuffer, **m_cbImage[0], VK_IMAGE_LAYOUT_GENERAL, **m_cbReadBuffer[0],
1956 1u, &m_defaultBufferImageCopy);
1957
1958 endCommandBuffer(vk, *graphicsCmdBuffer);
1959
1960 // create synchronization objects
1961 Move<VkSemaphore> semaphore = createSemaphore(vk, device);
1962 Move<VkFence> transferFence = createFence(vk, device);
1963 Move<VkFence> graphicsFence = createFence(vk, device);
1964
1965 const VkSubmitInfo transferSubmitInfo{
1966 VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType;
1967 DE_NULL, // const void* pNext;
1968 0u, // uint32_t waitSemaphoreCount;
1969 DE_NULL, // const VkSemaphore* pWaitSemaphores;
1970 DE_NULL, // const VkPipelineStageFlags* pWaitDstStageMask;
1971 1u, // uint32_t commandBufferCount;
1972 &*transferCmdBuffer, // const VkCommandBuffer* pCommandBuffers;
1973 1u, // uint32_t signalSemaphoreCount;
1974 &*semaphore, // const VkSemaphore* pSignalSemaphores;
1975 };
1976 const VkPipelineStageFlags waitDstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
1977 const VkSubmitInfo graphicsSubmitInfo{
1978 VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType;
1979 DE_NULL, // const void* pNext;
1980 1u, // uint32_t waitSemaphoreCount;
1981 &*semaphore, // const VkSemaphore* pWaitSemaphores;
1982 &waitDstStageMask, // const VkPipelineStageFlags* pWaitDstStageMask;
1983 1u, // uint32_t commandBufferCount;
1984 &*graphicsCmdBuffer, // const VkCommandBuffer* pCommandBuffers;
1985 0u, // uint32_t signalSemaphoreCount;
1986 DE_NULL, // const VkSemaphore* pSignalSemaphores;
1987 };
1988
1989 // submit commands to both queues
1990 VK_CHECK(vk.queueSubmit(transferQueue, 1u, &transferSubmitInfo, *transferFence));
1991 VK_CHECK(vk.queueSubmit(graphicsQueue, 1u, &graphicsSubmitInfo, *graphicsFence));
1992
1993 VkFence fences[] = {*graphicsFence, *transferFence};
1994 VK_CHECK(vk.waitForFences(device, 2u, fences, true, ~0ull));
1995
1996 invalidateAlloc(vk, device, m_cbReadBuffer[0]->getAllocation());
1997 if (!verifyUsingAtomicChecks(tileWidth, tileHeight, m_params->srRate.width, m_params->srRate.height,
1998 (uint32_t *)m_cbReadBuffer[0]->getAllocation().getHostPtr()))
1999 return false;
2000
2001 } // iterate over all possible tile sizes
2002
2003 return true;
2004 }
2005
runFillLinearTiledImage(void)2006 bool AttachmentRateInstance::runFillLinearTiledImage(void)
2007 {
2008 // Create a linear tiled fragment shading rate attachment image and set
2009 // its data on the host, then draw a basic triangle and do basic checks
2010
2011 const DeviceInterface &vk = m_context.getDeviceInterface();
2012 VkDevice device = m_context.getDevice();
2013 uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
2014 VkImageSubresource imageSubresource = makeImageSubresource(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u);
2015 VkMemoryBarrier memoryBarrier{VK_STRUCTURE_TYPE_MEMORY_BARRIER, DE_NULL, 0u, 0u};
2016 VkSubresourceLayout srImageLayout;
2017
2018 Move<VkShaderModule> vertShader = createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0);
2019 Move<VkShaderModule> fragShader = createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0);
2020
2021 Move<VkCommandPool> cmdPool =
2022 createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex);
2023 Move<VkCommandBuffer> cmdBuffer = allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
2024
2025 buildCounterBufferObjects(device, vk, m_context.getDefaultAllocator());
2026 buildColorBufferObjects(device, vk, m_context.getDefaultAllocator(), 0, m_cbUsage);
2027
2028 // iterate over all possible tile sizes
2029 for (uint32_t tileWidth = m_minTileSize.width; tileWidth <= m_maxTileSize.width; tileWidth *= 2)
2030 for (uint32_t tileHeight = m_minTileSize.height; tileHeight <= m_maxTileSize.height; tileHeight *= 2)
2031 {
2032 // skip tile sizes that have unsuported aspect ratio
2033 uint32_t aspectRatio = (tileHeight > tileWidth) ? (tileHeight / tileWidth) : (tileWidth / tileHeight);
2034 if (aspectRatio > m_maxAspectRatio)
2035 continue;
2036
2037 // calculate size of shading rate attachment
2038 uint32_t srWidth = (m_cbWidth + tileWidth - 1) / tileWidth;
2039 uint32_t srHeight = (m_cbHeight + tileHeight - 1) / tileHeight;
2040
2041 buildShadingRateObjects(device, vk, m_context.getDefaultAllocator(), 0, srWidth, srHeight, m_srUsage,
2042 VK_IMAGE_TILING_LINEAR);
2043
2044 uint8_t *imagePtr = reinterpret_cast<uint8_t *>(m_srImage[0]->getAllocation().getHostPtr());
2045 uint8_t value = (uint8_t)calculateRate(m_params->srRate.width, m_params->srRate.height);
2046
2047 // fill sr image on the host row by row
2048 vk.getImageSubresourceLayout(device, **m_srImage[0], &imageSubresource, &srImageLayout);
2049 for (uint32_t srTexelRow = 0; srTexelRow < srHeight; srTexelRow++)
2050 {
2051 uint8_t *rowDst = imagePtr + srImageLayout.offset + srImageLayout.rowPitch * srTexelRow;
2052 deMemset(rowDst, value, (size_t)srWidth);
2053 }
2054
2055 const auto dsFormat = m_params->getDSFormat();
2056 Move<VkPipelineLayout> graphicsPipelineLayout =
2057 buildPipelineLayout(device, vk, &(*m_counterBufferDescriptorSetLayout));
2058 Move<VkRenderPass> renderPass = buildRenderPass(device, vk, m_cbFormat, dsFormat, tileWidth, tileHeight);
2059 Move<VkPipeline> graphicsPipeline = buildGraphicsPipeline(
2060 device, vk, 0, *renderPass, m_cbFormat, dsFormat, *graphicsPipelineLayout, *vertShader, *fragShader);
2061
2062 std::vector<FBAttachmentInfo> attachmentInfo{
2063 {m_cbFormat, m_cbUsage, m_cbWidth, m_cbHeight, *m_cbImageView[0]},
2064 {m_params->srFormat, m_srUsage, srWidth, srHeight, *m_srImageView[0]},
2065 };
2066 // This would need an additional attachment with m_dsImageView and a barrier to transition the DS layout.
2067 // See runFragmentShaderMode for more details.
2068 DE_ASSERT(!m_params->useDepthStencil());
2069
2070 Move<VkFramebuffer> framebuffer = buildFramebuffer(device, vk, *renderPass, attachmentInfo);
2071
2072 beginCommandBuffer(vk, *cmdBuffer, 0u);
2073
2074 // wait till sr image layout is changed
2075 VkPipelineStageFlags srcStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
2076 VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR;
2077 VkImageMemoryBarrier srImageBarrierAttachment = makeImageMemoryBarrier(
2078 VK_ACCESS_NONE_KHR, VK_ACCESS_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR, VK_IMAGE_LAYOUT_UNDEFINED,
2079 VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR, **m_srImage[0],
2080 m_defaultImageSubresourceRange);
2081 vk.cmdPipelineBarrier(*cmdBuffer, srcStageMask, dstStageMask, 0, 0, DE_NULL, 0, DE_NULL, 1,
2082 &srImageBarrierAttachment);
2083
2084 // wait till cb image layout is changed
2085 srcStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
2086 dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
2087 VkImageMemoryBarrier cbImageBarrier = makeImageMemoryBarrier(
2088 VK_ACCESS_NONE_KHR, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
2089 VK_IMAGE_LAYOUT_GENERAL, **m_cbImage[0], m_defaultImageSubresourceRange);
2090 vk.cmdPipelineBarrier(*cmdBuffer, srcStageMask, dstStageMask, 0, 0, DE_NULL, 0, DE_NULL, 1,
2091 &cbImageBarrier);
2092
2093 startRendering(*cmdBuffer, *renderPass, *framebuffer, makeRect2D(m_cbWidth, m_cbHeight), attachmentInfo,
2094 tileWidth, tileHeight);
2095
2096 // draw single triangle to cb
2097 vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *graphicsPipelineLayout, 0, 1,
2098 &(*m_counterBufferDescriptorSet), 0, DE_NULL);
2099 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *graphicsPipeline);
2100 vk.cmdDraw(*cmdBuffer, 3u, 1, 0u, 0u);
2101
2102 finishRendering(*cmdBuffer);
2103
2104 // wait till color attachment is fully written
2105 srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
2106 dstStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
2107 memoryBarrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
2108 memoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
2109 vk.cmdPipelineBarrier(*cmdBuffer, srcStageMask, dstStageMask, 0, 1, &memoryBarrier, 0, DE_NULL, 0, DE_NULL);
2110
2111 // read back color buffer image
2112 vk.cmdCopyImageToBuffer(*cmdBuffer, **m_cbImage[0], VK_IMAGE_LAYOUT_GENERAL, **m_cbReadBuffer[0], 1u,
2113 &m_defaultBufferImageCopy);
2114
2115 endCommandBuffer(vk, *cmdBuffer);
2116
2117 // submit commands and wait
2118 const VkQueue queue = m_context.getUniversalQueue();
2119 submitCommandsAndWait(vk, device, queue, cmdBuffer.get());
2120
2121 invalidateAlloc(vk, device, m_cbReadBuffer[0]->getAllocation());
2122 if (!verifyUsingAtomicChecks(tileWidth, tileHeight, m_params->srRate.width, m_params->srRate.height,
2123 (uint32_t *)m_cbReadBuffer[0]->getAllocation().getHostPtr()))
2124 return false;
2125
2126 } // iterate over all possible tile sizes
2127
2128 return true;
2129 }
2130
runTwoSubpassMode(void)2131 bool AttachmentRateInstance::runTwoSubpassMode(void)
2132 {
2133 // Set up a two-subpass render pass with different shading rate attachments used in each subpass.
2134 // Then draw a basic triangle in each subpass and do basic checks.
2135
2136 const InstanceInterface &vki = m_context.getInstanceInterface();
2137 const DeviceInterface &vk = m_context.getDeviceInterface();
2138 VkPhysicalDevice pd = m_context.getPhysicalDevice();
2139 VkDevice device = m_context.getDevice();
2140 uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
2141 VkMemoryBarrier memoryBarrier{VK_STRUCTURE_TYPE_MEMORY_BARRIER, DE_NULL, 0u, 0u};
2142
2143 Move<VkShaderModule> vertShader0 = createShaderModule(vk, device, m_context.getBinaryCollection().get("vert0"), 0);
2144 Move<VkShaderModule> vertShader1 = createShaderModule(vk, device, m_context.getBinaryCollection().get("vert1"), 0);
2145 Move<VkShaderModule> fragShader = createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0);
2146
2147 Move<VkCommandPool> cmdPool =
2148 createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex);
2149 Move<VkCommandBuffer> cmdBuffer = allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
2150
2151 // fetch information about supported rates
2152 uint32_t supportedFragmentShadingRateCount;
2153 std::vector<VkPhysicalDeviceFragmentShadingRateKHR> supportedFragmentShadingRates;
2154 vki.getPhysicalDeviceFragmentShadingRatesKHR(pd, &supportedFragmentShadingRateCount, DE_NULL);
2155 supportedFragmentShadingRates.resize(
2156 supportedFragmentShadingRateCount,
2157 {
2158 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_KHR, // VkStructureType sType;
2159 DE_NULL, // void* pNext;
2160 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlags sampleCounts;
2161 {0, 0} // VkExtent2D fragmentSize;
2162 });
2163 vki.getPhysicalDeviceFragmentShadingRatesKHR(pd, &supportedFragmentShadingRateCount,
2164 &supportedFragmentShadingRates[0]);
2165
2166 // grab min and max tile sieze and biggest and smallest rate
2167 uint32_t sr0Width = (m_cbWidth + m_minTileSize.width - 1) / m_minTileSize.width;
2168 uint32_t sr0Height = (m_cbHeight + m_minTileSize.height - 1) / m_minTileSize.height;
2169 uint32_t sr1Width = (m_cbWidth + m_maxTileSize.width - 1) / m_maxTileSize.width;
2170 uint32_t sr1Height = (m_cbHeight + m_maxTileSize.height - 1) / m_maxTileSize.height;
2171 uint32_t sr0RateWidth = supportedFragmentShadingRates[0].fragmentSize.width; // bigets supported rate
2172 uint32_t sr0RateHeight = supportedFragmentShadingRates[0].fragmentSize.height;
2173 uint32_t sr1RateWidth = supportedFragmentShadingRates[supportedFragmentShadingRateCount - 2]
2174 .fragmentSize.width; // smallest supported rate excluding {1, 1}
2175 uint32_t sr1RateHeight = supportedFragmentShadingRates[supportedFragmentShadingRateCount - 2].fragmentSize.height;
2176
2177 buildColorBufferObjects(device, vk, m_context.getDefaultAllocator(), 0, m_cbUsage);
2178 buildColorBufferObjects(device, vk, m_context.getDefaultAllocator(), 1, m_cbUsage);
2179 buildShadingRateObjects(device, vk, m_context.getDefaultAllocator(), 0, sr0Width, sr0Height, m_srUsage);
2180 buildShadingRateObjects(device, vk, m_context.getDefaultAllocator(), 1, sr1Width, sr1Height, m_srUsage);
2181 buildCounterBufferObjects(device, vk, m_context.getDefaultAllocator());
2182
2183 const auto dsFormat = m_params->getDSFormat();
2184 Move<VkRenderPass> renderPass = buildRenderPass(device, vk, m_cbFormat, dsFormat, m_minTileSize.width,
2185 m_minTileSize.height, m_maxTileSize.width, m_maxTileSize.height);
2186 Move<VkPipelineLayout> pipelineLayout = buildPipelineLayout(device, vk, &(*m_counterBufferDescriptorSetLayout));
2187 Move<VkPipeline> graphicsPipeline0 = buildGraphicsPipeline(device, vk, 0, *renderPass, m_cbFormat, dsFormat,
2188 *pipelineLayout, *vertShader0, *fragShader);
2189 Move<VkPipeline> graphicsPipeline1 = buildGraphicsPipeline(device, vk, 1, *renderPass, m_cbFormat, dsFormat,
2190 *pipelineLayout, *vertShader1, *fragShader);
2191
2192 std::vector<FBAttachmentInfo> attachmentInfo{
2193 {m_cbFormat, m_cbUsage, m_cbWidth, m_cbHeight, *m_cbImageView[0]},
2194 {m_params->srFormat, m_srUsage, sr0Width, sr0Height, *m_srImageView[0]},
2195 {m_cbFormat, m_cbUsage, m_cbWidth, m_cbHeight, *m_cbImageView[1]},
2196 {m_params->srFormat, m_srUsage, sr1Width, sr1Height, *m_srImageView[1]},
2197 };
2198 // This would need an additional attachment with m_dsImageView and a barrier to transition the DS layout.
2199 // See runFragmentShaderMode for more details.
2200 DE_ASSERT(!m_params->useDepthStencil());
2201
2202 Move<VkFramebuffer> framebuffer = buildFramebuffer(device, vk, *renderPass, attachmentInfo);
2203
2204 beginCommandBuffer(vk, *cmdBuffer, 0u);
2205
2206 // change sr image layouts to general
2207 VkPipelineStageFlags srcStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
2208 VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
2209 std::vector<VkImageMemoryBarrier> srImageBarrierGeneral(
2210 2, makeImageMemoryBarrier(VK_ACCESS_NONE_KHR, (VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_TRANSFER_WRITE_BIT),
2211 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, **m_srImage[0],
2212 m_defaultImageSubresourceRange));
2213 srImageBarrierGeneral[1].image = **m_srImage[1];
2214 vk.cmdPipelineBarrier(*cmdBuffer, srcStageMask, dstStageMask, 0, 0, DE_NULL, 0, DE_NULL, 2,
2215 srImageBarrierGeneral.data());
2216
2217 VkClearColorValue clearValues[2] = {{{0, 0, 0, 0}}, {{0, 0, 0, 0}}};
2218 clearValues[0].uint32[0] = calculateRate(sr0RateWidth, sr0RateHeight);
2219 clearValues[1].uint32[0] = calculateRate(sr1RateWidth, sr1RateHeight);
2220 vk.cmdClearColorImage(*cmdBuffer, **m_srImage[0], VK_IMAGE_LAYOUT_GENERAL, &clearValues[0], 1,
2221 &m_defaultImageSubresourceRange);
2222 vk.cmdClearColorImage(*cmdBuffer, **m_srImage[1], VK_IMAGE_LAYOUT_GENERAL, &clearValues[1], 1,
2223 &m_defaultImageSubresourceRange);
2224
2225 // wait till sr data is ready and change sr images layout
2226 srcStageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
2227 dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR;
2228 memoryBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
2229 memoryBarrier.dstAccessMask = VK_ACCESS_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR;
2230 std::vector<VkImageMemoryBarrier> srImageBarrierShadingRate(
2231 2, makeImageMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR,
2232 VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR,
2233 **m_srImage[0], m_defaultImageSubresourceRange));
2234 srImageBarrierShadingRate[1].image = **m_srImage[1];
2235 vk.cmdPipelineBarrier(*cmdBuffer, srcStageMask, dstStageMask, 0, 1, &memoryBarrier, 0, DE_NULL, 2,
2236 srImageBarrierShadingRate.data());
2237
2238 // wait till cb image layouts are changed
2239 srcStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
2240 dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
2241 std::vector<VkImageMemoryBarrier> cbImageBarrier(
2242 2, makeImageMemoryBarrier(VK_ACCESS_NONE_KHR, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
2243 VK_IMAGE_LAYOUT_GENERAL, **m_cbImage[0], m_defaultImageSubresourceRange));
2244 cbImageBarrier[1].image = **m_cbImage[1];
2245 vk.cmdPipelineBarrier(*cmdBuffer, srcStageMask, dstStageMask, 0, 0, DE_NULL, 0, DE_NULL, 2, cbImageBarrier.data());
2246
2247 startRendering(*cmdBuffer, *renderPass, *framebuffer, makeRect2D(m_cbWidth, m_cbHeight), attachmentInfo);
2248
2249 // draw single triangle to first cb
2250 vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0, 1,
2251 &(*m_counterBufferDescriptorSet), 0, DE_NULL);
2252 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *graphicsPipeline0);
2253 vk.cmdDraw(*cmdBuffer, 3u, 1, 0u, 0u);
2254
2255 vk.cmdNextSubpass(*cmdBuffer, VK_SUBPASS_CONTENTS_INLINE);
2256
2257 // draw single triangle to second cb
2258 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *graphicsPipeline1);
2259 vk.cmdDraw(*cmdBuffer, 3u, 1, 0u, 0u);
2260
2261 finishRendering(*cmdBuffer);
2262
2263 // wait till color attachments are fully written
2264 srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
2265 dstStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
2266 memoryBarrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
2267 memoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
2268 vk.cmdPipelineBarrier(*cmdBuffer, srcStageMask, dstStageMask, 0, 1, &memoryBarrier, 0, DE_NULL, 0, DE_NULL);
2269
2270 // read back color buffer images
2271 vk.cmdCopyImageToBuffer(*cmdBuffer, **m_cbImage[0], VK_IMAGE_LAYOUT_GENERAL, **m_cbReadBuffer[0], 1u,
2272 &m_defaultBufferImageCopy);
2273 vk.cmdCopyImageToBuffer(*cmdBuffer, **m_cbImage[1], VK_IMAGE_LAYOUT_GENERAL, **m_cbReadBuffer[1], 1u,
2274 &m_defaultBufferImageCopy);
2275
2276 endCommandBuffer(vk, *cmdBuffer);
2277
2278 // submit commands and wait
2279 const VkQueue queue = m_context.getUniversalQueue();
2280 submitCommandsAndWait(vk, device, queue, cmdBuffer.get());
2281
2282 // read back buffer with color attachment 1 data
2283 Allocation &cb0BuffAlloc = m_cbReadBuffer[0]->getAllocation();
2284 invalidateAlloc(vk, device, cb0BuffAlloc);
2285
2286 // read back buffer with color attachment 2 data
2287 Allocation &cb1BuffAlloc = m_cbReadBuffer[1]->getAllocation();
2288 invalidateAlloc(vk, device, cb1BuffAlloc);
2289
2290 // validate both attachemtns triangle
2291 return (verifyUsingAtomicChecks(m_minTileSize.width, m_minTileSize.height, sr0RateWidth, sr0RateHeight,
2292 (uint32_t *)m_cbReadBuffer[0]->getAllocation().getHostPtr()) &&
2293 verifyUsingAtomicChecks(m_maxTileSize.width, m_maxTileSize.height, sr1RateWidth, sr1RateHeight,
2294 (uint32_t *)m_cbReadBuffer[1]->getAllocation().getHostPtr()));
2295 }
2296
2297 class AttachmentRateTestCase : public TestCase
2298 {
2299 public:
2300 AttachmentRateTestCase(tcu::TestContext &context, const char *name, de::SharedPtr<TestParams> params);
2301 ~AttachmentRateTestCase(void) = default;
2302
2303 void initPrograms(SourceCollections &programCollection) const override;
2304 TestInstance *createInstance(Context &context) const override;
2305 void checkSupport(Context &context) const override;
2306
2307 private:
2308 const de::SharedPtr<TestParams> m_params;
2309 };
2310
AttachmentRateTestCase(tcu::TestContext & context,const char * name,de::SharedPtr<TestParams> params)2311 AttachmentRateTestCase::AttachmentRateTestCase(tcu::TestContext &context, const char *name,
2312 de::SharedPtr<TestParams> params)
2313 : vkt::TestCase(context, name)
2314 , m_params(params)
2315 {
2316 }
2317
checkSupport(Context & context) const2318 void AttachmentRateTestCase::checkSupport(Context &context) const
2319 {
2320 context.requireDeviceFunctionality("VK_KHR_fragment_shading_rate");
2321
2322 if (m_params->useDynamicRendering)
2323 context.requireDeviceFunctionality("VK_KHR_dynamic_rendering");
2324 if (m_params->useImagelessFramebuffer)
2325 context.requireDeviceFunctionality("VK_KHR_imageless_framebuffer");
2326
2327 if (!context.getFragmentShadingRateFeatures().attachmentFragmentShadingRate)
2328 TCU_THROW(NotSupportedError, "attachmentFragmentShadingRate not supported");
2329
2330 const vk::InstanceInterface &vk = context.getInstanceInterface();
2331 const vk::VkPhysicalDevice pd = context.getPhysicalDevice();
2332
2333 VkImageFormatProperties imageProperties;
2334 VkImageUsageFlags srUsage =
2335 VK_IMAGE_USAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
2336
2337 VkResult result = vk.getPhysicalDeviceImageFormatProperties(pd, m_params->srFormat, VK_IMAGE_TYPE_2D,
2338 VK_IMAGE_TILING_OPTIMAL, srUsage, 0, &imageProperties);
2339 if (result == VK_ERROR_FORMAT_NOT_SUPPORTED)
2340 TCU_THROW(NotSupportedError, "Format not supported");
2341
2342 if (m_params->mode != TM_TWO_SUBPASS)
2343 {
2344 uint32_t supportedFragmentShadingRateCount;
2345 VkExtent2D testedRate = m_params->srRate;
2346 std::vector<VkPhysicalDeviceFragmentShadingRateKHR> supportedFragmentShadingRates;
2347
2348 // fetch information about supported rates
2349 vk.getPhysicalDeviceFragmentShadingRatesKHR(pd, &supportedFragmentShadingRateCount, DE_NULL);
2350 supportedFragmentShadingRates.resize(
2351 supportedFragmentShadingRateCount,
2352 {
2353 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_KHR, // VkStructureType sType;
2354 DE_NULL, // void* pNext;
2355 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlags sampleCounts;
2356 {0, 0} // VkExtent2D fragmentSize;
2357 });
2358 vk.getPhysicalDeviceFragmentShadingRatesKHR(pd, &supportedFragmentShadingRateCount,
2359 &supportedFragmentShadingRates[0]);
2360
2361 // check if rate required by test is not supported
2362 if (std::none_of(supportedFragmentShadingRates.begin(), supportedFragmentShadingRates.end(),
2363 [&testedRate](const VkPhysicalDeviceFragmentShadingRateKHR &r) {
2364 return (r.fragmentSize.width == testedRate.width &&
2365 r.fragmentSize.height == testedRate.height);
2366 }))
2367 {
2368 TCU_THROW(NotSupportedError, "Rate not supported");
2369 }
2370 }
2371
2372 if (m_params->mode == TM_MAINTENANCE_5)
2373 context.requireDeviceFunctionality("VK_KHR_maintenance5");
2374
2375 VkFormatFeatureFlags requiredFeatures = 0;
2376 if (m_params->mode == TM_SETUP_RATE_WITH_ATOMICS_IN_COMPUTE_SHADER)
2377 requiredFeatures =
2378 VK_FORMAT_FEATURE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR | VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT;
2379 else if ((m_params->mode == TM_SETUP_RATE_WITH_COPYING_FROM_OTHER_IMAGE) ||
2380 (m_params->mode == TM_SETUP_RATE_WITH_COPYING_FROM_EXCLUSIVE_IMAGE_USING_TRANSFER_QUEUE) ||
2381 (m_params->mode == TM_SETUP_RATE_WITH_COPYING_FROM_CONCURENT_IMAGE_USING_TRANSFER_QUEUE) ||
2382 (m_params->mode == TM_SETUP_RATE_WITH_LINEAR_TILED_IMAGE))
2383 requiredFeatures = VK_FORMAT_FEATURE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR;
2384 else if (m_params->mode == TM_SETUP_RATE_WITH_FRAGMENT_SHADER)
2385 requiredFeatures =
2386 VK_FORMAT_FEATURE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT;
2387
2388 #if DEBUG_USE_STORE_INSTEAD_OF_ATOMICS == 1
2389 if (m_params->mode == TM_SETUP_RATE_WITH_ATOMICS_IN_COMPUTE_SHADER)
2390 requiredFeatures =
2391 VK_FORMAT_FEATURE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT;
2392 #endif
2393
2394 if (requiredFeatures)
2395 {
2396 const VkFormatProperties formatProperties = getPhysicalDeviceFormatProperties(vk, pd, m_params->srFormat);
2397
2398 if (m_params->mode == TM_SETUP_RATE_WITH_LINEAR_TILED_IMAGE)
2399 {
2400 if ((formatProperties.linearTilingFeatures & requiredFeatures) != requiredFeatures)
2401 TCU_THROW(NotSupportedError, "Required format feature bits not supported");
2402 }
2403 else if ((formatProperties.optimalTilingFeatures & requiredFeatures) != requiredFeatures)
2404 TCU_THROW(NotSupportedError, "Required format feature bits not supported");
2405 }
2406
2407 if (m_params->useDepthStencil())
2408 {
2409 const auto dsFormat = m_params->getDSFormat();
2410 const VkFormatProperties dsFormatProperties = getPhysicalDeviceFormatProperties(vk, pd, dsFormat);
2411
2412 if ((dsFormatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) == 0)
2413 {
2414 std::ostringstream msg;
2415 msg << dsFormat << " not supported";
2416 TCU_THROW(NotSupportedError, msg.str());
2417 }
2418 }
2419 }
2420
initPrograms(SourceCollections & programCollection) const2421 void AttachmentRateTestCase::initPrograms(SourceCollections &programCollection) const
2422 {
2423 uint32_t rateValue = calculateRate(m_params->srRate.width, m_params->srRate.height);
2424
2425 if (m_params->mode == TM_SETUP_RATE_WITH_ATOMICS_IN_COMPUTE_SHADER)
2426 {
2427 std::stringstream compStream;
2428 compStream << "#version 450\n"
2429 "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
2430 "layout(r32ui, binding = 0) coherent uniform highp uimage2D srImage;\n"
2431 "void main (void)\n"
2432 "{\n"
2433 #if DEBUG_USE_STORE_INSTEAD_OF_ATOMICS == 1
2434 " imageStore(srImage, ivec2(gl_GlobalInvocationID.xy), uvec4("
2435 << rateValue
2436 << "));\n"
2437 #else
2438 " imageAtomicAdd(srImage, ivec2(gl_GlobalInvocationID.xy), "
2439 << rateValue
2440 << ");\n"
2441 #endif
2442 "}\n";
2443
2444 programCollection.glslSources.add("comp") << glu::ComputeSource(compStream.str());
2445 }
2446
2447 tcu::StringTemplate vertTemplate(
2448 "#version 450 core\n"
2449 "out gl_PerVertex\n"
2450 "{\n"
2451 " vec4 gl_Position;\n"
2452 "};\n"
2453 "void main()\n"
2454 "{\n"
2455 " gl_Position = vec4(float(1.0 - 2.0 * int(gl_VertexIndex != 1)) * ${SCALE} + ${TRANSLATE},\n"
2456 " float(1.0 - 2.0 * int(gl_VertexIndex > 0)) * ${SCALE} + ${TRANSLATE}, 0.0, 1.0);\n"
2457 "}\n");
2458
2459 std::map<std::string, std::string> specializationMap{
2460 {"SCALE", "0.8"},
2461 {"TRANSLATE", "0.0"},
2462 };
2463
2464 if (m_params->mode == TM_TWO_SUBPASS)
2465 {
2466 specializationMap["SCALE"] = "0.4";
2467 specializationMap["TRANSLATE"] = "-0.5";
2468 programCollection.glslSources.add("vert0") << glu::VertexSource(vertTemplate.specialize(specializationMap));
2469
2470 specializationMap["SCALE"] = "0.4";
2471 specializationMap["TRANSLATE"] = "0.5";
2472 programCollection.glslSources.add("vert1") << glu::VertexSource(vertTemplate.specialize(specializationMap));
2473 }
2474 else
2475 {
2476 programCollection.glslSources.add("vert") << glu::VertexSource(vertTemplate.specialize(specializationMap));
2477 }
2478
2479 if ((m_params->mode == TM_SETUP_RATE_WITH_FRAGMENT_SHADER) || (m_params->mode == TM_MEMORY_ACCESS) ||
2480 (m_params->mode == TM_MAINTENANCE_5))
2481 {
2482 // use large triangle that will cover whole color buffer
2483 specializationMap["SCALE"] = "9.0";
2484 specializationMap["TRANSLATE"] = "0.0";
2485 programCollection.glslSources.add("vert_setup")
2486 << glu::VertexSource(vertTemplate.specialize(specializationMap));
2487
2488 std::stringstream fragStream;
2489 fragStream << "#version 450 core\n"
2490 "layout(location = 0) out uint outColor;\n"
2491 "void main()\n"
2492 "{\n"
2493 " outColor.x = "
2494 << rateValue
2495 << ";\n"
2496 "}\n";
2497 programCollection.glslSources.add("frag_setup") << glu::FragmentSource(fragStream.str());
2498 }
2499
2500 std::string frag = "#version 450 core\n"
2501 "#extension GL_EXT_fragment_shading_rate : enable\n"
2502 "layout(set = 0, binding = 0) buffer Block { uint counter; } buf;\n"
2503 "layout(location = 0) out uvec4 outColor;\n"
2504 "void main()\n"
2505 "{\n"
2506 " outColor.x = gl_ShadingRateEXT;\n"
2507 " outColor.y = 0;\n"
2508 " outColor.z = atomicAdd(buf.counter, 1);\n"
2509 " outColor.w = 0;\n"
2510 "}\n";
2511 programCollection.glslSources.add("frag") << glu::FragmentSource(frag);
2512 }
2513
createInstance(Context & context) const2514 TestInstance *AttachmentRateTestCase::createInstance(Context &context) const
2515 {
2516 return new AttachmentRateInstance(context, m_params);
2517 }
2518
2519 } // namespace
2520
createAttachmentRateTests(tcu::TestContext & testCtx,tcu::TestCaseGroup * parentGroup,SharedGroupParams groupParams)2521 void createAttachmentRateTests(tcu::TestContext &testCtx, tcu::TestCaseGroup *parentGroup,
2522 SharedGroupParams groupParams)
2523 {
2524 struct SRFormat
2525 {
2526 VkFormat format;
2527 const char *name;
2528 };
2529
2530 const std::vector<SRFormat> srFormats{
2531 {VK_FORMAT_R8_UINT, "r8_uint"},
2532 {VK_FORMAT_R8G8_UINT, "r8g8_uint"},
2533 {VK_FORMAT_R8G8B8_UINT, "r8g8b8_uint"},
2534 {VK_FORMAT_R8G8B8A8_UINT, "r8g8b8a8_uint"},
2535 {VK_FORMAT_R16_UINT, "r16_uint"},
2536 {VK_FORMAT_R16G16_UINT, "r16g16_uint"},
2537 {VK_FORMAT_R16G16B16_UINT, "r16g16b16_uint"},
2538 {VK_FORMAT_R16G16B16A16_UINT, "r16g16b16a16_uint"},
2539 {VK_FORMAT_R32_UINT, "r32_uint"},
2540 {VK_FORMAT_R32G32_UINT, "r32g32_uint"},
2541 {VK_FORMAT_R32G32B32_UINT, "r32g32b32_uint"},
2542 {VK_FORMAT_R32G32B32A32_UINT, "r32g32b32a32_uint"},
2543 {VK_FORMAT_R64_UINT, "r64_uint"},
2544 {VK_FORMAT_R64G64_UINT, "r64g64_uint"},
2545 {VK_FORMAT_R64G64B64_UINT, "r64g64b64_uint"},
2546 {VK_FORMAT_R64G64B64A64_UINT, "r64g64b64a64_uint"},
2547 };
2548
2549 struct SRRate
2550 {
2551 VkExtent2D count;
2552 const char *name;
2553 };
2554
2555 const std::vector<SRRate> srRates{
2556 {{1, 1}, "rate_1x1"}, {{1, 2}, "rate_1x2"}, {{1, 4}, "rate_1x4"}, {{2, 1}, "rate_2x1"}, {{2, 2}, "rate_2x2"},
2557 {{2, 4}, "rate_2x4"}, {{4, 1}, "rate_4x1"}, {{4, 2}, "rate_4x2"}, {{4, 4}, "rate_4x4"},
2558 };
2559
2560 struct TestModeParam
2561 {
2562 TestMode mode;
2563 const char *name;
2564 };
2565
2566 const std::vector<TestModeParam> testModeParams{
2567 {TM_SETUP_RATE_WITH_ATOMICS_IN_COMPUTE_SHADER, "setup_with_atomics"},
2568 {TM_SETUP_RATE_WITH_FRAGMENT_SHADER, "setup_with_fragment"},
2569 {TM_SETUP_RATE_WITH_COPYING_FROM_OTHER_IMAGE, "setup_with_copying"},
2570 {TM_SETUP_RATE_WITH_COPYING_FROM_CONCURENT_IMAGE_USING_TRANSFER_QUEUE,
2571 "setup_with_copying_using_transfer_queue_concurent"},
2572 {TM_SETUP_RATE_WITH_COPYING_FROM_EXCLUSIVE_IMAGE_USING_TRANSFER_QUEUE,
2573 "setup_with_copying_using_transfer_queue_exclusive"},
2574 {TM_SETUP_RATE_WITH_LINEAR_TILED_IMAGE, "setup_with_linear_tiled_image"},
2575 };
2576
2577 de::MovePtr<tcu::TestCaseGroup> mainGroup(new tcu::TestCaseGroup(testCtx, "attachment_rate"));
2578
2579 for (const auto &testModeParam : testModeParams)
2580 {
2581 de::MovePtr<tcu::TestCaseGroup> testModeGroup(new tcu::TestCaseGroup(testCtx, testModeParam.name));
2582
2583 for (const auto &srFormat : srFormats)
2584 {
2585 de::MovePtr<tcu::TestCaseGroup> formatGroup(new tcu::TestCaseGroup(testCtx, srFormat.name));
2586 for (const auto &srRate : srRates)
2587 {
2588 formatGroup->addChild(
2589 new AttachmentRateTestCase(testCtx, srRate.name,
2590 de::SharedPtr<TestParams>(new TestParams{
2591 testModeParam.mode, // TestMode mode;
2592 srFormat.format, // VkFormat srFormat;
2593 srRate.count, // VkExtent2D srRate;
2594 groupParams->useDynamicRendering, // bool useDynamicRendering;
2595 false, // bool useImagelessFramebuffer;
2596 false, // bool useNullShadingRateImage;
2597 tcu::Nothing, // OptDSParams dsParams;
2598 })));
2599
2600 if (groupParams->useDynamicRendering)
2601 {
2602 // Duplicate all tests using dynamic rendering for NULL shading image.
2603 std::string nullShadingName = std::string(srRate.name) + "_null_shading";
2604 formatGroup->addChild(new AttachmentRateTestCase(testCtx, nullShadingName.c_str(),
2605 de::SharedPtr<TestParams>(new TestParams{
2606 testModeParam.mode, // TestMode mode;
2607 srFormat.format, // VkFormat srFormat;
2608 srRate.count, // VkExtent2D srRate;
2609 false, // bool useDynamicRendering;
2610 false, // bool useImagelessFramebuffer;
2611 true, // bool useNullShadingRateImage;
2612 tcu::Nothing, // OptDSParams dsParams;
2613 })));
2614 }
2615
2616 if (!groupParams->useDynamicRendering)
2617 {
2618 // duplicate all tests for imageless framebuffer
2619 std::string imagelessName = std::string(srRate.name) + "_imageless";
2620 formatGroup->addChild(new AttachmentRateTestCase(testCtx, imagelessName.c_str(),
2621 de::SharedPtr<TestParams>(new TestParams{
2622 testModeParam.mode, // TestMode mode;
2623 srFormat.format, // VkFormat srFormat;
2624 srRate.count, // VkExtent2D srRate;
2625 false, // bool useDynamicRendering;
2626 true, // bool useImagelessFramebuffer;
2627 false, // bool useNullShadingRateImage;
2628 tcu::Nothing, // OptDSParams dsParams;
2629 })));
2630 }
2631 }
2632
2633 testModeGroup->addChild(formatGroup.release());
2634 }
2635
2636 mainGroup->addChild(testModeGroup.release());
2637 }
2638
2639 de::MovePtr<tcu::TestCaseGroup> miscGroup(new tcu::TestCaseGroup(testCtx, "misc"));
2640 if (!groupParams->useDynamicRendering)
2641 {
2642 miscGroup->addChild(new AttachmentRateTestCase(
2643 testCtx, "two_subpass",
2644 de::SharedPtr<TestParams>(new TestParams{
2645 TM_TWO_SUBPASS, // TestMode mode;
2646 VK_FORMAT_R8_UINT, // VkFormat srFormat;
2647 {0, 0}, // VkExtent2D srRate; // not used in TM_TWO_SUBPASS
2648 false, // bool useDynamicRendering;
2649 false, // bool useImagelessFramebuffer;
2650 false, // bool useNullShadingRateImage;
2651 tcu::Nothing, // OptDSParams dsParams;
2652 })));
2653 miscGroup->addChild(new AttachmentRateTestCase(testCtx, "memory_access",
2654 de::SharedPtr<TestParams>(new TestParams{
2655 TM_MEMORY_ACCESS, // TestMode mode;
2656 VK_FORMAT_R8_UINT, // VkFormat srFormat;
2657 {1, 1}, // VkExtent2D srRate;
2658 false, // bool useDynamicRendering;
2659 false, // bool useImagelessFramebuffer;
2660 false, // bool useNullShadingRateImage;
2661 tcu::Nothing, // OptDSParams dsParams;
2662 })));
2663 {
2664 const VkImageLayout testedLayouts[] = {
2665 VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL_KHR,
2666 VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL,
2667 VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL,
2668 VK_IMAGE_LAYOUT_GENERAL,
2669 };
2670
2671 const auto skip = strlen("VK_IMAGE_LAYOUT_");
2672
2673 for (const auto &layout : testedLayouts)
2674 {
2675 const auto dsFormat =
2676 ((layout == VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL) ? VK_FORMAT_S8_UINT : VK_FORMAT_D16_UNORM);
2677 const std::string layoutName = de::toLower(de::toString(layout).substr(skip));
2678 const std::string testName = "ro_ds_" + layoutName;
2679
2680 miscGroup->addChild(
2681 new AttachmentRateTestCase(testCtx, testName.c_str(),
2682 de::SharedPtr<TestParams>(new TestParams{
2683 TM_MEMORY_ACCESS, // TestMode mode;
2684 VK_FORMAT_R8_UINT, // VkFormat srFormat;
2685 {2, 2}, // VkExtent2D srRate;
2686 false, // bool useDynamicRendering;
2687 false, // bool useImagelessFramebuffer;
2688 false, // bool useNullShadingRateImage;
2689 DepthStencilParams{dsFormat, layout}, // OptDSParams dsParams;
2690 })));
2691 }
2692 }
2693 }
2694 else
2695 {
2696 #ifndef CTS_USES_VULKANSC
2697 miscGroup->addChild(new AttachmentRateTestCase(testCtx, "maintenance5",
2698 de::SharedPtr<TestParams>(new TestParams{
2699 TM_MAINTENANCE_5, // TestMode mode;
2700 VK_FORMAT_R8_UINT, // VkFormat srFormat;
2701 {1, 1}, // VkExtent2D srRate;
2702 true, // bool useDynamicRendering;
2703 false, // bool useImagelessFramebuffer;
2704 false, // bool useNullShadingRateImage;
2705 tcu::Nothing // OptDSParams dsParams;
2706 })));
2707 #endif
2708 }
2709 if (!miscGroup->empty())
2710 mainGroup->addChild(miscGroup.release());
2711
2712 parentGroup->addChild(mainGroup.release());
2713 }
2714
2715 } // namespace FragmentShadingRate
2716 } // namespace vkt
2717