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