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