Add test for sparse render target.
[platform/upstream/VK-GL-CTS.git] / external / vulkancts / modules / vulkan / renderpass / vktRenderPassSparseRenderTargetTests.cpp
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
26 #include "vktTestCaseUtil.hpp"
27 #include "vktTestGroupUtil.hpp"
28 #include "pipeline/vktPipelineImageUtil.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
39 #include "tcuImageCompare.hpp"
40 #include "tcuResultCollector.hpp"
41 #include "tcuTextureUtil.hpp"
42
43 #include "deUniquePtr.hpp"
44 #include "deSharedPtr.hpp"
45
46 using namespace vk;
47
48 using tcu::UVec4;
49 using tcu::Vec4;
50
51 using tcu::ConstPixelBufferAccess;
52 using tcu::PixelBufferAccess;
53
54 using tcu::TestLog;
55
56 using std::string;
57 using std::vector;
58
59 namespace vkt
60 {
61 namespace
62 {
63
64 deUint32 findQueueFamilyIndexWithCaps (const InstanceInterface& vkInstance, VkPhysicalDevice physicalDevice, VkQueueFlags requiredCaps)
65 {
66         const std::vector<VkQueueFamilyProperties>      queueProps      = getPhysicalDeviceQueueFamilyProperties(vkInstance, physicalDevice);
67
68         for (size_t queueNdx = 0; queueNdx < queueProps.size(); queueNdx++)
69         {
70                 if ((queueProps[queueNdx].queueFlags & requiredCaps) == requiredCaps)
71                         return (deUint32)queueNdx;
72         }
73
74         TCU_THROW(NotSupportedError, "No matching queue found");
75 }
76
77 Move<VkDevice> createDevice(const InstanceInterface& vkInstance, VkPhysicalDevice physicalDevice, deUint32 queueFamilyIndex)
78 {
79         const VkPhysicalDeviceFeatures          deviceFeatures      = getPhysicalDeviceFeatures(vkInstance, physicalDevice);
80
81         VkDeviceQueueCreateInfo                 queueInfo;
82         VkDeviceCreateInfo                      deviceInfo;
83         const float                             queuePriority       = 1.0f;
84
85         deMemset(&queueInfo,    0, sizeof(queueInfo));
86         deMemset(&deviceInfo,   0, sizeof(deviceInfo));
87
88         queueInfo.sType                         = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
89         queueInfo.pNext                         = DE_NULL;
90         queueInfo.flags                         = (VkDeviceQueueCreateFlags)0u;
91         queueInfo.queueFamilyIndex              = queueFamilyIndex;
92         queueInfo.queueCount                    = 1u;
93         queueInfo.pQueuePriorities              = &queuePriority;
94
95         deviceInfo.sType                        = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
96         deviceInfo.pNext                        = DE_NULL;
97         deviceInfo.queueCreateInfoCount         = 1u;
98         deviceInfo.pQueueCreateInfos            = &queueInfo;
99         deviceInfo.enabledExtensionCount        = 0u;
100         deviceInfo.ppEnabledExtensionNames      = DE_NULL;
101         deviceInfo.enabledLayerCount            = 0u;
102         deviceInfo.ppEnabledLayerNames          = DE_NULL;
103         deviceInfo.pEnabledFeatures             = &deviceFeatures;
104
105         if (!deviceFeatures.sparseBinding)
106                 TCU_THROW(NotSupportedError, "Sparse binding not supported");
107
108         return createDevice(vkInstance, physicalDevice, &deviceInfo);
109 }
110
111 de::MovePtr<Allocation> createBufferMemory (const DeviceInterface&      vk,
112                                                                                         VkDevice                                device,
113                                                                                         Allocator&                              allocator,
114                                                                                         VkBuffer                                buffer)
115 {
116         de::MovePtr<Allocation> allocation (allocator.allocate(getBufferMemoryRequirements(vk, device, buffer), MemoryRequirement::HostVisible));
117         VK_CHECK(vk.bindBufferMemory(device, buffer, allocation->getMemory(), allocation->getOffset()));
118         return allocation;
119 }
120
121 Move<VkImage> createSparseImageAndMemory (const DeviceInterface&                                vk,
122                                                                                   VkDevice                                                              device,
123                                                                                   const VkPhysicalDevice                                physicalDevice,
124                                                                                   const InstanceInterface&                              instance,
125                                                                                   Allocator&                                                    allocator,
126                                                                                   vector<de::SharedPtr<Allocation> >&   allocations,
127                                                                                   deUint32                                                              queueFamilyIndex,
128                                                                                   VkQueue&                                                              queue,
129                                                                                   const VkSemaphore&                                    bindSemaphore,
130                                                                                   VkFormat                                                              format,
131                                                                                   deUint32                                                              width,
132                                                                                   deUint32                                                              height)
133 {
134         const VkExtent3D                imageExtent                     =
135         {
136                 width,
137                 height,
138                 1u
139         };
140
141         const VkImageCreateInfo imageCreateInfo         =
142         {
143                 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
144                 DE_NULL,
145                 VK_IMAGE_CREATE_SPARSE_BINDING_BIT | VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT,
146                 VK_IMAGE_TYPE_2D,
147                 format,
148                 imageExtent,
149                 1u,
150                 1u,
151                 VK_SAMPLE_COUNT_1_BIT,
152                 VK_IMAGE_TILING_OPTIMAL,
153                 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
154                 VK_SHARING_MODE_EXCLUSIVE,
155                 1u,
156                 &queueFamilyIndex,
157                 VK_IMAGE_LAYOUT_UNDEFINED
158         };
159
160         Move<VkImage>                   destImage                       = createImage(vk, device, &imageCreateInfo);
161
162         vkt::pipeline::allocateAndBindSparseImage(vk, device, physicalDevice, instance, imageCreateInfo, bindSemaphore, queue, allocator, allocations, mapVkFormat(format), *destImage);
163
164         return destImage;
165 }
166
167 Move<VkImageView> createImageView (const DeviceInterface&       vk,
168                                                                    VkDevice                                     device,
169                                                                    VkImageViewCreateFlags       flags,
170                                                                    VkImage                                      image,
171                                                                    VkImageViewType                      viewType,
172                                                                    VkFormat                                     format,
173                                                                    VkComponentMapping           components,
174                                                                    VkImageSubresourceRange      subresourceRange)
175 {
176         const VkImageViewCreateInfo pCreateInfo =
177         {
178                 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
179                 DE_NULL,
180                 flags,
181                 image,
182                 viewType,
183                 format,
184                 components,
185                 subresourceRange,
186         };
187
188         return createImageView(vk, device, &pCreateInfo);
189 }
190
191 Move<VkImageView> createImageView (const DeviceInterface&       vkd,
192                                                                    VkDevice                                     device,
193                                                                    VkImage                                      image,
194                                                                    VkFormat                                     format,
195                                                                    VkImageAspectFlags           aspect)
196 {
197         const VkImageSubresourceRange range =
198         {
199                 aspect,
200                 0u,
201                 1u,
202                 0u,
203                 1u
204         };
205
206         return createImageView(vkd, device, 0u, image, VK_IMAGE_VIEW_TYPE_2D, format, makeComponentMappingRGBA(), range);
207 }
208
209 Move<VkBuffer> createBuffer (const DeviceInterface&             vkd,
210                                                          VkDevice                                       device,
211                                                          VkFormat                                       format,
212                                                          deUint32                                       width,
213                                                          deUint32                                       height)
214 {
215         const VkBufferUsageFlags        bufferUsage                     (VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT);
216         const VkDeviceSize                      pixelSize                       = mapVkFormat(format).getPixelSize();
217         const VkBufferCreateInfo        createInfo                      =
218         {
219                 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
220                 DE_NULL,
221                 0u,
222
223                 width * height * pixelSize,
224                 bufferUsage,
225
226                 VK_SHARING_MODE_EXCLUSIVE,
227                 0u,
228                 DE_NULL
229         };
230
231         return createBuffer(vkd, device, &createInfo);
232 }
233
234 Move<VkRenderPass> createRenderPass (const DeviceInterface&     vkd,
235                                                                          VkDevice                               device,
236                                                                          VkFormat                               dstFormat)
237 {
238         const VkAttachmentReference             dstAttachmentRef        =
239         {
240                 0u,
241                 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
242         };
243         const VkAttachmentDescription   dstAttachment           =
244         {
245                 0u,
246
247                 dstFormat,
248                 VK_SAMPLE_COUNT_1_BIT,
249
250                 VK_ATTACHMENT_LOAD_OP_DONT_CARE,
251                 VK_ATTACHMENT_STORE_OP_STORE,
252
253                 VK_ATTACHMENT_LOAD_OP_DONT_CARE,
254                 VK_ATTACHMENT_STORE_OP_DONT_CARE,
255
256                 VK_IMAGE_LAYOUT_UNDEFINED,
257                 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
258         };
259         const VkSubpassDescription              subpasses[]                     =
260         {
261                 {
262                         (VkSubpassDescriptionFlags)0,
263                         VK_PIPELINE_BIND_POINT_GRAPHICS,
264
265                         0u,
266                         DE_NULL,
267
268                         1u,
269                         &dstAttachmentRef,
270                         DE_NULL,
271
272                         DE_NULL,
273                         0u,
274                         DE_NULL
275                 }
276         };
277         const VkRenderPassCreateInfo    createInfo                      =
278         {
279                 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
280                 DE_NULL,
281                 (VkRenderPassCreateFlags)0u,
282
283                 1u,
284                 &dstAttachment,
285
286                 1u,
287                 subpasses,
288
289                 0u,
290                 DE_NULL
291         };
292
293         return createRenderPass(vkd, device, &createInfo);
294 }
295
296 Move<VkFramebuffer> createFramebuffer (const DeviceInterface&   vkd,
297                                                                            VkDevice                                     device,
298                                                                            VkRenderPass                         renderPass,
299                                                                            VkImageView                          dstImageView,
300                                                                            deUint32                                     width,
301                                                                            deUint32                                     height)
302 {
303         const VkFramebufferCreateInfo createInfo =
304         {
305                 VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
306                 DE_NULL,
307                 0u,
308
309                 renderPass,
310                 1u,
311                 &dstImageView,
312
313                 width,
314                 height,
315                 1u
316         };
317
318         return createFramebuffer(vkd, device, &createInfo);
319 }
320
321 Move<VkPipelineLayout> createRenderPipelineLayout (const DeviceInterface&       vkd,
322                                                                                                    VkDevice                                     device)
323 {
324         const VkPipelineLayoutCreateInfo createInfo =
325         {
326                 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
327                 DE_NULL,
328                 (vk::VkPipelineLayoutCreateFlags)0,
329
330                 0u,
331                 DE_NULL,
332
333                 0u,
334                 DE_NULL
335         };
336
337         return createPipelineLayout(vkd, device, &createInfo);
338 }
339
340 Move<VkPipeline> createRenderPipeline (const DeviceInterface&                                                   vkd,
341                                                                            VkDevice                                                                                     device,
342                                                                            VkRenderPass                                                                         renderPass,
343                                                                            VkPipelineLayout                                                                     pipelineLayout,
344                                                                            const vk::ProgramCollection<vk::ProgramBinary>&      binaryCollection,
345                                                                            deUint32                                                                                     width,
346                                                                            deUint32                                                                                     height)
347 {
348         const Unique<VkShaderModule>                                    vertexShaderModule                              (createShaderModule(vkd, device, binaryCollection.get("quad-vert"), 0u));
349         const Unique<VkShaderModule>                                    fragmentShaderModule                    (createShaderModule(vkd, device, binaryCollection.get("quad-frag"), 0u));
350         const VkSpecializationInfo                                              emptyShaderSpecializations              =
351         {
352                 0u,
353                 DE_NULL,
354
355                 0u,
356                 DE_NULL
357         };
358         // Disable blending
359         const VkPipelineColorBlendAttachmentState               attachmentBlendState                    =
360         {
361                 VK_FALSE,
362                 VK_BLEND_FACTOR_SRC_ALPHA,
363                 VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,
364                 VK_BLEND_OP_ADD,
365                 VK_BLEND_FACTOR_ONE,
366                 VK_BLEND_FACTOR_ONE,
367                 VK_BLEND_OP_ADD,
368                 VK_COLOR_COMPONENT_R_BIT|VK_COLOR_COMPONENT_G_BIT|VK_COLOR_COMPONENT_B_BIT|VK_COLOR_COMPONENT_A_BIT
369         };
370         const VkPipelineShaderStageCreateInfo                   shaderStages[2]                                 =
371         {
372                 {
373                         VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
374                         DE_NULL,
375                         (VkPipelineShaderStageCreateFlags)0u,
376                         VK_SHADER_STAGE_VERTEX_BIT,
377                         *vertexShaderModule,
378                         "main",
379                         &emptyShaderSpecializations
380                 },
381                 {
382                         VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
383                         DE_NULL,
384                         (VkPipelineShaderStageCreateFlags)0u,
385                         VK_SHADER_STAGE_FRAGMENT_BIT,
386                         *fragmentShaderModule,
387                         "main",
388                         &emptyShaderSpecializations
389                 }
390         };
391         const VkPipelineVertexInputStateCreateInfo              vertexInputState                                =
392         {
393                 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
394                 DE_NULL,
395                 (VkPipelineVertexInputStateCreateFlags)0u,
396
397                 0u,
398                 DE_NULL,
399
400                 0u,
401                 DE_NULL
402         };
403         const VkPipelineInputAssemblyStateCreateInfo    inputAssemblyState                              =
404         {
405                 VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
406                 DE_NULL,
407
408                 (VkPipelineInputAssemblyStateCreateFlags)0u,
409                 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
410                 VK_FALSE
411         };
412         const VkViewport                                                                viewport                                                =
413         {
414                 0.0f,  0.0f,
415                 (float)width, (float)height,
416
417                 0.0f, 1.0f
418         };
419         const VkRect2D                                                                  scissor                                                 =
420         {
421                 { 0u, 0u },
422                 { width, height }
423         };
424         const VkPipelineViewportStateCreateInfo                 viewportState                                   =
425         {
426                 VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
427                 DE_NULL,
428                 (VkPipelineViewportStateCreateFlags)0u,
429
430                 1u,
431                 &viewport,
432
433                 1u,
434                 &scissor
435         };
436         const VkPipelineRasterizationStateCreateInfo    rasterState                                             =
437         {
438                 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
439                 DE_NULL,
440                 (VkPipelineRasterizationStateCreateFlags)0u,
441                 VK_TRUE,
442                 VK_FALSE,
443                 VK_POLYGON_MODE_FILL,
444                 VK_CULL_MODE_NONE,
445                 VK_FRONT_FACE_COUNTER_CLOCKWISE,
446                 VK_FALSE,
447                 0.0f,
448                 0.0f,
449                 0.0f,
450                 1.0f
451         };
452         const VkPipelineMultisampleStateCreateInfo              multisampleState                                =
453         {
454                 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
455                 DE_NULL,
456                 (VkPipelineMultisampleStateCreateFlags)0u,
457
458                 VK_SAMPLE_COUNT_1_BIT,
459                 VK_FALSE,
460                 0.0f,
461                 DE_NULL,
462                 VK_FALSE,
463                 VK_FALSE,
464         };
465         const VkPipelineColorBlendStateCreateInfo               blendState                                              =
466         {
467                 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
468                 DE_NULL,
469                 (VkPipelineColorBlendStateCreateFlags)0u,
470
471                 VK_FALSE,
472                 VK_LOGIC_OP_COPY,
473                 1u,
474                 &attachmentBlendState,
475                 { 0.0f, 0.0f, 0.0f, 0.0f }
476         };
477         const VkGraphicsPipelineCreateInfo                              createInfo                                              =
478         {
479                 VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
480                 DE_NULL,
481                 (VkPipelineCreateFlags)0u,
482
483                 2u,
484                 shaderStages,
485
486                 &vertexInputState,
487                 &inputAssemblyState,
488                 DE_NULL,
489                 &viewportState,
490                 &rasterState,
491                 &multisampleState,
492                 DE_NULL,
493                 &blendState,
494                 (const VkPipelineDynamicStateCreateInfo*)DE_NULL,
495                 pipelineLayout,
496
497                 renderPass,
498                 0u,
499                 DE_NULL,
500                 0u
501         };
502
503         return createGraphicsPipeline(vkd, device, DE_NULL, &createInfo);
504 }
505
506 class SparseRenderTargetTestInstance : public TestInstance
507 {
508 public:
509                                                                                         SparseRenderTargetTestInstance  (Context& context, VkFormat format);
510                                                                                         ~SparseRenderTargetTestInstance (void);
511
512                                                                                         tcu::TestStatus iterate (void);
513
514 private:
515         const deUint32                                                  m_width;
516         const deUint32                                                  m_height;
517         const VkFormat                                                  m_format;
518
519         deUint32                                                                m_queueFamilyIndex;
520         const Unique<VkDevice>                                  m_device;
521         VkQueue                                                                 m_queue;
522
523         SimpleAllocator                                                 m_allocator;
524         vector<de::SharedPtr<Allocation> >              m_allocations;
525
526         const Unique<VkSemaphore>                               m_bindSemaphore;
527
528         const Unique<VkImage>                                   m_dstImage;
529         const Unique<VkImageView>                               m_dstImageView;
530
531         const Unique<VkBuffer>                                  m_dstBuffer;
532         const de::UniquePtr<Allocation>                 m_dstBufferMemory;
533
534         const Unique<VkRenderPass>                              m_renderPass;
535         const Unique<VkFramebuffer>                             m_framebuffer;
536
537         const Unique<VkPipelineLayout>                  m_renderPipelineLayout;
538         const Unique<VkPipeline>                                m_renderPipeline;
539
540         const Unique<VkCommandPool>                             m_commandPool;
541         tcu::ResultCollector                                    m_resultCollector;
542 };
543
544 SparseRenderTargetTestInstance::SparseRenderTargetTestInstance (Context& context, VkFormat format)
545         : TestInstance                          (context)
546         , m_width                                       (32u)
547         , m_height                                      (32u)
548         , m_format                                      (format)
549         , m_queueFamilyIndex            (findQueueFamilyIndexWithCaps(context.getInstanceInterface(), context.getPhysicalDevice(), VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_SPARSE_BINDING_BIT))
550         , m_device                                      (createDevice(context.getInstanceInterface(), context.getPhysicalDevice(), m_queueFamilyIndex))
551         , m_queue                                       (getDeviceQueue(context.getDeviceInterface(), *m_device, m_queueFamilyIndex, 0))
552         , m_allocator                           (context.getDeviceInterface(), *m_device, getPhysicalDeviceMemoryProperties(context.getInstanceInterface(), context.getPhysicalDevice()))
553         , m_bindSemaphore                       (createSemaphore(context.getDeviceInterface(), *m_device))
554         , m_dstImage                            (createSparseImageAndMemory(context.getDeviceInterface(), *m_device, context.getPhysicalDevice(), context.getInstanceInterface(), m_allocator, m_allocations, m_queueFamilyIndex, m_queue, *m_bindSemaphore, m_format, m_width, m_height))
555         , m_dstImageView                        (createImageView(context.getDeviceInterface(), *m_device, *m_dstImage, m_format, VK_IMAGE_ASPECT_COLOR_BIT))
556         , m_dstBuffer                           (createBuffer(context.getDeviceInterface(), *m_device, m_format, m_width, m_height))
557         , m_dstBufferMemory                     (createBufferMemory(context.getDeviceInterface(), *m_device, m_allocator, *m_dstBuffer))
558         , m_renderPass                          (createRenderPass(context.getDeviceInterface(), *m_device, m_format))
559         , m_framebuffer                         (createFramebuffer(context.getDeviceInterface(), *m_device, *m_renderPass, *m_dstImageView, m_width, m_height))
560         , m_renderPipelineLayout        (createRenderPipelineLayout(context.getDeviceInterface(), *m_device))
561         , m_renderPipeline                      (createRenderPipeline(context.getDeviceInterface(), *m_device, *m_renderPass, *m_renderPipelineLayout, context.getBinaryCollection(), m_width, m_height))
562         , m_commandPool                         (createCommandPool(context.getDeviceInterface(), *m_device, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, m_queueFamilyIndex))
563 {
564 }
565
566 SparseRenderTargetTestInstance::~SparseRenderTargetTestInstance (void)
567 {
568 }
569
570 tcu::TestStatus SparseRenderTargetTestInstance::iterate (void)
571 {
572         const DeviceInterface&                  vkd                             (m_context.getDeviceInterface());
573         const Unique<VkCommandBuffer>   commandBuffer   (allocateCommandBuffer(vkd, *m_device, *m_commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
574
575         {
576                 const VkCommandBufferBeginInfo beginInfo =
577                 {
578                         VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
579                         DE_NULL,
580
581                         VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
582                         DE_NULL
583                 };
584
585                 VK_CHECK(vkd.beginCommandBuffer(*commandBuffer, &beginInfo));
586         }
587
588         {
589                 const VkRenderPassBeginInfo beginInfo =
590                 {
591                         VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
592                         DE_NULL,
593
594                         *m_renderPass,
595                         *m_framebuffer,
596
597                         {
598                                 { 0u, 0u },
599                                 { m_width, m_height }
600                         },
601
602                         0u,
603                         DE_NULL
604                 };
605                 vkd.cmdBeginRenderPass(*commandBuffer, &beginInfo, VK_SUBPASS_CONTENTS_INLINE);
606         }
607
608         vkd.cmdBindPipeline(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_renderPipeline);
609         vkd.cmdDraw(*commandBuffer, 6u, 1u, 0u, 0u);
610         vkd.cmdEndRenderPass(*commandBuffer);
611
612         // Memory barrier between rendering and copy
613         {
614                 const VkImageMemoryBarrier barrier =
615                 {
616                         VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
617                         DE_NULL,
618
619                         VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
620                         VK_ACCESS_TRANSFER_READ_BIT,
621
622                         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
623                         VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
624
625                         VK_QUEUE_FAMILY_IGNORED,
626                         VK_QUEUE_FAMILY_IGNORED,
627
628                         *m_dstImage,
629                         {
630                                 VK_IMAGE_ASPECT_COLOR_BIT,
631                                 0u,
632                                 1u,
633                                 0u,
634                                 1u
635                         }
636                 };
637
638                 vkd.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &barrier);
639         }
640
641         // Copy image memory to buffer
642         {
643                 const VkBufferImageCopy region =
644                 {
645                         0u,
646                         0u,
647                         0u,
648                         {
649                                 VK_IMAGE_ASPECT_COLOR_BIT,
650                                 0u,
651                                 0u,
652                                 1u,
653                         },
654                         { 0u, 0u, 0u },
655                         { m_width, m_height, 1u }
656                 };
657
658                 vkd.cmdCopyImageToBuffer(*commandBuffer, *m_dstImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *m_dstBuffer, 1u, &region);
659         }
660
661         // Memory barrier between copy and host access
662         {
663                 const VkBufferMemoryBarrier barrier =
664                 {
665                         VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
666                         DE_NULL,
667
668                         VK_ACCESS_TRANSFER_WRITE_BIT,
669                         VK_ACCESS_HOST_READ_BIT,
670
671                         VK_QUEUE_FAMILY_IGNORED,
672                         VK_QUEUE_FAMILY_IGNORED,
673
674                         *m_dstBuffer,
675                         0u,
676                         VK_WHOLE_SIZE
677                 };
678
679                 vkd.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u, DE_NULL, 1u, &barrier, 0u, DE_NULL);
680         }
681
682         VK_CHECK(vkd.endCommandBuffer(*commandBuffer));
683
684         {
685                 const VkSubmitInfo submitInfo =
686                 {
687                         VK_STRUCTURE_TYPE_SUBMIT_INFO,
688                         DE_NULL,
689
690                         0u,
691                         DE_NULL,
692                         DE_NULL,
693
694                         1u,
695                         &*commandBuffer,
696
697                         0u,
698                         DE_NULL
699                 };
700
701                 VK_CHECK(vkd.queueSubmit(m_queue, 1u, &submitInfo, (VkFence)0u));
702                 VK_CHECK(vkd.queueWaitIdle(m_queue));
703         }
704
705         {
706                 const tcu::TextureFormat                        format                  (mapVkFormat(m_format));
707                 const void* const                                       ptr                             (m_dstBufferMemory->getHostPtr());
708                 const tcu::ConstPixelBufferAccess       access                  (format, m_width, m_height, 1, ptr);
709                 tcu::TextureLevel                                       reference               (format, m_width, m_height);
710                 const tcu::TextureChannelClass          channelClass    (tcu::getTextureChannelClass(format.type));
711
712                 switch (channelClass)
713                 {
714                         case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
715                         {
716                                 const UVec4     bits    (tcu::getTextureFormatBitDepth(format).cast<deUint32>());
717                                 const UVec4     color   (1u << (bits.x()-1), 1u << (bits.y()-2), 1u << (bits.z()-3), 0xffffffff);
718
719                                 for (deUint32 y = 0; y < m_height; y++)
720                                 for (deUint32 x = 0; x < m_width; x++)
721                                 {
722                                         reference.getAccess().setPixel(color, x, y);
723                                 }
724
725                                 if (!tcu::intThresholdCompare(m_context.getTestContext().getLog(), "", "", reference.getAccess(), access, UVec4(0u), tcu::COMPARE_LOG_ON_ERROR))
726                                         m_resultCollector.fail("Compare failed.");
727                         }
728                         break;
729
730                         case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
731                         {
732                                 const UVec4     bits    (tcu::getTextureFormatBitDepth(format).cast<deUint32>());
733                                 const UVec4     color   (1u << (bits.x()-2), 1u << (bits.y()-3), 1u << (bits.z()-4), 0xffffffff);
734
735                                 for (deUint32 y = 0; y < m_height; y++)
736                                 for (deUint32 x = 0; x < m_width; x++)
737                                 {
738                                         reference.getAccess().setPixel(color, x, y);
739                                 }
740
741                                 if (!tcu::intThresholdCompare(m_context.getTestContext().getLog(), "", "", reference.getAccess(), access, UVec4(0u), tcu::COMPARE_LOG_ON_ERROR))
742                                         m_resultCollector.fail("Compare failed.");
743                         }
744                         break;
745
746                         case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
747                         case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
748                         {
749                                 const tcu::TextureFormatInfo    info            (tcu::getTextureFormatInfo(format));
750                                 const Vec4                                              maxValue        (info.valueMax);
751                                 const Vec4                                              color           (maxValue.x() / 2.0f, maxValue.y() / 4.0f, maxValue.z() / 8.0f, maxValue.w());
752
753                                 for (deUint32 y = 0; y < m_height; y++)
754                                 for (deUint32 x = 0; x < m_width; x++)
755                                 {
756                                         if (tcu::isSRGB(format))
757                                                 reference.getAccess().setPixel(tcu::linearToSRGB(color), x, y);
758                                         else
759                                                 reference.getAccess().setPixel(color, x, y);
760                                 }
761
762                                 {
763                                         // Allow error of 4 times the minimum presentable difference
764                                         const Vec4 threshold (4.0f * 1.0f / ((UVec4(1u) << tcu::getTextureFormatMantissaBitDepth(format).cast<deUint32>()) - 1u).cast<float>());
765
766                                         if (!tcu::floatThresholdCompare(m_context.getTestContext().getLog(), "", "", reference.getAccess(), access, threshold, tcu::COMPARE_LOG_ON_ERROR))
767                                                 m_resultCollector.fail("Compare failed.");
768                                 }
769                         }
770                         break;
771
772                         case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
773                         {
774                                 const Vec4 color(0.5f, 0.25f, 0.125f, 1.0f);
775
776                                 for (deUint32 y = 0; y < m_height; y++)
777                                 for (deUint32 x = 0; x < m_width; x++)
778                                 {
779                                         if (tcu::isSRGB(format))
780                                                 reference.getAccess().setPixel(tcu::linearToSRGB(color), x, y);
781                                         else
782                                                 reference.getAccess().setPixel(color, x, y);
783                                 }
784
785                                 {
786                                         // Convert target format ulps to float ulps and allow 64ulp differences
787                                         const UVec4 threshold (64u * (UVec4(1u) << (UVec4(23) - tcu::getTextureFormatMantissaBitDepth(format).cast<deUint32>())));
788
789                                         if (!tcu::floatUlpThresholdCompare(m_context.getTestContext().getLog(), "", "", reference.getAccess(), access, threshold, tcu::COMPARE_LOG_ON_ERROR))
790                                                 m_resultCollector.fail("Compare failed.");
791                                 }
792                         }
793                         break;
794
795                         default:
796                                 DE_FATAL("Unknown channel class");
797                 }
798         }
799
800         return tcu::TestStatus(m_resultCollector.getResult(), m_resultCollector.getMessage());
801 }
802
803 struct Programs
804 {
805         void init (vk::SourceCollections& dst, VkFormat format) const
806         {
807                 std::ostringstream                              fragmentShader;
808                 const tcu::TextureFormat                texFormat               (mapVkFormat(format));
809                 const UVec4                                             bits                    (tcu::getTextureFormatBitDepth(texFormat).cast<deUint32>());
810                 const tcu::TextureChannelClass  channelClass    (tcu::getTextureChannelClass(texFormat.type));
811
812                 dst.glslSources.add("quad-vert") << glu::VertexSource(
813                         "#version 450\n"
814                         "out gl_PerVertex {\n"
815                         "\tvec4 gl_Position;\n"
816                         "};\n"
817                         "highp float;\n"
818                         "void main (void)\n"
819                         "{\n"
820                         "    gl_Position = vec4(((gl_VertexIndex + 2) / 3) % 2 == 0 ? -1.0 : 1.0,\n"
821                         "                       ((gl_VertexIndex + 1) / 3) % 2 == 0 ? -1.0 : 1.0, 0.0, 1.0);\n"
822                         "}\n");
823
824                 switch (channelClass)
825                 {
826                         case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
827                         {
828                                 fragmentShader <<
829                                         "#version 450\n"
830                                         "layout(location = 0) out highp uvec4 o_color;\n"
831                                         "void main (void)\n"
832                                         "{\n"
833                                         "    o_color = uvec4(" << de::toString(1u << (bits.x()-1)) << ", " << de::toString(1u << (bits.y()-2)) << ", " << de::toString(1u << (bits.z()-3)) << ", 0xffffffff);"
834                                         "}\n";
835                         }
836                         break;
837
838                         case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
839                         {
840                                 fragmentShader <<
841                                         "#version 450\n"
842                                         "layout(location = 0) out highp ivec4 o_color;\n"
843                                         "void main (void)\n"
844                                         "{\n"
845                                         "    o_color = ivec4(" << de::toString(1u << (bits.x()-2)) << ", " << de::toString(1u << (bits.y()-3)) << ", " << de::toString(1u << (bits.z()-4)) << ", 0xffffffff);"
846                                         "}\n";
847                         }
848                         break;
849
850                         default:
851                         {
852                                 fragmentShader <<
853                                         "#version 450\n"
854                                         "layout(location = 0) out highp vec4 o_color;\n"
855                                         "void main (void)\n"
856                                         "{\n"
857                                         "    o_color = vec4(0.5, 0.25, 0.125, 1.0);\n"
858                                         "}\n";
859                         }
860                         break;
861                 };
862
863                 dst.glslSources.add("quad-frag") << glu::FragmentSource(fragmentShader.str());
864         }
865 };
866
867 std::string formatToName (VkFormat format)
868 {
869         const std::string       formatStr       = de::toString(format);
870         const std::string       prefix          = "VK_FORMAT_";
871
872         DE_ASSERT(formatStr.substr(0, prefix.length()) == prefix);
873
874         return de::toLower(formatStr.substr(prefix.length()));
875 }
876
877 void initTests (tcu::TestCaseGroup* group)
878 {
879         static const VkFormat   formats[]       =
880         {
881                 VK_FORMAT_R5G6B5_UNORM_PACK16,
882                 VK_FORMAT_R8_UNORM,
883                 VK_FORMAT_R8_SNORM,
884                 VK_FORMAT_R8_UINT,
885                 VK_FORMAT_R8_SINT,
886                 VK_FORMAT_R8G8_UNORM,
887                 VK_FORMAT_R8G8_SNORM,
888                 VK_FORMAT_R8G8_UINT,
889                 VK_FORMAT_R8G8_SINT,
890                 VK_FORMAT_R8G8B8A8_UNORM,
891                 VK_FORMAT_R8G8B8A8_SNORM,
892                 VK_FORMAT_R8G8B8A8_UINT,
893                 VK_FORMAT_R8G8B8A8_SINT,
894                 VK_FORMAT_R8G8B8A8_SRGB,
895                 VK_FORMAT_A8B8G8R8_UNORM_PACK32,
896                 VK_FORMAT_A8B8G8R8_SNORM_PACK32,
897                 VK_FORMAT_A8B8G8R8_UINT_PACK32,
898                 VK_FORMAT_A8B8G8R8_SINT_PACK32,
899                 VK_FORMAT_A8B8G8R8_SRGB_PACK32,
900                 VK_FORMAT_B8G8R8A8_UNORM,
901                 VK_FORMAT_B8G8R8A8_SRGB,
902                 VK_FORMAT_A2R10G10B10_UNORM_PACK32,
903                 VK_FORMAT_A2B10G10R10_UNORM_PACK32,
904                 VK_FORMAT_A2B10G10R10_UINT_PACK32,
905                 VK_FORMAT_R16_UNORM,
906                 VK_FORMAT_R16_SNORM,
907                 VK_FORMAT_R16_UINT,
908                 VK_FORMAT_R16_SINT,
909                 VK_FORMAT_R16_SFLOAT,
910                 VK_FORMAT_R16G16_UNORM,
911                 VK_FORMAT_R16G16_SNORM,
912                 VK_FORMAT_R16G16_UINT,
913                 VK_FORMAT_R16G16_SINT,
914                 VK_FORMAT_R16G16_SFLOAT,
915                 VK_FORMAT_R16G16B16A16_UNORM,
916                 VK_FORMAT_R16G16B16A16_SNORM,
917                 VK_FORMAT_R16G16B16A16_UINT,
918                 VK_FORMAT_R16G16B16A16_SINT,
919                 VK_FORMAT_R16G16B16A16_SFLOAT,
920                 VK_FORMAT_R32_UINT,
921                 VK_FORMAT_R32_SINT,
922                 VK_FORMAT_R32_SFLOAT,
923                 VK_FORMAT_R32G32_UINT,
924                 VK_FORMAT_R32G32_SINT,
925                 VK_FORMAT_R32G32_SFLOAT,
926                 VK_FORMAT_R32G32B32A32_UINT,
927                 VK_FORMAT_R32G32B32A32_SINT,
928                 VK_FORMAT_R32G32B32A32_SFLOAT
929         };
930
931         tcu::TestContext&               testCtx         (group->getTestContext());
932
933         for (size_t formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); formatNdx++)
934         {
935                 const VkFormat  format          (formats[formatNdx]);
936                 string                  testName        (formatToName(format));
937
938                 group->addChild(new InstanceFactory1<SparseRenderTargetTestInstance, VkFormat, Programs>(testCtx, tcu::NODETYPE_SELF_VALIDATE, testName.c_str(), testName.c_str(), format));
939         }
940 }
941
942 } // anonymous
943
944 tcu::TestCaseGroup* createRenderPassSparseRenderTargetTests (tcu::TestContext& testCtx)
945 {
946         return createTestGroup(testCtx, "sparserendertarget", "Sparse render target tests", initTests);
947 }
948
949 } // vkt