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