Fix texture/sampler mapping in sRGB tests am: 102cfe8b11
[platform/upstream/VK-GL-CTS.git] / external / vulkancts / modules / vulkan / renderpass / vktRenderPassMultisampleResolveTests.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 for render pass multisample resolve
22  *//*--------------------------------------------------------------------*/
23
24 #include "vktRenderPassMultisampleResolveTests.hpp"
25
26 #include "vktTestCaseUtil.hpp"
27 #include "vktTestGroupUtil.hpp"
28
29 #include "vkDefs.hpp"
30 #include "vkDeviceUtil.hpp"
31 #include "vkImageUtil.hpp"
32 #include "vkMemUtil.hpp"
33 #include "vkPlatform.hpp"
34 #include "vkPrograms.hpp"
35 #include "vkQueryUtil.hpp"
36 #include "vkRef.hpp"
37 #include "vkRefUtil.hpp"
38 #include "vkTypeUtil.hpp"
39
40 #include "tcuFloat.hpp"
41 #include "tcuImageCompare.hpp"
42 #include "tcuFormatUtil.hpp"
43 #include "tcuMaybe.hpp"
44 #include "tcuResultCollector.hpp"
45 #include "tcuTestLog.hpp"
46 #include "tcuTextureUtil.hpp"
47 #include "tcuVectorUtil.hpp"
48
49 #include "deUniquePtr.hpp"
50 #include "deSharedPtr.hpp"
51
52 using namespace vk;
53
54 using tcu::BVec4;
55 using tcu::IVec2;
56 using tcu::IVec4;
57 using tcu::UVec2;
58 using tcu::UVec4;
59 using tcu::Vec2;
60 using tcu::Vec4;
61
62 using tcu::Maybe;
63 using tcu::just;
64 using tcu::nothing;
65
66 using tcu::ConstPixelBufferAccess;
67 using tcu::PixelBufferAccess;
68
69 using tcu::TestLog;
70
71 using std::pair;
72 using std::string;
73 using std::vector;
74
75 typedef de::SharedPtr<vk::Unique<VkImage> >             VkImageSp;
76 typedef de::SharedPtr<vk::Unique<VkImageView> > VkImageViewSp;
77 typedef de::SharedPtr<vk::Unique<VkBuffer> >    VkBufferSp;
78 typedef de::SharedPtr<vk::Unique<VkPipeline> >  VkPipelineSp;
79
80 namespace vkt
81 {
82 namespace
83 {
84 enum
85 {
86         MAX_COLOR_ATTACHMENT_COUNT = 4u
87 };
88
89 template<typename T>
90 de::SharedPtr<T> safeSharedPtr (T* ptr)
91 {
92         try
93         {
94                 return de::SharedPtr<T>(ptr);
95         }
96         catch (...)
97         {
98                 delete ptr;
99                 throw;
100         }
101 }
102
103 void bindBufferMemory (const DeviceInterface& vk, VkDevice device, VkBuffer buffer, VkDeviceMemory mem, VkDeviceSize memOffset)
104 {
105         VK_CHECK(vk.bindBufferMemory(device, buffer, mem, memOffset));
106 }
107
108 void bindImageMemory (const DeviceInterface& vk, VkDevice device, VkImage image, VkDeviceMemory mem, VkDeviceSize memOffset)
109 {
110         VK_CHECK(vk.bindImageMemory(device, image, mem, memOffset));
111 }
112
113 de::MovePtr<Allocation> createBufferMemory (const DeviceInterface&      vk,
114                                                                                         VkDevice                                device,
115                                                                                         Allocator&                              allocator,
116                                                                                         VkBuffer                                buffer)
117 {
118         de::MovePtr<Allocation> allocation (allocator.allocate(getBufferMemoryRequirements(vk, device, buffer), MemoryRequirement::HostVisible));
119         bindBufferMemory(vk, device, buffer, allocation->getMemory(), allocation->getOffset());
120         return allocation;
121 }
122
123 de::MovePtr<Allocation> createImageMemory (const DeviceInterface&       vk,
124                                                                                    VkDevice                                     device,
125                                                                                    Allocator&                           allocator,
126                                                                                    VkImage                                      image)
127 {
128         de::MovePtr<Allocation> allocation (allocator.allocate(getImageMemoryRequirements(vk, device, image), MemoryRequirement::Any));
129         bindImageMemory(vk, device, image, allocation->getMemory(), allocation->getOffset());
130         return allocation;
131 }
132
133 Move<VkImage> createImage (const DeviceInterface&       vk,
134                                                    VkDevice                                     device,
135                                                    VkImageCreateFlags           flags,
136                                                    VkImageType                          imageType,
137                                                    VkFormat                                     format,
138                                                    VkExtent3D                           extent,
139                                                    deUint32                                     mipLevels,
140                                                    deUint32                                     arrayLayers,
141                                                    VkSampleCountFlagBits        samples,
142                                                    VkImageTiling                        tiling,
143                                                    VkImageUsageFlags            usage,
144                                                    VkSharingMode                        sharingMode,
145                                                    deUint32                                     queueFamilyCount,
146                                                    const deUint32*                      pQueueFamilyIndices,
147                                                    VkImageLayout                        initialLayout)
148 {
149         const VkImageCreateInfo pCreateInfo =
150         {
151                 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
152                 DE_NULL,
153                 flags,
154                 imageType,
155                 format,
156                 extent,
157                 mipLevels,
158                 arrayLayers,
159                 samples,
160                 tiling,
161                 usage,
162                 sharingMode,
163                 queueFamilyCount,
164                 pQueueFamilyIndices,
165                 initialLayout
166         };
167         return createImage(vk, device, &pCreateInfo);
168 }
169
170 Move<VkImageView> createImageView (const DeviceInterface&       vk,
171                                                                    VkDevice                                     device,
172                                                                    VkImageViewCreateFlags       flags,
173                                                                    VkImage                                      image,
174                                                                    VkImageViewType                      viewType,
175                                                                    VkFormat                                     format,
176                                                                    VkComponentMapping           components,
177                                                                    VkImageSubresourceRange      subresourceRange)
178 {
179         const VkImageViewCreateInfo pCreateInfo =
180         {
181                 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
182                 DE_NULL,
183                 flags,
184                 image,
185                 viewType,
186                 format,
187                 components,
188                 subresourceRange,
189         };
190         return createImageView(vk, device, &pCreateInfo);
191 }
192
193 Move<VkImage> createImage (const InstanceInterface&     vki,
194                                                    VkPhysicalDevice                     physicalDevice,
195                                                    const DeviceInterface&       vkd,
196                                                    VkDevice                                     device,
197                                                    VkFormat                                     vkFormat,
198                                                    VkSampleCountFlagBits        sampleCountBit,
199                                                    VkImageUsageFlags            usage,
200                                                    deUint32                                     width,
201                                                    deUint32                                     height)
202 {
203         try
204         {
205                 const tcu::TextureFormat                format                                  (mapVkFormat(vkFormat));
206                 const VkImageType                               imageType                               (VK_IMAGE_TYPE_2D);
207                 const VkImageTiling                             imageTiling                             (VK_IMAGE_TILING_OPTIMAL);
208                 const VkFormatProperties                formatProperties                (getPhysicalDeviceFormatProperties(vki, physicalDevice, vkFormat));
209                 const VkImageFormatProperties   imageFormatProperties   (getPhysicalDeviceImageFormatProperties(vki, physicalDevice, vkFormat, imageType, imageTiling, usage, 0u));
210                 const VkExtent3D                                imageExtent                             =
211                 {
212                         width,
213                         height,
214                         1u
215                 };
216
217                 if ((tcu::hasDepthComponent(format.order) || tcu::hasStencilComponent(format.order))
218                         && (formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) == 0)
219                         TCU_THROW(NotSupportedError, "Format can't be used as depth stencil attachment");
220
221                 if (!(tcu::hasDepthComponent(format.order) || tcu::hasStencilComponent(format.order))
222                         && (formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT) == 0)
223                         TCU_THROW(NotSupportedError, "Format can't be used as color attachment");
224
225                 if (imageFormatProperties.maxExtent.width < imageExtent.width
226                         || imageFormatProperties.maxExtent.height < imageExtent.height
227                         || ((imageFormatProperties.sampleCounts & sampleCountBit) == 0))
228                 {
229                         TCU_THROW(NotSupportedError, "Image type not supported");
230                 }
231
232                 return createImage(vkd, device, 0u, imageType, vkFormat, imageExtent, 1u, 1u, sampleCountBit, imageTiling, usage, VK_SHARING_MODE_EXCLUSIVE, 0u, DE_NULL, VK_IMAGE_LAYOUT_UNDEFINED);
233         }
234         catch (const vk::Error& error)
235         {
236                 if (error.getError() == VK_ERROR_FORMAT_NOT_SUPPORTED)
237                         TCU_THROW(NotSupportedError, "Image format not supported");
238
239                 throw;
240         }
241 }
242
243 Move<VkImageView> createImageView (const DeviceInterface&       vkd,
244                                                                    VkDevice                                     device,
245                                                                    VkImage                                      image,
246                                                                    VkFormat                                     format,
247                                                                    VkImageAspectFlags           aspect)
248 {
249         const VkImageSubresourceRange   range =
250         {
251                 aspect,
252                 0u,
253                 1u,
254                 0u,
255                 1u
256         };
257
258         return createImageView(vkd, device, 0u, image, VK_IMAGE_VIEW_TYPE_2D, format, makeComponentMappingRGBA(), range);
259 }
260
261 VkDeviceSize getPixelSize (VkFormat vkFormat)
262 {
263         const tcu::TextureFormat        format  (mapVkFormat(vkFormat));
264
265         return format.getPixelSize();
266 }
267
268 Move<VkBuffer> createBuffer (const DeviceInterface&             vkd,
269                                                          VkDevice                                       device,
270                                                          VkFormat                                       format,
271                                                          deUint32                                       width,
272                                                          deUint32                                       height)
273 {
274         const VkBufferUsageFlags        bufferUsage                     (VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT);
275         const VkDeviceSize                      pixelSize                       (getPixelSize(format));
276         const VkBufferCreateInfo        createInfo                      =
277         {
278                 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
279                 DE_NULL,
280                 0u,
281
282                 width * height * pixelSize,
283                 bufferUsage,
284
285                 VK_SHARING_MODE_EXCLUSIVE,
286                 0u,
287                 DE_NULL
288         };
289         return createBuffer(vkd, device, &createInfo);
290 }
291
292 VkSampleCountFlagBits sampleCountBitFromSampleCount (deUint32 count)
293 {
294         switch (count)
295         {
296                 case 1:  return VK_SAMPLE_COUNT_1_BIT;
297                 case 2:  return VK_SAMPLE_COUNT_2_BIT;
298                 case 4:  return VK_SAMPLE_COUNT_4_BIT;
299                 case 8:  return VK_SAMPLE_COUNT_8_BIT;
300                 case 16: return VK_SAMPLE_COUNT_16_BIT;
301                 case 32: return VK_SAMPLE_COUNT_32_BIT;
302                 case 64: return VK_SAMPLE_COUNT_64_BIT;
303
304                 default:
305                         DE_FATAL("Invalid sample count");
306                         return (VkSampleCountFlagBits)0x0;
307         }
308 }
309
310 std::vector<VkImageSp> createMultisampleImages (const InstanceInterface&        vki,
311                                                                                                 VkPhysicalDevice                        physicalDevice,
312                                                                                                 const DeviceInterface&          vkd,
313                                                                                                 VkDevice                                        device,
314                                                                                                 VkFormat                                        format,
315                                                                                                 deUint32                                        sampleCount,
316                                                                                                 deUint32                                        width,
317                                                                                                 deUint32                                        height)
318 {
319         std::vector<VkImageSp> images (MAX_COLOR_ATTACHMENT_COUNT);
320
321         for (size_t imageNdx = 0; imageNdx < images.size(); imageNdx++)
322                 images[imageNdx] = safeSharedPtr(new Unique<VkImage>(createImage(vki, physicalDevice, vkd, device, format, sampleCountBitFromSampleCount(sampleCount), VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, width, height)));
323
324         return images;
325 }
326
327 std::vector<VkImageSp> createSingleSampleImages (const InstanceInterface&       vki,
328                                                                                                  VkPhysicalDevice                       physicalDevice,
329                                                                                                  const DeviceInterface&         vkd,
330                                                                                                  VkDevice                                       device,
331                                                                                                  VkFormat                                       format,
332                                                                                                  deUint32                                       width,
333                                                                                                  deUint32                                       height)
334 {
335         std::vector<VkImageSp> images (MAX_COLOR_ATTACHMENT_COUNT);
336
337         for (size_t imageNdx = 0; imageNdx < images.size(); imageNdx++)
338                 images[imageNdx] = safeSharedPtr(new Unique<VkImage>(createImage(vki, physicalDevice, vkd, device, format, VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, width, height)));
339
340         return images;
341 }
342
343 std::vector<de::SharedPtr<Allocation> > createImageMemory (const DeviceInterface&               vkd,
344                                                                                                                    VkDevice                                             device,
345                                                                                                                    Allocator&                                   allocator,
346                                                                                                                    const std::vector<VkImageSp> images)
347 {
348         std::vector<de::SharedPtr<Allocation> > memory (images.size());
349
350         for (size_t memoryNdx = 0; memoryNdx < memory.size(); memoryNdx++)
351                 memory[memoryNdx] = safeSharedPtr(createImageMemory(vkd, device, allocator, **images[memoryNdx]).release());
352
353         return memory;
354 }
355
356 std::vector<VkImageViewSp> createImageViews (const DeviceInterface&                     vkd,
357                                                                                          VkDevice                                               device,
358                                                                                          const std::vector<VkImageSp>&  images,
359                                                                                          VkFormat                                               format,
360                                                                                          VkImageAspectFlagBits                  aspect)
361 {
362         std::vector<VkImageViewSp> views (images.size());
363
364         for (size_t imageNdx = 0; imageNdx < images.size(); imageNdx++)
365                 views[imageNdx] = safeSharedPtr(new Unique<VkImageView>(createImageView(vkd, device, **images[imageNdx], format, aspect)));
366
367         return views;
368 }
369
370 std::vector<VkBufferSp> createBuffers (const DeviceInterface&   vkd,
371                                                                            VkDevice                                     device,
372                                                                            VkFormat                                     format,
373                                                                            deUint32                                     width,
374                                                                            deUint32                                     height)
375 {
376         std::vector<VkBufferSp> buffers (MAX_COLOR_ATTACHMENT_COUNT);
377
378         for (size_t bufferNdx = 0; bufferNdx < buffers.size(); bufferNdx++)
379                 buffers[bufferNdx] = safeSharedPtr(new Unique<VkBuffer>(createBuffer(vkd, device, format, width, height)));
380
381         return buffers;
382 }
383
384 std::vector<de::SharedPtr<Allocation> > createBufferMemory (const DeviceInterface&                      vkd,
385                                                                                                                         VkDevice                                                device,
386                                                                                                                         Allocator&                                              allocator,
387                                                                                                                         const std::vector<VkBufferSp>   buffers)
388 {
389         std::vector<de::SharedPtr<Allocation> > memory (buffers.size());
390
391         for (size_t memoryNdx = 0; memoryNdx < memory.size(); memoryNdx++)
392                 memory[memoryNdx] = safeSharedPtr(createBufferMemory(vkd, device, allocator, **buffers[memoryNdx]).release());
393
394         return memory;
395 }
396
397 Move<VkRenderPass> createRenderPass (const DeviceInterface&     vkd,
398                                                                          VkDevice                               device,
399                                                                          VkFormat                               format,
400                                                                          deUint32                               sampleCount)
401 {
402         const VkSampleCountFlagBits                             samples                                         (sampleCountBitFromSampleCount(sampleCount));
403         std::vector<VkAttachmentDescription>    attachments;
404         std::vector<VkAttachmentReference>              colorAttachmentRefs;
405         std::vector<VkAttachmentReference>              resolveAttachmentRefs;
406
407         for (size_t attachmentNdx = 0; attachmentNdx < 4; attachmentNdx++)
408         {
409                 {
410                         const VkAttachmentDescription multisampleAttachment =
411                         {
412                                 0u,
413
414                                 format,
415                                 samples,
416
417                                 VK_ATTACHMENT_LOAD_OP_DONT_CARE,
418                                 VK_ATTACHMENT_STORE_OP_DONT_CARE,
419
420                                 VK_ATTACHMENT_LOAD_OP_DONT_CARE,
421                                 VK_ATTACHMENT_STORE_OP_DONT_CARE,
422
423                                 VK_IMAGE_LAYOUT_UNDEFINED,
424                                 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL
425                         };
426                         const VkAttachmentReference attachmentRef =
427                         {
428                                 (deUint32)attachments.size(),
429                                 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
430                         };
431                         colorAttachmentRefs.push_back(attachmentRef);
432                         attachments.push_back(multisampleAttachment);
433                 }
434                 {
435                         const VkAttachmentDescription singlesampleAttachment =
436                         {
437                                 0u,
438
439                                 format,
440                                 VK_SAMPLE_COUNT_1_BIT,
441
442                                 VK_ATTACHMENT_LOAD_OP_DONT_CARE,
443                                 VK_ATTACHMENT_STORE_OP_STORE,
444
445                                 VK_ATTACHMENT_LOAD_OP_DONT_CARE,
446                                 VK_ATTACHMENT_STORE_OP_DONT_CARE,
447
448                                 VK_IMAGE_LAYOUT_UNDEFINED,
449                                 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL
450                         };
451                         const VkAttachmentReference attachmentRef =
452                         {
453                                 (deUint32)attachments.size(),
454                                 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
455                         };
456                         resolveAttachmentRefs.push_back(attachmentRef);
457                         attachments.push_back(singlesampleAttachment);
458                 }
459         }
460
461         DE_ASSERT(colorAttachmentRefs.size() == resolveAttachmentRefs.size());
462         DE_ASSERT(attachments.size() == colorAttachmentRefs.size() + resolveAttachmentRefs.size());
463
464         {
465                 const VkSubpassDescription      subpass =
466                 {
467                         (VkSubpassDescriptionFlags)0,
468                         VK_PIPELINE_BIND_POINT_GRAPHICS,
469
470                         0u,
471                         DE_NULL,
472
473                         (deUint32)colorAttachmentRefs.size(),
474                         &colorAttachmentRefs[0],
475                         &resolveAttachmentRefs[0],
476
477                         DE_NULL,
478                         0u,
479                         DE_NULL
480                 };
481                 const VkRenderPassCreateInfo    createInfo      =
482                 {
483                         VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
484                         DE_NULL,
485                         (VkRenderPassCreateFlags)0u,
486
487                         (deUint32)attachments.size(),
488                         &attachments[0],
489
490                         1u,
491                         &subpass,
492
493                         0u,
494                         DE_NULL
495                 };
496
497                 return createRenderPass(vkd, device, &createInfo);
498         }
499 }
500
501 Move<VkFramebuffer> createFramebuffer (const DeviceInterface&                   vkd,
502                                                                            VkDevice                                                     device,
503                                                                            VkRenderPass                                         renderPass,
504                                                                            const std::vector<VkImageViewSp>&    multisampleImageViews,
505                                                                            const std::vector<VkImageViewSp>&    singlesampleImageViews,
506                                                                            deUint32                                                     width,
507                                                                            deUint32                                                     height)
508 {
509         std::vector<VkImageView> attachments;
510
511         attachments.reserve(multisampleImageViews.size() + singlesampleImageViews.size());
512
513         DE_ASSERT(multisampleImageViews.size() == singlesampleImageViews.size());
514
515         for (size_t ndx = 0; ndx < multisampleImageViews.size(); ndx++)
516         {
517                 attachments.push_back(**multisampleImageViews[ndx]);
518                 attachments.push_back(**singlesampleImageViews[ndx]);
519         }
520
521         const VkFramebufferCreateInfo createInfo =
522         {
523                 VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
524                 DE_NULL,
525                 0u,
526
527                 renderPass,
528                 (deUint32)attachments.size(),
529                 &attachments[0],
530
531                 width,
532                 height,
533                 1u
534         };
535
536         return createFramebuffer(vkd, device, &createInfo);
537 }
538
539 Move<VkPipelineLayout> createRenderPipelineLayout (const DeviceInterface&       vkd,
540                                                                                                    VkDevice                                     device)
541 {
542         const VkPushConstantRange                       pushConstant                    =
543         {
544                 VK_SHADER_STAGE_FRAGMENT_BIT,
545                 0u,
546                 4u
547         };
548         const VkPipelineLayoutCreateInfo        createInfo      =
549         {
550                 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
551                 DE_NULL,
552                 (vk::VkPipelineLayoutCreateFlags)0,
553
554                 0u,
555                 DE_NULL,
556
557                 1u,
558                 &pushConstant
559         };
560
561         return createPipelineLayout(vkd, device, &createInfo);
562 }
563
564 Move<VkPipeline> createRenderPipeline (const DeviceInterface&                                                   vkd,
565                                                                            VkDevice                                                                                     device,
566                                                                            VkRenderPass                                                                         renderPass,
567                                                                            VkPipelineLayout                                                                     pipelineLayout,
568                                                                            const vk::ProgramCollection<vk::ProgramBinary>&      binaryCollection,
569                                                                            deUint32                                                                                     width,
570                                                                            deUint32                                                                                     height,
571                                                                            deUint32                                                                                     sampleCount)
572 {
573         const Unique<VkShaderModule>    vertexShaderModule                      (createShaderModule(vkd, device, binaryCollection.get("quad-vert"), 0u));
574         const Unique<VkShaderModule>    fragmentShaderModule            (createShaderModule(vkd, device, binaryCollection.get("quad-frag"), 0u));
575         const VkSpecializationInfo              emptyShaderSpecializations      =
576         {
577                 0u,
578                 DE_NULL,
579
580                 0u,
581                 DE_NULL
582         };
583         // Disable blending
584         const VkPipelineColorBlendAttachmentState attachmentBlendState =
585         {
586                 VK_FALSE,
587                 VK_BLEND_FACTOR_SRC_ALPHA,
588                 VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,
589                 VK_BLEND_OP_ADD,
590                 VK_BLEND_FACTOR_ONE,
591                 VK_BLEND_FACTOR_ONE,
592                 VK_BLEND_OP_ADD,
593                 VK_COLOR_COMPONENT_R_BIT|VK_COLOR_COMPONENT_G_BIT|VK_COLOR_COMPONENT_B_BIT|VK_COLOR_COMPONENT_A_BIT
594         };
595         const VkPipelineColorBlendAttachmentState attachmentBlendStates[] =
596         {
597                 attachmentBlendState,
598                 attachmentBlendState,
599                 attachmentBlendState,
600                 attachmentBlendState,
601         };
602         const VkPipelineShaderStageCreateInfo shaderStages[2] =
603         {
604                 {
605                         VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
606                         DE_NULL,
607                         (VkPipelineShaderStageCreateFlags)0u,
608                         VK_SHADER_STAGE_VERTEX_BIT,
609                         *vertexShaderModule,
610                         "main",
611                         &emptyShaderSpecializations
612                 },
613                 {
614                         VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
615                         DE_NULL,
616                         (VkPipelineShaderStageCreateFlags)0u,
617                         VK_SHADER_STAGE_FRAGMENT_BIT,
618                         *fragmentShaderModule,
619                         "main",
620                         &emptyShaderSpecializations
621                 }
622         };
623         const VkPipelineVertexInputStateCreateInfo vertexInputState =
624         {
625                 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
626                 DE_NULL,
627                 (VkPipelineVertexInputStateCreateFlags)0u,
628
629                 0u,
630                 DE_NULL,
631
632                 0u,
633                 DE_NULL
634         };
635         const VkPipelineInputAssemblyStateCreateInfo inputAssemblyState =
636         {
637                 VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
638                 DE_NULL,
639
640                 (VkPipelineInputAssemblyStateCreateFlags)0u,
641                 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
642                 VK_FALSE
643         };
644         const VkViewport viewport =
645         {
646                 0.0f,  0.0f,
647                 (float)width, (float)height,
648
649                 0.0f, 1.0f
650         };
651         const VkRect2D scissor =
652         {
653                 { 0u, 0u },
654                 { width, height }
655         };
656         const VkPipelineViewportStateCreateInfo viewportState =
657         {
658                 VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
659                 DE_NULL,
660                 (VkPipelineViewportStateCreateFlags)0u,
661
662                 1u,
663                 &viewport,
664
665                 1u,
666                 &scissor
667         };
668         const VkPipelineRasterizationStateCreateInfo rasterState =
669         {
670                 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
671                 DE_NULL,
672                 (VkPipelineRasterizationStateCreateFlags)0u,
673                 VK_TRUE,
674                 VK_FALSE,
675                 VK_POLYGON_MODE_FILL,
676                 VK_CULL_MODE_NONE,
677                 VK_FRONT_FACE_COUNTER_CLOCKWISE,
678                 VK_FALSE,
679                 0.0f,
680                 0.0f,
681                 0.0f,
682                 1.0f
683         };
684         const VkPipelineMultisampleStateCreateInfo multisampleState =
685         {
686                 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
687                 DE_NULL,
688                 (VkPipelineMultisampleStateCreateFlags)0u,
689
690                 sampleCountBitFromSampleCount(sampleCount),
691                 VK_FALSE,
692                 0.0f,
693                 DE_NULL,
694                 VK_FALSE,
695                 VK_FALSE,
696         };
697         const VkPipelineDepthStencilStateCreateInfo depthStencilState =
698         {
699                 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
700                 DE_NULL,
701                 (VkPipelineDepthStencilStateCreateFlags)0u,
702
703                 VK_FALSE,
704                 VK_TRUE,
705                 VK_COMPARE_OP_ALWAYS,
706                 VK_FALSE,
707                 VK_TRUE,
708                 {
709                         VK_STENCIL_OP_KEEP,
710                         VK_STENCIL_OP_INCREMENT_AND_WRAP,
711                         VK_STENCIL_OP_KEEP,
712                         VK_COMPARE_OP_ALWAYS,
713                         ~0u,
714                         ~0u,
715                         0xFFu / (sampleCount + 1)
716                 },
717                 {
718                         VK_STENCIL_OP_KEEP,
719                         VK_STENCIL_OP_INCREMENT_AND_WRAP,
720                         VK_STENCIL_OP_KEEP,
721                         VK_COMPARE_OP_ALWAYS,
722                         ~0u,
723                         ~0u,
724                         0xFFu / (sampleCount + 1)
725                 },
726
727                 0.0f,
728                 1.0f
729         };
730         const VkPipelineColorBlendStateCreateInfo blendState =
731         {
732                 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
733                 DE_NULL,
734                 (VkPipelineColorBlendStateCreateFlags)0u,
735
736                 VK_FALSE,
737                 VK_LOGIC_OP_COPY,
738                 DE_LENGTH_OF_ARRAY(attachmentBlendStates),
739                 attachmentBlendStates,
740                 { 0.0f, 0.0f, 0.0f, 0.0f }
741         };
742         const VkGraphicsPipelineCreateInfo createInfo =
743         {
744                 VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
745                 DE_NULL,
746                 (VkPipelineCreateFlags)0u,
747
748                 2,
749                 shaderStages,
750
751                 &vertexInputState,
752                 &inputAssemblyState,
753                 DE_NULL,
754                 &viewportState,
755                 &rasterState,
756                 &multisampleState,
757                 &depthStencilState,
758                 &blendState,
759                 (const VkPipelineDynamicStateCreateInfo*)DE_NULL,
760                 pipelineLayout,
761
762                 renderPass,
763                 0u,
764                 DE_NULL,
765                 0u
766         };
767
768         return createGraphicsPipeline(vkd, device, DE_NULL, &createInfo);
769 }
770
771 struct TestConfig
772 {
773                                 TestConfig              (VkFormat       format_,
774                                                                  deUint32       sampleCount_)
775                 : format                (format_)
776                 , sampleCount   (sampleCount_)
777         {
778         }
779
780         VkFormat        format;
781         deUint32        sampleCount;
782 };
783
784 class MultisampleRenderPassTestInstance : public TestInstance
785 {
786 public:
787                                                                                                         MultisampleRenderPassTestInstance       (Context& context, TestConfig config);
788                                                                                                         ~MultisampleRenderPassTestInstance      (void);
789
790         tcu::TestStatus                                                                 iterate                                                         (void);
791
792 private:
793         void                                                                                    submit                                                          (void);
794         void                                                                                    verify                                                          (void);
795
796         const VkFormat                                                                  m_format;
797         const deUint32                                                                  m_sampleCount;
798         const deUint32                                                                  m_width;
799         const deUint32                                                                  m_height;
800
801         const std::vector<VkImageSp>                                    m_multisampleImages;
802         const std::vector<de::SharedPtr<Allocation> >   m_multisampleImageMemory;
803         const std::vector<VkImageViewSp>                                m_multisampleImageViews;
804
805         const std::vector<VkImageSp>                                    m_singlesampleImages;
806         const std::vector<de::SharedPtr<Allocation> >   m_singlesampleImageMemory;
807         const std::vector<VkImageViewSp>                                m_singlesampleImageViews;
808
809         const Unique<VkRenderPass>                                              m_renderPass;
810         const Unique<VkFramebuffer>                                             m_framebuffer;
811
812         const Unique<VkPipelineLayout>                                  m_renderPipelineLayout;
813         const Unique<VkPipeline>                                                m_renderPipeline;
814
815         const std::vector<VkBufferSp>                                   m_buffers;
816         const std::vector<de::SharedPtr<Allocation> >   m_bufferMemory;
817
818         const Unique<VkCommandPool>                                             m_commandPool;
819         tcu::TextureLevel                                                               m_sum;
820         deUint32                                                                                m_sampleMask;
821         tcu::ResultCollector                                                    m_resultCollector;
822 };
823
824 MultisampleRenderPassTestInstance::MultisampleRenderPassTestInstance (Context& context, TestConfig config)
825         : TestInstance                          (context)
826         , m_format                                      (config.format)
827         , m_sampleCount                         (config.sampleCount)
828         , m_width                                       (32u)
829         , m_height                                      (32u)
830
831         , m_multisampleImages           (createMultisampleImages(context.getInstanceInterface(), context.getPhysicalDevice(), context.getDeviceInterface(), context.getDevice(), m_format, m_sampleCount, m_width, m_height))
832         , m_multisampleImageMemory      (createImageMemory(context.getDeviceInterface(), context.getDevice(), context.getDefaultAllocator(), m_multisampleImages))
833         , m_multisampleImageViews       (createImageViews(context.getDeviceInterface(), context.getDevice(), m_multisampleImages, m_format, VK_IMAGE_ASPECT_COLOR_BIT))
834
835         , m_singlesampleImages          (createSingleSampleImages(context.getInstanceInterface(), context.getPhysicalDevice(), context.getDeviceInterface(), context.getDevice(), m_format, m_width, m_height))
836         , m_singlesampleImageMemory     (createImageMemory(context.getDeviceInterface(), context.getDevice(), context.getDefaultAllocator(), m_singlesampleImages))
837         , m_singlesampleImageViews      (createImageViews(context.getDeviceInterface(), context.getDevice(), m_singlesampleImages, m_format, VK_IMAGE_ASPECT_COLOR_BIT))
838
839         , m_renderPass                          (createRenderPass(context.getDeviceInterface(), context.getDevice(), m_format, m_sampleCount))
840         , m_framebuffer                         (createFramebuffer(context.getDeviceInterface(), context.getDevice(), *m_renderPass, m_multisampleImageViews, m_singlesampleImageViews, m_width, m_height))
841
842         , m_renderPipelineLayout        (createRenderPipelineLayout(context.getDeviceInterface(), context.getDevice()))
843         , m_renderPipeline                      (createRenderPipeline(context.getDeviceInterface(), context.getDevice(), *m_renderPass, *m_renderPipelineLayout, context.getBinaryCollection(), m_width, m_height, m_sampleCount))
844
845         , m_buffers                                     (createBuffers(context.getDeviceInterface(), context.getDevice(), m_format, m_width, m_height))
846         , m_bufferMemory                        (createBufferMemory(context.getDeviceInterface(), context.getDevice(), context.getDefaultAllocator(), m_buffers))
847
848         , m_commandPool                         (createCommandPool(context.getDeviceInterface(), context.getDevice(), VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, context.getUniversalQueueFamilyIndex()))
849         , m_sum                                         (tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::FLOAT), m_width, m_height)
850         , m_sampleMask                          (0x0u)
851 {
852         tcu::clear(m_sum.getAccess(), Vec4(0.0f, 0.0f, 0.0f, 0.0f));
853 }
854
855 MultisampleRenderPassTestInstance::~MultisampleRenderPassTestInstance (void)
856 {
857 }
858
859 void MultisampleRenderPassTestInstance::submit (void)
860 {
861         const DeviceInterface&                  vkd                             (m_context.getDeviceInterface());
862         const VkDevice                                  device                  (m_context.getDevice());
863         const Unique<VkCommandBuffer>   commandBuffer   (allocateCommandBuffer(vkd, device, *m_commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
864
865         {
866                 const VkCommandBufferBeginInfo beginInfo =
867                 {
868                         VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
869                         DE_NULL,
870
871                         VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
872                         DE_NULL
873                 };
874
875                 VK_CHECK(vkd.beginCommandBuffer(*commandBuffer, &beginInfo));
876         }
877
878         {
879                 const VkRenderPassBeginInfo beginInfo =
880                 {
881                         VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
882                         DE_NULL,
883
884                         *m_renderPass,
885                         *m_framebuffer,
886
887                         {
888                                 { 0u, 0u },
889                                 { m_width, m_height }
890                         },
891
892                         0u,
893                         DE_NULL
894                 };
895                 vkd.cmdBeginRenderPass(*commandBuffer, &beginInfo, VK_SUBPASS_CONTENTS_INLINE);
896         }
897
898         // Memory barriers between previous copies and rendering
899         {
900                 std::vector<VkImageMemoryBarrier> barriers;
901
902                 for (size_t dstNdx = 0; dstNdx < m_singlesampleImages.size(); dstNdx++)
903                 {
904                         const VkImageMemoryBarrier barrier =
905                         {
906                                 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
907                                 DE_NULL,
908
909                                 VK_ACCESS_TRANSFER_READ_BIT,
910                                 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
911
912                                 VK_IMAGE_LAYOUT_UNDEFINED,
913                                 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
914
915                                 VK_QUEUE_FAMILY_IGNORED,
916                                 VK_QUEUE_FAMILY_IGNORED,
917
918                                 **m_singlesampleImages[dstNdx],
919                                 {
920                                         VK_IMAGE_ASPECT_COLOR_BIT,
921                                         0u,
922                                         1u,
923                                         0u,
924                                         1u
925                                 }
926                         };
927
928                         barriers.push_back(barrier);
929                 }
930
931                 vkd.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, (deUint32)barriers.size(), &barriers[0]);
932         }
933
934         // Clear everything to black
935         {
936                 const tcu::TextureFormat                        format                  (mapVkFormat(m_format));
937                 const tcu::TextureChannelClass          channelClass    (tcu::getTextureChannelClass(format.type));
938                 VkClearValue                                            value;
939
940                 switch (channelClass)
941                 {
942                         case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
943                                 value = makeClearValueColorF32(-1.0f, -1.0f, -1.0f, -1.0f);
944                                 break;
945
946                         case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
947                                 value = makeClearValueColorF32(0.0f, 0.0f, 0.0f, 0.0f);
948                                 break;
949
950                         case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
951                                 value = makeClearValueColorF32(-1.0f, -1.0f, -1.0f, -1.0f);
952                                 break;
953
954                         case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
955                                 value = makeClearValueColorI32(-128, -128, -128, -128);
956                                 break;
957
958                         case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
959                                 value = makeClearValueColorU32(0u, 0u, 0u, 0u);
960                                 break;
961
962                         default:
963                                 DE_FATAL("Unknown channel class");
964                 }
965                 const VkClearAttachment                         colors[]                =
966                 {
967                         {
968                                 VK_IMAGE_ASPECT_COLOR_BIT,
969                                 0u,
970                                 value
971                         },
972                         {
973                                 VK_IMAGE_ASPECT_COLOR_BIT,
974                                 1u,
975                                 value
976                         },
977                         {
978                                 VK_IMAGE_ASPECT_COLOR_BIT,
979                                 2u,
980                                 value
981                         },
982                         {
983                                 VK_IMAGE_ASPECT_COLOR_BIT,
984                                 3u,
985                                 value
986                         }
987                 };
988                 const VkClearRect rect =
989                 {
990                         {
991                                 { 0u, 0u },
992                                 { m_width, m_height }
993                         },
994                         0u,
995                         1u,
996                 };
997                 vkd.cmdClearAttachments(*commandBuffer, DE_LENGTH_OF_ARRAY(colors), colors, 1u, &rect);
998         }
999
1000         // Render black samples
1001         {
1002                 vkd.cmdBindPipeline(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_renderPipeline);
1003                 vkd.cmdPushConstants(*commandBuffer, *m_renderPipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, 0u, sizeof(m_sampleMask), &m_sampleMask);
1004                 vkd.cmdDraw(*commandBuffer, 6u, 1u, 0u, 0u);
1005         }
1006
1007         vkd.cmdEndRenderPass(*commandBuffer);
1008
1009         // Memory barriers between rendering and copies
1010         {
1011                 std::vector<VkImageMemoryBarrier> barriers;
1012
1013                 for (size_t dstNdx = 0; dstNdx < m_singlesampleImages.size(); dstNdx++)
1014                 {
1015                         const VkImageMemoryBarrier barrier =
1016                         {
1017                                 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
1018                                 DE_NULL,
1019
1020                                 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
1021                                 VK_ACCESS_TRANSFER_READ_BIT,
1022
1023                                 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
1024                                 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
1025
1026                                 VK_QUEUE_FAMILY_IGNORED,
1027                                 VK_QUEUE_FAMILY_IGNORED,
1028
1029                                 **m_singlesampleImages[dstNdx],
1030                                 {
1031                                         VK_IMAGE_ASPECT_COLOR_BIT,
1032                                         0u,
1033                                         1u,
1034                                         0u,
1035                                         1u
1036                                 }
1037                         };
1038
1039                         barriers.push_back(barrier);
1040                 }
1041
1042                 vkd.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, (deUint32)barriers.size(), &barriers[0]);
1043         }
1044
1045         // Copy image memory to buffers
1046         for (size_t dstNdx = 0; dstNdx < m_singlesampleImages.size(); dstNdx++)
1047         {
1048                 const VkBufferImageCopy region =
1049                 {
1050                         0u,
1051                         0u,
1052                         0u,
1053                         {
1054                                 VK_IMAGE_ASPECT_COLOR_BIT,
1055                                 0u,
1056                                 0u,
1057                                 1u,
1058                         },
1059                         { 0u, 0u, 0u },
1060                         { m_width, m_height, 1u }
1061                 };
1062
1063                 vkd.cmdCopyImageToBuffer(*commandBuffer, **m_singlesampleImages[dstNdx], VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, **m_buffers[dstNdx], 1u, &region);
1064         }
1065
1066         // Memory barriers between copies and host access
1067         {
1068                 std::vector<VkBufferMemoryBarrier> barriers;
1069
1070                 for (size_t dstNdx = 0; dstNdx < m_buffers.size(); dstNdx++)
1071                 {
1072                         const VkBufferMemoryBarrier barrier =
1073                         {
1074                                 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
1075                                 DE_NULL,
1076
1077                                 VK_ACCESS_TRANSFER_WRITE_BIT,
1078                                 VK_ACCESS_HOST_READ_BIT,
1079
1080                                 VK_QUEUE_FAMILY_IGNORED,
1081                                 VK_QUEUE_FAMILY_IGNORED,
1082
1083                                 **m_buffers[dstNdx],
1084                                 0u,
1085                                 VK_WHOLE_SIZE
1086                         };
1087
1088                         barriers.push_back(barrier);
1089                 }
1090
1091                 vkd.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u, DE_NULL, (deUint32)barriers.size(), &barriers[0], 0u, DE_NULL);
1092         }
1093
1094         VK_CHECK(vkd.endCommandBuffer(*commandBuffer));
1095
1096         {
1097                 const VkSubmitInfo submitInfo =
1098                 {
1099                         VK_STRUCTURE_TYPE_SUBMIT_INFO,
1100                         DE_NULL,
1101
1102                         0u,
1103                         DE_NULL,
1104                         DE_NULL,
1105
1106                         1u,
1107                         &*commandBuffer,
1108
1109                         0u,
1110                         DE_NULL
1111                 };
1112
1113                 VK_CHECK(vkd.queueSubmit(m_context.getUniversalQueue(), 1u, &submitInfo, (VkFence)0u));
1114
1115                 VK_CHECK(vkd.queueWaitIdle(m_context.getUniversalQueue()));
1116         }
1117 }
1118
1119 void MultisampleRenderPassTestInstance::verify (void)
1120 {
1121         const Vec4                                                      errorColor              (1.0f, 0.0f, 0.0f, 1.0f);
1122         const Vec4                                                      okColor                 (0.0f, 0.0f, 0.0f, 1.0f);
1123         const tcu::TextureFormat                        format                  (mapVkFormat(m_format));
1124         const tcu::TextureChannelClass          channelClass    (tcu::getTextureChannelClass(format.type));
1125         const void* const                                       ptrs[]                  =
1126         {
1127                 m_bufferMemory[0]->getHostPtr(),
1128                 m_bufferMemory[1]->getHostPtr(),
1129                 m_bufferMemory[2]->getHostPtr(),
1130                 m_bufferMemory[3]->getHostPtr()
1131         };
1132         const tcu::ConstPixelBufferAccess       accesses[]              =
1133         {
1134                 tcu::ConstPixelBufferAccess(format, m_width, m_height, 1, ptrs[0]),
1135                 tcu::ConstPixelBufferAccess(format, m_width, m_height, 1, ptrs[1]),
1136                 tcu::ConstPixelBufferAccess(format, m_width, m_height, 1, ptrs[2]),
1137                 tcu::ConstPixelBufferAccess(format, m_width, m_height, 1, ptrs[3])
1138         };
1139         tcu::TextureLevel                                       errorMask               (tcu::TextureFormat(tcu::TextureFormat::RGB, tcu::TextureFormat::UNORM_INT8), m_width, m_height);
1140         tcu::TestLog&                                           log                             (m_context.getTestContext().getLog());
1141
1142         switch (channelClass)
1143         {
1144                 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
1145                 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
1146                 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
1147                 {
1148                         const int       componentCount  (tcu::getNumUsedChannels(format.order));
1149                         bool            isOk                    = true;
1150                         float           clearValue;
1151                         float           renderValue;
1152
1153                         switch (channelClass)
1154                         {
1155                                 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
1156                                 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
1157                                         clearValue  = -1.0f;
1158                                         renderValue = 1.0f;
1159                                         break;
1160
1161                                 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
1162                                         clearValue  = 0.0f;
1163                                         renderValue = 1.0f;
1164                                         break;
1165
1166                                 default:
1167                                         clearValue  = 0.0f;
1168                                         renderValue = 0.0f;
1169                                         DE_FATAL("Unknown channel class");
1170                         }
1171
1172                         for (deUint32 y = 0; y < m_height; y++)
1173                         for (deUint32 x = 0; x < m_width; x++)
1174                         {
1175                                 // Color has to be black if no samples were covered, white if all samples were covered or same in every attachment
1176                                 const Vec4      firstColor      (accesses[0].getPixel(x, y));
1177                                 const Vec4      refColor        (m_sampleMask == 0x0u
1178                                                                                 ? Vec4(clearValue,
1179                                                                                                 componentCount > 1 ? clearValue : 0.0f,
1180                                                                                                 componentCount > 2 ? clearValue : 0.0f,
1181                                                                                                 componentCount > 3 ? clearValue : 1.0f)
1182                                                                                 : m_sampleMask == ((0x1u << m_sampleCount) - 1u)
1183                                                                                 ? Vec4(renderValue,
1184                                                                                                 componentCount > 1 ? renderValue : 0.0f,
1185                                                                                                 componentCount > 2 ? renderValue : 0.0f,
1186                                                                                                 componentCount > 3 ? renderValue : 1.0f)
1187                                                                                 : firstColor);
1188
1189                                 errorMask.getAccess().setPixel(okColor, x, y);
1190
1191                                 for (size_t attachmentNdx = 0; attachmentNdx < MAX_COLOR_ATTACHMENT_COUNT; attachmentNdx++)
1192                                 {
1193                                         const Vec4 color (accesses[attachmentNdx].getPixel(x, y));
1194
1195                                         if (refColor != color)
1196                                         {
1197                                                 isOk = false;
1198                                                 errorMask.getAccess().setPixel(errorColor, x, y);
1199                                                 break;
1200                                         }
1201                                 }
1202
1203                                 {
1204                                         const Vec4 old = m_sum.getAccess().getPixel(x, y);
1205
1206                                         m_sum.getAccess().setPixel(old + firstColor, x, y);
1207                                 }
1208                         }
1209
1210                         if (!isOk)
1211                         {
1212                                 const std::string                       sectionName     ("ResolveVerifyWithMask" + de::toString(m_sampleMask));
1213                                 const tcu::ScopedLogSection     section         (log, sectionName, sectionName);
1214
1215                                 for (size_t attachmentNdx = 0; attachmentNdx < MAX_COLOR_ATTACHMENT_COUNT; attachmentNdx++)
1216                                 {
1217                                         const std::string       name    ("Attachment" + de::toString(attachmentNdx));
1218                                         m_context.getTestContext().getLog() << tcu::LogImage(name.c_str(), name.c_str(), accesses[attachmentNdx]);
1219                                 }
1220
1221                                 m_context.getTestContext().getLog() << tcu::LogImage("ErrorMask", "ErrorMask", errorMask.getAccess());
1222
1223                                 if (m_sampleMask == 0x0u)
1224                                 {
1225                                         m_context.getTestContext().getLog() << tcu::TestLog::Message << "Empty sample mask didn't produce all " << clearValue << " pixels" << tcu::TestLog::EndMessage;
1226                                         m_resultCollector.fail("Empty sample mask didn't produce correct pixel values");
1227                                 }
1228                                 else if (m_sampleMask == ((0x1u << m_sampleCount) - 1u))
1229                                 {
1230                                         m_context.getTestContext().getLog() << tcu::TestLog::Message << "Full sample mask didn't produce all " << renderValue << " pixels" << tcu::TestLog::EndMessage;
1231                                         m_resultCollector.fail("Full sample mask didn't produce correct pixel values");
1232                                 }
1233                                 else
1234                                 {
1235                                         m_context.getTestContext().getLog() << tcu::TestLog::Message << "Resolve is inconsistent between attachments" << tcu::TestLog::EndMessage;
1236                                         m_resultCollector.fail("Resolve is inconsistent between attachments");
1237                                 }
1238                         }
1239                         break;
1240                 }
1241
1242                 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
1243                 {
1244                         const int               componentCount                  (tcu::getNumUsedChannels(format.order));
1245                         const UVec4             bitDepth                                (tcu::getTextureFormatBitDepth(format).cast<deUint32>());
1246                         const UVec4             renderValue                             (tcu::select((UVec4(1u) << tcu::min(UVec4(8u), bitDepth)) - UVec4(1u),
1247                                                                                                                                   UVec4(0u, 0u, 0u, 1u),
1248                                                                                                                                   tcu::lessThan(IVec4(0, 1, 2, 3), IVec4(componentCount))));
1249                         const UVec4             clearValue                              (tcu::select(UVec4(0u),
1250                                                                                                                                  UVec4(0u, 0u, 0u, 1u),
1251                                                                                                                                  tcu::lessThan(IVec4(0, 1, 2, 3), IVec4(componentCount))));
1252                         bool                    unexpectedValues                = false;
1253                         bool                    inconsistentComponents  = false;
1254                         bool                    inconsistentAttachments = false;
1255
1256                         for (deUint32 y = 0; y < m_height; y++)
1257                         for (deUint32 x = 0; x < m_width; x++)
1258                         {
1259                                 // Color has to be all zeros if no samples were covered, all 255 if all samples were covered or consistent across all attachments
1260                                 const UVec4 refColor    (m_sampleMask == 0x0u
1261                                                                                 ? clearValue
1262                                                                                 : m_sampleMask == ((0x1u << m_sampleCount) - 1u)
1263                                                                                 ? renderValue
1264                                                                                 : accesses[0].getPixelUint(x, y));
1265
1266                                 errorMask.getAccess().setPixel(okColor, x, y);
1267
1268                                 // If reference value was taken from first attachment, check that it is valid value i.e. clear or render value
1269                                 if (m_sampleMask != 0x0u && m_sampleMask != ((0x1u << m_sampleCount) - 1u))
1270                                 {
1271                                         // Each component must be resolved same way
1272                                         const BVec4             isRenderValue   (refColor == renderValue);
1273                                         const BVec4             isClearValue    (refColor == clearValue);
1274
1275                                         unexpectedValues                = tcu::anyNotEqual(tcu::logicalOr(isRenderValue, isClearValue), BVec4(true));
1276                                         inconsistentComponents  = !(tcu::allEqual(isRenderValue, BVec4(true)) || tcu::allEqual(isClearValue, BVec4(true)));
1277
1278                                         if (unexpectedValues || inconsistentComponents)
1279                                                 errorMask.getAccess().setPixel(errorColor, x, y);
1280                                 }
1281
1282                                 for (size_t attachmentNdx = 0; attachmentNdx < MAX_COLOR_ATTACHMENT_COUNT; attachmentNdx++)
1283                                 {
1284                                         const UVec4 color (accesses[attachmentNdx].getPixelUint(x, y));
1285
1286                                         if (refColor != color)
1287                                         {
1288                                                 inconsistentAttachments = true;
1289                                                 errorMask.getAccess().setPixel(errorColor, x, y);
1290                                                 break;
1291                                         }
1292                                 }
1293                         }
1294
1295                         if (unexpectedValues || inconsistentComponents || inconsistentAttachments)
1296                         {
1297                                 const std::string                       sectionName     ("ResolveVerifyWithMask" + de::toString(m_sampleMask));
1298                                 const tcu::ScopedLogSection     section         (log, sectionName, sectionName);
1299
1300                                 for (size_t attachmentNdx = 0; attachmentNdx < MAX_COLOR_ATTACHMENT_COUNT; attachmentNdx++)
1301                                 {
1302                                         const std::string       name    ("Attachment" + de::toString(attachmentNdx));
1303                                         m_context.getTestContext().getLog() << tcu::LogImage(name.c_str(), name.c_str(), accesses[attachmentNdx]);
1304                                 }
1305
1306                                 m_context.getTestContext().getLog() << tcu::LogImage("ErrorMask", "ErrorMask", errorMask.getAccess());
1307
1308                                 if (m_sampleMask == 0x0u)
1309                                 {
1310                                         m_context.getTestContext().getLog() << tcu::TestLog::Message << "Empty sample mask didn't produce all " << clearValue << " pixels" << tcu::TestLog::EndMessage;
1311                                         m_resultCollector.fail("Empty sample mask didn't produce correct pixels");
1312                                 }
1313                                 else if (m_sampleMask == ((0x1u << m_sampleCount) - 1u))
1314                                 {
1315                                         m_context.getTestContext().getLog() << tcu::TestLog::Message << "Full sample mask didn't produce all " << renderValue << " pixels" << tcu::TestLog::EndMessage;
1316                                         m_resultCollector.fail("Full sample mask didn't produce correct pixels");
1317                                 }
1318                                 else
1319                                 {
1320                                         if (unexpectedValues)
1321                                         {
1322                                                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Resolve produced unexpected values i.e. not " << clearValue << " or " << renderValue << tcu::TestLog::EndMessage;
1323                                                 m_resultCollector.fail("Resolve produced unexpected values");
1324                                         }
1325
1326                                         if (inconsistentComponents)
1327                                         {
1328                                                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Different components of attachment were resolved to different values." << tcu::TestLog::EndMessage;
1329                                                 m_resultCollector.fail("Different components of attachment were resolved to different values.");
1330                                         }
1331
1332                                         if (inconsistentAttachments)
1333                                         {
1334                                                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Different attachments were resolved to different values." << tcu::TestLog::EndMessage;
1335                                                 m_resultCollector.fail("Different attachments were resolved to different values.");
1336                                         }
1337                                 }
1338                         }
1339                         break;
1340                 }
1341
1342                 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
1343                 {
1344                         const int               componentCount                  (tcu::getNumUsedChannels(format.order));
1345                         const IVec4             bitDepth                                (tcu::getTextureFormatBitDepth(format));
1346                         const IVec4             renderValue                             (tcu::select((IVec4(1) << (tcu::min(IVec4(8), bitDepth) - IVec4(1))) - IVec4(1),
1347                                                                                                                                   IVec4(0, 0, 0, 1),
1348                                                                                                                                   tcu::lessThan(IVec4(0, 1, 2, 3), IVec4(componentCount))));
1349                         const IVec4             clearValue                              (tcu::select(-(IVec4(1) << (tcu::min(IVec4(8), bitDepth) - IVec4(1))),
1350                                                                                                                                  IVec4(0, 0, 0, 1),
1351                                                                                                                                  tcu::lessThan(IVec4(0, 1, 2, 3), IVec4(componentCount))));
1352                         bool                    unexpectedValues                = false;
1353                         bool                    inconsistentComponents  = false;
1354                         bool                    inconsistentAttachments = false;
1355
1356                         for (deUint32 y = 0; y < m_height; y++)
1357                         for (deUint32 x = 0; x < m_width; x++)
1358                         {
1359                                 // Color has to be all zeros if no samples were covered, all 255 if all samples were covered or consistent across all attachments
1360                                 const IVec4 refColor    (m_sampleMask == 0x0u
1361                                                                                 ? clearValue
1362                                                                                 : m_sampleMask == ((0x1u << m_sampleCount) - 1u)
1363                                                                                 ? renderValue
1364                                                                                 : accesses[0].getPixelInt(x, y));
1365
1366                                 errorMask.getAccess().setPixel(okColor, x, y);
1367
1368                                 // If reference value was taken from first attachment, check that it is valid value i.e. clear or render value
1369                                 if (m_sampleMask != 0x0u && m_sampleMask != ((0x1u << m_sampleCount) - 1u))
1370                                 {
1371                                         // Each component must be resolved same way
1372                                         const BVec4             isRenderValue   (refColor == renderValue);
1373                                         const BVec4             isClearValue    (refColor == clearValue);
1374
1375                                         unexpectedValues                = tcu::anyNotEqual(tcu::logicalOr(isRenderValue, isClearValue), BVec4(true));
1376                                         inconsistentComponents  = !(tcu::allEqual(isRenderValue, BVec4(true)) || tcu::allEqual(isClearValue, BVec4(true)));
1377
1378                                         if (unexpectedValues || inconsistentComponents)
1379                                                 errorMask.getAccess().setPixel(errorColor, x, y);
1380                                 }
1381                         }
1382
1383                         if (unexpectedValues || inconsistentComponents || inconsistentAttachments)
1384                         {
1385                                 const std::string                       sectionName     ("ResolveVerifyWithMask" + de::toString(m_sampleMask));
1386                                 const tcu::ScopedLogSection     section         (log, sectionName, sectionName);
1387
1388                                 for (size_t attachmentNdx = 0; attachmentNdx < MAX_COLOR_ATTACHMENT_COUNT; attachmentNdx++)
1389                                 {
1390                                         const std::string       name    ("Attachment" + de::toString(attachmentNdx));
1391                                         m_context.getTestContext().getLog() << tcu::LogImage(name.c_str(), name.c_str(), accesses[attachmentNdx]);
1392                                 }
1393
1394                                 m_context.getTestContext().getLog() << tcu::LogImage("ErrorMask", "ErrorMask", errorMask.getAccess());
1395
1396                                 if (m_sampleMask == 0x0u)
1397                                 {
1398                                         m_context.getTestContext().getLog() << tcu::TestLog::Message << "Empty sample mask didn't produce all " << clearValue << " pixels" << tcu::TestLog::EndMessage;
1399                                         m_resultCollector.fail("Empty sample mask didn't produce correct pixels");
1400                                 }
1401                                 else if (m_sampleMask == ((0x1u << m_sampleCount) - 1u))
1402                                 {
1403                                         m_context.getTestContext().getLog() << tcu::TestLog::Message << "Full sample mask didn't produce all " << renderValue << " pixels" << tcu::TestLog::EndMessage;
1404                                         m_resultCollector.fail("Full sample mask didn't produce correct pixels");
1405                                 }
1406                                 else
1407                                 {
1408                                         if (unexpectedValues)
1409                                         {
1410                                                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Resolve produced unexpected values i.e. not " << clearValue << " or " << renderValue << tcu::TestLog::EndMessage;
1411                                                 m_resultCollector.fail("Resolve produced unexpected values");
1412                                         }
1413
1414                                         if (inconsistentComponents)
1415                                         {
1416                                                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Different components of attachment were resolved to different values." << tcu::TestLog::EndMessage;
1417                                                 m_resultCollector.fail("Different components of attachment were resolved to different values.");
1418                                         }
1419
1420                                         if (inconsistentAttachments)
1421                                         {
1422                                                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Different attachments were resolved to different values." << tcu::TestLog::EndMessage;
1423                                                 m_resultCollector.fail("Different attachments were resolved to different values.");
1424                                         }
1425                                 }
1426                         }
1427                         break;
1428                 }
1429
1430                 default:
1431                         DE_FATAL("Unknown channel class");
1432         }
1433 }
1434
1435 tcu::TestStatus MultisampleRenderPassTestInstance::iterate (void)
1436 {
1437         if (m_sampleMask == 0u)
1438         {
1439                 const tcu::TextureFormat                format                  (mapVkFormat(m_format));
1440                 const tcu::TextureChannelClass  channelClass    (tcu::getTextureChannelClass(format.type));
1441                 tcu::TestLog&                                   log                             (m_context.getTestContext().getLog());
1442
1443                 switch (channelClass)
1444                 {
1445                         case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
1446                                 log << TestLog::Message << "Clearing target to zero and rendering 255 pixels with every possible sample mask" << TestLog::EndMessage;
1447                                 break;
1448
1449                         case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
1450                                 log << TestLog::Message << "Clearing target to -128 and rendering 127 pixels with every possible sample mask" << TestLog::EndMessage;
1451                                 break;
1452
1453                         case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
1454                         case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
1455                         case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
1456                                 log << TestLog::Message << "Clearing target to black and rendering white pixels with every possible sample mask" << TestLog::EndMessage;
1457                                 break;
1458
1459                         default:
1460                                 DE_FATAL("Unknown channel class");
1461                 }
1462         }
1463
1464         submit();
1465         verify();
1466
1467         if (m_sampleMask == ((0x1u << m_sampleCount) - 1u))
1468         {
1469                 const tcu::TextureFormat                format                  (mapVkFormat(m_format));
1470                 const tcu::TextureChannelClass  channelClass    (tcu::getTextureChannelClass(format.type));
1471                 tcu::TestLog&                                   log                             (m_context.getTestContext().getLog());
1472
1473                 if (channelClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT
1474                                 || channelClass == tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT
1475                                 || channelClass == tcu::TEXTURECHANNELCLASS_FLOATING_POINT)
1476                 {
1477                         const float                     threshold               = 0.05f;
1478                         const int                       componentCount  (tcu::getNumUsedChannels(format.order));
1479                         const Vec4                      errorColor              (1.0f, 0.0f, 0.0f, 1.0f);
1480                         const Vec4                      okColor                 (0.0f, 0.0f, 0.0f, 1.0f);
1481                         tcu::TextureLevel       errorMask               (tcu::TextureFormat(tcu::TextureFormat::RGB, tcu::TextureFormat::UNORM_INT8), m_width, m_height);
1482                         bool                            isOk                    = true;
1483                         Vec4                            maxDiff                 (0.0f);
1484                         Vec4                            expectedAverage;
1485
1486                         switch (channelClass)
1487                         {
1488                                 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
1489                                 {
1490                                         expectedAverage = Vec4(0.5f, componentCount > 1 ? 0.5f : 0.0f, componentCount > 2 ? 0.5f : 0.0f, componentCount > 3 ? 0.5f : 1.0f);
1491                                         break;
1492                                 }
1493
1494                                 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
1495                                 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
1496                                 {
1497                                         expectedAverage = Vec4(0.0f, 0.0f, 0.0f, componentCount > 3 ? 0.0f : 1.0f);
1498                                         break;
1499                                 }
1500
1501                                 default:
1502                                         DE_FATAL("Unknown channel class");
1503                         }
1504
1505                         for (deUint32 y = 0; y < m_height; y++)
1506                         for (deUint32 x = 0; x < m_width; x++)
1507                         {
1508                                 const Vec4      sum             (m_sum.getAccess().getPixel(x, y));
1509                                 const Vec4      average (sum / Vec4((float)(0x1u << m_sampleCount)));
1510                                 const Vec4      diff    (tcu::abs(average - expectedAverage));
1511
1512                                 m_sum.getAccess().setPixel(average, x, y);
1513                                 errorMask.getAccess().setPixel(okColor, x, y);
1514
1515                                 if (diff[0] > threshold
1516                                                 || diff[1] > threshold
1517                                                 || diff[2] > threshold
1518                                                 || diff[3] > threshold)
1519                                 {
1520                                         isOk    = false;
1521                                         maxDiff = tcu::max(maxDiff, diff);
1522                                         errorMask.getAccess().setPixel(errorColor, x, y);
1523                                 }
1524                         }
1525
1526                         log << TestLog::Image("Average resolved values in attachment 0", "Average resolved values in attachment 0", m_sum);
1527
1528                         if (!isOk)
1529                         {
1530                                 m_context.getTestContext().getLog() << tcu::LogImage("ErrorMask", "ErrorMask", errorMask.getAccess());
1531
1532                                 log << TestLog::Message << "Average resolved values differ from expected average values by more than " << threshold << " max per component diff " << maxDiff << TestLog::EndMessage;
1533                         }
1534                 }
1535
1536                 return tcu::TestStatus(m_resultCollector.getResult(), m_resultCollector.getMessage());
1537         }
1538         else
1539         {
1540                 m_sampleMask++;
1541                 return tcu::TestStatus::incomplete();
1542         }
1543 }
1544
1545 struct Programs
1546 {
1547         void init (vk::SourceCollections& dst, TestConfig config) const
1548         {
1549                 const tcu::TextureFormat                format                  (mapVkFormat(config.format));
1550                 const tcu::TextureChannelClass  channelClass    (tcu::getTextureChannelClass(format.type));
1551
1552                 dst.glslSources.add("quad-vert") << glu::VertexSource(
1553                         "#version 450\n"
1554                         "out gl_PerVertex {\n"
1555                         "\tvec4 gl_Position;\n"
1556                         "};\n"
1557                         "highp float;\n"
1558                         "void main (void) {\n"
1559                         "\tgl_Position = vec4(((gl_VertexIndex + 2) / 3) % 2 == 0 ? -1.0 : 1.0,\n"
1560                         "\t                   ((gl_VertexIndex + 1) / 3) % 2 == 0 ? -1.0 : 1.0, 0.0, 1.0);\n"
1561                         "}\n");
1562
1563                 switch (channelClass)
1564                 {
1565                         case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
1566                                 dst.glslSources.add("quad-frag") << glu::FragmentSource(
1567                                         "#version 450\n"
1568                                         "layout(push_constant) uniform PushConstant {\n"
1569                                         "\thighp uint sampleMask;\n"
1570                                         "} pushConstants;\n"
1571                                         "layout(location = 0) out highp uvec4 o_color0;\n"
1572                                         "layout(location = 1) out highp uvec4 o_color1;\n"
1573                                         "layout(location = 2) out highp uvec4 o_color2;\n"
1574                                         "layout(location = 3) out highp uvec4 o_color3;\n"
1575                                         "void main (void)\n"
1576                                         "{\n"
1577                                         "\tgl_SampleMask[0] = int(pushConstants.sampleMask);\n"
1578                                         "\to_color0 = uvec4(255);\n"
1579                                         "\to_color1 = uvec4(255);\n"
1580                                         "\to_color2 = uvec4(255);\n"
1581                                         "\to_color3 = uvec4(255);\n"
1582                                         "}\n");
1583                                 break;
1584
1585                         case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
1586                                 dst.glslSources.add("quad-frag") << glu::FragmentSource(
1587                                         "#version 450\n"
1588                                         "layout(push_constant) uniform PushConstant {\n"
1589                                         "\thighp uint sampleMask;\n"
1590                                         "} pushConstants;\n"
1591                                         "layout(location = 0) out highp ivec4 o_color0;\n"
1592                                         "layout(location = 1) out highp ivec4 o_color1;\n"
1593                                         "layout(location = 2) out highp ivec4 o_color2;\n"
1594                                         "layout(location = 3) out highp ivec4 o_color3;\n"
1595                                         "void main (void)\n"
1596                                         "{\n"
1597                                         "\tgl_SampleMask[0] = int(pushConstants.sampleMask);\n"
1598                                         "\to_color0 = ivec4(127);\n"
1599                                         "\to_color1 = ivec4(127);\n"
1600                                         "\to_color2 = ivec4(127);\n"
1601                                         "\to_color3 = ivec4(127);\n"
1602                                         "}\n");
1603                                 break;
1604
1605                         case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
1606                         case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
1607                         case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
1608                                 dst.glslSources.add("quad-frag") << glu::FragmentSource(
1609                                         "#version 450\n"
1610                                         "layout(push_constant) uniform PushConstant {\n"
1611                                         "\thighp uint sampleMask;\n"
1612                                         "} pushConstants;\n"
1613                                         "layout(location = 0) out highp vec4 o_color0;\n"
1614                                         "layout(location = 1) out highp vec4 o_color1;\n"
1615                                         "layout(location = 2) out highp vec4 o_color2;\n"
1616                                         "layout(location = 3) out highp vec4 o_color3;\n"
1617                                         "void main (void)\n"
1618                                         "{\n"
1619                                         "\tgl_SampleMask[0] = int(pushConstants.sampleMask);\n"
1620                                         "\to_color0 = vec4(1.0);\n"
1621                                         "\to_color1 = vec4(1.0);\n"
1622                                         "\to_color2 = vec4(1.0);\n"
1623                                         "\to_color3 = vec4(1.0);\n"
1624                                         "}\n");
1625                                 break;
1626
1627                         default:
1628                                 DE_FATAL("Unknown channel class");
1629                 }
1630         }
1631 };
1632
1633 std::string formatToName (VkFormat format)
1634 {
1635         const std::string       formatStr       = de::toString(format);
1636         const std::string       prefix          = "VK_FORMAT_";
1637
1638         DE_ASSERT(formatStr.substr(0, prefix.length()) == prefix);
1639
1640         return de::toLower(formatStr.substr(prefix.length()));
1641 }
1642
1643 void initTests (tcu::TestCaseGroup* group)
1644 {
1645         static const VkFormat   formats[]       =
1646         {
1647                 VK_FORMAT_R5G6B5_UNORM_PACK16,
1648                 VK_FORMAT_R8_UNORM,
1649                 VK_FORMAT_R8_SNORM,
1650                 VK_FORMAT_R8_UINT,
1651                 VK_FORMAT_R8_SINT,
1652                 VK_FORMAT_R8G8_UNORM,
1653                 VK_FORMAT_R8G8_SNORM,
1654                 VK_FORMAT_R8G8_UINT,
1655                 VK_FORMAT_R8G8_SINT,
1656                 VK_FORMAT_R8G8B8A8_UNORM,
1657                 VK_FORMAT_R8G8B8A8_SNORM,
1658                 VK_FORMAT_R8G8B8A8_UINT,
1659                 VK_FORMAT_R8G8B8A8_SINT,
1660                 VK_FORMAT_R8G8B8A8_SRGB,
1661                 VK_FORMAT_A8B8G8R8_UNORM_PACK32,
1662                 VK_FORMAT_A8B8G8R8_SNORM_PACK32,
1663                 VK_FORMAT_A8B8G8R8_UINT_PACK32,
1664                 VK_FORMAT_A8B8G8R8_SINT_PACK32,
1665                 VK_FORMAT_A8B8G8R8_SRGB_PACK32,
1666                 VK_FORMAT_B8G8R8A8_UNORM,
1667                 VK_FORMAT_B8G8R8A8_SRGB,
1668                 VK_FORMAT_A2R10G10B10_UNORM_PACK32,
1669                 VK_FORMAT_A2B10G10R10_UNORM_PACK32,
1670                 VK_FORMAT_A2B10G10R10_UINT_PACK32,
1671                 VK_FORMAT_R16_UNORM,
1672                 VK_FORMAT_R16_SNORM,
1673                 VK_FORMAT_R16_UINT,
1674                 VK_FORMAT_R16_SINT,
1675                 VK_FORMAT_R16_SFLOAT,
1676                 VK_FORMAT_R16G16_UNORM,
1677                 VK_FORMAT_R16G16_SNORM,
1678                 VK_FORMAT_R16G16_UINT,
1679                 VK_FORMAT_R16G16_SINT,
1680                 VK_FORMAT_R16G16_SFLOAT,
1681                 VK_FORMAT_R16G16B16A16_UNORM,
1682                 VK_FORMAT_R16G16B16A16_SNORM,
1683                 VK_FORMAT_R16G16B16A16_UINT,
1684                 VK_FORMAT_R16G16B16A16_SINT,
1685                 VK_FORMAT_R16G16B16A16_SFLOAT,
1686                 VK_FORMAT_R32_UINT,
1687                 VK_FORMAT_R32_SINT,
1688                 VK_FORMAT_R32_SFLOAT,
1689                 VK_FORMAT_R32G32_UINT,
1690                 VK_FORMAT_R32G32_SINT,
1691                 VK_FORMAT_R32G32_SFLOAT,
1692                 VK_FORMAT_R32G32B32A32_UINT,
1693                 VK_FORMAT_R32G32B32A32_SINT,
1694                 VK_FORMAT_R32G32B32A32_SFLOAT,
1695         };
1696         const deUint32                  sampleCounts[] =
1697         {
1698                 2u, 4u, 8u
1699         };
1700         tcu::TestContext&               testCtx         (group->getTestContext());
1701
1702         for (size_t formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); formatNdx++)
1703         {
1704                 const VkFormat                                  format          (formats[formatNdx]);
1705                 const std::string                               formatName      (formatToName(format));
1706                 de::MovePtr<tcu::TestCaseGroup> formatGroup     (new tcu::TestCaseGroup(testCtx, formatName.c_str(), formatName.c_str()));
1707
1708                 for (size_t sampleCountNdx = 0; sampleCountNdx < DE_LENGTH_OF_ARRAY(sampleCounts); sampleCountNdx++)
1709                 {
1710                         const deUint32          sampleCount     (sampleCounts[sampleCountNdx]);
1711                         const std::string       testName        ("samples_" + de::toString(sampleCount));
1712
1713                         formatGroup->addChild(new InstanceFactory1<MultisampleRenderPassTestInstance, TestConfig, Programs>(testCtx, tcu::NODETYPE_SELF_VALIDATE, testName.c_str(), testName.c_str(), TestConfig(format, sampleCount)));
1714                 }
1715
1716                 group->addChild(formatGroup.release());
1717         }
1718 }
1719
1720 } // anonymous
1721
1722 tcu::TestCaseGroup* createRenderPassMultisampleResolveTests (tcu::TestContext& testCtx)
1723 {
1724         return createTestGroup(testCtx, "multisample_resolve", "Multisample render pass resolve tests", initTests);
1725 }
1726
1727 } // vkt