1 /*-------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2017 Google 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 sparse render target.
22 *//*--------------------------------------------------------------------*/
23
24 #include "vktRenderPassSparseRenderTargetTests.hpp"
25 #include "vktRenderPassTestsUtil.hpp"
26
27 #include "vktTestCaseUtil.hpp"
28 #include "vktTestGroupUtil.hpp"
29
30 #include "vkDefs.hpp"
31 #include "vkImageUtil.hpp"
32 #include "vkMemUtil.hpp"
33 #include "vkPrograms.hpp"
34 #include "vkQueryUtil.hpp"
35 #include "vkRef.hpp"
36 #include "vkRefUtil.hpp"
37 #include "vkTypeUtil.hpp"
38 #include "vkCmdUtil.hpp"
39 #include "vkObjUtil.hpp"
40
41 #include "tcuImageCompare.hpp"
42 #include "tcuResultCollector.hpp"
43 #include "tcuTextureUtil.hpp"
44
45 #include "deUniquePtr.hpp"
46 #include "deSharedPtr.hpp"
47
48 using namespace vk;
49
50 using tcu::UVec4;
51 using tcu::Vec4;
52
53 using tcu::ConstPixelBufferAccess;
54 using tcu::PixelBufferAccess;
55
56 using tcu::TestLog;
57
58 using std::string;
59 using std::vector;
60
61 namespace vkt
62 {
63 namespace
64 {
65 using namespace renderpass;
66
createBufferMemory(const DeviceInterface & vk,VkDevice device,Allocator & allocator,VkBuffer buffer)67 de::MovePtr<Allocation> createBufferMemory(const DeviceInterface &vk, VkDevice device, Allocator &allocator,
68 VkBuffer buffer)
69 {
70 de::MovePtr<Allocation> allocation(
71 allocator.allocate(getBufferMemoryRequirements(vk, device, buffer), MemoryRequirement::HostVisible));
72 VK_CHECK(vk.bindBufferMemory(device, buffer, allocation->getMemory(), allocation->getOffset()));
73 return allocation;
74 }
75
createSparseImageAndMemory(const DeviceInterface & vk,VkDevice device,const VkPhysicalDevice physicalDevice,const InstanceInterface & instance,Allocator & allocator,vector<de::SharedPtr<Allocation>> & allocations,uint32_t universalQueueFamilyIndex,VkQueue sparseQueue,uint32_t sparseQueueFamilyIndex,const VkSemaphore & bindSemaphore,VkFormat format,uint32_t width,uint32_t height)76 Move<VkImage> createSparseImageAndMemory(const DeviceInterface &vk, VkDevice device,
77 const VkPhysicalDevice physicalDevice, const InstanceInterface &instance,
78 Allocator &allocator, vector<de::SharedPtr<Allocation>> &allocations,
79 uint32_t universalQueueFamilyIndex, VkQueue sparseQueue,
80 uint32_t sparseQueueFamilyIndex, const VkSemaphore &bindSemaphore,
81 VkFormat format, uint32_t width, uint32_t height)
82 {
83 uint32_t queueFamilyIndices[] = {universalQueueFamilyIndex, sparseQueueFamilyIndex};
84 const VkSharingMode sharingMode =
85 universalQueueFamilyIndex != sparseQueueFamilyIndex ? VK_SHARING_MODE_CONCURRENT : VK_SHARING_MODE_EXCLUSIVE;
86
87 const VkExtent3D imageExtent = {width, height, 1u};
88
89 const VkImageCreateInfo imageCreateInfo = {VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
90 DE_NULL,
91 VK_IMAGE_CREATE_SPARSE_BINDING_BIT |
92 VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT,
93 VK_IMAGE_TYPE_2D,
94 format,
95 imageExtent,
96 1u,
97 1u,
98 VK_SAMPLE_COUNT_1_BIT,
99 VK_IMAGE_TILING_OPTIMAL,
100 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
101 sharingMode,
102 sharingMode == VK_SHARING_MODE_CONCURRENT ? 2u : 1u,
103 queueFamilyIndices,
104 VK_IMAGE_LAYOUT_UNDEFINED};
105
106 if (!checkSparseImageFormatSupport(physicalDevice, instance, imageCreateInfo))
107 TCU_THROW(NotSupportedError, "The image format does not support sparse operations");
108
109 Move<VkImage> destImage = createImage(vk, device, &imageCreateInfo);
110 allocateAndBindSparseImage(vk, device, physicalDevice, instance, imageCreateInfo, bindSemaphore, sparseQueue,
111 allocator, allocations, mapVkFormat(format), *destImage);
112
113 return destImage;
114 }
115
createImageView(const DeviceInterface & vk,VkDevice device,VkImageViewCreateFlags flags,VkImage image,VkImageViewType viewType,VkFormat format,VkComponentMapping components,VkImageSubresourceRange subresourceRange)116 Move<VkImageView> createImageView(const DeviceInterface &vk, VkDevice device, VkImageViewCreateFlags flags,
117 VkImage image, VkImageViewType viewType, VkFormat format,
118 VkComponentMapping components, VkImageSubresourceRange subresourceRange)
119 {
120 const VkImageViewCreateInfo pCreateInfo = {
121 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, DE_NULL, flags, image, viewType, format, components, subresourceRange,
122 };
123
124 return createImageView(vk, device, &pCreateInfo);
125 }
126
createImageView(const DeviceInterface & vkd,VkDevice device,VkImage image,VkFormat format,VkImageAspectFlags aspect)127 Move<VkImageView> createImageView(const DeviceInterface &vkd, VkDevice device, VkImage image, VkFormat format,
128 VkImageAspectFlags aspect)
129 {
130 const VkImageSubresourceRange range = {aspect, 0u, 1u, 0u, 1u};
131
132 return createImageView(vkd, device, 0u, image, VK_IMAGE_VIEW_TYPE_2D, format, makeComponentMappingRGBA(), range);
133 }
134
createBuffer(const DeviceInterface & vkd,VkDevice device,VkFormat format,uint32_t width,uint32_t height)135 Move<VkBuffer> createBuffer(const DeviceInterface &vkd, VkDevice device, VkFormat format, uint32_t width,
136 uint32_t height)
137 {
138 const VkBufferUsageFlags bufferUsage(VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT);
139 const VkDeviceSize pixelSize = mapVkFormat(format).getPixelSize();
140 const VkBufferCreateInfo createInfo = {VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
141 DE_NULL,
142 0u,
143
144 width * height * pixelSize,
145 bufferUsage,
146
147 VK_SHARING_MODE_EXCLUSIVE,
148 0u,
149 DE_NULL};
150
151 return createBuffer(vkd, device, &createInfo);
152 }
153
154 template <typename AttachmentDesc, typename AttachmentRef, typename SubpassDesc, typename SubpassDep,
155 typename RenderPassCreateInfo>
createRenderPass(const DeviceInterface & vkd,VkDevice device,VkFormat dstFormat)156 Move<VkRenderPass> createRenderPass(const DeviceInterface &vkd, VkDevice device, VkFormat dstFormat)
157 {
158 const AttachmentRef
159 dstAttachmentRef // VkAttachmentReference || VkAttachmentReference2KHR
160 (
161 // || VkStructureType sType;
162 DE_NULL, // || const void* pNext;
163 0u, // uint32_t attachment; || uint32_t attachment;
164 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout layout; || VkImageLayout layout;
165 0u // || VkImageAspectFlags aspectMask;
166 );
167 const AttachmentDesc
168 dstAttachment // VkAttachmentDescription || VkAttachmentDescription2KHR
169 (
170 // || VkStructureType sType;
171 DE_NULL, // || const void* pNext;
172 0u, // VkAttachmentDescriptionFlags flags; || VkAttachmentDescriptionFlags flags;
173 dstFormat, // VkFormat format; || VkFormat format;
174 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples; || VkSampleCountFlagBits samples;
175 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp loadOp; || VkAttachmentLoadOp loadOp;
176 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp; || VkAttachmentStoreOp storeOp;
177 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp; || VkAttachmentLoadOp stencilLoadOp;
178 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp; || VkAttachmentStoreOp stencilStoreOp;
179 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; || VkImageLayout initialLayout;
180 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout finalLayout; || VkImageLayout finalLayout;
181 );
182 const SubpassDesc
183 subpass // VkSubpassDescription || VkSubpassDescription2KHR
184 (
185 // || VkStructureType sType;
186 DE_NULL, // || const void* pNext;
187 (VkSubpassDescriptionFlags)0, // VkSubpassDescriptionFlags flags; || VkSubpassDescriptionFlags flags;
188 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint; || VkPipelineBindPoint pipelineBindPoint;
189 0u, // || uint32_t viewMask;
190 0u, // uint32_t inputAttachmentCount; || uint32_t inputAttachmentCount;
191 DE_NULL, // const VkAttachmentReference* pInputAttachments; || const VkAttachmentReference2KHR* pInputAttachments;
192 1u, // uint32_t colorAttachmentCount; || uint32_t colorAttachmentCount;
193 &dstAttachmentRef, // const VkAttachmentReference* pColorAttachments; || const VkAttachmentReference2KHR* pColorAttachments;
194 DE_NULL, // const VkAttachmentReference* pResolveAttachments; || const VkAttachmentReference2KHR* pResolveAttachments;
195 DE_NULL, // const VkAttachmentReference* pDepthStencilAttachment; || const VkAttachmentReference2KHR* pDepthStencilAttachment;
196 0u, // uint32_t preserveAttachmentCount; || uint32_t preserveAttachmentCount;
197 DE_NULL // const uint32_t* pPreserveAttachments; || const uint32_t* pPreserveAttachments;
198 );
199 const RenderPassCreateInfo
200 renderPassCreator // VkRenderPassCreateInfo || VkRenderPassCreateInfo2KHR
201 (
202 // VkStructureType sType; || VkStructureType sType;
203 DE_NULL, // const void* pNext; || const void* pNext;
204 (VkRenderPassCreateFlags)0u, // VkRenderPassCreateFlags flags; || VkRenderPassCreateFlags flags;
205 1u, // uint32_t attachmentCount; || uint32_t attachmentCount;
206 &dstAttachment, // const VkAttachmentDescription* pAttachments; || const VkAttachmentDescription2KHR* pAttachments;
207 1u, // uint32_t subpassCount; || uint32_t subpassCount;
208 &subpass, // const VkSubpassDescription* pSubpasses; || const VkSubpassDescription2KHR* pSubpasses;
209 0u, // uint32_t dependencyCount; || uint32_t dependencyCount;
210 DE_NULL, // const VkSubpassDependency* pDependencies; || const VkSubpassDependency2KHR* pDependencies;
211 0u, // || uint32_t correlatedViewMaskCount;
212 DE_NULL // || const uint32_t* pCorrelatedViewMasks;
213 );
214
215 return renderPassCreator.createRenderPass(vkd, device);
216 }
217
createRenderPass(const DeviceInterface & vkd,VkDevice device,VkFormat dstFormat,const RenderingType renderingType)218 Move<VkRenderPass> createRenderPass(const DeviceInterface &vkd, VkDevice device, VkFormat dstFormat,
219 const RenderingType renderingType)
220 {
221 switch (renderingType)
222 {
223 case RENDERING_TYPE_RENDERPASS_LEGACY:
224 return createRenderPass<AttachmentDescription1, AttachmentReference1, SubpassDescription1, SubpassDependency1,
225 RenderPassCreateInfo1>(vkd, device, dstFormat);
226 case RENDERING_TYPE_RENDERPASS2:
227 return createRenderPass<AttachmentDescription2, AttachmentReference2, SubpassDescription2, SubpassDependency2,
228 RenderPassCreateInfo2>(vkd, device, dstFormat);
229 case RENDERING_TYPE_DYNAMIC_RENDERING:
230 return Move<VkRenderPass>();
231 default:
232 TCU_THROW(InternalError, "Impossible");
233 }
234 }
235
createFramebuffer(const DeviceInterface & vkd,VkDevice device,VkRenderPass renderPass,VkImageView dstImageView,uint32_t width,uint32_t height)236 Move<VkFramebuffer> createFramebuffer(const DeviceInterface &vkd, VkDevice device, VkRenderPass renderPass,
237 VkImageView dstImageView, uint32_t width, uint32_t height)
238 {
239 // when RenderPass was not created then we are testing dynamic rendering
240 // and we can't create framebuffer without valid RenderPass object
241 if (!renderPass)
242 return Move<VkFramebuffer>();
243
244 const VkFramebufferCreateInfo createInfo = {VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
245 DE_NULL,
246 0u,
247
248 renderPass,
249 1u,
250 &dstImageView,
251
252 width,
253 height,
254 1u};
255
256 return createFramebuffer(vkd, device, &createInfo);
257 }
258
createRenderPipelineLayout(const DeviceInterface & vkd,VkDevice device)259 Move<VkPipelineLayout> createRenderPipelineLayout(const DeviceInterface &vkd, VkDevice device)
260 {
261 const VkPipelineLayoutCreateInfo createInfo = {VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
262 DE_NULL,
263 (vk::VkPipelineLayoutCreateFlags)0,
264
265 0u,
266 DE_NULL,
267
268 0u,
269 DE_NULL};
270
271 return createPipelineLayout(vkd, device, &createInfo);
272 }
273
createRenderPipeline(const DeviceInterface & vkd,VkDevice device,VkRenderPass renderPass,VkFormat format,VkPipelineLayout pipelineLayout,const BinaryCollection & binaryCollection,uint32_t width,uint32_t height)274 Move<VkPipeline> createRenderPipeline(const DeviceInterface &vkd, VkDevice device, VkRenderPass renderPass,
275 VkFormat format, VkPipelineLayout pipelineLayout,
276 const BinaryCollection &binaryCollection, uint32_t width, uint32_t height)
277 {
278 const Unique<VkShaderModule> vertexShaderModule(
279 createShaderModule(vkd, device, binaryCollection.get("quad-vert"), 0u));
280 const Unique<VkShaderModule> fragmentShaderModule(
281 createShaderModule(vkd, device, binaryCollection.get("quad-frag"), 0u));
282
283 const VkPipelineVertexInputStateCreateInfo vertexInputState = {
284 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
285 DE_NULL,
286 (VkPipelineVertexInputStateCreateFlags)0u,
287
288 0u,
289 DE_NULL,
290
291 0u,
292 DE_NULL};
293
294 const std::vector<VkViewport> viewports(1, makeViewport(tcu::UVec2(width, height)));
295 const std::vector<VkRect2D> scissors(1, makeRect2D(tcu::UVec2(width, height)));
296
297 VkPipelineRenderingCreateInfoKHR *pNext = DE_NULL;
298 VkPipelineRenderingCreateInfoKHR renderingCreateInfo{VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR,
299 0u,
300 DE_NULL,
301 1u,
302 &format,
303 VK_FORMAT_UNDEFINED,
304 VK_FORMAT_UNDEFINED};
305 if (renderPass == DE_NULL)
306 pNext = &renderingCreateInfo;
307
308 return makeGraphicsPipeline(
309 vkd, // const DeviceInterface& vk
310 device, // const VkDevice device
311 pipelineLayout, // const VkPipelineLayout pipelineLayout
312 *vertexShaderModule, // const VkShaderModule vertexShaderModule
313 DE_NULL, // const VkShaderModule tessellationControlShaderModule
314 DE_NULL, // const VkShaderModule tessellationEvalShaderModule
315 DE_NULL, // const VkShaderModule geometryShaderModule
316 *fragmentShaderModule, // const VkShaderModule fragmentShaderModule
317 renderPass, // const VkRenderPass renderPass
318 viewports, // const std::vector<VkViewport>& viewports
319 scissors, // const std::vector<VkRect2D>& scissors
320 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, // const VkPrimitiveTopology topology
321 0u, // const uint32_t subpass
322 0u, // const uint32_t patchControlPoints
323 &vertexInputState, // const VkPipelineVertexInputStateCreateInfo* vertexInputStateCreateInfo
324 DE_NULL, // const VkPipelineRasterizationStateCreateInfo* rasterizationStateCreateInfo
325 DE_NULL, // const VkPipelineMultisampleStateCreateInfo* multisampleStateCreateInfo
326 DE_NULL, // const VkPipelineDepthStencilStateCreateInfo* depthStencilStateCreateInfo
327 DE_NULL, // const VkPipelineColorBlendStateCreateInfo* colorBlendStateCreateInfo
328 DE_NULL, // const VkPipelineDynamicStateCreateInfo* dynamicStateCreateInfo
329 pNext); // const void* pNext
330 }
331
beginSecondaryCmdBuffer(const DeviceInterface & vkd,VkCommandBuffer cmdBuffer,VkFormat colorFormat,VkRenderingFlagsKHR renderingFlags=0u)332 void beginSecondaryCmdBuffer(const DeviceInterface &vkd, VkCommandBuffer cmdBuffer, VkFormat colorFormat,
333 VkRenderingFlagsKHR renderingFlags = 0u)
334 {
335 VkCommandBufferInheritanceRenderingInfoKHR inheritanceRenderingInfo{
336 VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_RENDERING_INFO_KHR, // VkStructureType sType;
337 DE_NULL, // const void* pNext;
338 renderingFlags, // VkRenderingFlagsKHR flags;
339 0u, // uint32_t viewMask;
340 1u, // uint32_t colorAttachmentCount;
341 &colorFormat, // const VkFormat* pColorAttachmentFormats;
342 VK_FORMAT_UNDEFINED, // VkFormat depthAttachmentFormat;
343 VK_FORMAT_UNDEFINED, // VkFormat stencilAttachmentFormat;
344 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits rasterizationSamples;
345 };
346 const VkCommandBufferInheritanceInfo bufferInheritanceInfo = initVulkanStructure(&inheritanceRenderingInfo);
347
348 VkCommandBufferUsageFlags usageFlags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
349 if (renderingFlags == 0u)
350 usageFlags |= VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT;
351
352 const VkCommandBufferBeginInfo commandBufBeginParams{
353 VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType;
354 DE_NULL, // const void* pNext;
355 usageFlags, // VkCommandBufferUsageFlags flags;
356 &bufferInheritanceInfo};
357
358 vkd.beginCommandBuffer(cmdBuffer, &commandBufBeginParams);
359 }
360
361 struct TestConfig
362 {
TestConfigvkt::__anon410e28ef0111::TestConfig363 TestConfig(VkFormat format_, const SharedGroupParams groupParams_) : format(format_), groupParams(groupParams_)
364 {
365 }
366
367 VkFormat format;
368 const SharedGroupParams groupParams;
369 };
370
371 class SparseRenderTargetTestInstance : public TestInstance
372 {
373 public:
374 SparseRenderTargetTestInstance(Context &context, TestConfig testConfig);
375 ~SparseRenderTargetTestInstance(void);
376
377 tcu::TestStatus iterate(void);
378
379 template <typename RenderpassSubpass>
380 tcu::TestStatus iterateInternal(void);
381 tcu::TestStatus iterateInternalDynamicRendering(void);
382
383 tcu::TestStatus verify(void);
384
385 private:
386 const SharedGroupParams m_groupParams;
387
388 const uint32_t m_width;
389 const uint32_t m_height;
390 const VkFormat m_format;
391
392 vector<de::SharedPtr<Allocation>> m_allocations;
393
394 const Unique<VkSemaphore> m_bindSemaphore;
395
396 const Unique<VkImage> m_dstImage;
397 const Unique<VkImageView> m_dstImageView;
398
399 const Unique<VkBuffer> m_dstBuffer;
400 const de::UniquePtr<Allocation> m_dstBufferMemory;
401
402 const Unique<VkRenderPass> m_renderPass;
403 const Unique<VkFramebuffer> m_framebuffer;
404
405 const Unique<VkPipelineLayout> m_renderPipelineLayout;
406 const Unique<VkPipeline> m_renderPipeline;
407
408 const Unique<VkCommandPool> m_commandPool;
409 tcu::ResultCollector m_resultCollector;
410 };
411
SparseRenderTargetTestInstance(Context & context,TestConfig testConfig)412 SparseRenderTargetTestInstance::SparseRenderTargetTestInstance(Context &context, TestConfig testConfig)
413 : TestInstance(context)
414 , m_groupParams(testConfig.groupParams)
415 , m_width(32u)
416 , m_height(32u)
417 , m_format(testConfig.format)
418 , m_bindSemaphore(createSemaphore(context.getDeviceInterface(), context.getDevice()))
419 , m_dstImage(createSparseImageAndMemory(
420 context.getDeviceInterface(), context.getDevice(), context.getPhysicalDevice(),
421 context.getInstanceInterface(), context.getDefaultAllocator(), m_allocations,
422 context.getUniversalQueueFamilyIndex(), context.getSparseQueue(), context.getSparseQueueFamilyIndex(),
423 *m_bindSemaphore, m_format, m_width, m_height))
424 , m_dstImageView(createImageView(context.getDeviceInterface(), context.getDevice(), *m_dstImage, m_format,
425 VK_IMAGE_ASPECT_COLOR_BIT))
426 , m_dstBuffer(createBuffer(context.getDeviceInterface(), context.getDevice(), m_format, m_width, m_height))
427 , m_dstBufferMemory(createBufferMemory(context.getDeviceInterface(), context.getDevice(),
428 context.getDefaultAllocator(), *m_dstBuffer))
429 , m_renderPass(createRenderPass(context.getDeviceInterface(), context.getDevice(), m_format,
430 testConfig.groupParams->renderingType))
431 , m_framebuffer(createFramebuffer(context.getDeviceInterface(), context.getDevice(), *m_renderPass, *m_dstImageView,
432 m_width, m_height))
433 , m_renderPipelineLayout(createRenderPipelineLayout(context.getDeviceInterface(), context.getDevice()))
434 , m_renderPipeline(createRenderPipeline(context.getDeviceInterface(), context.getDevice(), *m_renderPass,
435 testConfig.format, *m_renderPipelineLayout, context.getBinaryCollection(),
436 m_width, m_height))
437 , m_commandPool(createCommandPool(context.getDeviceInterface(), context.getDevice(),
438 VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, context.getUniversalQueueFamilyIndex()))
439 {
440 }
441
~SparseRenderTargetTestInstance(void)442 SparseRenderTargetTestInstance::~SparseRenderTargetTestInstance(void)
443 {
444 }
445
iterate(void)446 tcu::TestStatus SparseRenderTargetTestInstance::iterate(void)
447 {
448 switch (m_groupParams->renderingType)
449 {
450 case RENDERING_TYPE_RENDERPASS_LEGACY:
451 return iterateInternal<RenderpassSubpass1>();
452 case RENDERING_TYPE_RENDERPASS2:
453 return iterateInternal<RenderpassSubpass2>();
454 case RENDERING_TYPE_DYNAMIC_RENDERING:
455 return iterateInternalDynamicRendering();
456 default:
457 TCU_THROW(InternalError, "Impossible");
458 }
459 }
460
461 template <typename RenderpassSubpass>
iterateInternal(void)462 tcu::TestStatus SparseRenderTargetTestInstance::iterateInternal(void)
463 {
464 const DeviceInterface &vkd(m_context.getDeviceInterface());
465 const Unique<VkCommandBuffer> commandBuffer(
466 allocateCommandBuffer(vkd, m_context.getDevice(), *m_commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
467 const VkRect2D renderArea = makeRect2D(m_width, m_height);
468
469 beginCommandBuffer(vkd, *commandBuffer);
470
471 const typename RenderpassSubpass::SubpassBeginInfo subpassBeginInfo(DE_NULL, VK_SUBPASS_CONTENTS_INLINE);
472 const VkRenderPassBeginInfo beginInfo{
473 VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, DE_NULL, *m_renderPass, *m_framebuffer, renderArea, 0u, DE_NULL};
474 RenderpassSubpass::cmdBeginRenderPass(vkd, *commandBuffer, &beginInfo, &subpassBeginInfo);
475
476 vkd.cmdBindPipeline(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_renderPipeline);
477 vkd.cmdDraw(*commandBuffer, 6u, 1u, 0u, 0u);
478
479 const typename RenderpassSubpass::SubpassEndInfo subpassEndInfo(DE_NULL);
480 RenderpassSubpass::cmdEndRenderPass(vkd, *commandBuffer, &subpassEndInfo);
481
482 copyImageToBuffer(vkd, *commandBuffer, *m_dstImage, *m_dstBuffer, tcu::IVec2(m_width, m_height));
483
484 endCommandBuffer(vkd, *commandBuffer);
485
486 const VkPipelineStageFlags stageBits[] = {VK_PIPELINE_STAGE_TRANSFER_BIT};
487 submitCommandsAndWait(vkd, m_context.getDevice(), m_context.getUniversalQueue(), *commandBuffer, false, 1u, 1u,
488 &m_bindSemaphore.get(), stageBits);
489
490 return verify();
491 }
492
iterateInternalDynamicRendering(void)493 tcu::TestStatus SparseRenderTargetTestInstance::iterateInternalDynamicRendering(void)
494 {
495 const DeviceInterface &vkd(m_context.getDeviceInterface());
496 const Unique<VkCommandBuffer> cmdBuffer(
497 allocateCommandBuffer(vkd, m_context.getDevice(), *m_commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
498 Move<VkCommandBuffer> secCmdBuffer;
499 const VkRect2D renderArea = makeRect2D(m_width, m_height);
500 const VkClearValue clearValue = makeClearValueColor({0.0f, 0.0f, 0.0f, 1.0f});
501 const VkImageMemoryBarrier barrier{VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
502 DE_NULL,
503
504 0,
505 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
506
507 VK_IMAGE_LAYOUT_UNDEFINED,
508 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
509
510 VK_QUEUE_FAMILY_IGNORED,
511 VK_QUEUE_FAMILY_IGNORED,
512
513 *m_dstImage,
514 {VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u}};
515
516 if (m_groupParams->useSecondaryCmdBuffer)
517 {
518 secCmdBuffer =
519 allocateCommandBuffer(vkd, m_context.getDevice(), *m_commandPool, VK_COMMAND_BUFFER_LEVEL_SECONDARY);
520
521 // record secondary command buffer
522 if (m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
523 {
524 beginSecondaryCmdBuffer(vkd, *secCmdBuffer, m_format,
525 vk::VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT);
526 beginRendering(vkd, *secCmdBuffer, *m_dstImageView, renderArea, clearValue,
527 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_ATTACHMENT_LOAD_OP_DONT_CARE);
528 }
529 else
530 beginSecondaryCmdBuffer(vkd, *secCmdBuffer, m_format);
531
532 vkd.cmdBindPipeline(*secCmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_renderPipeline);
533 vkd.cmdDraw(*secCmdBuffer, 6u, 1u, 0u, 0u);
534
535 if (m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
536 vkd.cmdEndRendering(*secCmdBuffer);
537
538 endCommandBuffer(vkd, *secCmdBuffer);
539
540 // record primary command buffer
541 beginCommandBuffer(vkd, *cmdBuffer, 0u);
542 vkd.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
543 VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u,
544 &barrier);
545
546 if (!m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
547 beginRendering(vkd, *cmdBuffer, *m_dstImageView, renderArea, clearValue,
548 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_ATTACHMENT_LOAD_OP_DONT_CARE,
549 VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS);
550
551 vkd.cmdExecuteCommands(*cmdBuffer, 1u, &*secCmdBuffer);
552
553 if (!m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
554 vkd.cmdEndRendering(*cmdBuffer);
555 }
556 else
557 {
558 beginCommandBuffer(vkd, *cmdBuffer);
559
560 vkd.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
561 VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u,
562 &barrier);
563
564 beginRendering(vkd, *cmdBuffer, *m_dstImageView, renderArea, clearValue,
565 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_ATTACHMENT_LOAD_OP_DONT_CARE);
566
567 vkd.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_renderPipeline);
568 vkd.cmdDraw(*cmdBuffer, 6u, 1u, 0u, 0u);
569
570 vkd.cmdEndRendering(*cmdBuffer);
571 }
572
573 copyImageToBuffer(vkd, *cmdBuffer, *m_dstImage, *m_dstBuffer, tcu::IVec2(m_width, m_height));
574
575 endCommandBuffer(vkd, *cmdBuffer);
576
577 const VkPipelineStageFlags stageBits[] = {VK_PIPELINE_STAGE_TRANSFER_BIT};
578 submitCommandsAndWait(vkd, m_context.getDevice(), m_context.getUniversalQueue(), *cmdBuffer, false, 1u, 1u,
579 &m_bindSemaphore.get(), stageBits);
580
581 return verify();
582 }
583
verify(void)584 tcu::TestStatus SparseRenderTargetTestInstance::verify(void)
585 {
586 const tcu::TextureFormat format(mapVkFormat(m_format));
587 const void *const ptr(m_dstBufferMemory->getHostPtr());
588 const tcu::ConstPixelBufferAccess access(format, m_width, m_height, 1, ptr);
589 tcu::TextureLevel reference(format, m_width, m_height);
590 const tcu::TextureChannelClass channelClass(tcu::getTextureChannelClass(format.type));
591
592 switch (channelClass)
593 {
594 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
595 {
596 const UVec4 bits(tcu::getTextureFormatBitDepth(format).cast<uint32_t>());
597 const UVec4 color(1u << (bits.x() - 1), 1u << (bits.y() - 2), 1u << (bits.z() - 3), 0xffffffff);
598
599 for (uint32_t y = 0; y < m_height; y++)
600 for (uint32_t x = 0; x < m_width; x++)
601 reference.getAccess().setPixel(color, x, y);
602
603 if (!tcu::intThresholdCompare(m_context.getTestContext().getLog(), "", "", reference.getAccess(), access,
604 UVec4(0u), tcu::COMPARE_LOG_ON_ERROR))
605 m_resultCollector.fail("Compare failed.");
606 }
607 break;
608
609 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
610 {
611 const UVec4 bits(tcu::getTextureFormatBitDepth(format).cast<uint32_t>());
612 const UVec4 color(1u << (bits.x() - 2), 1u << (bits.y() - 3), 1u << (bits.z() - 4), 0xffffffff);
613
614 for (uint32_t y = 0; y < m_height; y++)
615 for (uint32_t x = 0; x < m_width; x++)
616 reference.getAccess().setPixel(color, x, y);
617
618 if (!tcu::intThresholdCompare(m_context.getTestContext().getLog(), "", "", reference.getAccess(), access,
619 UVec4(0u), tcu::COMPARE_LOG_ON_ERROR))
620 m_resultCollector.fail("Compare failed.");
621 }
622 break;
623
624 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
625 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
626 {
627 const tcu::TextureFormatInfo info(tcu::getTextureFormatInfo(format));
628 const Vec4 maxValue(info.valueMax);
629 const Vec4 color(maxValue.x() / 2.0f, maxValue.y() / 4.0f, maxValue.z() / 8.0f, maxValue.w());
630
631 for (uint32_t y = 0; y < m_height; y++)
632 for (uint32_t x = 0; x < m_width; x++)
633 {
634 if (tcu::isSRGB(format))
635 reference.getAccess().setPixel(tcu::linearToSRGB(color), x, y);
636 else
637 reference.getAccess().setPixel(color, x, y);
638 }
639
640 {
641 // Allow error of 4 times the minimum presentable difference
642 const Vec4 threshold(
643 4.0f * 1.0f /
644 ((UVec4(1u) << tcu::getTextureFormatMantissaBitDepth(format).cast<uint32_t>()) - 1u).cast<float>());
645
646 if (!tcu::floatThresholdCompare(m_context.getTestContext().getLog(), "", "", reference.getAccess(), access,
647 threshold, tcu::COMPARE_LOG_ON_ERROR))
648 m_resultCollector.fail("Compare failed.");
649 }
650 }
651 break;
652
653 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
654 {
655 const Vec4 color(0.5f, 0.25f, 0.125f, 1.0f);
656
657 for (uint32_t y = 0; y < m_height; y++)
658 for (uint32_t x = 0; x < m_width; x++)
659 {
660 if (tcu::isSRGB(format))
661 reference.getAccess().setPixel(tcu::linearToSRGB(color), x, y);
662 else
663 reference.getAccess().setPixel(color, x, y);
664 }
665
666 {
667 // Convert target format ulps to float ulps and allow 64ulp differences
668 const UVec4 threshold(
669 64u * (UVec4(1u) << (UVec4(23) - tcu::getTextureFormatMantissaBitDepth(format).cast<uint32_t>())));
670
671 if (!tcu::floatUlpThresholdCompare(m_context.getTestContext().getLog(), "", "", reference.getAccess(),
672 access, threshold, tcu::COMPARE_LOG_ON_ERROR))
673 m_resultCollector.fail("Compare failed.");
674 }
675 }
676 break;
677
678 default:
679 DE_FATAL("Unknown channel class");
680 }
681
682 return tcu::TestStatus(m_resultCollector.getResult(), m_resultCollector.getMessage());
683 }
684
685 struct Programs
686 {
initvkt::__anon410e28ef0111::Programs687 void init(vk::SourceCollections &dst, TestConfig testConfig) const
688 {
689 std::ostringstream fragmentShader;
690 const VkFormat format(testConfig.format);
691 const tcu::TextureFormat texFormat(mapVkFormat(format));
692 const UVec4 bits(tcu::getTextureFormatBitDepth(texFormat).cast<uint32_t>());
693 const tcu::TextureChannelClass channelClass(tcu::getTextureChannelClass(texFormat.type));
694
695 dst.glslSources.add("quad-vert") << glu::VertexSource(
696 "#version 450\n"
697 "out gl_PerVertex {\n"
698 "\tvec4 gl_Position;\n"
699 "};\n"
700 "highp float;\n"
701 "void main (void)\n"
702 "{\n"
703 " gl_Position = vec4(((gl_VertexIndex + 2) / 3) % 2 == 0 ? -1.0 : 1.0,\n"
704 " ((gl_VertexIndex + 1) / 3) % 2 == 0 ? -1.0 : 1.0, 0.0, 1.0);\n"
705 "}\n");
706
707 switch (channelClass)
708 {
709 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
710 {
711 fragmentShader << "#version 450\n"
712 "layout(location = 0) out highp uvec4 o_color;\n"
713 "void main (void)\n"
714 "{\n"
715 " o_color = uvec4("
716 << de::toString(1u << (bits.x() - 1)) << ", " << de::toString(1u << (bits.y() - 2)) << ", "
717 << de::toString(1u << (bits.z() - 3))
718 << ", 0xffffffff);"
719 "}\n";
720 }
721 break;
722
723 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
724 {
725 fragmentShader << "#version 450\n"
726 "layout(location = 0) out highp ivec4 o_color;\n"
727 "void main (void)\n"
728 "{\n"
729 " o_color = ivec4("
730 << de::toString(1u << (bits.x() - 2)) << ", " << de::toString(1u << (bits.y() - 3)) << ", "
731 << de::toString(1u << (bits.z() - 4))
732 << ", 0xffffffff);"
733 "}\n";
734 }
735 break;
736
737 default:
738 {
739 fragmentShader << "#version 450\n"
740 "layout(location = 0) out highp vec4 o_color;\n"
741 "void main (void)\n"
742 "{\n"
743 " o_color = vec4(0.5, 0.25, 0.125, 1.0);\n"
744 "}\n";
745 }
746 break;
747 }
748
749 dst.glslSources.add("quad-frag") << glu::FragmentSource(fragmentShader.str());
750 }
751 };
752
formatToName(VkFormat format)753 std::string formatToName(VkFormat format)
754 {
755 const std::string formatStr = de::toString(format);
756 const std::string prefix = "VK_FORMAT_";
757
758 DE_ASSERT(formatStr.substr(0, prefix.length()) == prefix);
759
760 return de::toLower(formatStr.substr(prefix.length()));
761 }
762
763 template <class TestConfigType>
checkSupport(Context & context,TestConfigType config)764 void checkSupport(Context &context, TestConfigType config)
765 {
766 #ifndef CTS_USES_VULKANSC
767 if (config.format == VK_FORMAT_A8_UNORM_KHR)
768 context.requireDeviceFunctionality("VK_KHR_maintenance5");
769 #endif // CTS_USES_VULKANSC
770
771 if (config.groupParams->renderingType == RENDERING_TYPE_RENDERPASS2)
772 context.requireDeviceFunctionality("VK_KHR_create_renderpass2");
773
774 if (config.groupParams->renderingType == RENDERING_TYPE_DYNAMIC_RENDERING)
775 context.requireDeviceFunctionality("VK_KHR_dynamic_rendering");
776
777 const auto &vki = context.getInstanceInterface();
778 const auto &physicalDevice = context.getPhysicalDevice();
779 VkImageFormatProperties formatProperties;
780 const auto result = vki.getPhysicalDeviceImageFormatProperties(
781 physicalDevice, config.format, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL,
782 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, 0u, &formatProperties);
783 if (result == VK_ERROR_FORMAT_NOT_SUPPORTED)
784 {
785 TCU_THROW(NotSupportedError, "Image format not supported");
786 }
787 }
788
initTests(tcu::TestCaseGroup * group,const SharedGroupParams groupParams)789 void initTests(tcu::TestCaseGroup *group, const SharedGroupParams groupParams)
790 {
791 static const VkFormat formats[] = {VK_FORMAT_R5G6B5_UNORM_PACK16,
792 VK_FORMAT_R8_UNORM,
793 VK_FORMAT_R8_SNORM,
794 VK_FORMAT_R8_UINT,
795 VK_FORMAT_R8_SINT,
796 #ifndef CTS_USES_VULKANSC
797 VK_FORMAT_A8_UNORM_KHR,
798 #endif // CTS_USES_VULKANSC
799 VK_FORMAT_R8G8_UNORM,
800 VK_FORMAT_R8G8_SNORM,
801 VK_FORMAT_R8G8_UINT,
802 VK_FORMAT_R8G8_SINT,
803 VK_FORMAT_R8G8B8A8_UNORM,
804 VK_FORMAT_R8G8B8A8_SNORM,
805 VK_FORMAT_R8G8B8A8_UINT,
806 VK_FORMAT_R8G8B8A8_SINT,
807 VK_FORMAT_R8G8B8A8_SRGB,
808 VK_FORMAT_A8B8G8R8_UNORM_PACK32,
809 VK_FORMAT_A8B8G8R8_SNORM_PACK32,
810 VK_FORMAT_A8B8G8R8_UINT_PACK32,
811 VK_FORMAT_A8B8G8R8_SINT_PACK32,
812 VK_FORMAT_A8B8G8R8_SRGB_PACK32,
813 VK_FORMAT_B8G8R8A8_UNORM,
814 VK_FORMAT_B8G8R8A8_SRGB,
815 VK_FORMAT_A2R10G10B10_UNORM_PACK32,
816 VK_FORMAT_A2B10G10R10_UNORM_PACK32,
817 VK_FORMAT_A2B10G10R10_UINT_PACK32,
818 VK_FORMAT_R16_UNORM,
819 VK_FORMAT_R16_SNORM,
820 VK_FORMAT_R16_UINT,
821 VK_FORMAT_R16_SINT,
822 VK_FORMAT_R16_SFLOAT,
823 VK_FORMAT_R16G16_UNORM,
824 VK_FORMAT_R16G16_SNORM,
825 VK_FORMAT_R16G16_UINT,
826 VK_FORMAT_R16G16_SINT,
827 VK_FORMAT_R16G16_SFLOAT,
828 VK_FORMAT_R16G16B16A16_UNORM,
829 VK_FORMAT_R16G16B16A16_SNORM,
830 VK_FORMAT_R16G16B16A16_UINT,
831 VK_FORMAT_R16G16B16A16_SINT,
832 VK_FORMAT_R16G16B16A16_SFLOAT,
833 VK_FORMAT_R32_UINT,
834 VK_FORMAT_R32_SINT,
835 VK_FORMAT_R32_SFLOAT,
836 VK_FORMAT_R32G32_UINT,
837 VK_FORMAT_R32G32_SINT,
838 VK_FORMAT_R32G32_SFLOAT,
839 VK_FORMAT_R32G32B32A32_UINT,
840 VK_FORMAT_R32G32B32A32_SINT,
841 VK_FORMAT_R32G32B32A32_SFLOAT,
842 VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16};
843
844 tcu::TestContext &testCtx(group->getTestContext());
845
846 for (size_t formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); formatNdx++)
847 {
848 const VkFormat format(formats[formatNdx]);
849 const TestConfig testConfig(format, groupParams);
850 string testName(formatToName(format));
851
852 group->addChild(new InstanceFactory1WithSupport<SparseRenderTargetTestInstance, TestConfig,
853 FunctionSupport1<TestConfig>, Programs>(
854 testCtx, testName.c_str(), testConfig,
855 typename FunctionSupport1<TestConfig>::Args(checkSupport, testConfig)));
856 }
857 }
858
859 } // namespace
860
createRenderPassSparseRenderTargetTests(tcu::TestContext & testCtx,const renderpass::SharedGroupParams groupParams)861 tcu::TestCaseGroup *createRenderPassSparseRenderTargetTests(tcu::TestContext &testCtx,
862 const renderpass::SharedGroupParams groupParams)
863 {
864 return createTestGroup(testCtx, "sparserendertarget", initTests, groupParams);
865 }
866
867 } // namespace vkt
868