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