Fix missing dependency on sparse binds
[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 #include "vktRenderPassTestsUtil.hpp"
26
27 #include "vktTestCaseUtil.hpp"
28 #include "vktTestGroupUtil.hpp"
29
30 #include "vkDefs.hpp"
31 #include "vkDeviceUtil.hpp"
32 #include "vkImageUtil.hpp"
33 #include "vkMemUtil.hpp"
34 #include "vkPlatform.hpp"
35 #include "vkPrograms.hpp"
36 #include "vkQueryUtil.hpp"
37 #include "vkRef.hpp"
38 #include "vkRefUtil.hpp"
39 #include "vkTypeUtil.hpp"
40 #include "vkCmdUtil.hpp"
41 #include "vkObjUtil.hpp"
42
43 #include "tcuFloat.hpp"
44 #include "tcuImageCompare.hpp"
45 #include "tcuFormatUtil.hpp"
46 #include "tcuMaybe.hpp"
47 #include "tcuResultCollector.hpp"
48 #include "tcuTestLog.hpp"
49 #include "tcuTextureUtil.hpp"
50 #include "tcuVectorUtil.hpp"
51 #include "tcuStringTemplate.hpp"
52
53 #include "deUniquePtr.hpp"
54 #include "deSharedPtr.hpp"
55
56 using namespace vk;
57
58 using tcu::BVec4;
59 using tcu::IVec2;
60 using tcu::IVec4;
61 using tcu::UVec2;
62 using tcu::UVec4;
63 using tcu::Vec2;
64 using tcu::Vec3;
65 using tcu::Vec4;
66
67 using tcu::ConstPixelBufferAccess;
68 using tcu::PixelBufferAccess;
69 using tcu::TestLog;
70
71 using std::vector;
72
73 typedef de::SharedPtr<Allocation>                                                       AllocationSp;
74 typedef de::SharedPtr<vk::Unique<VkImage> >                                     VkImageSp;
75 typedef de::SharedPtr<vk::Unique<VkImageView> >                         VkImageViewSp;
76 typedef de::SharedPtr<vk::Unique<VkBuffer> >                            VkBufferSp;
77 typedef de::SharedPtr<vk::Unique<VkSampler> >                           VkSamplerSp;
78 typedef de::SharedPtr<vk::Unique<VkPipeline> >                          VkPipelineSp;
79 typedef de::SharedPtr<vk::Unique<VkDescriptorSetLayout> >       VkDescriptorSetLayoutSp;
80 typedef de::SharedPtr<vk::Unique<VkDescriptorPool> >            VkDescriptorPoolSp;
81 typedef de::SharedPtr<vk::Unique<VkDescriptorSet> >                     VkDescriptorSetSp;
82
83 namespace vkt
84 {
85 namespace
86 {
87
88 using namespace renderpass;
89
90 template<typename T>
91 de::SharedPtr<T> safeSharedPtr (T* ptr)
92 {
93         try
94         {
95                 return de::SharedPtr<T>(ptr);
96         }
97         catch (...)
98         {
99                 delete ptr;
100                 throw;
101         }
102 }
103
104 enum TestType
105 {
106         RESOLVE                 = 0,
107         MAX_ATTACHMENTS,
108         COMPATIBILITY
109 };
110
111 struct TestConfig
112 {
113         TestType                                        testType;
114         VkFormat                                        format;
115         deUint32                                        sampleCount;
116         deUint32                                        layerCount;
117         deUint32                                        attachmentCount;
118         deUint32                                        width;
119         deUint32                                        height;
120         const SharedGroupParams         groupParams;
121 };
122
123 struct TestConfig2 : TestConfig
124 {
125         TestConfig2(const TestConfig& src, deUint32 level)
126                 : TestConfig    (src)
127                 , resolveLevel  (level)
128         {
129         }
130         deUint32                resolveLevel;
131 };
132
133 // Render pass traits that groups render pass related types together and by that help
134 // to reduce number of template parrameters passed to number of functions in those tests
135 struct RenderPass1Trait
136 {
137         typedef AttachmentDescription1  AttDesc;
138         typedef AttachmentReference1    AttRef;
139         typedef SubpassDescription1             SubpassDesc;
140         typedef SubpassDependency1              SubpassDep;
141         typedef RenderPassCreateInfo1   RenderPassCreateInfo;
142 };
143 struct RenderPass2Trait
144 {
145         typedef AttachmentDescription2  AttDesc;
146         typedef AttachmentReference2    AttRef;
147         typedef SubpassDescription2             SubpassDesc;
148         typedef SubpassDependency2              SubpassDep;
149         typedef RenderPassCreateInfo2   RenderPassCreateInfo;
150 };
151
152 class MultisampleRenderPassTestBase : public TestInstance
153 {
154 public:
155         MultisampleRenderPassTestBase   (Context& context, TestConfig config);
156         ~MultisampleRenderPassTestBase  (void);
157
158 protected:
159
160         Move<VkImage>                   createImage                     (VkSampleCountFlagBits          sampleCountBit,
161                                                                                                  VkImageUsageFlags                      usage) const;
162         Move<VkImage>                   createImage                     (VkSampleCountFlagBits          sampleCountBit,
163                                                                                                  VkImageUsageFlags                      usage,
164                                                                                                  deUint32                                       width,
165                                                                                                  deUint32                                       height,
166                                                                                                  deUint32                                       mipLevels) const;
167         vector<VkImageSp>               createImages            (VkSampleCountFlagBits          sampleCountBit,
168                                                                                                  VkImageUsageFlags                      usage) const;
169         vector<VkImageSp>               createImages            (VkSampleCountFlagBits          sampleCountBit,
170                                                                                                  VkImageUsageFlags                      usage,
171                                                                                                  deUint32                                       width,
172                                                                                                  deUint32                                       height,
173                                                                                                  deUint32                                       mipLevels) const;
174         vector<AllocationSp>    createImageMemory       (const vector<VkImageSp>&       images) const;
175         vector<VkImageViewSp>   createImageViews        (const vector<VkImageSp>&       images,
176                                                                                                  deUint32                                       mipLevel = 0) const;
177
178         vector<VkBufferSp>              createBuffers           () const;
179         vector<VkBufferSp>              createBuffers           (deUint32                                       width,
180                                                                                                  deUint32                                       height,
181                                                                                                  deUint32                                       mipLevels) const;
182         vector<AllocationSp>    createBufferMemory      (const vector<VkBufferSp>& buffers) const;
183
184         Move<VkFramebuffer>             createFramebuffer       (const std::vector<VkImageViewSp>       multisampleImageViews,
185                                                                                                  const std::vector<VkImageViewSp>       singlesampleImageViews,
186                                                                                                  VkRenderPass                                           renderPass) const;
187
188         void                                    clearAttachments                                (VkCommandBuffer commandBuffer) const;
189         VkDeviceSize                    getPixelSize                                    () const;
190         tcu::Vec4                               getFormatThreshold                              () const;
191         VkSampleCountFlagBits   sampleCountBitFromSampleCount   (deUint32 count) const;
192         void                                    logImage                                                (const std::string& name,
193                                                                                                                          const tcu::ConstPixelBufferAccess& image) const;
194
195 protected:
196
197         const bool                                              m_testCompatibility;
198         const SharedGroupParams                 m_groupParams;
199
200         const VkFormat                                  m_format;
201         const VkSampleCountFlagBits             m_sampleCount;
202         const deUint32                                  m_layerCount;
203         const deUint32                                  m_attachmentsCount;
204         const deUint32                                  m_width;
205         const deUint32                                  m_height;
206 };
207
208 MultisampleRenderPassTestBase::MultisampleRenderPassTestBase (Context& context, TestConfig config)
209         : TestInstance                          (context)
210         , m_testCompatibility           (config.testType == COMPATIBILITY)
211         , m_groupParams                         (config.groupParams)
212         , m_format                                      (config.format)
213         , m_sampleCount                         (sampleCountBitFromSampleCount(config.sampleCount))
214         , m_layerCount                          (config.layerCount)
215         , m_attachmentsCount            (config.attachmentCount)
216         , m_width                                       (config.width)
217         , m_height                                      (config.height)
218 {
219 }
220
221 MultisampleRenderPassTestBase::~MultisampleRenderPassTestBase ()
222 {
223 }
224
225 Move<VkImage> MultisampleRenderPassTestBase::createImage (VkSampleCountFlagBits sampleCountBit, VkImageUsageFlags usage) const
226 {
227         return createImage(sampleCountBit, usage, m_width, m_height, 1u);
228 }
229
230 Move<VkImage> MultisampleRenderPassTestBase::createImage (VkSampleCountFlagBits sampleCountBit,
231                                                                                                                   VkImageUsageFlags             usage,
232                                                                                                                   deUint32                              width,
233                                                                                                                   deUint32                              height,
234                                                                                                                   deUint32                              mipLevels) const
235 {
236         const InstanceInterface&                vki                                             = m_context.getInstanceInterface();
237         const DeviceInterface&                  vkd                                             = m_context.getDeviceInterface();
238         VkDevice                                                device                                  = m_context.getDevice();
239         VkPhysicalDevice                                physicalDevice                  = m_context.getPhysicalDevice();
240         const tcu::TextureFormat                format                                  (mapVkFormat(m_format));
241         const VkImageType                               imageType                               (VK_IMAGE_TYPE_2D);
242         const VkImageTiling                             imageTiling                             (VK_IMAGE_TILING_OPTIMAL);
243         const VkFormatProperties                formatProperties                (getPhysicalDeviceFormatProperties(vki, physicalDevice, m_format));
244         const VkExtent3D                                imageExtent =
245         {
246                 width,
247                 height,
248                 1u
249         };
250
251         try
252         {
253                 const VkImageFormatProperties   imageFormatProperties(getPhysicalDeviceImageFormatProperties(vki, physicalDevice, m_format, imageType, imageTiling, usage, 0u));
254
255                 if ((tcu::hasDepthComponent(format.order) || tcu::hasStencilComponent(format.order))
256                         && (formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) == 0)
257                         TCU_THROW(NotSupportedError, "Format can't be used as depth stencil attachment");
258
259                 if (!(tcu::hasDepthComponent(format.order) || tcu::hasStencilComponent(format.order))
260                         && (formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT) == 0)
261                         TCU_THROW(NotSupportedError, "Format can't be used as color attachment");
262
263                 if (imageFormatProperties.maxExtent.width < imageExtent.width
264                         || imageFormatProperties.maxExtent.height < imageExtent.height
265                         || ((imageFormatProperties.sampleCounts & m_sampleCount) == 0)
266                         || imageFormatProperties.maxArrayLayers < m_layerCount)
267                 {
268                         TCU_THROW(NotSupportedError, "Image type not supported");
269                 }
270
271                 const VkImageCreateInfo pCreateInfo =
272                 {
273                         VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
274                         DE_NULL,
275                         0u,
276                         imageType,
277                         m_format,
278                         imageExtent,
279                         mipLevels,
280                         m_layerCount,
281                         sampleCountBit,
282                         imageTiling,
283                         usage,
284                         VK_SHARING_MODE_EXCLUSIVE,
285                         0u,
286                         DE_NULL,
287                         VK_IMAGE_LAYOUT_UNDEFINED
288                 };
289
290                 return ::createImage(vkd, device, &pCreateInfo);
291         }
292         catch (const vk::Error& error)
293         {
294                 if (error.getError() == VK_ERROR_FORMAT_NOT_SUPPORTED)
295                         TCU_THROW(NotSupportedError, "Image format not supported");
296
297                 throw;
298         }
299 }
300
301 vector<VkImageSp> MultisampleRenderPassTestBase::createImages (VkSampleCountFlagBits sampleCountBit, VkImageUsageFlags usage) const
302 {
303         std::vector<VkImageSp> images (m_attachmentsCount);
304         for (size_t imageNdx = 0; imageNdx < m_attachmentsCount; imageNdx++)
305                 images[imageNdx] = safeSharedPtr(new Unique<VkImage>(createImage(sampleCountBit, usage)));
306         return images;
307 }
308
309 vector<VkImageSp> MultisampleRenderPassTestBase::createImages (VkSampleCountFlagBits    sampleCountBit,
310                                                                                                                            VkImageUsageFlags            usage,
311                                                                                                                            deUint32                                     width,
312                                                                                                                            deUint32                                     height,
313                                                                                                                            deUint32                                     mipLevels) const
314 {
315         std::vector<VkImageSp> images (m_attachmentsCount);
316         for (size_t imageNdx = 0; imageNdx < m_attachmentsCount; imageNdx++)
317                 images[imageNdx] = safeSharedPtr(new Unique<VkImage>(createImage(sampleCountBit, usage, width, height, mipLevels)));
318         return images;
319 }
320
321 vector<AllocationSp> MultisampleRenderPassTestBase::createImageMemory (const vector<VkImageSp>& images) const
322 {
323         const DeviceInterface&          vkd                     = m_context.getDeviceInterface();
324         VkDevice                                        device          = m_context.getDevice();
325         Allocator&                                      allocator       = m_context.getDefaultAllocator();
326         std::vector<AllocationSp>       memory          (images.size());
327
328         for (size_t memoryNdx = 0; memoryNdx < memory.size(); memoryNdx++)
329         {
330                 VkImage                                 image                   = **images[memoryNdx];
331                 VkMemoryRequirements    requirements    = getImageMemoryRequirements(vkd, device, image);
332
333                 de::MovePtr<Allocation> allocation              (allocator.allocate(requirements, MemoryRequirement::Any));
334                 VK_CHECK(vkd.bindImageMemory(device, image, allocation->getMemory(), allocation->getOffset()));
335                 memory[memoryNdx] = safeSharedPtr(allocation.release());
336         }
337         return memory;
338 }
339
340 vector<VkImageViewSp> MultisampleRenderPassTestBase::createImageViews (const vector<VkImageSp>& images, deUint32 mipLevel) const
341 {
342         const DeviceInterface&                  vkd             = m_context.getDeviceInterface();
343         VkDevice                                                device  = m_context.getDevice();
344         std::vector<VkImageViewSp>              views   (images.size());
345         const VkImageSubresourceRange   range =
346         {
347                 VK_IMAGE_ASPECT_COLOR_BIT,
348                 mipLevel,
349                 1u,
350                 0u,
351                 m_layerCount
352         };
353
354         for (size_t imageNdx = 0; imageNdx < images.size(); imageNdx++)
355         {
356                 const VkImageViewCreateInfo pCreateInfo =
357                 {
358                         VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
359                         DE_NULL,
360                         0u,
361                         **images[imageNdx],
362                         VK_IMAGE_VIEW_TYPE_2D_ARRAY,
363                         m_format,
364                         makeComponentMappingRGBA(),
365                         range,
366                 };
367                 views[imageNdx] = safeSharedPtr(new Unique<VkImageView>(createImageView(vkd, device, &pCreateInfo)));
368         }
369
370         return views;
371 }
372
373 vector<VkBufferSp> MultisampleRenderPassTestBase::createBuffers () const
374 {
375         return createBuffers(m_width, m_height, 1u);
376 }
377
378 vector<VkBufferSp> MultisampleRenderPassTestBase::createBuffers (deUint32 width, deUint32 height, deUint32 mipLevels) const
379 {
380         DE_ASSERT(mipLevels);
381
382         VkDeviceSize                            size            = 0;
383         for (deUint32 level = 0; level < mipLevels; ++level)
384         {
385                 DE_ASSERT(width && height);
386
387                 size += (width * height);
388                 height /= 2;
389                 width /=2;
390         }
391
392         const DeviceInterface&          vkd                     = m_context.getDeviceInterface();
393         VkDevice                                        device          = m_context.getDevice();
394         std::vector<VkBufferSp>         buffers         (m_attachmentsCount);
395         const VkDeviceSize                      pixelSize       (getPixelSize());
396         const VkBufferCreateInfo        createInfo =
397         {
398                 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
399                 DE_NULL,
400                 0u,
401
402                 size * m_layerCount * pixelSize,
403                 VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
404
405                 VK_SHARING_MODE_EXCLUSIVE,
406                 0u,
407                 DE_NULL
408         };
409
410         for (size_t bufferNdx = 0; bufferNdx < buffers.size(); bufferNdx++)
411                 buffers[bufferNdx] = safeSharedPtr(new Unique<VkBuffer>(createBuffer(vkd, device, &createInfo)));
412
413         return buffers;
414 }
415
416 vector<AllocationSp> MultisampleRenderPassTestBase::createBufferMemory (const vector<VkBufferSp>& buffers) const
417 {
418         const DeviceInterface&                                  vkd                     = m_context.getDeviceInterface();
419         VkDevice                                                                device          = m_context.getDevice();
420         Allocator&                                                              allocator       = m_context.getDefaultAllocator();
421         std::vector<de::SharedPtr<Allocation> > memory          (buffers.size());
422
423         for (size_t memoryNdx = 0; memoryNdx < memory.size(); memoryNdx++)
424         {
425                 VkBuffer                                buffer                  = **buffers[memoryNdx];
426                 VkMemoryRequirements    requirements    = getBufferMemoryRequirements(vkd, device, buffer);
427                 de::MovePtr<Allocation> allocation              (allocator.allocate(requirements, MemoryRequirement::HostVisible));
428
429                 VK_CHECK(vkd.bindBufferMemory(device, buffer, allocation->getMemory(), allocation->getOffset()));
430                 memory[memoryNdx] = safeSharedPtr(allocation.release());
431         }
432         return memory;
433 }
434
435 Move<VkFramebuffer> MultisampleRenderPassTestBase::createFramebuffer (const std::vector<VkImageViewSp>  multisampleImageViews,
436                                                                                                                                           const std::vector<VkImageViewSp>      singlesampleImageViews,
437                                                                                                                                           VkRenderPass                                          renderPass) const
438 {
439         // when RenderPass was not created then we are testing dynamic rendering
440         // and we can't create framebuffer without valid RenderPass object
441         if (!renderPass)
442                 return Move<VkFramebuffer>();
443
444         const DeviceInterface&  vkd             = m_context.getDeviceInterface();
445         VkDevice                                device  = m_context.getDevice();
446
447         std::vector<VkImageView> attachments;
448         attachments.reserve(multisampleImageViews.size() + singlesampleImageViews.size());
449
450         DE_ASSERT(multisampleImageViews.size() == singlesampleImageViews.size());
451
452         for (size_t ndx = 0; ndx < multisampleImageViews.size(); ndx++)
453         {
454                 attachments.push_back(**multisampleImageViews[ndx]);
455                 attachments.push_back(**singlesampleImageViews[ndx]);
456         }
457
458         const VkFramebufferCreateInfo createInfo =
459         {
460                 VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
461                 DE_NULL,
462                 0u,
463
464                 renderPass,
465                 (deUint32)attachments.size(),
466                 &attachments[0],
467
468                 m_width,
469                 m_height,
470                 m_layerCount
471         };
472
473         return ::createFramebuffer(vkd, device, &createInfo);
474 }
475
476 void MultisampleRenderPassTestBase::clearAttachments (VkCommandBuffer commandBuffer) const
477 {
478         const DeviceInterface&                  vkd                             = m_context.getDeviceInterface();
479         const tcu::TextureFormat                format                  (mapVkFormat(m_format));
480         const tcu::TextureChannelClass  channelClass    (tcu::getTextureChannelClass(format.type));
481         VkClearValue                                    value;
482
483         // Clear everything to black
484         switch (channelClass)
485         {
486                 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
487                         value = makeClearValueColorF32(-1.0f, -1.0f, -1.0f, -1.0f);
488                         break;
489
490                 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
491                         value = makeClearValueColorF32(0.0f, 0.0f, 0.0f, 0.0f);
492                         break;
493
494                 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
495                         value = makeClearValueColorF32(-1.0f, -1.0f, -1.0f, -1.0f);
496                         break;
497
498                 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
499                         value = makeClearValueColorI32(-128, -128, -128, -128);
500                         break;
501
502                 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
503                         value = makeClearValueColorU32(0u, 0u, 0u, 0u);
504                         break;
505
506                 default:
507                         DE_FATAL("Unknown channel class");
508         }
509         std::vector<VkClearAttachment> colors(m_attachmentsCount);
510         for (deUint32 attachmentNdx = 0; attachmentNdx < m_attachmentsCount; attachmentNdx++)
511         {
512                 colors[attachmentNdx].aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
513                 colors[attachmentNdx].colorAttachment = attachmentNdx;
514                 colors[attachmentNdx].clearValue = value;
515         }
516         const VkClearRect rect =
517         {
518                 {
519                         { 0u, 0u },
520                         { m_width, m_height }
521                 },
522                 0u,
523                 m_layerCount,
524         };
525         vkd.cmdClearAttachments(commandBuffer, deUint32(colors.size()), &colors[0], 1u, &rect);
526 }
527
528 VkDeviceSize MultisampleRenderPassTestBase::getPixelSize () const
529 {
530         const tcu::TextureFormat format(mapVkFormat(m_format));
531         return format.getPixelSize();
532 }
533
534 tcu::Vec4 MultisampleRenderPassTestBase::getFormatThreshold () const
535 {
536         const tcu::TextureFormat        tcuFormat               (mapVkFormat(m_format));
537         const deUint32                          componentCount  (tcu::getNumUsedChannels(tcuFormat.order));
538
539         if (isSnormFormat(m_format))
540         {
541                 return Vec4((componentCount >= 1) ? 1.5f * getRepresentableDiffSnorm(m_format, 0) : 0.0f,
542                                         (componentCount >= 2) ? 1.5f * getRepresentableDiffSnorm(m_format, 1) : 0.0f,
543                                         (componentCount >= 3) ? 1.5f * getRepresentableDiffSnorm(m_format, 2) : 0.0f,
544                                         (componentCount == 4) ? 1.5f * getRepresentableDiffSnorm(m_format, 3) : 0.0f);
545         }
546         else if (isUnormFormat(m_format))
547         {
548                 return Vec4((componentCount >= 1) ? 1.5f * getRepresentableDiffUnorm(m_format, 0) : 0.0f,
549                                         (componentCount >= 2) ? 1.5f * getRepresentableDiffUnorm(m_format, 1) : 0.0f,
550                                         (componentCount >= 3) ? 1.5f * getRepresentableDiffUnorm(m_format, 2) : 0.0f,
551                                         (componentCount == 4) ? 1.5f * getRepresentableDiffUnorm(m_format, 3) : 0.0f);
552         }
553         else if (isFloatFormat(m_format))
554         {
555                 return (tcuFormat.type == tcu::TextureFormat::HALF_FLOAT) ? tcu::Vec4(0.005f) : Vec4(0.00001f);
556         }
557         else
558                 return Vec4(0.001f);
559 }
560
561 VkSampleCountFlagBits MultisampleRenderPassTestBase::sampleCountBitFromSampleCount (deUint32 count) const
562 {
563         switch (count)
564         {
565                 case 1:  return VK_SAMPLE_COUNT_1_BIT;
566                 case 2:  return VK_SAMPLE_COUNT_2_BIT;
567                 case 4:  return VK_SAMPLE_COUNT_4_BIT;
568                 case 8:  return VK_SAMPLE_COUNT_8_BIT;
569                 case 16: return VK_SAMPLE_COUNT_16_BIT;
570                 case 32: return VK_SAMPLE_COUNT_32_BIT;
571                 case 64: return VK_SAMPLE_COUNT_64_BIT;
572
573                 default:
574                         DE_FATAL("Invalid sample count");
575                         return (VkSampleCountFlagBits)0x0;
576         }
577 }
578
579 void MultisampleRenderPassTestBase::logImage (const std::string& name, const tcu::ConstPixelBufferAccess& image) const
580 {
581         m_context.getTestContext().getLog() << tcu::LogImage(name.c_str(), name.c_str(), image);
582
583         for (deUint32 layerNdx = 0; layerNdx < m_layerCount; ++layerNdx)
584         {
585                 const std::string                       layerName       (name + " Layer:" + de::toString(layerNdx));
586                 tcu::ConstPixelBufferAccess     layerImage      (image.getFormat(), m_width, m_height, 1, image.getPixelPtr(0, 0, layerNdx));
587
588                 m_context.getTestContext().getLog() << tcu::LogImage(layerName.c_str(), layerName.c_str(), layerImage);
589         }
590 }
591
592 class MultisampleRenderPassTestInstance : public MultisampleRenderPassTestBase
593 {
594 public:
595         MultisampleRenderPassTestInstance       (Context& context, TestConfig config);
596         ~MultisampleRenderPassTestInstance      (void);
597
598         tcu::TestStatus                 iterate         (void);
599
600 private:
601
602         void                                    drawCommands                            (VkCommandBuffer cmdBuffer, VkPipeline pipeline, VkPipelineLayout pipelineLayout) const;
603
604         template<typename RenderpassSubpass>
605         void                                    submit                                          (void);
606         void                                    submitDynamicRendering          (void);
607         void                                    submitSwitch                            (const SharedGroupParams groupParams);
608         void                                    verify                                          (void);
609
610         template<typename RenderPassTrait>
611         Move<VkRenderPass>              createRenderPass                        (bool usedResolveAttachment);
612         Move<VkRenderPass>              createRenderPassSwitch          (bool usedResolveAttachment);
613         Move<VkRenderPass>              createRenderPassCompatible      (void);
614         Move<VkPipelineLayout>  createRenderPipelineLayout      (void);
615         Move<VkPipeline>                createRenderPipeline            (void);
616
617 #ifndef CTS_USES_VULKANSC
618         void                                    beginSecondaryCmdBuffer         (VkCommandBuffer cmdBuffer, VkRenderingFlagsKHR renderingFlags = 0u) const;
619 #endif // CTS_USES_VULKANSC
620
621 private:
622
623         const std::vector<VkImageSp>            m_multisampleImages;
624         const std::vector<AllocationSp>         m_multisampleImageMemory;
625         const std::vector<VkImageViewSp>        m_multisampleImageViews;
626
627         const std::vector<VkImageSp>            m_singlesampleImages;
628         const std::vector<AllocationSp>         m_singlesampleImageMemory;
629         const std::vector<VkImageViewSp>        m_singlesampleImageViews;
630
631         const Unique<VkRenderPass>                      m_renderPass;
632         const Unique<VkRenderPass>                      m_renderPassCompatible;
633         const Unique<VkFramebuffer>                     m_framebuffer;
634
635         const Unique<VkPipelineLayout>          m_renderPipelineLayout;
636         const Unique<VkPipeline>                        m_renderPipeline;
637
638         const std::vector<VkBufferSp>           m_buffers;
639         const std::vector<AllocationSp>         m_bufferMemory;
640
641         const Unique<VkCommandPool>                     m_commandPool;
642         tcu::TextureLevel                                       m_sum;
643         tcu::TextureLevel                                       m_sumSrgb;
644         deUint32                                                        m_sampleMask;
645         tcu::ResultCollector                            m_resultCollector;
646
647 protected:
648         MultisampleRenderPassTestInstance       (Context& context, TestConfig config, deUint32 renderLevel);
649
650         const deUint32                                          m_renderLevel;
651 };
652
653 MultisampleRenderPassTestInstance::MultisampleRenderPassTestInstance (Context& context, TestConfig config)
654         : MultisampleRenderPassTestInstance (context, config, /*defaulf render level*/0u)
655 {
656 }
657
658 MultisampleRenderPassTestInstance::MultisampleRenderPassTestInstance (Context& context, TestConfig config, deUint32 renderLevel)
659         : MultisampleRenderPassTestBase(context, config)
660
661         , m_multisampleImages           (createImages(m_sampleCount, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT))
662         , m_multisampleImageMemory      (createImageMemory(m_multisampleImages))
663         , m_multisampleImageViews       (createImageViews(m_multisampleImages))
664
665         , m_singlesampleImages          (createImages(VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, (1u << renderLevel)*m_width, (1u << renderLevel)*m_height, renderLevel+1 ))
666         , m_singlesampleImageMemory     (createImageMemory(m_singlesampleImages))
667         , m_singlesampleImageViews      (createImageViews(m_singlesampleImages, renderLevel))
668
669         // The "normal" render pass has an unused resolve attachment when testing compatibility.
670         , m_renderPass                          (createRenderPassSwitch(!m_testCompatibility))
671         , m_renderPassCompatible        (createRenderPassCompatible())
672         , m_framebuffer                         (createFramebuffer(m_multisampleImageViews, m_singlesampleImageViews, *m_renderPass))
673
674         , m_renderPipelineLayout        (createRenderPipelineLayout())
675         , m_renderPipeline                      (createRenderPipeline())
676
677         , m_buffers                                     (createBuffers((1u << renderLevel)*m_width, (1u << renderLevel)*m_height, renderLevel+1 ))
678         , m_bufferMemory                        (createBufferMemory(m_buffers))
679
680         , m_commandPool                         (createCommandPool(context.getDeviceInterface(), context.getDevice(), VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, context.getUniversalQueueFamilyIndex()))
681         , m_sum                                         (tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::FLOAT), m_width, m_height, m_layerCount)
682         , m_sumSrgb                                     (tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::FLOAT), m_width, m_height, m_layerCount)
683         , m_sampleMask                          (0x0u)
684
685         , m_renderLevel                         (renderLevel)
686 {
687         tcu::clear(m_sum.getAccess(), Vec4(0.0f, 0.0f, 0.0f, 0.0f));
688         tcu::clear(m_sumSrgb.getAccess(), Vec4(0.0f, 0.0f, 0.0f, 0.0f));
689 }
690
691 MultisampleRenderPassTestInstance::~MultisampleRenderPassTestInstance (void)
692 {
693 }
694
695 void MultisampleRenderPassTestInstance::drawCommands(VkCommandBuffer cmdBuffer, VkPipeline pipeline, VkPipelineLayout pipelineLayout) const
696 {
697         const DeviceInterface& vkd = m_context.getDeviceInterface();
698
699         // Clear everything to black
700         clearAttachments(cmdBuffer);
701
702         // Render black samples
703         vkd.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
704         vkd.cmdPushConstants(cmdBuffer, pipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, 0u, sizeof(m_sampleMask), &m_sampleMask);
705         vkd.cmdDraw(cmdBuffer, 6u, 1u, 0u, 0u);
706 }
707
708 template<typename RenderpassSubpass>
709 void MultisampleRenderPassTestInstance::submit (void)
710 {
711         const DeviceInterface&                  vkd                             (m_context.getDeviceInterface());
712         const VkDevice                                  device                  (m_context.getDevice());
713         const Unique<VkCommandBuffer>   commandBuffer   (allocateCommandBuffer(vkd, device, *m_commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
714
715         beginCommandBuffer(vkd, *commandBuffer);
716
717         // Memory barriers between previous copies and rendering
718         {
719                 std::vector<VkImageMemoryBarrier> barriers;
720
721                 for (size_t dstNdx = 0; dstNdx < m_singlesampleImages.size(); dstNdx++)
722                 {
723                         const VkImageMemoryBarrier barrier =
724                         {
725                                 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
726                                 DE_NULL,
727
728                                 VK_ACCESS_TRANSFER_READ_BIT,
729                                 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
730
731                                 VK_IMAGE_LAYOUT_UNDEFINED,
732                                 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
733
734                                 VK_QUEUE_FAMILY_IGNORED,
735                                 VK_QUEUE_FAMILY_IGNORED,
736
737                                 **m_singlesampleImages[dstNdx],
738                                 {
739                                         VK_IMAGE_ASPECT_COLOR_BIT,
740                                         m_renderLevel,
741                                         1u,
742                                         0u,
743                                         m_layerCount
744                                 }
745                         };
746
747                         barriers.push_back(barrier);
748                 }
749
750                 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]);
751         }
752
753         VkRect2D renderArea = makeRect2D(m_width, m_height);
754         const typename RenderpassSubpass::SubpassBeginInfo subpassBeginInfo(DE_NULL, VK_SUBPASS_CONTENTS_INLINE);
755         const VkRenderPassBeginInfo beginInfo =
756         {
757                 VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
758                 DE_NULL,
759
760                 m_testCompatibility ? *m_renderPassCompatible : *m_renderPass,
761                 *m_framebuffer,
762                 renderArea,
763
764                 0u,
765                 DE_NULL
766         };
767         RenderpassSubpass::cmdBeginRenderPass(vkd, *commandBuffer, &beginInfo, &subpassBeginInfo);
768
769         drawCommands(*commandBuffer, *m_renderPipeline, *m_renderPipelineLayout);
770
771         const typename RenderpassSubpass::SubpassEndInfo subpassEndInfo(DE_NULL);
772         RenderpassSubpass::cmdEndRenderPass(vkd, *commandBuffer, &subpassEndInfo);
773
774         for (size_t dstNdx = 0; dstNdx < m_singlesampleImages.size(); dstNdx++)
775         {
776                 // assume that buffer(s) have enough memory to store desired amount of mipmaps
777                 copyImageToBuffer(vkd, *commandBuffer, **m_singlesampleImages[dstNdx], **m_buffers[dstNdx],
778                                                   m_format, tcu::IVec2((1u << m_renderLevel)*m_width, (1u << m_renderLevel)*m_height), m_renderLevel,
779                                                   VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, m_layerCount);
780         }
781
782         endCommandBuffer(vkd, *commandBuffer);
783
784         submitCommandsAndWait(vkd, device, m_context.getUniversalQueue(), *commandBuffer);
785
786         for (size_t memoryBufferNdx = 0; memoryBufferNdx < m_bufferMemory.size(); memoryBufferNdx++)
787                 invalidateMappedMemoryRange(vkd, device, m_bufferMemory[memoryBufferNdx]->getMemory(), 0u, VK_WHOLE_SIZE);
788 }
789
790 void MultisampleRenderPassTestInstance::submitDynamicRendering (void)
791 {
792 #ifndef CTS_USES_VULKANSC
793
794         const DeviceInterface&                  vkd                             (m_context.getDeviceInterface());
795         const VkDevice                                  device                  (m_context.getDevice());
796         const Unique<VkCommandBuffer>   cmdBuffer               (allocateCommandBuffer(vkd, device, *m_commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
797         Move<VkCommandBuffer>                   secCmdBuffer;
798
799         // Memory barriers between previous copies and rendering
800         std::vector<VkImageMemoryBarrier> singlesampleImageBarriers(m_singlesampleImages.size(),
801                 {
802                         VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
803                         DE_NULL,
804
805                         VK_ACCESS_TRANSFER_READ_BIT,
806                         VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
807
808                         VK_IMAGE_LAYOUT_UNDEFINED,
809                         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
810
811                         VK_QUEUE_FAMILY_IGNORED,
812                         VK_QUEUE_FAMILY_IGNORED,
813
814                         DE_NULL,
815                         {
816                                 VK_IMAGE_ASPECT_COLOR_BIT,
817                                 m_renderLevel,
818                                 1u,
819                                 0u,
820                                 m_layerCount
821                         }
822                 });
823         for (size_t dstNdx = 0; dstNdx < m_singlesampleImages.size(); dstNdx++)
824                 singlesampleImageBarriers[dstNdx].image = **m_singlesampleImages[dstNdx];
825
826         // Memory barriers to set multisample image layout to COLOR_ATTACHMENT_OPTIMAL
827         std::vector<VkImageMemoryBarrier> multisampleImageBarriers(m_multisampleImages.size(),
828                 {
829                         VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
830                         DE_NULL,
831
832                         0,
833                         VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
834
835                         VK_IMAGE_LAYOUT_UNDEFINED,
836                         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
837
838                         VK_QUEUE_FAMILY_IGNORED,
839                         VK_QUEUE_FAMILY_IGNORED,
840
841                         DE_NULL,
842                         {
843                                 VK_IMAGE_ASPECT_COLOR_BIT,
844                                 0u,
845                                 1u,
846                                 0u,
847                                 m_layerCount
848                         }
849                 });
850         for (size_t dstNdx = 0; dstNdx < m_multisampleImages.size(); dstNdx++)
851                 multisampleImageBarriers[dstNdx].image = **m_multisampleImages[dstNdx];
852
853         VkRect2D                        renderArea = makeRect2D(m_width, m_height);
854         const VkClearValue      clearValue = makeClearValueColor( { 0.0f, 0.0f, 0.0f, 1.0f } );
855         std::vector<vk::VkRenderingAttachmentInfoKHR> colorAttachments(m_attachmentsCount,
856                 {
857                         vk::VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR,    // VkStructureType                                              sType;
858                         DE_NULL,                                                                                                // const void*                                                  pNext;
859                         DE_NULL,                                                                                                // VkImageView                                                  imageView;
860                         vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,                   // VkImageLayout                                                imageLayout;
861                         vk::VK_RESOLVE_MODE_NONE,                                                               // VkResolveModeFlagBits                                resolveMode;
862                         DE_NULL,                                                                                                // VkImageView                                                  resolveImageView;
863                         vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,                   // VkImageLayout                                                resolveImageLayout;
864                         vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE,                                    // VkAttachmentLoadOp                                   loadOp;
865                         vk::VK_ATTACHMENT_STORE_OP_DONT_CARE,                                   // VkAttachmentStoreOp                                  storeOp;
866                         clearValue                                                                                              // VkClearValue                                                 clearValue;
867                 });
868
869         for (deUint32 i = 0; i < m_attachmentsCount; ++i)
870         {
871                 colorAttachments[i].imageView = **m_multisampleImageViews[i];
872                 colorAttachments[i].resolveImageView = **m_singlesampleImageViews[i];
873                 if (isIntFormat(m_format) || isUintFormat(m_format))
874                         colorAttachments[i].resolveMode = vk::VK_RESOLVE_MODE_SAMPLE_ZERO_BIT;
875                 else
876                         colorAttachments[i].resolveMode = vk::VK_RESOLVE_MODE_AVERAGE_BIT;
877         }
878
879         vk::VkRenderingInfoKHR renderingInfo
880         {
881                 vk::VK_STRUCTURE_TYPE_RENDERING_INFO_KHR,
882                 DE_NULL,
883                 0,                                                                                                              // VkRenderingFlagsKHR                                  flags;
884                 renderArea,                                                                                             // VkRect2D                                                             renderArea;
885                 m_layerCount,                                                                                   // deUint32                                                             layerCount;
886                 0u,                                                                                                             // deUint32                                                             viewMask;
887                 m_attachmentsCount,                                                                             // deUint32                                                             colorAttachmentCount;
888                 colorAttachments.data(),                                                                // const VkRenderingAttachmentInfoKHR*  pColorAttachments;
889                 DE_NULL,                                                                                                // const VkRenderingAttachmentInfoKHR*  pDepthAttachment;
890                 DE_NULL,                                                                                                // const VkRenderingAttachmentInfoKHR*  pStencilAttachment;
891         };
892
893         if (m_groupParams->useSecondaryCmdBuffer)
894         {
895                 secCmdBuffer = allocateCommandBuffer(vkd, device, *m_commandPool, VK_COMMAND_BUFFER_LEVEL_SECONDARY);
896
897                 // record secondary command buffer
898                 if (m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
899                 {
900                         beginSecondaryCmdBuffer(*secCmdBuffer, VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT);
901                         vkd.cmdBeginRendering(*secCmdBuffer, &renderingInfo);
902                 }
903                 else
904                         beginSecondaryCmdBuffer(*secCmdBuffer);
905
906                 drawCommands(*secCmdBuffer, *m_renderPipeline, *m_renderPipelineLayout);
907
908                 if (m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
909                         vkd.cmdEndRendering(*secCmdBuffer);
910
911                 endCommandBuffer(vkd, *secCmdBuffer);
912
913                 // record primary command buffer
914                 beginCommandBuffer(vkd, *cmdBuffer);
915
916                 vkd.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT,    VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, (deUint32)singlesampleImageBarriers.size(), &singlesampleImageBarriers[0]);
917                 vkd.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, (deUint32)multisampleImageBarriers.size(), &multisampleImageBarriers[0]);
918
919                 if (!m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
920                 {
921                         renderingInfo.flags = vk::VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS;
922                         vkd.cmdBeginRendering(*cmdBuffer, &renderingInfo);
923                 }
924                 vkd.cmdExecuteCommands(*cmdBuffer, 1u, &*secCmdBuffer);
925
926                 if (!m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
927                         vkd.cmdEndRendering(*cmdBuffer);
928         }
929         else
930         {
931                 beginCommandBuffer(vkd, *cmdBuffer);
932
933                 vkd.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT,    VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, (deUint32)singlesampleImageBarriers.size(), &singlesampleImageBarriers[0]);
934                 vkd.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, (deUint32)multisampleImageBarriers.size(), &multisampleImageBarriers[0]);
935
936                 vkd.cmdBeginRendering(*cmdBuffer, &renderingInfo);
937                 drawCommands(*cmdBuffer, *m_renderPipeline, *m_renderPipelineLayout);
938                 vkd.cmdEndRendering(*cmdBuffer);
939         }
940
941         // Memory barriers to set single-sample image layout to TRANSFER_SRC_OPTIMAL
942         {
943                 std::vector<VkImageMemoryBarrier> barriers;
944
945                 for (size_t dstNdx = 0; dstNdx < m_singlesampleImages.size(); dstNdx++)
946                 {
947                         const VkImageMemoryBarrier barrier =
948                         {
949                                 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
950                                 DE_NULL,
951
952                                 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
953                                 VK_ACCESS_TRANSFER_READ_BIT,
954
955                                 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
956                                 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
957
958                                 VK_QUEUE_FAMILY_IGNORED,
959                                 VK_QUEUE_FAMILY_IGNORED,
960
961                                 **m_singlesampleImages[dstNdx],
962                                 {
963                                         VK_IMAGE_ASPECT_COLOR_BIT,
964                                         m_renderLevel,
965                                         1u,
966                                         0u,
967                                         m_layerCount
968                                 }
969                         };
970
971                         barriers.push_back(barrier);
972                 }
973
974                 vkd.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, (deUint32)barriers.size(), &barriers[0]);
975         }
976
977         for (size_t dstNdx = 0; dstNdx < m_singlesampleImages.size(); dstNdx++)
978         {
979                 // assume that buffer(s) have enough memory to store desired amount of mipmaps
980                 copyImageToBuffer(vkd, *cmdBuffer, **m_singlesampleImages[dstNdx], **m_buffers[dstNdx],
981                                                   m_format, tcu::IVec2((1u << m_renderLevel)*m_width, (1u << m_renderLevel)*m_height), m_renderLevel,
982                                                   VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, m_layerCount);
983         }
984
985         endCommandBuffer(vkd, *cmdBuffer);
986
987         submitCommandsAndWait(vkd, device, m_context.getUniversalQueue(), *cmdBuffer);
988
989         for (size_t memoryBufferNdx = 0; memoryBufferNdx < m_bufferMemory.size(); memoryBufferNdx++)
990                 invalidateMappedMemoryRange(vkd, device, m_bufferMemory[memoryBufferNdx]->getMemory(), 0u, VK_WHOLE_SIZE);
991
992 #endif // CTS_USES_VULKANSC
993 }
994
995 void MultisampleRenderPassTestInstance::submitSwitch (const SharedGroupParams groupParams)
996 {
997         switch (groupParams->renderingType)
998         {
999                 case RENDERING_TYPE_RENDERPASS_LEGACY:
1000                         submit<RenderpassSubpass1>();
1001                         break;
1002                 case RENDERING_TYPE_RENDERPASS2:
1003                         submit<RenderpassSubpass2>();
1004                         break;
1005                 case RENDERING_TYPE_DYNAMIC_RENDERING:
1006                         submitDynamicRendering();
1007                         break;
1008                 default:
1009                         TCU_THROW(InternalError, "Impossible");
1010         }
1011 }
1012
1013 void MultisampleRenderPassTestInstance::verify (void)
1014 {
1015         const Vec4                                                      errorColor              (1.0f, 0.0f, 0.0f, 1.0f);
1016         const Vec4                                                      okColor                 (0.0f, 1.0f, 0.0f, 1.0f);
1017         const tcu::TextureFormat                        format                  (mapVkFormat(m_format));
1018         const tcu::TextureChannelClass          channelClass    (tcu::getTextureChannelClass(format.type));
1019
1020         deUint32                                                        offset                  (0u);
1021         deUint32                                                        width                   ((1u << m_renderLevel) * m_width);
1022         deUint32                                                        height                  ((1u << m_renderLevel) * m_height);
1023         deUint32                                                        pixelSize               (static_cast<deUint32>(getPixelSize()));
1024         for (deUint32 level = 0; level < m_renderLevel; ++level)
1025         {
1026                 offset += (width * height * pixelSize);
1027                 height /= 2;
1028                 width /= 2;
1029         }
1030
1031         std::vector<tcu::ConstPixelBufferAccess> accesses;
1032         for (deUint32 attachmentIdx = 0; attachmentIdx < m_attachmentsCount; ++attachmentIdx)
1033         {
1034                 void* const ptr = static_cast<deUint8*>(m_bufferMemory[attachmentIdx]->getHostPtr()) + offset;
1035                 accesses.push_back(tcu::ConstPixelBufferAccess(format, m_width, m_height, m_layerCount, ptr));
1036         }
1037
1038         tcu::TextureLevel                                       errorMask               (tcu::TextureFormat(tcu::TextureFormat::RGB, tcu::TextureFormat::UNORM_INT8), m_width, m_height, m_layerCount);
1039         tcu::TestLog&                                           log                             (m_context.getTestContext().getLog());
1040
1041         switch (channelClass)
1042         {
1043                 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
1044                 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
1045                 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
1046                 {
1047                         const int       componentCount  (tcu::getNumUsedChannels(format.order));
1048                         bool            isOk                    = true;
1049                         float           clearValue;
1050                         float           renderValue;
1051
1052                         switch (channelClass)
1053                         {
1054                                 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
1055                                 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
1056                                         clearValue      = -1.0f;
1057                                         renderValue     = 1.0f;
1058                                         break;
1059
1060                                 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
1061                                         clearValue      = 0.0f;
1062                                         renderValue     = 1.0f;
1063                                         break;
1064
1065                                 default:
1066                                         clearValue      = 0.0f;
1067                                         renderValue     = 0.0f;
1068                                         DE_FATAL("Unknown channel class");
1069                         }
1070
1071                         for (deUint32 z = 0; z < m_layerCount; z++)
1072                         for (deUint32 y = 0; y < m_height; y++)
1073                         for (deUint32 x = 0; x < m_width; x++)
1074                         {
1075                                 // Color has to be black if no samples were covered, white if all samples were covered or same in every attachment
1076                                 const Vec4      firstColor      (accesses[0].getPixel(x, y, z));
1077                                 const Vec4      refColor        (m_sampleMask == 0x0u
1078                                                                                 ? Vec4(clearValue,
1079                                                                                                 componentCount > 1 ? clearValue : 0.0f,
1080                                                                                                 componentCount > 2 ? clearValue : 0.0f,
1081                                                                                                 componentCount > 3 ? clearValue : 1.0f)
1082                                                                                 : m_sampleMask == ((0x1u << m_sampleCount) - 1u)
1083                                                                                 ? Vec4(renderValue,
1084                                                                                                 componentCount > 1 ? renderValue : 0.0f,
1085                                                                                                 componentCount > 2 ? renderValue : 0.0f,
1086                                                                                                 componentCount > 3 ? renderValue : 1.0f)
1087                                                                                 : firstColor);
1088
1089                                 errorMask.getAccess().setPixel(okColor, x, y, z);
1090
1091                                 for (size_t attachmentNdx = 0; attachmentNdx < m_attachmentsCount; attachmentNdx++)
1092                                 {
1093                                         const Vec4 color (accesses[attachmentNdx].getPixel(x, y, z));
1094
1095                                         if (refColor != color)
1096                                         {
1097                                                 isOk = false;
1098                                                 errorMask.getAccess().setPixel(errorColor, x, y, z);
1099                                                 break;
1100                                         }
1101                                 }
1102
1103                                 {
1104                                         const Vec4 old = m_sum.getAccess().getPixel(x, y, z);
1105                                         m_sum.getAccess().setPixel(old + (tcu::isSRGB(format) ? tcu::sRGBToLinear(firstColor) : firstColor), x, y, z);
1106
1107                                         const Vec4 oldSrgb = m_sumSrgb.getAccess().getPixel(x, y, z);
1108                                         m_sumSrgb.getAccess().setPixel(oldSrgb + firstColor, x, y, z);
1109                                 }
1110                         }
1111
1112                         if (!isOk)
1113                         {
1114                                 const std::string                       sectionName     ("ResolveVerifyWithMask" + de::toString(m_sampleMask));
1115                                 const tcu::ScopedLogSection     section         (log, sectionName, sectionName);
1116
1117                                 for (size_t attachmentNdx = 0; attachmentNdx < m_attachmentsCount; attachmentNdx++)
1118                                         logImage(std::string("Attachment") + de::toString(attachmentNdx), accesses[attachmentNdx]);
1119
1120                                 logImage("ErrorMask", errorMask.getAccess());
1121
1122                                 if (m_sampleMask == 0x0u)
1123                                 {
1124                                         m_context.getTestContext().getLog() << tcu::TestLog::Message << "Empty sample mask didn't produce all " << clearValue << " pixels" << tcu::TestLog::EndMessage;
1125                                         m_resultCollector.fail("Empty sample mask didn't produce correct pixel values");
1126                                 }
1127                                 else if (m_sampleMask == ((0x1u << m_sampleCount) - 1u))
1128                                 {
1129                                         m_context.getTestContext().getLog() << tcu::TestLog::Message << "Full sample mask didn't produce all " << renderValue << " pixels" << tcu::TestLog::EndMessage;
1130                                         m_resultCollector.fail("Full sample mask didn't produce correct pixel values");
1131                                 }
1132                                 else
1133                                 {
1134                                         m_context.getTestContext().getLog() << tcu::TestLog::Message << "Resolve is inconsistent between attachments" << tcu::TestLog::EndMessage;
1135                                         m_resultCollector.fail("Resolve is inconsistent between attachments");
1136                                 }
1137                         }
1138                         break;
1139                 }
1140
1141                 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
1142                 {
1143                         const int               componentCount                  (tcu::getNumUsedChannels(format.order));
1144                         const UVec4             bitDepth                                (tcu::getTextureFormatBitDepth(format).cast<deUint32>());
1145                         const UVec4             renderValue                             (tcu::select((UVec4(1u) << tcu::min(UVec4(8u), bitDepth)) - UVec4(1u),
1146                                                                                                                                   UVec4(0u, 0u, 0u, 1u),
1147                                                                                                                                   tcu::lessThan(IVec4(0, 1, 2, 3), IVec4(componentCount))));
1148                         const UVec4             clearValue                              (tcu::select(UVec4(0u),
1149                                                                                                                                  UVec4(0u, 0u, 0u, 1u),
1150                                                                                                                                  tcu::lessThan(IVec4(0, 1, 2, 3), IVec4(componentCount))));
1151                         bool                    unexpectedValues                = false;
1152                         bool                    inconsistentComponents  = false;
1153                         bool                    inconsistentAttachments = false;
1154
1155                         for (deUint32 z = 0; z < m_layerCount; z++)
1156                         for (deUint32 y = 0; y < m_height; y++)
1157                         for (deUint32 x = 0; x < m_width; x++)
1158                         {
1159                                 // Color has to be all zeros if no samples were covered, all 255 if all samples were covered or consistent across all attachments
1160                                 const UVec4 refColor    (m_sampleMask == 0x0u
1161                                                                                 ? clearValue
1162                                                                                 : m_sampleMask == ((0x1u << m_sampleCount) - 1u)
1163                                                                                 ? renderValue
1164                                                                                 : accesses[0].getPixelUint(x, y, z));
1165                                 bool            isOk            = true;
1166
1167                                 // If reference value was taken from first attachment, check that it is valid value i.e. clear or render value
1168                                 if (m_sampleMask != 0x0u && m_sampleMask != ((0x1u << m_sampleCount) - 1u))
1169                                 {
1170                                         // Each component must be resolved same way
1171                                         const BVec4             isRenderValue                   (refColor == renderValue);
1172                                         const BVec4             isClearValue                    (refColor == clearValue);
1173                                         const bool              unexpectedValue                 (tcu::anyNotEqual(tcu::logicalOr(isRenderValue, isClearValue), BVec4(true)));
1174                                         const bool              inconsistentComponent   (!(tcu::allEqual(isRenderValue, BVec4(true)) || tcu::allEqual(isClearValue, BVec4(true))));
1175
1176                                         unexpectedValues                |= unexpectedValue;
1177                                         inconsistentComponents  |= inconsistentComponent;
1178
1179                                         if (unexpectedValue || inconsistentComponent)
1180                                                 isOk = false;
1181                                 }
1182
1183                                 for (size_t attachmentNdx = 0; attachmentNdx < m_attachmentsCount; attachmentNdx++)
1184                                 {
1185                                         const UVec4 color (accesses[attachmentNdx].getPixelUint(x, y, z));
1186
1187                                         if (refColor != color)
1188                                         {
1189                                                 isOk = false;
1190                                                 inconsistentAttachments = true;
1191                                                 break;
1192                                         }
1193                                 }
1194
1195                                 errorMask.getAccess().setPixel((isOk ? okColor : errorColor), x, y, z);
1196                         }
1197
1198                         if (unexpectedValues || inconsistentComponents || inconsistentAttachments)
1199                         {
1200                                 const std::string                       sectionName     ("ResolveVerifyWithMask" + de::toString(m_sampleMask));
1201                                 const tcu::ScopedLogSection     section         (log, sectionName, sectionName);
1202
1203                                 for (size_t attachmentNdx = 0; attachmentNdx < m_attachmentsCount; attachmentNdx++)
1204                                         logImage(std::string("Attachment") + de::toString(attachmentNdx), accesses[attachmentNdx]);
1205
1206                                 logImage("ErrorMask", errorMask.getAccess());
1207
1208                                 if (m_sampleMask == 0x0u)
1209                                 {
1210                                         m_context.getTestContext().getLog() << tcu::TestLog::Message << "Empty sample mask didn't produce all " << clearValue << " pixels" << tcu::TestLog::EndMessage;
1211                                         m_resultCollector.fail("Empty sample mask didn't produce correct pixels");
1212                                 }
1213                                 else if (m_sampleMask == ((0x1u << m_sampleCount) - 1u))
1214                                 {
1215                                         m_context.getTestContext().getLog() << tcu::TestLog::Message << "Full sample mask didn't produce all " << renderValue << " pixels" << tcu::TestLog::EndMessage;
1216                                         m_resultCollector.fail("Full sample mask didn't produce correct pixels");
1217                                 }
1218                                 else
1219                                 {
1220                                         if (unexpectedValues)
1221                                         {
1222                                                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Resolve produced unexpected values i.e. not " << clearValue << " or " << renderValue << tcu::TestLog::EndMessage;
1223                                                 m_resultCollector.fail("Resolve produced unexpected values");
1224                                         }
1225
1226                                         if (inconsistentComponents)
1227                                         {
1228                                                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Different components of attachment were resolved to different values." << tcu::TestLog::EndMessage;
1229                                                 m_resultCollector.fail("Different components of attachment were resolved to different values.");
1230                                         }
1231
1232                                         if (inconsistentAttachments)
1233                                         {
1234                                                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Different attachments were resolved to different values." << tcu::TestLog::EndMessage;
1235                                                 m_resultCollector.fail("Different attachments were resolved to different values.");
1236                                         }
1237                                 }
1238                         }
1239                         break;
1240                 }
1241
1242                 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
1243                 {
1244                         const int               componentCount                  (tcu::getNumUsedChannels(format.order));
1245                         const IVec4             bitDepth                                (tcu::getTextureFormatBitDepth(format));
1246                         const IVec4             renderValue                             (tcu::select((IVec4(1) << (tcu::min(IVec4(8), bitDepth) - IVec4(1))) - IVec4(1),
1247                                                                                                                                   IVec4(0, 0, 0, 1),
1248                                                                                                                                   tcu::lessThan(IVec4(0, 1, 2, 3), IVec4(componentCount))));
1249                         const IVec4             clearValue                              (tcu::select(-(IVec4(1) << (tcu::min(IVec4(8), bitDepth) - IVec4(1))),
1250                                                                                                                                  IVec4(0, 0, 0, 1),
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 z = 0; z < m_layerCount; z++)
1257                         for (deUint32 y = 0; y < m_height; y++)
1258                         for (deUint32 x = 0; x < m_width; x++)
1259                         {
1260                                 // Color has to be all zeros if no samples were covered, all 255 if all samples were covered or consistent across all attachments
1261                                 const IVec4 refColor    (m_sampleMask == 0x0u
1262                                                                                 ? clearValue
1263                                                                                 : m_sampleMask == ((0x1u << m_sampleCount) - 1u)
1264                                                                                 ? renderValue
1265                                                                                 : accesses[0].getPixelInt(x, y, z));
1266                                 bool            isOk            = true;
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                                         const bool              unexpectedValue                 (tcu::anyNotEqual(tcu::logicalOr(isRenderValue, isClearValue), BVec4(true)));
1275                                         const bool              inconsistentComponent   (!(tcu::allEqual(isRenderValue, BVec4(true)) || tcu::allEqual(isClearValue, BVec4(true))));
1276
1277                                         unexpectedValues                |= unexpectedValue;
1278                                         inconsistentComponents  |= inconsistentComponent;
1279
1280                                         if (unexpectedValue || inconsistentComponent)
1281                                                 isOk = false;
1282                                 }
1283
1284                                 for (size_t attachmentNdx = 0; attachmentNdx < m_attachmentsCount; attachmentNdx++)
1285                                 {
1286                                         const IVec4 color (accesses[attachmentNdx].getPixelInt(x, y, z));
1287
1288                                         if (refColor != color)
1289                                         {
1290                                                 isOk = false;
1291                                                 inconsistentAttachments = true;
1292                                                 break;
1293                                         }
1294                                 }
1295
1296                                 errorMask.getAccess().setPixel((isOk ? okColor : errorColor), x, y, z);
1297                         }
1298
1299                         if (unexpectedValues || inconsistentComponents || inconsistentAttachments)
1300                         {
1301                                 const std::string                       sectionName     ("ResolveVerifyWithMask" + de::toString(m_sampleMask));
1302                                 const tcu::ScopedLogSection     section         (log, sectionName, sectionName);
1303
1304                                 for (size_t attachmentNdx = 0; attachmentNdx < m_attachmentsCount; attachmentNdx++)
1305                                         logImage(std::string("Attachment") + de::toString(attachmentNdx), accesses[attachmentNdx]);
1306
1307                                 logImage("ErrorMask", errorMask.getAccess());
1308
1309                                 if (m_sampleMask == 0x0u)
1310                                 {
1311                                         m_context.getTestContext().getLog() << tcu::TestLog::Message << "Empty sample mask didn't produce all " << clearValue << " pixels" << tcu::TestLog::EndMessage;
1312                                         m_resultCollector.fail("Empty sample mask didn't produce correct pixels");
1313                                 }
1314                                 else if (m_sampleMask == ((0x1u << m_sampleCount) - 1u))
1315                                 {
1316                                         m_context.getTestContext().getLog() << tcu::TestLog::Message << "Full sample mask didn't produce all " << renderValue << " pixels" << tcu::TestLog::EndMessage;
1317                                         m_resultCollector.fail("Full sample mask didn't produce correct pixels");
1318                                 }
1319                                 else
1320                                 {
1321                                         if (unexpectedValues)
1322                                         {
1323                                                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Resolve produced unexpected values i.e. not " << clearValue << " or " << renderValue << tcu::TestLog::EndMessage;
1324                                                 m_resultCollector.fail("Resolve produced unexpected values");
1325                                         }
1326
1327                                         if (inconsistentComponents)
1328                                         {
1329                                                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Different components of attachment were resolved to different values." << tcu::TestLog::EndMessage;
1330                                                 m_resultCollector.fail("Different components of attachment were resolved to different values.");
1331                                         }
1332
1333                                         if (inconsistentAttachments)
1334                                         {
1335                                                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Different attachments were resolved to different values." << tcu::TestLog::EndMessage;
1336                                                 m_resultCollector.fail("Different attachments were resolved to different values.");
1337                                         }
1338                                 }
1339                         }
1340                         break;
1341                 }
1342
1343                 default:
1344                         DE_FATAL("Unknown channel class");
1345         }
1346 }
1347
1348 tcu::TestStatus MultisampleRenderPassTestInstance::iterate (void)
1349 {
1350         if (m_sampleMask == 0u)
1351         {
1352                 const tcu::TextureFormat                format                  (mapVkFormat(m_format));
1353                 const tcu::TextureChannelClass  channelClass    (tcu::getTextureChannelClass(format.type));
1354                 tcu::TestLog&                                   log                             (m_context.getTestContext().getLog());
1355
1356                 switch (channelClass)
1357                 {
1358                         case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
1359                                 log << TestLog::Message << "Clearing target to zero and rendering 255 pixels with every possible sample mask" << TestLog::EndMessage;
1360                                 break;
1361
1362                         case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
1363                                 log << TestLog::Message << "Clearing target to -128 and rendering 127 pixels with every possible sample mask" << TestLog::EndMessage;
1364                                 break;
1365
1366                         case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
1367                         case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
1368                         case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
1369                                 log << TestLog::Message << "Clearing target to black and rendering white pixels with every possible sample mask" << TestLog::EndMessage;
1370                                 break;
1371
1372                         default:
1373                                 DE_FATAL("Unknown channel class");
1374                 }
1375         }
1376
1377         submitSwitch(m_groupParams);
1378         verify();
1379
1380         if (m_sampleMask == ((0x1u << m_sampleCount) - 1u))
1381         {
1382                 const tcu::TextureFormat                format                  (mapVkFormat(m_format));
1383                 const tcu::TextureChannelClass  channelClass    (tcu::getTextureChannelClass(format.type));
1384                 const Vec4                                              threshold               (getFormatThreshold());
1385                 tcu::TestLog&                                   log                             (m_context.getTestContext().getLog());
1386
1387                 if (channelClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT
1388                                 || channelClass == tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT
1389                                 || channelClass == tcu::TEXTURECHANNELCLASS_FLOATING_POINT)
1390                 {
1391                         const int                       componentCount  (tcu::getNumUsedChannels(format.order));
1392                         const Vec4                      errorColor              (1.0f, 0.0f, 0.0f, 1.0f);
1393                         const Vec4                      okColor                 (0.0f, 1.0f, 0.0f, 1.0f);
1394                         tcu::TextureLevel       errorMask               (tcu::TextureFormat(tcu::TextureFormat::RGB, tcu::TextureFormat::UNORM_INT8), m_width, m_height, m_layerCount);
1395                         bool                            isOk                    = true;
1396                         Vec4                            maxDiff                 (0.0f);
1397                         Vec4                            expectedAverage;
1398
1399                         switch (channelClass)
1400                         {
1401                                 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
1402                                 {
1403                                         expectedAverage = Vec4(0.5f, componentCount > 1 ? 0.5f : 0.0f, componentCount > 2 ? 0.5f : 0.0f, componentCount > 3 ? 0.5f : 1.0f);
1404                                         break;
1405                                 }
1406
1407                                 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
1408                                 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
1409                                 {
1410                                         expectedAverage = Vec4(0.0f, 0.0f, 0.0f, componentCount > 3 ? 0.0f : 1.0f);
1411                                         break;
1412                                 }
1413
1414                                 default:
1415                                         DE_FATAL("Unknown channel class");
1416                         }
1417
1418                         for (deUint32 z = 0; z < m_layerCount; z++)
1419                         for (deUint32 y = 0; y < m_height; y++)
1420                         for (deUint32 x = 0; x < m_width; x++)
1421                         {
1422                                 const Vec4      sum             (m_sum.getAccess().getPixel(x, y, z));
1423                                 const Vec4      average (sum / Vec4((float)(0x1u << m_sampleCount)));
1424                                 const Vec4      diff    (tcu::abs(average - expectedAverage));
1425
1426                                 m_sum.getAccess().setPixel(average, x, y, z);
1427                                 errorMask.getAccess().setPixel(okColor, x, y, z);
1428
1429                                 bool failThreshold;
1430
1431                                 if (!tcu::isSRGB(format))
1432                                 {
1433                                         failThreshold = (diff[0] > threshold.x()
1434                                                                                 || diff[1] > threshold.y()
1435                                                                                 || diff[2] > threshold.z()
1436                                                                                 || diff[3] > threshold.w());
1437                                 }
1438                                 else
1439                                 {
1440                                         const Vec4      sumSrgb(m_sumSrgb.getAccess().getPixel(x, y, z));
1441                                         const Vec4      averageSrgb(sumSrgb / Vec4((float)(0x1u << m_sampleCount)));
1442                                         const Vec4      diffSrgb(tcu::abs(averageSrgb - expectedAverage));
1443
1444                                         m_sumSrgb.getAccess().setPixel(averageSrgb, x, y, z);
1445
1446                                         // Spec doesn't restrict implementation to downsample in linear color space. So, comparing both non linear and
1447                                         // linear diff's in case of srgb formats.
1448                                         failThreshold = ((diff[0] > threshold.x()
1449                                                                                 || diff[1] > threshold.y()
1450                                                                                 || diff[2] > threshold.z()
1451                                                                                 || diff[3] > threshold.w()) &&
1452                                                                         (diffSrgb[0] > threshold.x()
1453                                                                                 || diffSrgb[1] > threshold.y()
1454                                                                                 || diffSrgb[2] > threshold.z()
1455                                                                                 || diffSrgb[3] > threshold.w()));
1456
1457                                 }
1458
1459                                 if (failThreshold)
1460                                 {
1461                                         isOk    = false;
1462                                         maxDiff = tcu::max(maxDiff, diff);
1463                                         errorMask.getAccess().setPixel(errorColor, x, y, z);
1464                                 }
1465                         }
1466
1467                         log << TestLog::Image("Average resolved values in attachment 0", "Average resolved values in attachment 0", m_sum);
1468
1469                         if (!isOk)
1470                         {
1471                                 std::stringstream       message;
1472
1473                                 m_context.getTestContext().getLog() << tcu::LogImage("ErrorMask", "ErrorMask", errorMask.getAccess());
1474
1475                                 message << "Average resolved values differ from expected average values by more than ";
1476
1477                                 switch (componentCount)
1478                                 {
1479                                         case 1:
1480                                                 message << threshold.x();
1481                                                 break;
1482                                         case 2:
1483                                                 message << "vec2" << Vec2(threshold.x(), threshold.y());
1484                                                 break;
1485                                         case 3:
1486                                                 message << "vec3" << Vec3(threshold.x(), threshold.y(), threshold.z());
1487                                                 break;
1488                                         default:
1489                                                 message << "vec4" << threshold;
1490                                 }
1491
1492                                 message << ". Max diff " << maxDiff;
1493                                 log << TestLog::Message << message.str() << TestLog::EndMessage;
1494
1495                                 m_resultCollector.fail("Average resolved values differ from expected average values");
1496                         }
1497                 }
1498
1499                 return tcu::TestStatus(m_resultCollector.getResult(), m_resultCollector.getMessage());
1500         }
1501         else
1502         {
1503                 m_sampleMask++;
1504                 return tcu::TestStatus::incomplete();
1505         }
1506 }
1507
1508 template<typename RenderPassTrait>
1509 Move<VkRenderPass> MultisampleRenderPassTestInstance::createRenderPass (bool usedResolveAttachment)
1510 {
1511         // make name for RenderPass1Trait or RenderPass2Trait shorter
1512         typedef RenderPassTrait RPT;
1513         typedef typename RPT::AttDesc                           AttDesc;
1514         typedef typename RPT::AttRef                            AttRef;
1515         typedef typename RPT::SubpassDesc                       SubpassDesc;
1516         typedef typename RPT::RenderPassCreateInfo      RenderPassCreateInfo;
1517
1518         const DeviceInterface&  vkd                                             = m_context.getDeviceInterface();
1519         VkDevice                                device                                  = m_context.getDevice();
1520         std::vector<AttDesc>    attachments;
1521         std::vector<AttRef>             colorAttachmentRefs;
1522         std::vector<AttRef>             resolveAttachmentRefs;
1523
1524         for (size_t attachmentNdx = 0; attachmentNdx < m_attachmentsCount; attachmentNdx++)
1525         {
1526                 {
1527                         const AttDesc multisampleAttachment
1528                         (
1529                                                                                                                         // sType
1530                                 DE_NULL,                                                                        // pNext
1531                                 0u,                                                                                     // flags
1532                                 m_format,                                                                       // format
1533                                 m_sampleCount,                                                          // samples
1534                                 VK_ATTACHMENT_LOAD_OP_DONT_CARE,                        // loadOp
1535                                 VK_ATTACHMENT_STORE_OP_DONT_CARE,                       // storeOp
1536                                 VK_ATTACHMENT_LOAD_OP_DONT_CARE,                        // stencilLoadOp
1537                                 VK_ATTACHMENT_STORE_OP_DONT_CARE,                       // stencilStoreOp
1538                                 VK_IMAGE_LAYOUT_UNDEFINED,                                      // initialLayout
1539                                 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL        // finalLayout
1540                         );
1541                         const AttRef attachmentRef
1542                         (
1543                                                                                                                         // sType
1544                                 DE_NULL,                                                                        // pNext
1545                                 (deUint32)attachments.size(),                           // attachment
1546                                 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,       // layout
1547                                 0u                                                                                      // aspectMask
1548                         );
1549                         colorAttachmentRefs.push_back(attachmentRef);
1550                         attachments.push_back(multisampleAttachment);
1551                 }
1552                 {
1553                         const AttDesc singlesampleAttachment
1554                         (
1555                                                                                                                         // sType
1556                                 DE_NULL,                                                                        // pNext
1557                                 0u,                                                                                     // flags
1558                                 m_format,                                                                       // format
1559                                 VK_SAMPLE_COUNT_1_BIT,                                          // samples
1560                                 VK_ATTACHMENT_LOAD_OP_DONT_CARE,                        // loadOp
1561                                 VK_ATTACHMENT_STORE_OP_STORE,                           // storeOp
1562                                 VK_ATTACHMENT_LOAD_OP_DONT_CARE,                        // stencilLoadOp
1563                                 VK_ATTACHMENT_STORE_OP_DONT_CARE,                       // stencilStoreOp
1564                                 VK_IMAGE_LAYOUT_UNDEFINED,                                      // initialLayout
1565                                 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL            // finalLayout
1566                         );
1567                         const auto attachmentId = (usedResolveAttachment ? static_cast<deUint32>(attachments.size()) : VK_ATTACHMENT_UNUSED);
1568                         const AttRef attachmentRef
1569                         (
1570                                                                                                                         // sType
1571                                 DE_NULL,                                                                        // pNext
1572                                 attachmentId,                                                           // attachment
1573                                 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,       // layout
1574                                 0u                                                                                      // aspectMask
1575                         );
1576                         resolveAttachmentRefs.push_back(attachmentRef);
1577                         attachments.push_back(singlesampleAttachment);
1578                 }
1579         }
1580
1581         DE_ASSERT(colorAttachmentRefs.size() == resolveAttachmentRefs.size());
1582         DE_ASSERT(attachments.size() == colorAttachmentRefs.size() + resolveAttachmentRefs.size());
1583
1584         const SubpassDesc subpass
1585         (
1586                                                                                                                 // sType
1587                 DE_NULL,                                                                                // pNext
1588                 (VkSubpassDescriptionFlags)0,                                   // flags
1589                 VK_PIPELINE_BIND_POINT_GRAPHICS,                                // pipelineBindPoint
1590                 0u,                                                                                             // viewMask
1591                 0u,                                                                                             // inputAttachmentCount
1592                 DE_NULL,                                                                                // pInputAttachments
1593                 (deUint32)colorAttachmentRefs.size(),                   // colorAttachmentCount
1594                 &colorAttachmentRefs[0],                                                // pColorAttachments
1595                 &resolveAttachmentRefs[0],                                              // pResolveAttachments
1596                 DE_NULL,                                                                                // pDepthStencilAttachment
1597                 0u,                                                                                             // preserveAttachmentCount
1598                 DE_NULL                                                                                 // pPreserveAttachments
1599         );
1600         const RenderPassCreateInfo renderPassCreator
1601         (
1602                                                                                                                 // sType
1603                 DE_NULL,                                                                                // pNext
1604                 (VkRenderPassCreateFlags)0u,                                    // flags
1605                 (deUint32)attachments.size(),                                   // attachmentCount
1606                 &attachments[0],                                                                // pAttachments
1607                 1u,                                                                                             // subpassCount
1608                 &subpass,                                                                               // pSubpasses
1609                 0u,                                                                                             // dependencyCount
1610                 DE_NULL,                                                                                // pDependencies
1611                 0u,                                                                                             // correlatedViewMaskCount
1612                 DE_NULL                                                                                 // pCorrelatedViewMasks
1613         );
1614
1615         return renderPassCreator.createRenderPass(vkd, device);
1616 }
1617
1618 Move<VkRenderPass> MultisampleRenderPassTestInstance::createRenderPassSwitch (bool usedResolveAttachment)
1619 {
1620         switch (m_groupParams->renderingType)
1621         {
1622                 case RENDERING_TYPE_RENDERPASS_LEGACY:
1623                         return createRenderPass<RenderPass1Trait>(usedResolveAttachment);
1624                 case RENDERING_TYPE_RENDERPASS2:
1625                         return createRenderPass<RenderPass2Trait>(usedResolveAttachment);
1626                 case RENDERING_TYPE_DYNAMIC_RENDERING:
1627                         return Move<VkRenderPass>();
1628                 default:
1629                         TCU_THROW(InternalError, "Impossible");
1630         }
1631 }
1632
1633 Move<VkRenderPass> MultisampleRenderPassTestInstance::createRenderPassCompatible (void)
1634 {
1635         if (m_testCompatibility)
1636         {
1637                 // The compatible render pass is always created with a used resolve attachment.
1638                 return createRenderPassSwitch(true);
1639         }
1640         else
1641         {
1642                 return {};
1643         }
1644 }
1645
1646 Move<VkPipelineLayout> MultisampleRenderPassTestInstance::createRenderPipelineLayout (void)
1647 {
1648         const DeviceInterface&  vkd             = m_context.getDeviceInterface();
1649         VkDevice                                device  = m_context.getDevice();
1650
1651         const VkPushConstantRange pushConstant =
1652         {
1653                 VK_SHADER_STAGE_FRAGMENT_BIT,
1654                 0u,
1655                 4u
1656         };
1657         const VkPipelineLayoutCreateInfo createInfo =
1658         {
1659                 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
1660                 DE_NULL,
1661                 (vk::VkPipelineLayoutCreateFlags)0,
1662
1663                 0u,
1664                 DE_NULL,
1665
1666                 1u,
1667                 &pushConstant
1668         };
1669
1670         return createPipelineLayout(vkd, device, &createInfo);
1671 }
1672
1673 Move<VkPipeline> MultisampleRenderPassTestInstance::createRenderPipeline (void)
1674 {
1675         const DeviceInterface&                  vkd                                             = m_context.getDeviceInterface();
1676         VkDevice                                                device                                  = m_context.getDevice();
1677         const vk::BinaryCollection&             binaryCollection                = m_context.getBinaryCollection();
1678         const Unique<VkShaderModule>    vertexShaderModule              (createShaderModule(vkd, device, binaryCollection.get("quad-vert"), 0u));
1679         const Unique<VkShaderModule>    fragmentShaderModule    (createShaderModule(vkd, device, binaryCollection.get("quad-frag"), 0u));
1680         const Move<VkShaderModule>              geometryShaderModule    (m_layerCount == 1 ? Move<VkShaderModule>() : createShaderModule(vkd, device, binaryCollection.get("geom"), 0u));
1681         // Disable blending
1682         const VkPipelineColorBlendAttachmentState attachmentBlendState =
1683         {
1684                 VK_FALSE,
1685                 VK_BLEND_FACTOR_SRC_ALPHA,
1686                 VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,
1687                 VK_BLEND_OP_ADD,
1688                 VK_BLEND_FACTOR_ONE,
1689                 VK_BLEND_FACTOR_ONE,
1690                 VK_BLEND_OP_ADD,
1691                 VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT
1692         };
1693         std::vector<VkPipelineColorBlendAttachmentState>        attachmentBlendStates(m_attachmentsCount, attachmentBlendState);
1694         const VkPipelineVertexInputStateCreateInfo                      vertexInputState =
1695         {
1696                 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
1697                 DE_NULL,
1698                 (VkPipelineVertexInputStateCreateFlags)0u,
1699
1700                 0u,
1701                 DE_NULL,
1702
1703                 0u,
1704                 DE_NULL
1705         };
1706         const tcu::UVec2                                renderArea      (m_width, m_height);
1707         const std::vector<VkViewport>   viewports       (1, makeViewport(renderArea));
1708         const std::vector<VkRect2D>             scissors        (1, makeRect2D(renderArea));
1709
1710         const VkPipelineMultisampleStateCreateInfo multisampleState =
1711         {
1712                 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
1713                 DE_NULL,
1714                 (VkPipelineMultisampleStateCreateFlags)0u,
1715
1716                 sampleCountBitFromSampleCount(m_sampleCount),
1717                 VK_FALSE,
1718                 0.0f,
1719                 DE_NULL,
1720                 VK_FALSE,
1721                 VK_FALSE,
1722         };
1723         const VkPipelineDepthStencilStateCreateInfo depthStencilState =
1724         {
1725                 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
1726                 DE_NULL,
1727                 (VkPipelineDepthStencilStateCreateFlags)0u,
1728
1729                 VK_FALSE,
1730                 VK_TRUE,
1731                 VK_COMPARE_OP_ALWAYS,
1732                 VK_FALSE,
1733                 VK_TRUE,
1734                 {
1735                         VK_STENCIL_OP_KEEP,
1736                         VK_STENCIL_OP_INCREMENT_AND_WRAP,
1737                         VK_STENCIL_OP_KEEP,
1738                         VK_COMPARE_OP_ALWAYS,
1739                         ~0u,
1740                         ~0u,
1741                         0xFFu / (m_sampleCount + 1)
1742                 },
1743                 {
1744                         VK_STENCIL_OP_KEEP,
1745                         VK_STENCIL_OP_INCREMENT_AND_WRAP,
1746                         VK_STENCIL_OP_KEEP,
1747                         VK_COMPARE_OP_ALWAYS,
1748                         ~0u,
1749                         ~0u,
1750                         0xFFu / (m_sampleCount + 1)
1751                 },
1752
1753                 0.0f,
1754                 1.0f
1755         };
1756         const VkPipelineColorBlendStateCreateInfo blendState =
1757         {
1758                 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
1759                 DE_NULL,
1760                 (VkPipelineColorBlendStateCreateFlags)0u,
1761
1762                 VK_FALSE,
1763                 VK_LOGIC_OP_COPY,
1764                 deUint32(attachmentBlendStates.size()),
1765                 &attachmentBlendStates[0],
1766                 { 0.0f, 0.0f, 0.0f, 0.0f }
1767         };
1768
1769         void* pNext = DE_NULL;
1770
1771 #ifndef CTS_USES_VULKANSC
1772         std::vector<VkFormat> attachmentFormats(m_attachmentsCount, m_format);
1773         VkPipelineRenderingCreateInfoKHR renderingCreateInfo
1774         {
1775                 VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR,
1776                 DE_NULL,
1777                 0u,
1778                 m_attachmentsCount,
1779                 attachmentFormats.data(),
1780                 VK_FORMAT_UNDEFINED,
1781                 VK_FORMAT_UNDEFINED
1782         };
1783         if (m_groupParams->renderingType == RENDERING_TYPE_DYNAMIC_RENDERING)
1784                 pNext = &renderingCreateInfo;
1785 #endif // CTS_USES_VULKANSC
1786
1787         return makeGraphicsPipeline(vkd,                                                                                                // const DeviceInterface&                        vk
1788                                                                 device,                                                                                         // const VkDevice                                device
1789                                                                 *m_renderPipelineLayout,                                                        // const VkPipelineLayout                        pipelineLayout
1790                                                                 *vertexShaderModule,                                                            // const VkShaderModule                          vertexShaderModule
1791                                                                 DE_NULL,                                                                                        // const VkShaderModule                          tessellationControlShaderModule
1792                                                                 DE_NULL,                                                                                        // const VkShaderModule                          tessellationEvalShaderModule
1793                                                                 m_layerCount != 1 ? *geometryShaderModule : DE_NULL,// const VkShaderModule                          geometryShaderModule
1794                                                                 *fragmentShaderModule,                                                          // const VkShaderModule                          fragmentShaderModule
1795                                                                 *m_renderPass,                                                                          // const VkRenderPass                            renderPass
1796                                                                 viewports,                                                                                      // const std::vector<VkViewport>&                viewports
1797                                                                 scissors,                                                                                       // const std::vector<VkRect2D>&                  scissors
1798                                                                 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,                            // const VkPrimitiveTopology                     topology
1799                                                                 0u,                                                                                                     // const deUint32                                subpass
1800                                                                 0u,                                                                                                     // const deUint32                                patchControlPoints
1801                                                                 &vertexInputState,                                                                      // const VkPipelineVertexInputStateCreateInfo*   vertexInputStateCreateInfo
1802                                                                 DE_NULL,                                                                                        // const VkPipelineRasterizationStateCreateInfo* rasterizationStateCreateInfo
1803                                                                 &multisampleState,                                                                      // const VkPipelineMultisampleStateCreateInfo*   multisampleStateCreateInfo
1804                                                                 &depthStencilState,                                                                     // const VkPipelineDepthStencilStateCreateInfo*  depthStencilStateCreateInfo
1805                                                                 &blendState,                                                                            // const VkPipelineColorBlendStateCreateInfo*    colorBlendStateCreateInfo
1806                                                                 DE_NULL,                                                                                        // const VkPipelineDynamicStateCreateInfo*       dynamicStateCreateInfo
1807                                                                 pNext);                                                                                         // const void*                                   pNext
1808 }
1809
1810 #ifndef CTS_USES_VULKANSC
1811 void MultisampleRenderPassTestInstance::beginSecondaryCmdBuffer(VkCommandBuffer cmdBuffer, VkRenderingFlagsKHR renderingFlags) const
1812 {
1813         const DeviceInterface& vkd = m_context.getDeviceInterface();
1814         std::vector<VkFormat> formats(m_attachmentsCount, m_format);
1815
1816         VkCommandBufferInheritanceRenderingInfoKHR inheritanceRenderingInfo
1817         {
1818                 VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_RENDERING_INFO_KHR,                // VkStructureType                                      sType;
1819                 DE_NULL,                                                                                                                                // const void*                                          pNext;
1820                 renderingFlags,                                                                                                                 // VkRenderingFlagsKHR                          flags;
1821                 0u,                                                                                                                                             // uint32_t                                                     viewMask;
1822                 m_attachmentsCount,                                                                                                             // uint32_t                                                     colorAttachmentCount;
1823                 formats.data(),                                                                                                                 // const VkFormat*                                      pColorAttachmentFormats;
1824                 VK_FORMAT_UNDEFINED,                                                                                                    // VkFormat                                                     depthAttachmentFormat;
1825                 VK_FORMAT_UNDEFINED,                                                                                                    // VkFormat                                                     stencilAttachmentFormat;
1826                 m_sampleCount,                                                                                                                  // VkSampleCountFlagBits                        rasterizationSamples;
1827         };
1828
1829         const VkCommandBufferInheritanceInfo bufferInheritanceInfo = initVulkanStructure(&inheritanceRenderingInfo);
1830         VkCommandBufferUsageFlags usageFlags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
1831         if (!m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
1832                 usageFlags |= VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT;
1833
1834         const VkCommandBufferBeginInfo commandBufBeginParams
1835         {
1836                 VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,                                                    // VkStructureType                                      sType;
1837                 DE_NULL,                                                                                                                                // const void*                                          pNext;
1838                 usageFlags,                                                                                                                             // VkCommandBufferUsageFlags            flags;
1839                 &bufferInheritanceInfo
1840         };
1841
1842         VK_CHECK(vkd.beginCommandBuffer(cmdBuffer, &commandBufBeginParams));
1843 }
1844 #endif // CTS_USES_VULKANSC
1845
1846 class MaxAttachmenstsRenderPassTestInstance : public MultisampleRenderPassTestBase
1847 {
1848 public:
1849         MaxAttachmenstsRenderPassTestInstance   (Context& context, TestConfig config);
1850         ~MaxAttachmenstsRenderPassTestInstance  (void);
1851
1852         tcu::TestStatus                 iterate                 (void);
1853
1854 private:
1855
1856         template<typename RenderpassSubpass>
1857         void                                    submit                                          (void);
1858         void                                    submitSwitch                            (RenderingType renderingType);
1859         void                                    verify                                          (void);
1860
1861         Move<VkDescriptorSetLayout>     createDescriptorSetLayout       (void);
1862         Move<VkDescriptorPool>          createDescriptorPool            (void);
1863         Move<VkDescriptorSet>           createDescriptorSet                     (void);
1864
1865         template<typename RenderPassTrait>
1866         Move<VkRenderPass>              createRenderPass                        (void);
1867         Move<VkRenderPass>              createRenderPassSwitch          (const RenderingType renderingType);
1868         Move<VkPipelineLayout>  createRenderPipelineLayout      (bool secondSubpass);
1869         Move<VkPipeline>                createRenderPipeline            (bool secondSubpass);
1870
1871 private:
1872
1873         const std::vector<VkImageSp>                    m_multisampleImages;
1874         const std::vector<AllocationSp>                 m_multisampleImageMemory;
1875         const std::vector<VkImageViewSp>                m_multisampleImageViews;
1876
1877         const std::vector<VkImageSp>                    m_singlesampleImages;
1878         const std::vector<AllocationSp>                 m_singlesampleImageMemory;
1879         const std::vector<VkImageViewSp>                m_singlesampleImageViews;
1880
1881         const Unique<VkDescriptorSetLayout>             m_descriptorSetLayout;
1882         const Unique<VkDescriptorPool>                  m_descriptorPool;
1883         const Unique<VkDescriptorSet>                   m_descriptorSet;
1884
1885         const Unique<VkRenderPass>                              m_renderPass;
1886         const Unique<VkFramebuffer>                             m_framebuffer;
1887
1888         const Unique<VkPipelineLayout>                  m_pipelineLayoutPass0;
1889         const Unique<VkPipeline>                                m_pipelinePass0;
1890         const Unique<VkPipelineLayout>                  m_pipelineLayoutPass1;
1891         const Unique<VkPipeline>                                m_pipelinePass1;
1892
1893         const std::vector<VkBufferSp>                   m_buffers;
1894         const std::vector<AllocationSp>                 m_bufferMemory;
1895
1896         const Unique<VkCommandPool>                             m_commandPool;
1897         tcu::ResultCollector                                    m_resultCollector;
1898 };
1899
1900 MaxAttachmenstsRenderPassTestInstance::MaxAttachmenstsRenderPassTestInstance (Context& context, TestConfig config)
1901         : MultisampleRenderPassTestBase(context, config)
1902
1903         , m_multisampleImages           (createImages(m_sampleCount, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT))
1904         , m_multisampleImageMemory      (createImageMemory(m_multisampleImages))
1905         , m_multisampleImageViews       (createImageViews(m_multisampleImages))
1906
1907         , m_singlesampleImages          (createImages(VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT))
1908         , m_singlesampleImageMemory     (createImageMemory(m_singlesampleImages))
1909         , m_singlesampleImageViews      (createImageViews(m_singlesampleImages))
1910
1911         , m_descriptorSetLayout         (createDescriptorSetLayout())
1912         , m_descriptorPool                      (createDescriptorPool())
1913         , m_descriptorSet                       (createDescriptorSet())
1914
1915         , m_renderPass                          (createRenderPassSwitch(config.groupParams->renderingType))
1916         , m_framebuffer                         (createFramebuffer(m_multisampleImageViews, m_singlesampleImageViews, *m_renderPass))
1917
1918         , m_pipelineLayoutPass0         (createRenderPipelineLayout(0))
1919         , m_pipelinePass0                       (createRenderPipeline(0))
1920         , m_pipelineLayoutPass1         (createRenderPipelineLayout(1))
1921         , m_pipelinePass1                       (createRenderPipeline(1))
1922
1923         , m_buffers                                     (createBuffers())
1924         , m_bufferMemory                        (createBufferMemory(m_buffers))
1925
1926         , m_commandPool                         (createCommandPool(context.getDeviceInterface(), context.getDevice(), VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, context.getUniversalQueueFamilyIndex()))
1927 {
1928 }
1929
1930 MaxAttachmenstsRenderPassTestInstance::~MaxAttachmenstsRenderPassTestInstance (void)
1931 {
1932 }
1933
1934 template<typename RenderpassSubpass>
1935 void MaxAttachmenstsRenderPassTestInstance::submit (void)
1936 {
1937         const DeviceInterface&                                                          vkd                                     (m_context.getDeviceInterface());
1938         const VkDevice                                                                          device                          (m_context.getDevice());
1939         const Unique<VkCommandBuffer>                                           commandBuffer           (allocateCommandBuffer(vkd, device, *m_commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
1940         const typename RenderpassSubpass::SubpassBeginInfo      subpassBeginInfo        (DE_NULL, VK_SUBPASS_CONTENTS_INLINE);
1941         const typename RenderpassSubpass::SubpassEndInfo        subpassEndInfo          (DE_NULL);
1942
1943         beginCommandBuffer(vkd, *commandBuffer);
1944
1945         // Memory barriers between previous copies and rendering
1946         {
1947                 std::vector<VkImageMemoryBarrier> barriers;
1948
1949                 for (size_t dstNdx = 0; dstNdx < m_singlesampleImages.size(); dstNdx++)
1950                 {
1951                         const VkImageMemoryBarrier barrier =
1952                         {
1953                                 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
1954                                 DE_NULL,
1955
1956                                 VK_ACCESS_TRANSFER_READ_BIT,
1957                                 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
1958
1959                                 VK_IMAGE_LAYOUT_UNDEFINED,
1960                                 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
1961
1962                                 VK_QUEUE_FAMILY_IGNORED,
1963                                 VK_QUEUE_FAMILY_IGNORED,
1964
1965                                 **m_singlesampleImages[dstNdx],
1966                                 {
1967                                         VK_IMAGE_ASPECT_COLOR_BIT,
1968                                         0u,
1969                                         1u,
1970                                         0u,
1971                                         m_layerCount
1972                                 }
1973                         };
1974
1975                         barriers.push_back(barrier);
1976                 }
1977
1978                 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]);
1979         }
1980
1981         {
1982                 const VkRenderPassBeginInfo beginInfo =
1983                 {
1984                         VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
1985                         DE_NULL,
1986
1987                         *m_renderPass,
1988                         *m_framebuffer,
1989
1990                         {
1991                                 { 0u, 0u },
1992                                 { m_width, m_height }
1993                         },
1994
1995                         0u,
1996                         DE_NULL
1997                 };
1998                 RenderpassSubpass::cmdBeginRenderPass(vkd, *commandBuffer, &beginInfo, &subpassBeginInfo);
1999         }
2000
2001         // Clear everything to black
2002         clearAttachments(*commandBuffer);
2003
2004         // First subpass - render black samples
2005         {
2006                 vkd.cmdBindPipeline(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelinePass0);
2007                 vkd.cmdDraw(*commandBuffer, 6u, 1u, 0u, 0u);
2008         }
2009
2010         // Second subpasss - merge attachments
2011         {
2012                 RenderpassSubpass::cmdNextSubpass(vkd, *commandBuffer, &subpassBeginInfo, &subpassEndInfo);
2013                 vkd.cmdBindPipeline(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelinePass1);
2014                 vkd.cmdBindDescriptorSets(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayoutPass1, 0, 1u, &*m_descriptorSet, 0, NULL);
2015                 vkd.cmdDraw(*commandBuffer, 6u, 1u, 0u, 0u);
2016         }
2017
2018         RenderpassSubpass::cmdEndRenderPass(vkd, *commandBuffer, &subpassEndInfo);
2019
2020         // Memory barriers between rendering and copies
2021         {
2022                 std::vector<VkImageMemoryBarrier> barriers;
2023
2024                 for (size_t dstNdx = 0; dstNdx < m_singlesampleImages.size(); dstNdx++)
2025                 {
2026                         const VkImageMemoryBarrier barrier =
2027                         {
2028                                 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
2029                                 DE_NULL,
2030
2031                                 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
2032                                 VK_ACCESS_TRANSFER_READ_BIT,
2033
2034                                 VK_IMAGE_LAYOUT_GENERAL,
2035                                 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
2036
2037                                 VK_QUEUE_FAMILY_IGNORED,
2038                                 VK_QUEUE_FAMILY_IGNORED,
2039
2040                                 **m_singlesampleImages[dstNdx],
2041                                 {
2042                                         VK_IMAGE_ASPECT_COLOR_BIT,
2043                                         0u,
2044                                         1u,
2045                                         0u,
2046                                         m_layerCount
2047                                 }
2048                         };
2049
2050                         barriers.push_back(barrier);
2051                 }
2052
2053                 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]);
2054         }
2055
2056         // Copy image memory to buffers
2057         for (size_t dstNdx = 0; dstNdx < m_singlesampleImages.size(); dstNdx++)
2058         {
2059                 const VkBufferImageCopy region =
2060                 {
2061                         0u,
2062                         0u,
2063                         0u,
2064                         {
2065                                 VK_IMAGE_ASPECT_COLOR_BIT,
2066                                 0u,
2067                                 0u,
2068                                 m_layerCount,
2069                         },
2070                         { 0u, 0u, 0u },
2071                         { m_width, m_height, 1u }
2072                 };
2073
2074                 vkd.cmdCopyImageToBuffer(*commandBuffer, **m_singlesampleImages[dstNdx], VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, **m_buffers[dstNdx], 1u, &region);
2075         }
2076
2077         // Memory barriers between copies and host access
2078         {
2079                 std::vector<VkBufferMemoryBarrier> barriers;
2080
2081                 for (size_t dstNdx = 0; dstNdx < m_buffers.size(); dstNdx++)
2082                 {
2083                         const VkBufferMemoryBarrier barrier =
2084                         {
2085                                 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
2086                                 DE_NULL,
2087
2088                                 VK_ACCESS_TRANSFER_WRITE_BIT,
2089                                 VK_ACCESS_HOST_READ_BIT,
2090
2091                                 VK_QUEUE_FAMILY_IGNORED,
2092                                 VK_QUEUE_FAMILY_IGNORED,
2093
2094                                 **m_buffers[dstNdx],
2095                                 0u,
2096                                 VK_WHOLE_SIZE
2097                         };
2098
2099                         barriers.push_back(barrier);
2100                 }
2101
2102                 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);
2103         }
2104
2105         endCommandBuffer(vkd, *commandBuffer);
2106
2107         submitCommandsAndWait(vkd, device, m_context.getUniversalQueue(), *commandBuffer);
2108
2109         for (size_t memoryBufferNdx = 0; memoryBufferNdx < m_bufferMemory.size(); memoryBufferNdx++)
2110                 invalidateMappedMemoryRange(vkd, device, m_bufferMemory[memoryBufferNdx]->getMemory(), 0u, VK_WHOLE_SIZE);
2111 }
2112
2113 void MaxAttachmenstsRenderPassTestInstance::submitSwitch (RenderingType renderingType)
2114 {
2115         switch (renderingType)
2116         {
2117                 case RENDERING_TYPE_RENDERPASS_LEGACY:
2118                         submit<RenderpassSubpass1>();
2119                         break;
2120                 case RENDERING_TYPE_RENDERPASS2:
2121                         submit<RenderpassSubpass2>();
2122                         break;
2123                 default:
2124                         TCU_THROW(InternalError, "Impossible");
2125         }
2126 }
2127
2128 template <typename VecType>
2129 bool isValueAboveThreshold1 (const VecType& vale, const VecType& threshold)
2130 {
2131         return (vale[0] > threshold[0]);
2132 }
2133
2134 template <typename VecType>
2135 bool isValueAboveThreshold2 (const VecType& vale, const VecType& threshold)
2136 {
2137         return (vale[0] > threshold[0]) || (vale[1] > threshold[1]);
2138 }
2139
2140 template <typename VecType>
2141 bool isValueAboveThreshold3 (const VecType& vale, const VecType& threshold)
2142 {
2143         return (vale[0] > threshold[0]) || (vale[1] > threshold[1]) || (vale[2] > threshold[2]);
2144 }
2145
2146 template <typename VecType>
2147 bool isValueAboveThreshold4 (const VecType& vale, const VecType& threshold)
2148 {
2149         return (vale[0] > threshold[0]) || (vale[1] > threshold[1]) || (vale[2] > threshold[2]) || (vale[3] > threshold[3]);
2150 }
2151
2152 void MaxAttachmenstsRenderPassTestInstance::verify (void)
2153 {
2154         const Vec4                                                      errorColor              (1.0f, 0.0f, 0.0f, 1.0f);
2155         const Vec4                                                      okColor                 (0.0f, 1.0f, 0.0f, 1.0f);
2156         const tcu::TextureFormat                        format                  (mapVkFormat(m_format));
2157         const tcu::TextureChannelClass          channelClass    (tcu::getTextureChannelClass(format.type));
2158         const int                                                       componentCount  (tcu::getNumUsedChannels(format.order));
2159         const int                                                       outputsCount    = m_attachmentsCount / 2;
2160
2161         DE_ASSERT((componentCount >= 0) && (componentCount < 5));
2162
2163         std::vector<tcu::ConstPixelBufferAccess> accesses;
2164         for (int outputNdx = 0; outputNdx < outputsCount; ++outputNdx)
2165         {
2166                 void* const ptr = m_bufferMemory[outputNdx]->getHostPtr();
2167                 accesses.push_back(tcu::ConstPixelBufferAccess(format, m_width, m_height, 1, ptr));
2168         }
2169
2170         tcu::TextureLevel       errorMask       (tcu::TextureFormat(tcu::TextureFormat::RGB, tcu::TextureFormat::UNORM_INT8), m_width, m_height, outputsCount);
2171         tcu::TestLog&           log                     (m_context.getTestContext().getLog());
2172         bool                            isOk            = true;
2173
2174         switch (channelClass)
2175         {
2176                 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
2177                 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
2178                 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
2179                 {
2180                         const Vec4 refColor(0.0f, 0.3f, 0.6f, 0.75f);
2181                         const Vec4 threshold(getFormatThreshold());
2182
2183                         typedef bool(*ValueAboveThresholdFn)(const Vec4&, const Vec4&);
2184                         ValueAboveThresholdFn componentToFnMap[4] =
2185                         {
2186                                 isValueAboveThreshold1<Vec4>,
2187                                 isValueAboveThreshold2<Vec4>,
2188                                 isValueAboveThreshold3<Vec4>,
2189                                 isValueAboveThreshold4<Vec4>
2190                         };
2191                         ValueAboveThresholdFn   isValueAboveThreshold   = componentToFnMap[componentCount - 1];
2192                         bool                                    isSRGBFormat                    = tcu::isSRGB(format);
2193
2194                         for (int outputNdx = 0; outputNdx < outputsCount; outputNdx++)
2195                         for (int y = 0; y < (int)m_height; y++)
2196                         for (int x = 0; x < (int)m_width; x++)
2197                         {
2198                                 Vec4 color = accesses[outputNdx].getPixel(x, y);
2199                                 if (isSRGBFormat)
2200                                         color = tcu::sRGBToLinear(color);
2201
2202                                 const Vec4 diff(tcu::abs(color - refColor));
2203
2204                                 if (isValueAboveThreshold(diff, threshold))
2205                                 {
2206                                         isOk = false;
2207                                         errorMask.getAccess().setPixel(errorColor, x, y, outputNdx);
2208                                         break;
2209                                 }
2210                                 else
2211                                         errorMask.getAccess().setPixel(okColor, x, y, outputNdx);
2212                         }
2213                         break;
2214                 }
2215
2216                 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
2217                 {
2218                         const UVec4     refColor(0, 48, 144, 189);
2219                         UVec4           threshold(1, 1, 1, 1);
2220
2221                         if (m_format == VK_FORMAT_A2B10G10R10_UINT_PACK32)
2222                                 threshold[3] = 200;
2223
2224                         typedef bool(*ValueAboveThresholdFn)(const UVec4&, const UVec4&);
2225                         ValueAboveThresholdFn componentToFnMap[4] =
2226                         {
2227                                 isValueAboveThreshold1<UVec4>,
2228                                 isValueAboveThreshold2<UVec4>,
2229                                 isValueAboveThreshold3<UVec4>,
2230                                 isValueAboveThreshold4<UVec4>
2231                         };
2232                         ValueAboveThresholdFn isValueAboveThreshold = componentToFnMap[componentCount - 1];
2233
2234                         for (int outputNdx = 0; outputNdx < outputsCount; outputNdx++)
2235                         for (int y = 0; y < (int)m_height; y++)
2236                         for (int x = 0; x < (int)m_width; x++)
2237                         {
2238                                 const UVec4 color       (accesses[outputNdx].getPixelUint(x, y));
2239                                 const UVec4 diff        (std::abs(int(color.x()) - int(refColor.x())),
2240                                                                          std::abs(int(color.y()) - int(refColor.y())),
2241                                                                          std::abs(int(color.z()) - int(refColor.z())),
2242                                                                          std::abs(int(color.w()) - int(refColor.w())));
2243
2244                                 if (isValueAboveThreshold(diff, threshold))
2245                                 {
2246                                         isOk = false;
2247                                         errorMask.getAccess().setPixel(errorColor, x, y, outputNdx);
2248                                         break;
2249                                 }
2250                                 else
2251                                         errorMask.getAccess().setPixel(okColor, x, y, outputNdx);
2252                         }
2253                         break;
2254                 }
2255
2256                 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
2257                 {
2258                         const IVec4 refColor    (0, 24, 75, 93);
2259                         const IVec4 threshold   (1, 1, 1, 1);
2260
2261                         typedef bool(*ValueAboveThresholdFn)(const IVec4&, const IVec4&);
2262                         ValueAboveThresholdFn componentToFnMap[4] =
2263                         {
2264                                 isValueAboveThreshold1<IVec4>,
2265                                 isValueAboveThreshold2<IVec4>,
2266                                 isValueAboveThreshold3<IVec4>,
2267                                 isValueAboveThreshold4<IVec4>
2268                         };
2269                         ValueAboveThresholdFn isValueAboveThreshold = componentToFnMap[componentCount - 1];
2270
2271                         for (int outputNdx = 0; outputNdx < outputsCount; outputNdx++)
2272                         for (int y = 0; y < (int)m_height; y++)
2273                         for (int x = 0; x < (int)m_width; x++)
2274                         {
2275                                 const IVec4 color       (accesses[outputNdx].getPixelInt(x, y));
2276                                 const IVec4 diff        (std::abs(color.x() - refColor.x()),
2277                                                                          std::abs(color.y() - refColor.y()),
2278                                                                          std::abs(color.z() - refColor.z()),
2279                                                                          std::abs(color.w() - refColor.w()));
2280
2281                                 if (isValueAboveThreshold(diff, threshold))
2282                                 {
2283                                         isOk = false;
2284                                         errorMask.getAccess().setPixel(errorColor, x, y, outputNdx);
2285                                         break;
2286                                 }
2287                                 else
2288                                         errorMask.getAccess().setPixel(okColor, x, y, outputNdx);
2289                         }
2290                         break;
2291                 }
2292
2293                 default:
2294                         DE_FATAL("Unknown channel class");
2295         }
2296
2297         if (!isOk)
2298         {
2299                 const std::string                       sectionName     ("MaxAttachmentsVerify");
2300                 const tcu::ScopedLogSection     section         (log, sectionName, sectionName);
2301
2302                 logImage("ErrorMask", errorMask.getAccess());
2303                 m_resultCollector.fail("Fail");
2304         }
2305 }
2306
2307 tcu::TestStatus MaxAttachmenstsRenderPassTestInstance::iterate(void)
2308 {
2309         submitSwitch(m_groupParams->renderingType);
2310         verify();
2311
2312         return tcu::TestStatus(m_resultCollector.getResult(), m_resultCollector.getMessage());
2313 }
2314
2315 Move<VkDescriptorSetLayout> MaxAttachmenstsRenderPassTestInstance::createDescriptorSetLayout()
2316 {
2317         const VkDescriptorSetLayoutBinding bindingTemplate =
2318         {
2319                 0,                                                                                                              // binding
2320                 VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,                                    // descriptorType
2321                 1u,                                                                                                             // descriptorCount
2322                 VK_SHADER_STAGE_FRAGMENT_BIT,                                                   // stageFlags
2323                 DE_NULL                                                                                                 // pImmutableSamplers
2324         };
2325
2326         std::vector<VkDescriptorSetLayoutBinding> bindings(m_attachmentsCount, bindingTemplate);
2327         for (deUint32 idx = 0; idx < m_attachmentsCount; ++idx)
2328                 bindings[idx].binding = idx;
2329
2330         const VkDescriptorSetLayoutCreateInfo createInfo =
2331         {
2332                 VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,    // sType
2333                 DE_NULL,                                                                                                // pNext
2334                 0u,                                                                                                             // flags
2335                 m_attachmentsCount,                                                                             // bindingCount
2336                 &bindings[0]                                                                                    // pBindings
2337         };
2338
2339         return ::createDescriptorSetLayout(m_context.getDeviceInterface(), m_context.getDevice(), &createInfo);
2340 }
2341
2342 Move<VkDescriptorPool> MaxAttachmenstsRenderPassTestInstance::createDescriptorPool()
2343 {
2344         const VkDescriptorPoolSize size =
2345         {
2346                 VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,                                    // type
2347                 m_attachmentsCount                                                                              // descriptorCount
2348         };
2349
2350         const VkDescriptorPoolCreateInfo createInfo =
2351         {
2352                 VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,                  // sType
2353                 DE_NULL,                                                                                                // pNext
2354                 VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,              // flags
2355                 1u,                                                                                                             // maxSets
2356                 1u,                                                                                                             // poolSizeCount
2357                 &size                                                                                                   // pPoolSizes
2358         };
2359
2360         return ::createDescriptorPool(m_context.getDeviceInterface(), m_context.getDevice(), &createInfo);
2361 }
2362
2363 Move<VkDescriptorSet> MaxAttachmenstsRenderPassTestInstance::createDescriptorSet()
2364 {
2365         const VkDescriptorSetAllocateInfo allocateInfo =
2366         {
2367                 VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,                 // sType
2368                 DE_NULL,                                                                                                // pNext
2369                 *m_descriptorPool,                                                                              // descriptorPool
2370                 1u,                                                                                                             // descriptorSetCount
2371                 &*m_descriptorSetLayout                                                                 // pSetLayouts
2372         };
2373
2374         const vk::DeviceInterface&              vkd                                     = m_context.getDeviceInterface();
2375         vk::VkDevice                                    device                          = m_context.getDevice();
2376         Move<VkDescriptorSet>                   descriptorSet           = allocateDescriptorSet(vkd, device, &allocateInfo);
2377         vector<VkDescriptorImageInfo>   descriptorImageInfo     (m_attachmentsCount);
2378         vector<VkWriteDescriptorSet>    descriptorWrites        (m_attachmentsCount);
2379
2380         for (deUint32 idx = 0; idx < m_attachmentsCount; ++idx)
2381         {
2382                 const VkDescriptorImageInfo imageInfo =
2383                 {
2384                         DE_NULL,                                                                        // VkSampler            sampler
2385                         **m_singlesampleImageViews[idx],                        // VkImageView          imageView
2386                         VK_IMAGE_LAYOUT_GENERAL                                         // VkImageLayout        imageLayout
2387                 };
2388                 descriptorImageInfo[idx] = imageInfo;
2389
2390                 const VkWriteDescriptorSet      write =
2391                 {
2392                         VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,         // VkStructureType                                      sType
2393                         DE_NULL,                                                                        // const void*                                          pNext
2394                         *descriptorSet,                                                         // VkDescriptorSet                                      dstSet
2395                         (deUint32)idx,                                                          // uint32_t                                                     dstBinding
2396                         0u,                                                                                     // uint32_t                                                     dstArrayElement
2397                         1u,                                                                                     // uint32_t                                                     descriptorCount
2398                         VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,            // VkDescriptorType                                     descriptorType
2399                         &descriptorImageInfo[idx],                                      // const VkDescriptorImageInfo*         pImageInfo
2400                         DE_NULL,                                                                        // const VkDescriptorBufferInfo*        pBufferInfo
2401                         DE_NULL                                                                         // const VkBufferView*                          pTexelBufferView
2402                 };
2403
2404                 descriptorWrites[idx] = write;
2405         }
2406
2407         vkd.updateDescriptorSets(device, (deUint32)descriptorWrites.size(), &descriptorWrites[0], 0u, DE_NULL);
2408         return descriptorSet;
2409 }
2410
2411 template<typename RenderPassTrait>
2412 Move<VkRenderPass> MaxAttachmenstsRenderPassTestInstance::createRenderPass(void)
2413 {
2414         // make name for RenderPass1Trait or RenderPass2Trait shorter
2415         typedef RenderPassTrait RPT;
2416
2417         typedef typename RPT::AttDesc                           AttDesc;
2418         typedef typename RPT::AttRef                            AttRef;
2419         typedef typename RPT::SubpassDep                        SubpassDep;
2420         typedef typename RPT::SubpassDesc                       SubpassDesc;
2421         typedef typename RPT::RenderPassCreateInfo      RenderPassCreateInfo;
2422
2423         const DeviceInterface&  vkd             = m_context.getDeviceInterface();
2424         VkDevice                                device  = m_context.getDevice();
2425         std::vector<AttDesc>    attachments;
2426         std::vector<AttRef>             sp0colorAttachmentRefs;
2427         std::vector<AttRef>             sp0resolveAttachmentRefs;
2428         std::vector<AttRef>             sp1inAttachmentRefs;
2429         std::vector<AttRef>             sp1colorAttachmentRefs;
2430
2431         for (size_t attachmentNdx = 0; attachmentNdx < m_attachmentsCount; attachmentNdx++)
2432         {
2433                 // define first subpass outputs
2434                 {
2435                         const AttDesc multisampleAttachment
2436                         (
2437                                 DE_NULL,                                                                        // pNext
2438                                 0u,                                                                                     // flags
2439                                 m_format,                                                                       // format
2440                                 m_sampleCount,                                                          // samples
2441                                 VK_ATTACHMENT_LOAD_OP_DONT_CARE,                        // loadOp
2442                                 VK_ATTACHMENT_STORE_OP_STORE,                           // storeOp
2443                                 VK_ATTACHMENT_LOAD_OP_DONT_CARE,                        // stencilLoadOp
2444                                 VK_ATTACHMENT_STORE_OP_DONT_CARE,                       // stencilStoreOp
2445                                 VK_IMAGE_LAYOUT_UNDEFINED,                                      // initialLayout
2446                                 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL        // finalLayout
2447                         );
2448                         const AttRef attachmentRef
2449                         (
2450                                 DE_NULL,
2451                                 (deUint32)attachments.size(),                           // attachment
2452                                 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,       // layout
2453                                 0u                                                                                      // aspectMask
2454                         );
2455                         sp0colorAttachmentRefs.push_back(attachmentRef);
2456                         attachments.push_back(multisampleAttachment);
2457                 }
2458                 // define first subpass resolve attachments
2459                 {
2460                         const AttDesc singlesampleAttachment
2461                         (
2462                                 DE_NULL,                                                                        // pNext
2463                                 0u,                                                                                     // flags
2464                                 m_format,                                                                       // format
2465                                 VK_SAMPLE_COUNT_1_BIT,                                          // samples
2466                                 VK_ATTACHMENT_LOAD_OP_DONT_CARE,                        // loadOp
2467                                 VK_ATTACHMENT_STORE_OP_STORE,                           // storeOp
2468                                 VK_ATTACHMENT_LOAD_OP_DONT_CARE,                        // stencilLoadOp
2469                                 VK_ATTACHMENT_STORE_OP_DONT_CARE,                       // stencilStoreOp
2470                                 VK_IMAGE_LAYOUT_UNDEFINED,                                      // initialLayout
2471                                 VK_IMAGE_LAYOUT_GENERAL                                         // finalLayout
2472                         );
2473                         const AttRef attachmentRef
2474                         (
2475                                 DE_NULL,                                                                        // pNext
2476                                 (deUint32)attachments.size(),                           // attachment
2477                                 VK_IMAGE_LAYOUT_GENERAL,                                        // layout
2478                                 0u                                                                                      // aspectMask
2479                         );
2480                         sp0resolveAttachmentRefs.push_back(attachmentRef);
2481                         attachments.push_back(singlesampleAttachment);
2482                 }
2483                 // define second subpass inputs
2484                 {
2485                         const AttRef attachmentRef
2486                         (
2487                                 DE_NULL,                                                                        // pNext
2488                                 (deUint32)attachments.size() - 1,                       // attachment
2489                                 VK_IMAGE_LAYOUT_GENERAL,                                        // layout
2490                                 VK_IMAGE_ASPECT_COLOR_BIT                                       // aspectMask
2491                         );
2492                         sp1inAttachmentRefs.push_back(attachmentRef);
2493                 }
2494                 // define second subpass outputs - it merges pairs of
2495                 // results that were produced by the first subpass
2496                 if (attachmentNdx < (m_attachmentsCount / 2))
2497                 {
2498                         const AttRef colorAttachmentRef
2499                         (
2500                                 DE_NULL,                                                                        // pNext
2501                                 (deUint32)attachments.size() - 1,                       // attachment
2502                                 VK_IMAGE_LAYOUT_GENERAL,                                        // layout
2503                                 0u                                                                                      // aspectMask
2504                         );
2505                         sp1colorAttachmentRefs.push_back(colorAttachmentRef);
2506                 }
2507         }
2508
2509         DE_ASSERT(sp0colorAttachmentRefs.size() == sp0resolveAttachmentRefs.size());
2510         DE_ASSERT(attachments.size() == sp0colorAttachmentRefs.size() + sp0resolveAttachmentRefs.size());
2511
2512         {
2513                 const SubpassDesc subpass0
2514                 (
2515                                                                                                                         // sType
2516                         DE_NULL,                                                                                // pNext
2517                         (VkSubpassDescriptionFlags)0,                                   // flags
2518                         VK_PIPELINE_BIND_POINT_GRAPHICS,                                // pipelineBindPoint
2519                         0u,                                                                                             // viewMask
2520                         0u,                                                                                             // inputAttachmentCount
2521                         DE_NULL,                                                                                // pInputAttachments
2522                         (deUint32)sp0colorAttachmentRefs.size(),                // colorAttachmentCount
2523                         &sp0colorAttachmentRefs[0],                                             // pColorAttachments
2524                         &sp0resolveAttachmentRefs[0],                                   // pResolveAttachments
2525                         DE_NULL,                                                                                // pDepthStencilAttachment
2526                         0u,                                                                                             // preserveAttachmentCount
2527                         DE_NULL                                                                                 // pPreserveAttachments
2528                 );
2529                 const SubpassDesc subpass1
2530                 (
2531                                                                                                                         // sType
2532                         DE_NULL,                                                                                // pNext
2533                         (VkSubpassDescriptionFlags)0,                                   // flags
2534                         VK_PIPELINE_BIND_POINT_GRAPHICS,                                // pipelineBindPoint
2535                         0u,                                                                                             // viewMask
2536                         (deUint32)sp1inAttachmentRefs.size(),                   // inputAttachmentCount
2537                         &sp1inAttachmentRefs[0],                                                // pInputAttachments
2538                         (deUint32)sp1colorAttachmentRefs.size(),                // colorAttachmentCount
2539                         &sp1colorAttachmentRefs[0],                                             // pColorAttachments
2540                         DE_NULL,                                                                                // pResolveAttachments
2541                         DE_NULL,                                                                                // pDepthStencilAttachment
2542                         0u,                                                                                             // preserveAttachmentCount
2543                         DE_NULL                                                                                 // pPreserveAttachments
2544                 );
2545                 SubpassDesc subpasses[] =
2546                 {
2547                         subpass0,
2548                         subpass1
2549                 };
2550                 const SubpassDep subpassDependency
2551                 (
2552                         DE_NULL,                                                                                // pNext
2553                         0u,                                                                                             // srcSubpass
2554                         1u,                                                                                             // dstSubpass
2555                         VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,  // srcStageMask
2556                         VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,                  // dstStageMask
2557                         VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,                   // srcAccessMask
2558                         VK_ACCESS_INPUT_ATTACHMENT_READ_BIT,                    // dstAccessMask
2559                         0u,                                                                                             // dependencyFlags
2560                         0u                                                                                              // viewOffset
2561                 );
2562                 const RenderPassCreateInfo renderPassCreator
2563                 (
2564                                                                                                                         // sType
2565                         DE_NULL,                                                                                // pNext
2566                         (VkRenderPassCreateFlags)0u,                                    // flags
2567                         (deUint32)attachments.size(),                                   // attachmentCount
2568                         &attachments[0],                                                                // pAttachments
2569                         2u,                                                                                             // subpassCount
2570                         subpasses,                                                                              // pSubpasses
2571                         1u,                                                                                             // dependencyCount
2572                         &subpassDependency,                                                             // pDependencies
2573                         0u,                                                                                             // correlatedViewMaskCount
2574                         DE_NULL                                                                                 // pCorrelatedViewMasks
2575                 );
2576
2577                 return renderPassCreator.createRenderPass(vkd, device);
2578         }
2579 }
2580
2581 Move<VkRenderPass> MaxAttachmenstsRenderPassTestInstance::createRenderPassSwitch(const RenderingType renderingType)
2582 {
2583         switch (renderingType)
2584         {
2585                 case RENDERING_TYPE_RENDERPASS_LEGACY:
2586                         return createRenderPass<RenderPass1Trait>();
2587                 case RENDERING_TYPE_RENDERPASS2:
2588                         return createRenderPass<RenderPass2Trait>();
2589                 default:
2590                         TCU_THROW(InternalError, "Impossible");
2591         }
2592 }
2593
2594 Move<VkPipelineLayout> MaxAttachmenstsRenderPassTestInstance::createRenderPipelineLayout(bool secondSubpass)
2595 {
2596         const DeviceInterface&  vkd             = m_context.getDeviceInterface();
2597         VkDevice                                device  = m_context.getDevice();
2598
2599         const VkPipelineLayoutCreateInfo createInfo =
2600         {
2601                 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
2602                 DE_NULL,
2603                 (vk::VkPipelineLayoutCreateFlags)0,
2604
2605                 secondSubpass ? 1u : 0u,
2606                 secondSubpass ? &*m_descriptorSetLayout : DE_NULL,
2607
2608                 0u,
2609                 DE_NULL
2610         };
2611
2612         return createPipelineLayout(vkd, device, &createInfo);
2613 }
2614
2615 Move<VkPipeline> MaxAttachmenstsRenderPassTestInstance::createRenderPipeline(bool secondSubpass)
2616 {
2617         const DeviceInterface&                  vkd                                             = m_context.getDeviceInterface();
2618         VkDevice                                                device                                  = m_context.getDevice();
2619         const vk::BinaryCollection&             binaryCollection                = m_context.getBinaryCollection();
2620         VkSampleCountFlagBits                   sampleCount                             = sampleCountBitFromSampleCount(m_sampleCount);
2621         deUint32                                                blendStatesCount                = m_attachmentsCount;
2622         std::string                                             fragShaderNameBase              = "quad-frag-sp0-";
2623
2624         if (secondSubpass)
2625         {
2626                 sampleCount                     = VK_SAMPLE_COUNT_1_BIT;
2627                 blendStatesCount        /= 2;
2628                 fragShaderNameBase      = "quad-frag-sp1-";
2629         }
2630
2631         std::string                                             fragShaderName                  = fragShaderNameBase + de::toString(m_attachmentsCount);
2632         const Unique<VkShaderModule>    vertexShaderModule              (createShaderModule(vkd, device, binaryCollection.get("quad-vert"), 0u));
2633         const Unique<VkShaderModule>    fragmentShaderModule    (createShaderModule(vkd, device, binaryCollection.get(fragShaderName), 0u));
2634         const Move<VkShaderModule>              geometryShaderModule    (m_layerCount == 1 ? Move<VkShaderModule>() : createShaderModule(vkd, device, binaryCollection.get("geom"), 0u));
2635
2636         // Disable blending
2637         const VkPipelineColorBlendAttachmentState attachmentBlendState =
2638         {
2639                 VK_FALSE,
2640                 VK_BLEND_FACTOR_SRC_ALPHA,
2641                 VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,
2642                 VK_BLEND_OP_ADD,
2643                 VK_BLEND_FACTOR_ONE,
2644                 VK_BLEND_FACTOR_ONE,
2645                 VK_BLEND_OP_ADD,
2646                 VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT
2647         };
2648         std::vector<VkPipelineColorBlendAttachmentState>        attachmentBlendStates(blendStatesCount, attachmentBlendState);
2649         const VkPipelineVertexInputStateCreateInfo                      vertexInputState =
2650         {
2651                 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
2652                 DE_NULL,
2653                 (VkPipelineVertexInputStateCreateFlags)0u,
2654
2655                 0u,
2656                 DE_NULL,
2657
2658                 0u,
2659                 DE_NULL
2660         };
2661         const tcu::UVec2                                renderArea      (m_width, m_height);
2662         const std::vector<VkViewport>   viewports       (1, makeViewport(renderArea));
2663         const std::vector<VkRect2D>             scissors        (1, makeRect2D(renderArea));
2664
2665         const VkPipelineMultisampleStateCreateInfo multisampleState =
2666         {
2667                 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
2668                 DE_NULL,
2669                 (VkPipelineMultisampleStateCreateFlags)0u,
2670
2671                 sampleCount,
2672                 VK_FALSE,
2673                 0.0f,
2674                 DE_NULL,
2675                 VK_FALSE,
2676                 VK_FALSE,
2677         };
2678         const VkPipelineDepthStencilStateCreateInfo depthStencilState =
2679         {
2680                 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
2681                 DE_NULL,
2682                 (VkPipelineDepthStencilStateCreateFlags)0u,
2683
2684                 VK_FALSE,
2685                 VK_TRUE,
2686                 VK_COMPARE_OP_ALWAYS,
2687                 VK_FALSE,
2688                 VK_TRUE,
2689                 {
2690                         VK_STENCIL_OP_KEEP,
2691                         VK_STENCIL_OP_INCREMENT_AND_WRAP,
2692                         VK_STENCIL_OP_KEEP,
2693                         VK_COMPARE_OP_ALWAYS,
2694                         ~0u,
2695                         ~0u,
2696                         0xFFu / (m_sampleCount + 1)
2697                 },
2698                 {
2699                         VK_STENCIL_OP_KEEP,
2700                         VK_STENCIL_OP_INCREMENT_AND_WRAP,
2701                         VK_STENCIL_OP_KEEP,
2702                         VK_COMPARE_OP_ALWAYS,
2703                         ~0u,
2704                         ~0u,
2705                         0xFFu / (m_sampleCount + 1)
2706                 },
2707
2708                 0.0f,
2709                 1.0f
2710         };
2711         const VkPipelineColorBlendStateCreateInfo blendState =
2712         {
2713                 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
2714                 DE_NULL,
2715                 (VkPipelineColorBlendStateCreateFlags)0u,
2716
2717                 VK_FALSE,
2718                 VK_LOGIC_OP_COPY,
2719                 deUint32(attachmentBlendStates.size()),
2720                 &attachmentBlendStates[0],
2721                 { 0.0f, 0.0f, 0.0f, 0.0f }
2722         };
2723
2724         return makeGraphicsPipeline(vkd,                                                                                                                                // vk
2725                                                                 device,                                                                                                                         // device
2726                                                                 secondSubpass ? *m_pipelineLayoutPass1 : *m_pipelineLayoutPass0,        // pipelineLayout
2727                                                                 *vertexShaderModule,                                                                                            // vertexShaderModule
2728                                                                 DE_NULL,                                                                                                                        // tessellationControlShaderModule
2729                                                                 DE_NULL,                                                                                                                        // tessellationEvalShaderModule
2730                                                                 m_layerCount != 1 ? *geometryShaderModule : DE_NULL,                            // geometryShaderModule
2731                                                                 *fragmentShaderModule,                                                                                          // fragmentShaderModule
2732                                                                 *m_renderPass,                                                                                                          // renderPass
2733                                                                 viewports,                                                                                                                      // viewports
2734                                                                 scissors,                                                                                                                       // scissors
2735                                                                 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,                                                            // topology
2736                                                                 secondSubpass,                                                                                                          // subpass
2737                                                                 0u,                                                                                                                                     // patchControlPoints
2738                                                                 &vertexInputState,                                                                                                      // vertexInputStateCreateInfo
2739                                                                 DE_NULL,                                                                                                                        // rasterizationStateCreateInfo
2740                                                                 &multisampleState,                                                                                                      // multisampleStateCreateInfo
2741                                                                 &depthStencilState,                                                                                                     // depthStencilStateCreateInfo
2742                                                                 &blendState);                                                                                                           // colorBlendStateCreateInfo
2743 }
2744
2745 class MultisampleRenderPassResolveLevelTestInstance : public MultisampleRenderPassTestInstance
2746 {
2747 public:
2748         MultisampleRenderPassResolveLevelTestInstance   (Context& context, TestConfig2 config);
2749         ~MultisampleRenderPassResolveLevelTestInstance  (void) = default;
2750 };
2751
2752 MultisampleRenderPassResolveLevelTestInstance::MultisampleRenderPassResolveLevelTestInstance (Context& context, TestConfig2 config)
2753         : MultisampleRenderPassTestInstance(context, config, config.resolveLevel)
2754 {
2755 }
2756
2757 struct Programs
2758 {
2759         void init(vk::SourceCollections& dst, TestConfig config) const
2760         {
2761                 const tcu::TextureFormat                format                  (mapVkFormat(config.format));
2762                 const tcu::TextureChannelClass  channelClass    (tcu::getTextureChannelClass(format.type));
2763
2764                 dst.glslSources.add("quad-vert") << glu::VertexSource(
2765                         "#version 450\n"
2766                         "out gl_PerVertex {\n"
2767                         "\tvec4 gl_Position;\n"
2768                         "};\n"
2769                         "highp float;\n"
2770                         "void main (void) {\n"
2771                         "\tgl_Position = vec4(((gl_VertexIndex + 2) / 3) % 2 == 0 ? -1.0 : 1.0,\n"
2772                         "\t                   ((gl_VertexIndex + 1) / 3) % 2 == 0 ? -1.0 : 1.0, 0.0, 1.0);\n"
2773                         "}\n");
2774
2775                 if (config.layerCount > 1)
2776                 {
2777                         std::ostringstream src;
2778
2779                         src << "#version 450\n"
2780                                 << "highp float;\n"
2781                                 << "\n"
2782                                 << "layout(triangles) in;\n"
2783                                 << "layout(triangle_strip, max_vertices = " << 3 * 2 * config.layerCount << ") out;\n"
2784                                 << "\n"
2785                                 << "in gl_PerVertex {\n"
2786                                 << "    vec4 gl_Position;\n"
2787                                 << "} gl_in[];\n"
2788                                 << "\n"
2789                                 << "out gl_PerVertex {\n"
2790                                 << "    vec4 gl_Position;\n"
2791                                 << "};\n"
2792                                 << "\n"
2793                                 << "void main (void) {\n"
2794                                 << "    for (int layerNdx = 0; layerNdx < " << config.layerCount << "; ++layerNdx) {\n"
2795                                 << "        for(int vertexNdx = 0; vertexNdx < gl_in.length(); vertexNdx++) {\n"
2796                                 << "            gl_Position = gl_in[vertexNdx].gl_Position;\n"
2797                                 << "            gl_Layer    = layerNdx;\n"
2798                                 << "            EmitVertex();\n"
2799                                 << "        };\n"
2800                                 << "        EndPrimitive();\n"
2801                                 << "    };\n"
2802                                 << "}\n";
2803
2804                         dst.glslSources.add("geom") << glu::GeometrySource(src.str());
2805                 }
2806
2807                 const tcu::StringTemplate genericLayoutTemplate("layout(location = ${INDEX}) out ${TYPE_PREFIX}vec4 o_color${INDEX};\n");
2808                 const tcu::StringTemplate genericBodyTemplate("\to_color${INDEX} = ${TYPE_PREFIX}vec4(${COLOR_VAL});\n");
2809
2810                 if (config.testType == RESOLVE || config.testType == COMPATIBILITY)
2811                 {
2812                         const tcu::StringTemplate fragTemplate("#version 450\n"
2813                                                                                                    "layout(push_constant) uniform PushConstant {\n"
2814                                                                                                    "\thighp uint sampleMask;\n"
2815                                                                                                    "} pushConstants;\n"
2816                                                                                                    "${LAYOUT}"
2817                                                                                                    "void main (void)\n"
2818                                                                                                    "{\n"
2819                                                                                                    "${BODY}"
2820                                                                                                    "}\n");
2821
2822                         std::map<std::string, std::string> parameters;
2823                         switch (channelClass)
2824                         {
2825                                 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
2826                                         parameters["TYPE_PREFIX"] = "u";
2827                                         parameters["COLOR_VAL"] = "255";
2828                                         break;
2829
2830                                 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
2831                                         parameters["TYPE_PREFIX"] = "i";
2832                                         parameters["COLOR_VAL"] = "127";
2833                                         break;
2834
2835                                 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
2836                                 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
2837                                 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
2838                                         parameters["TYPE_PREFIX"] = "";
2839                                         parameters["COLOR_VAL"] = "1.0";
2840                                         break;
2841
2842                                 default:
2843                                         DE_FATAL("Unknown channel class");
2844                         }
2845
2846                         std::string layoutDefinitions = "";
2847                         std::string shaderBody = "\tgl_SampleMask[0] = int(pushConstants.sampleMask);\n";
2848
2849                         for (deUint32 attIdx = 0; attIdx < config.attachmentCount; ++attIdx)
2850                         {
2851                                 parameters["INDEX"]     = de::toString(attIdx);
2852                                 layoutDefinitions       += genericLayoutTemplate.specialize(parameters);
2853                                 shaderBody                      += genericBodyTemplate.specialize(parameters);
2854                         }
2855
2856                         parameters["LAYOUT"]    = layoutDefinitions;
2857                         parameters["BODY"]              = shaderBody;
2858                         dst.glslSources.add("quad-frag") << glu::FragmentSource(fragTemplate.specialize(parameters));
2859                 }
2860                 else    // MAX_ATTACMENTS
2861                 {
2862                         const tcu::StringTemplate fragTemplate("#version 450\n"
2863                                                                                                    "${LAYOUT}"
2864                                                                                                    "void main (void)\n"
2865                                                                                                    "{\n"
2866                                                                                                    "${BODY}"
2867                                                                                                    "}\n");
2868
2869                         std::map<std::string, std::string> parameters;
2870                         switch (channelClass)
2871                         {
2872                                 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
2873                                         parameters["TYPE_PREFIX"] = "u";
2874                                         parameters["COLOR_VAL"] = "0, 64, 192, 252";
2875                                         break;
2876
2877                                 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
2878                                         parameters["TYPE_PREFIX"] = "i";
2879                                         parameters["COLOR_VAL"] = "0, 32, 100, 124";
2880                                         break;
2881
2882                                 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
2883                                 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
2884                                 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
2885                                         parameters["TYPE_PREFIX"] = "";
2886                                         parameters["COLOR_VAL"] = "0.0, 0.4, 0.8, 1.0";
2887                                         break;
2888
2889                                 default:
2890                                         DE_FATAL("Unknown channel class");
2891                         }
2892
2893                         // parts of fragment shader for second subpass - Vulkan introduced a new uniform type and syntax to glsl for input attachments
2894                         const tcu::StringTemplate subpassLayoutTemplate("layout (input_attachment_index = ${INDEX}, set = 0, binding = ${INDEX}) uniform ${TYPE_PREFIX}subpassInput i_color${INDEX};\n");
2895                         const tcu::StringTemplate subpassFBodyTemplate("\to_color${INDEX} = subpassLoad(i_color${INDEX})*0.5 + subpassLoad(i_color${MIX_INDEX})*0.25;\n");
2896                         const tcu::StringTemplate subpassIBodyTemplate("\to_color${INDEX} = subpassLoad(i_color${INDEX}) / 2 + subpassLoad(i_color${MIX_INDEX}) / 4;\n");
2897
2898                         bool selectIBody = isIntFormat(config.format) || isUintFormat(config.format);
2899                         const tcu::StringTemplate& subpassBodyTemplate = selectIBody ? subpassIBodyTemplate : subpassFBodyTemplate;
2900
2901                         std::string sp0layoutDefinitions        = "";
2902                         std::string sp0shaderBody                       = "";
2903                         std::string sp1inLayoutDefinitions      = "";
2904                         std::string sp1outLayoutDefinitions     = "";
2905                         std::string sp1shaderBody                       = "";
2906
2907                         deUint32 halfAttachments = config.attachmentCount / 2;
2908                         for (deUint32 attIdx = 0; attIdx < config.attachmentCount; ++attIdx)
2909                         {
2910                                 parameters["INDEX"] = de::toString(attIdx);
2911
2912                                 sp0layoutDefinitions    += genericLayoutTemplate.specialize(parameters);
2913                                 sp0shaderBody                   += genericBodyTemplate.specialize(parameters);
2914
2915                                 sp1inLayoutDefinitions += subpassLayoutTemplate.specialize(parameters);
2916                                 if (attIdx < halfAttachments)
2917                                 {
2918                                         // we are combining pairs of input attachments to produce half the number of outputs
2919                                         parameters["MIX_INDEX"] = de::toString(halfAttachments + attIdx);
2920                                         sp1outLayoutDefinitions += genericLayoutTemplate.specialize(parameters);
2921                                         sp1shaderBody                   += subpassBodyTemplate.specialize(parameters);
2922                                 }
2923                         }
2924
2925                         // construct fragment shaders for subpass1 and subpass2; note that there
2926                         // is different shader definition depending on number of attachments
2927                         std::string nameBase    = "quad-frag-sp";
2928                         std::string namePostfix = de::toString(config.attachmentCount);
2929                         parameters["LAYOUT"]    = sp0layoutDefinitions;
2930                         parameters["BODY"]              = sp0shaderBody;
2931                         dst.glslSources.add(nameBase + "0-" + namePostfix) << glu::FragmentSource(fragTemplate.specialize(parameters));
2932                         parameters["LAYOUT"]    = sp1inLayoutDefinitions + sp1outLayoutDefinitions;
2933                         parameters["BODY"]              = sp1shaderBody;
2934                         dst.glslSources.add(nameBase + "1-" + namePostfix) << glu::FragmentSource(fragTemplate.specialize(parameters));
2935                 }
2936         }
2937 };
2938
2939 template<class TestConfigType>
2940 void checkSupport(Context& context, TestConfigType config)
2941 {
2942         if (config.layerCount > 1)
2943                 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_GEOMETRY_SHADER);
2944
2945         if (config.groupParams->renderingType == RENDERING_TYPE_RENDERPASS2)
2946                 context.requireDeviceFunctionality("VK_KHR_create_renderpass2");
2947
2948         if (config.groupParams->renderingType == RENDERING_TYPE_DYNAMIC_RENDERING)
2949                 context.requireDeviceFunctionality("VK_KHR_dynamic_rendering");
2950
2951 #ifndef CTS_USES_VULKANSC
2952         if (context.isDeviceFunctionalitySupported("VK_KHR_portability_subset") &&
2953                 !context.getPortabilitySubsetFeatures().multisampleArrayImage &&
2954                 (config.sampleCount != VK_SAMPLE_COUNT_1_BIT) && (config.layerCount != 1))
2955         {
2956                 TCU_THROW(NotSupportedError, "VK_KHR_portability_subset: Implementation does not support image array with multiple samples per texel");
2957         }
2958 #endif // CTS_USES_VULKANSC
2959
2960         const InstanceInterface&                                vki                             = context.getInstanceInterface();
2961         vk::VkPhysicalDevice                                    physicalDevice  = context.getPhysicalDevice();
2962         const vk::VkPhysicalDeviceProperties    properties              = vk::getPhysicalDeviceProperties(vki, physicalDevice);
2963
2964         if (config.attachmentCount > properties.limits.maxColorAttachments)
2965                 TCU_THROW(NotSupportedError, "Required number of color attachments not supported.");
2966 }
2967
2968 std::string formatToName (VkFormat format)
2969 {
2970         const std::string       formatStr       = de::toString(format);
2971         const std::string       prefix          = "VK_FORMAT_";
2972
2973         DE_ASSERT(formatStr.substr(0, prefix.length()) == prefix);
2974
2975         return de::toLower(formatStr.substr(prefix.length()));
2976 }
2977
2978 void initTests (tcu::TestCaseGroup* group, const SharedGroupParams groupParams)
2979 {
2980         static const VkFormat   formats[] =
2981         {
2982                 VK_FORMAT_R5G6B5_UNORM_PACK16,
2983                 VK_FORMAT_R8_UNORM,
2984                 VK_FORMAT_R8_SNORM,
2985                 VK_FORMAT_R8_UINT,
2986                 VK_FORMAT_R8_SINT,
2987                 VK_FORMAT_R8G8_UNORM,
2988                 VK_FORMAT_R8G8_SNORM,
2989                 VK_FORMAT_R8G8_UINT,
2990                 VK_FORMAT_R8G8_SINT,
2991                 VK_FORMAT_R8G8B8A8_UNORM,
2992                 VK_FORMAT_R8G8B8A8_SNORM,
2993                 VK_FORMAT_R8G8B8A8_UINT,
2994                 VK_FORMAT_R8G8B8A8_SINT,
2995                 VK_FORMAT_R8G8B8A8_SRGB,
2996                 VK_FORMAT_A8B8G8R8_UNORM_PACK32,
2997                 VK_FORMAT_A8B8G8R8_SNORM_PACK32,
2998                 VK_FORMAT_A8B8G8R8_UINT_PACK32,
2999                 VK_FORMAT_A8B8G8R8_SINT_PACK32,
3000                 VK_FORMAT_A8B8G8R8_SRGB_PACK32,
3001                 VK_FORMAT_B8G8R8A8_UNORM,
3002                 VK_FORMAT_B8G8R8A8_SRGB,
3003                 VK_FORMAT_A2R10G10B10_UNORM_PACK32,
3004                 VK_FORMAT_A2B10G10R10_UNORM_PACK32,
3005                 VK_FORMAT_A2B10G10R10_UINT_PACK32,
3006                 VK_FORMAT_R16_UNORM,
3007                 VK_FORMAT_R16_SNORM,
3008                 VK_FORMAT_R16_UINT,
3009                 VK_FORMAT_R16_SINT,
3010                 VK_FORMAT_R16_SFLOAT,
3011                 VK_FORMAT_R16G16_UNORM,
3012                 VK_FORMAT_R16G16_SNORM,
3013                 VK_FORMAT_R16G16_UINT,
3014                 VK_FORMAT_R16G16_SINT,
3015                 VK_FORMAT_R16G16_SFLOAT,
3016                 VK_FORMAT_R16G16B16A16_UNORM,
3017                 VK_FORMAT_R16G16B16A16_SNORM,
3018                 VK_FORMAT_R16G16B16A16_UINT,
3019                 VK_FORMAT_R16G16B16A16_SINT,
3020                 VK_FORMAT_R16G16B16A16_SFLOAT,
3021                 VK_FORMAT_R32_UINT,
3022                 VK_FORMAT_R32_SINT,
3023                 VK_FORMAT_R32_SFLOAT,
3024                 VK_FORMAT_R32G32_UINT,
3025                 VK_FORMAT_R32G32_SINT,
3026                 VK_FORMAT_R32G32_SFLOAT,
3027                 VK_FORMAT_R32G32B32A32_UINT,
3028                 VK_FORMAT_R32G32B32A32_SINT,
3029                 VK_FORMAT_R32G32B32A32_SFLOAT,
3030                 VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16,
3031         };
3032         const deUint32                  sampleCounts[] =
3033         {
3034                 2u, 4u, 8u
3035         };
3036         const deUint32                  layerCounts[] =
3037         {
3038                 1u, 3u, 6u
3039         };
3040         const deUint32                  resolveLevels[] =
3041         {
3042                 2u, 3u, 4u
3043         };
3044         tcu::TestContext&               testCtx (group->getTestContext());
3045
3046         for (size_t layerCountNdx = 0; layerCountNdx < DE_LENGTH_OF_ARRAY(layerCounts); layerCountNdx++)
3047         {
3048                 const deUint32                                  layerCount              (layerCounts[layerCountNdx]);
3049                 const std::string                               layerGroupName  ("layers_" + de::toString(layerCount));
3050                 de::MovePtr<tcu::TestCaseGroup> layerGroup              (new tcu::TestCaseGroup(testCtx, layerGroupName.c_str(), layerGroupName.c_str()));
3051
3052                 for (size_t formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); formatNdx++)
3053                 {
3054                         const VkFormat                                  format          (formats[formatNdx]);
3055                         const std::string                               formatName      (formatToName(format));
3056                         de::MovePtr<tcu::TestCaseGroup> formatGroup     (new tcu::TestCaseGroup(testCtx, formatName.c_str(), formatName.c_str()));
3057
3058                         for (size_t sampleCountNdx = 0; sampleCountNdx < DE_LENGTH_OF_ARRAY(sampleCounts); sampleCountNdx++)
3059                         {
3060                                 const deUint32  sampleCount(sampleCounts[sampleCountNdx]);
3061
3062                                 // Skip this test as it is rather slow
3063                                 if (layerCount == 6 && sampleCount == 8)
3064                                         continue;
3065
3066                                 // Reduce number of tests for dynamic rendering cases where secondary command buffer is used
3067                                 if (groupParams->useSecondaryCmdBuffer && ( (sampleCount > 2u) || (layerCount > 3u) ))
3068                                         continue;
3069
3070                                 std::string                     testName        ("samples_" + de::toString(sampleCount));
3071                                 const TestConfig        testConfig
3072                                 {
3073                                         RESOLVE,
3074                                         format,
3075                                         sampleCount,
3076                                         layerCount,
3077                                         4u,
3078                                         32u,
3079                                         32u,
3080                                         groupParams
3081                                 };
3082
3083                                 formatGroup->addChild(new InstanceFactory1WithSupport<MultisampleRenderPassTestInstance, TestConfig, FunctionSupport1<TestConfig>, Programs>(testCtx, tcu::NODETYPE_SELF_VALIDATE, testName.c_str(), testName.c_str(), testConfig, typename FunctionSupport1<TestConfig>::Args(checkSupport, testConfig)));
3084
3085                                 for (deUint32 resolveLevel : resolveLevels)
3086                                 {
3087                                         const TestConfig2 testConfig2(testConfig, resolveLevel);
3088                                         std::string resolveLevelTestNameStr(testName + "_resolve_level_" + de::toString(resolveLevel));
3089                                         const char* resolveLevelTestName = resolveLevelTestNameStr.c_str();
3090
3091                                         formatGroup->addChild(new InstanceFactory1WithSupport<MultisampleRenderPassResolveLevelTestInstance, TestConfig2, FunctionSupport1<TestConfig2>, Programs>(testCtx, tcu::NODETYPE_SELF_VALIDATE, resolveLevelTestName, resolveLevelTestName, testConfig2, typename FunctionSupport1<TestConfig2>::Args(checkSupport, testConfig2)));
3092
3093                                         // Reduce number of tests for dynamic rendering cases where secondary command buffer is used
3094                                         if (groupParams->useSecondaryCmdBuffer)
3095                                                 break;
3096                                 }
3097
3098                                 // MaxAttachmenstsRenderPassTest is ment to test extreme cases where applications might consume all available on-chip
3099                                 // memory. This is achieved by using maxColorAttachments attachments and two subpasses, but during test creation we
3100                                 // dont know what is the maximal number of attachments (spirv tools are not available on all platforms) so we cant
3101                                 // construct shaders during test execution. To be able to test this we need to execute tests for all available
3102                                 // numbers of attachments despite the fact that we are only interested in the maximal number; test construction code
3103                                 // assumes that the number of attachments is power of two
3104                                 if ((groupParams->renderingType != RENDERING_TYPE_DYNAMIC_RENDERING) && (layerCount == 1))
3105                                 {
3106                                         for (deUint32 power = 2; power < 5; ++power)
3107                                         {
3108                                                 deUint32        attachmentCount                                 = 1 << power;
3109                                                 std::string     maxAttName                                              = "max_attachments_" + de::toString(attachmentCount) + "_" + testName;
3110
3111                                                 TestConfig      maxAttachmentsTestConfig                = testConfig;
3112                                                 maxAttachmentsTestConfig.testType                       = MAX_ATTACHMENTS;
3113                                                 maxAttachmentsTestConfig.attachmentCount        = attachmentCount;
3114
3115                                                 formatGroup->addChild(new InstanceFactory1WithSupport<MaxAttachmenstsRenderPassTestInstance, TestConfig, FunctionSupport1<TestConfig>, Programs>(testCtx, tcu::NODETYPE_SELF_VALIDATE, maxAttName.c_str(), maxAttName.c_str(), maxAttachmentsTestConfig, typename FunctionSupport1<TestConfig>::Args(checkSupport, maxAttachmentsTestConfig)));
3116                                         }
3117
3118                                         {
3119                                                 std::string     compatibilityTestName                   = "compatibility_" + testName;
3120
3121                                                 TestConfig      compatibilityTestConfig                 = testConfig;
3122                                                 compatibilityTestConfig.testType                        = COMPATIBILITY;
3123                                                 compatibilityTestConfig.attachmentCount         = 1;
3124
3125                                                 formatGroup->addChild(new InstanceFactory1WithSupport<MultisampleRenderPassTestInstance, TestConfig, FunctionSupport1<TestConfig>, Programs>(testCtx, tcu::NODETYPE_SELF_VALIDATE, compatibilityTestName.c_str(), compatibilityTestName.c_str(), compatibilityTestConfig, typename FunctionSupport1<TestConfig>::Args(checkSupport, compatibilityTestConfig)));
3126                                         }
3127                                 }
3128                         }
3129
3130                         if (layerCount == 1)
3131                                 group->addChild(formatGroup.release());
3132                         else
3133                                 layerGroup->addChild(formatGroup.release());
3134                 }
3135
3136                 if (layerCount != 1)
3137                         group->addChild(layerGroup.release());
3138         }
3139 }
3140
3141 } // anonymous
3142
3143 tcu::TestCaseGroup* createRenderPassMultisampleResolveTests (tcu::TestContext& testCtx, const renderpass::SharedGroupParams groupParams)
3144 {
3145         return createTestGroup(testCtx, "multisample_resolve", "Multisample render pass resolve tests", initTests, groupParams);
3146 }
3147
3148 tcu::TestCaseGroup* createRenderPass2MultisampleResolveTests (tcu::TestContext& testCtx, const renderpass::SharedGroupParams groupParams)
3149 {
3150         return createTestGroup(testCtx, "multisample_resolve", "Multisample render pass resolve tests", initTests, groupParams);
3151 }
3152
3153 tcu::TestCaseGroup* createDynamicRenderingMultisampleResolveTests (tcu::TestContext& testCtx, const renderpass::SharedGroupParams groupParams)
3154 {
3155         return createTestGroup(testCtx, "multisample_resolve", "Multisample dynamic rendering resolve tests", initTests, groupParams);
3156 }
3157
3158 } // vkt