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