Merge "Merge "Try harder to defeat GLSL compiler dead-code optimizations" into nougat...
[platform/upstream/VK-GL-CTS.git] / external / vulkancts / modules / vulkan / renderpass / vktRenderPassMultisampleTests.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 passses with multisample attachments
22  *//*--------------------------------------------------------------------*/
23
24 #include "vktRenderPassMultisampleTests.hpp"
25
26 #include "vktTestCaseUtil.hpp"
27 #include "vktTestGroupUtil.hpp"
28
29 #include "vkDefs.hpp"
30 #include "vkDeviceUtil.hpp"
31 #include "vkImageUtil.hpp"
32 #include "vkMemUtil.hpp"
33 #include "vkPlatform.hpp"
34 #include "vkPrograms.hpp"
35 #include "vkQueryUtil.hpp"
36 #include "vkRef.hpp"
37 #include "vkRefUtil.hpp"
38 #include "vkTypeUtil.hpp"
39
40 #include "tcuFloat.hpp"
41 #include "tcuImageCompare.hpp"
42 #include "tcuFormatUtil.hpp"
43 #include "tcuMaybe.hpp"
44 #include "tcuResultCollector.hpp"
45 #include "tcuTestLog.hpp"
46 #include "tcuTextureUtil.hpp"
47 #include "tcuVectorUtil.hpp"
48
49 #include "deUniquePtr.hpp"
50 #include "deSharedPtr.hpp"
51
52 using namespace vk;
53
54 using tcu::BVec4;
55 using tcu::IVec2;
56 using tcu::IVec4;
57 using tcu::UVec2;
58 using tcu::UVec4;
59 using tcu::Vec2;
60 using tcu::Vec4;
61
62 using tcu::Maybe;
63 using tcu::just;
64 using tcu::nothing;
65
66 using tcu::ConstPixelBufferAccess;
67 using tcu::PixelBufferAccess;
68
69 using tcu::TestLog;
70
71 using std::pair;
72 using std::string;
73 using std::vector;
74
75 typedef de::SharedPtr<vk::Unique<VkImage> > VkImageSp;
76 typedef de::SharedPtr<vk::Unique<VkImageView> > VkImageViewSp;
77 typedef de::SharedPtr<vk::Unique<VkBuffer> > VkBufferSp;
78 typedef de::SharedPtr<vk::Unique<VkPipeline> > VkPipelineSp;
79
80 namespace vkt
81 {
82 namespace
83 {
84 enum
85 {
86         MAX_COLOR_ATTACHMENT_COUNT = 4u
87 };
88
89 template<typename T>
90 de::SharedPtr<T> safeSharedPtr (T* ptr)
91 {
92         try
93         {
94                 return de::SharedPtr<T>(ptr);
95         }
96         catch (...)
97         {
98                 delete ptr;
99                 throw;
100         }
101 }
102
103 VkImageAspectFlags getImageAspectFlags (VkFormat vkFormat)
104 {
105         const tcu::TextureFormat        format          (mapVkFormat(vkFormat));
106         const bool                                      hasDepth        (tcu::hasDepthComponent(format.order));
107         const bool                                      hasStencil      (tcu::hasStencilComponent(format.order));
108
109         if (hasDepth || hasStencil)
110         {
111                 return (hasDepth ? VK_IMAGE_ASPECT_DEPTH_BIT : (VkImageAspectFlagBits)0u)
112                                 | (hasStencil ? VK_IMAGE_ASPECT_STENCIL_BIT : (VkImageAspectFlagBits)0u);
113         }
114         else
115                 return VK_IMAGE_ASPECT_COLOR_BIT;
116 }
117
118 void bindBufferMemory (const DeviceInterface& vk, VkDevice device, VkBuffer buffer, VkDeviceMemory mem, VkDeviceSize memOffset)
119 {
120         VK_CHECK(vk.bindBufferMemory(device, buffer, mem, memOffset));
121 }
122
123 void bindImageMemory (const DeviceInterface& vk, VkDevice device, VkImage image, VkDeviceMemory mem, VkDeviceSize memOffset)
124 {
125         VK_CHECK(vk.bindImageMemory(device, image, mem, memOffset));
126 }
127
128 de::MovePtr<Allocation> createBufferMemory (const DeviceInterface&      vk,
129                                                                                         VkDevice                                device,
130                                                                                         Allocator&                              allocator,
131                                                                                         VkBuffer                                buffer)
132 {
133         de::MovePtr<Allocation> allocation (allocator.allocate(getBufferMemoryRequirements(vk, device, buffer), MemoryRequirement::HostVisible));
134         bindBufferMemory(vk, device, buffer, allocation->getMemory(), allocation->getOffset());
135         return allocation;
136 }
137
138 de::MovePtr<Allocation> createImageMemory (const DeviceInterface&       vk,
139                                                                                    VkDevice                                     device,
140                                                                                    Allocator&                           allocator,
141                                                                                    VkImage                                      image)
142 {
143         de::MovePtr<Allocation> allocation (allocator.allocate(getImageMemoryRequirements(vk, device, image), MemoryRequirement::Any));
144         bindImageMemory(vk, device, image, allocation->getMemory(), allocation->getOffset());
145         return allocation;
146 }
147
148 Move<VkImage> createImage (const DeviceInterface&       vk,
149                                                    VkDevice                                     device,
150                                                    VkImageCreateFlags           flags,
151                                                    VkImageType                          imageType,
152                                                    VkFormat                                     format,
153                                                    VkExtent3D                           extent,
154                                                    deUint32                                     mipLevels,
155                                                    deUint32                                     arrayLayers,
156                                                    VkSampleCountFlagBits        samples,
157                                                    VkImageTiling                        tiling,
158                                                    VkImageUsageFlags            usage,
159                                                    VkSharingMode                        sharingMode,
160                                                    deUint32                                     queueFamilyCount,
161                                                    const deUint32*                      pQueueFamilyIndices,
162                                                    VkImageLayout                        initialLayout)
163 {
164         const VkImageCreateInfo pCreateInfo =
165         {
166                 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
167                 DE_NULL,
168                 flags,
169                 imageType,
170                 format,
171                 extent,
172                 mipLevels,
173                 arrayLayers,
174                 samples,
175                 tiling,
176                 usage,
177                 sharingMode,
178                 queueFamilyCount,
179                 pQueueFamilyIndices,
180                 initialLayout
181         };
182         return createImage(vk, device, &pCreateInfo);
183 }
184
185 Move<VkImageView> createImageView (const DeviceInterface&       vk,
186                                                                    VkDevice                                     device,
187                                                                    VkImageViewCreateFlags       flags,
188                                                                    VkImage                                      image,
189                                                                    VkImageViewType                      viewType,
190                                                                    VkFormat                                     format,
191                                                                    VkComponentMapping           components,
192                                                                    VkImageSubresourceRange      subresourceRange)
193 {
194         const VkImageViewCreateInfo pCreateInfo =
195         {
196                 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
197                 DE_NULL,
198                 flags,
199                 image,
200                 viewType,
201                 format,
202                 components,
203                 subresourceRange,
204         };
205         return createImageView(vk, device, &pCreateInfo);
206 }
207
208 Move<VkImage> createImage (const InstanceInterface&     vki,
209                                                    VkPhysicalDevice                     physicalDevice,
210                                                    const DeviceInterface&       vkd,
211                                                    VkDevice                                     device,
212                                                    VkFormat                                     vkFormat,
213                                                    VkSampleCountFlagBits        sampleCountBit,
214                                                    VkImageUsageFlags            usage,
215                                                    deUint32                                     width,
216                                                    deUint32                                     height)
217 {
218         try
219         {
220                 const tcu::TextureFormat                format                                  (mapVkFormat(vkFormat));
221                 const VkImageType                               imageType                               (VK_IMAGE_TYPE_2D);
222                 const VkImageTiling                             imageTiling                             (VK_IMAGE_TILING_OPTIMAL);
223                 const VkFormatProperties                formatProperties                (getPhysicalDeviceFormatProperties(vki, physicalDevice, vkFormat));
224                 const VkImageFormatProperties   imageFormatProperties   (getPhysicalDeviceImageFormatProperties(vki, physicalDevice, vkFormat, imageType, imageTiling, usage, 0u));
225                 const VkExtent3D                                imageExtent                             =
226                 {
227                         width,
228                         height,
229                         1u
230                 };
231
232                 if ((tcu::hasDepthComponent(format.order) || tcu::hasStencilComponent(format.order))
233                         && (formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) == 0)
234                         TCU_THROW(NotSupportedError, "Format can't be used as depth stencil attachment");
235
236                 if (!(tcu::hasDepthComponent(format.order) || tcu::hasStencilComponent(format.order))
237                         && (formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT) == 0)
238                         TCU_THROW(NotSupportedError, "Format can't be used as color attachment");
239
240                 if (imageFormatProperties.maxExtent.width < imageExtent.width
241                         || imageFormatProperties.maxExtent.height < imageExtent.height
242                         || ((imageFormatProperties.sampleCounts & sampleCountBit) == 0))
243                 {
244                         TCU_THROW(NotSupportedError, "Image type not supported");
245                 }
246
247                 return createImage(vkd, device, 0u, imageType, vkFormat, imageExtent, 1u, 1u, sampleCountBit, imageTiling, usage, VK_SHARING_MODE_EXCLUSIVE, 0u, DE_NULL, VK_IMAGE_LAYOUT_UNDEFINED);
248         }
249         catch (const vk::Error& error)
250         {
251                 if (error.getError() == VK_ERROR_FORMAT_NOT_SUPPORTED)
252                         TCU_THROW(NotSupportedError, "Image format not supported");
253
254                 throw;
255         }
256 }
257
258 Move<VkImageView> createImageAttachmentView (const DeviceInterface&     vkd,
259                                                                                          VkDevice                               device,
260                                                                                          VkImage                                image,
261                                                                                          VkFormat                               format,
262                                                                                          VkImageAspectFlags             aspect)
263 {
264         const VkImageSubresourceRange   range =
265         {
266                 aspect,
267                 0u,
268                 1u,
269                 0u,
270                 1u
271         };
272
273         return createImageView(vkd, device, 0u, image, VK_IMAGE_VIEW_TYPE_2D, format, makeComponentMappingRGBA(), range);
274 }
275
276 Move<VkImageView> createSrcPrimaryInputImageView (const DeviceInterface&        vkd,
277                                                                                                   VkDevice                                      device,
278                                                                                                   VkImage                                       image,
279                                                                                                   VkFormat                                      format,
280                                                                                                   VkImageAspectFlags            aspect)
281 {
282         const VkImageSubresourceRange   range =
283         {
284                 aspect == (VK_IMAGE_ASPECT_STENCIL_BIT | VK_IMAGE_ASPECT_DEPTH_BIT)
285                         ? (VkImageAspectFlags)VK_IMAGE_ASPECT_DEPTH_BIT
286                         : aspect,
287                 0u,
288                 1u,
289                 0u,
290                 1u
291         };
292
293         return createImageView(vkd, device, 0u, image, VK_IMAGE_VIEW_TYPE_2D, format, makeComponentMappingRGBA(), range);
294 }
295
296 Move<VkImageView> createSrcSecondaryInputImageView (const DeviceInterface&      vkd,
297                                                                                                         VkDevice                                device,
298                                                                                                         VkImage                                 image,
299                                                                                                         VkFormat                                format,
300                                                                                                         VkImageAspectFlags              aspect)
301 {
302         if (aspect == (VK_IMAGE_ASPECT_STENCIL_BIT | VK_IMAGE_ASPECT_DEPTH_BIT))
303         {
304                 const VkImageSubresourceRange   range =
305                 {
306                         VK_IMAGE_ASPECT_STENCIL_BIT,
307                         0u,
308                         1u,
309                         0u,
310                         1u
311                 };
312
313                 return createImageView(vkd, device, 0u, image, VK_IMAGE_VIEW_TYPE_2D, format, makeComponentMappingRGBA(), range);
314         }
315         else
316                 return Move<VkImageView>();
317 }
318
319 VkDeviceSize getPixelSize (VkFormat vkFormat)
320 {
321         const tcu::TextureFormat        format  (mapVkFormat(vkFormat));
322
323         return format.getPixelSize();
324 }
325
326 Move<VkBuffer> createBuffer (const DeviceInterface&             vkd,
327                                                          VkDevice                                       device,
328                                                          VkFormat                                       format,
329                                                          deUint32                                       width,
330                                                          deUint32                                       height)
331 {
332         const VkBufferUsageFlags        bufferUsage                     (VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT);
333         const VkDeviceSize                      pixelSize                       (getPixelSize(format));
334         const VkBufferCreateInfo        createInfo                      =
335         {
336                 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
337                 DE_NULL,
338                 0u,
339
340                 width * height * pixelSize,
341                 bufferUsage,
342
343                 VK_SHARING_MODE_EXCLUSIVE,
344                 0u,
345                 DE_NULL
346         };
347         return createBuffer(vkd, device, &createInfo);
348 }
349
350 VkSampleCountFlagBits sampleCountBitFromomSampleCount (deUint32 count)
351 {
352         switch (count)
353         {
354                 case 1:  return VK_SAMPLE_COUNT_1_BIT;
355                 case 2:  return VK_SAMPLE_COUNT_2_BIT;
356                 case 4:  return VK_SAMPLE_COUNT_4_BIT;
357                 case 8:  return VK_SAMPLE_COUNT_8_BIT;
358                 case 16: return VK_SAMPLE_COUNT_16_BIT;
359                 case 32: return VK_SAMPLE_COUNT_32_BIT;
360                 case 64: return VK_SAMPLE_COUNT_64_BIT;
361
362                 default:
363                         DE_FATAL("Invalid sample count");
364                         return (VkSampleCountFlagBits)(0x1u << count);
365         }
366 }
367
368 std::vector<VkImageSp> createMultisampleImages (const InstanceInterface&        vki,
369                                                                                                 VkPhysicalDevice                        physicalDevice,
370                                                                                                 const DeviceInterface&          vkd,
371                                                                                                 VkDevice                                        device,
372                                                                                                 VkFormat                                        format,
373                                                                                                 deUint32                                        sampleCount,
374                                                                                                 deUint32                                        width,
375                                                                                                 deUint32                                        height)
376 {
377         std::vector<VkImageSp> images (sampleCount);
378
379         for (size_t imageNdx = 0; imageNdx < images.size(); imageNdx++)
380                 images[imageNdx] = safeSharedPtr(new vk::Unique<VkImage>(createImage(vki, physicalDevice, vkd, device, format, sampleCountBitFromomSampleCount(sampleCount), VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, width, height)));
381
382         return images;
383 }
384
385 std::vector<VkImageSp> createSingleSampleImages (const InstanceInterface&       vki,
386                                                                                                  VkPhysicalDevice                       physicalDevice,
387                                                                                                  const DeviceInterface&         vkd,
388                                                                                                  VkDevice                                       device,
389                                                                                                  VkFormat                                       format,
390                                                                                                  deUint32                                       sampleCount,
391                                                                                                  deUint32                                       width,
392                                                                                                  deUint32                                       height)
393 {
394         std::vector<VkImageSp> images (sampleCount);
395
396         for (size_t imageNdx = 0; imageNdx < images.size(); imageNdx++)
397                 images[imageNdx] = safeSharedPtr(new vk::Unique<VkImage>(createImage(vki, physicalDevice, vkd, device, format, VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, width, height)));
398
399         return images;
400 }
401
402 std::vector<de::SharedPtr<Allocation> > createImageMemory (const DeviceInterface&               vkd,
403                                                                                                                    VkDevice                                             device,
404                                                                                                                    Allocator&                                   allocator,
405                                                                                                                    const std::vector<VkImageSp> images)
406 {
407         std::vector<de::SharedPtr<Allocation> > memory (images.size());
408
409         for (size_t memoryNdx = 0; memoryNdx < memory.size(); memoryNdx++)
410                 memory[memoryNdx] = safeSharedPtr(createImageMemory(vkd, device, allocator, **images[memoryNdx]).release());
411
412         return memory;
413 }
414
415 std::vector<VkImageViewSp> createImageAttachmentViews (const DeviceInterface&                   vkd,
416                                                                                                            VkDevice                                                     device,
417                                                                                                            const std::vector<VkImageSp>&        images,
418                                                                                                            VkFormat                                                     format,
419                                                                                                            VkImageAspectFlagBits                        aspect)
420 {
421         std::vector<VkImageViewSp> views (images.size());
422
423         for (size_t imageNdx = 0; imageNdx < images.size(); imageNdx++)
424                 views[imageNdx] = safeSharedPtr(new vk::Unique<VkImageView>(createImageAttachmentView(vkd, device, **images[imageNdx], format, aspect)));
425
426         return views;
427 }
428
429 std::vector<VkBufferSp> createBuffers (const DeviceInterface&   vkd,
430                                                                            VkDevice                                     device,
431                                                                            VkFormat                                     format,
432                                                                            deUint32                                     sampleCount,
433                                                                            deUint32                                     width,
434                                                                            deUint32                                     height)
435 {
436         std::vector<VkBufferSp> buffers (sampleCount);
437
438         for (size_t bufferNdx = 0; bufferNdx < buffers.size(); bufferNdx++)
439                 buffers[bufferNdx] = safeSharedPtr(new vk::Unique<VkBuffer>(createBuffer(vkd, device, format, width, height)));
440
441         return buffers;
442 }
443
444 std::vector<de::SharedPtr<Allocation> > createBufferMemory (const DeviceInterface&                      vkd,
445                                                                                                                         VkDevice                                                device,
446                                                                                                                         Allocator&                                              allocator,
447                                                                                                                         const std::vector<VkBufferSp>   buffers)
448 {
449         std::vector<de::SharedPtr<Allocation> > memory (buffers.size());
450
451         for (size_t memoryNdx = 0; memoryNdx < memory.size(); memoryNdx++)
452                 memory[memoryNdx] = safeSharedPtr(createBufferMemory(vkd, device, allocator, **buffers[memoryNdx]).release());
453
454         return memory;
455 }
456
457 Move<VkRenderPass> createRenderPass (const DeviceInterface&     vkd,
458                                                                          VkDevice                               device,
459                                                                          VkFormat                               srcFormat,
460                                                                          VkFormat                               dstFormat,
461                                                                          deUint32                               sampleCount)
462 {
463         const VkSampleCountFlagBits                             samples                                         (sampleCountBitFromomSampleCount(sampleCount));
464         const deUint32                                                  splitSubpassCount                       (deDivRoundUp32(sampleCount, MAX_COLOR_ATTACHMENT_COUNT));
465         const tcu::TextureFormat                                format                                          (mapVkFormat(srcFormat));
466         const bool                                                              isDepthStencilFormat            (tcu::hasDepthComponent(format.order) || tcu::hasStencilComponent(format.order));
467         vector<VkSubpassDescription>                    subpasses;
468         vector<vector<VkAttachmentReference> >  dstAttachmentRefs                       (splitSubpassCount);
469         vector<vector<VkAttachmentReference> >  dstResolveAttachmentRefs        (splitSubpassCount);
470         vector<VkAttachmentDescription>                 attachments;
471         vector<VkSubpassDependency>                             dependencies;
472         const VkAttachmentReference                             srcAttachmentRef =
473         {
474                 0u,
475                 isDepthStencilFormat
476                         ? VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL
477                         : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
478         };
479         const VkAttachmentReference                             srcAttachmentInputRef =
480         {
481                 0u,
482                 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
483         };
484
485         {
486                 const VkAttachmentDescription srcAttachment =
487                 {
488                         0u,
489
490                         srcFormat,
491                         samples,
492
493                         VK_ATTACHMENT_LOAD_OP_DONT_CARE,
494                         VK_ATTACHMENT_STORE_OP_DONT_CARE,
495
496                         VK_ATTACHMENT_LOAD_OP_DONT_CARE,
497                         VK_ATTACHMENT_STORE_OP_DONT_CARE,
498
499                         VK_IMAGE_LAYOUT_UNDEFINED,
500                         VK_IMAGE_LAYOUT_GENERAL
501                 };
502
503                 attachments.push_back(srcAttachment);
504         }
505
506         for (deUint32 splitSubpassIndex = 0; splitSubpassIndex < splitSubpassCount; splitSubpassIndex++)
507         {
508                 for (deUint32 sampleNdx = 0; sampleNdx < de::min((deUint32)MAX_COLOR_ATTACHMENT_COUNT, sampleCount  - splitSubpassIndex * MAX_COLOR_ATTACHMENT_COUNT); sampleNdx++)
509                 {
510                         // Multisample color attachment
511                         {
512                                 const VkAttachmentDescription dstAttachment =
513                                 {
514                                         0u,
515
516                                         dstFormat,
517                                         samples,
518
519                                         VK_ATTACHMENT_LOAD_OP_DONT_CARE,
520                                         VK_ATTACHMENT_STORE_OP_DONT_CARE,
521
522                                         VK_ATTACHMENT_LOAD_OP_DONT_CARE,
523                                         VK_ATTACHMENT_STORE_OP_DONT_CARE,
524
525                                         VK_IMAGE_LAYOUT_UNDEFINED,
526                                         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
527                                 };
528                                 const VkAttachmentReference dstAttachmentRef =
529                                 {
530                                         (deUint32)attachments.size(),
531                                         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
532                                 };
533
534                                 attachments.push_back(dstAttachment);
535                                 dstAttachmentRefs[splitSubpassIndex].push_back(dstAttachmentRef);
536                         }
537                         // Resolve attachment
538                         {
539                                 const VkAttachmentDescription dstAttachment =
540                                 {
541                                         0u,
542
543                                         dstFormat,
544                                         VK_SAMPLE_COUNT_1_BIT,
545
546                                         VK_ATTACHMENT_LOAD_OP_DONT_CARE,
547                                         VK_ATTACHMENT_STORE_OP_STORE,
548
549                                         VK_ATTACHMENT_LOAD_OP_DONT_CARE,
550                                         VK_ATTACHMENT_STORE_OP_STORE,
551
552                                         VK_IMAGE_LAYOUT_UNDEFINED,
553                                         VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL
554                                 };
555                                 const VkAttachmentReference dstAttachmentRef =
556                                 {
557                                         (deUint32)attachments.size(),
558                                         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
559                                 };
560
561                                 attachments.push_back(dstAttachment);
562                                 dstResolveAttachmentRefs[splitSubpassIndex].push_back(dstAttachmentRef);
563                         }
564                 }
565         }
566
567         {
568                 {
569                         const VkSubpassDescription      subpass =
570                         {
571                                 (VkSubpassDescriptionFlags)0,
572                                 VK_PIPELINE_BIND_POINT_GRAPHICS,
573
574                                 0u,
575                                 DE_NULL,
576
577                                 isDepthStencilFormat ? 0u : 1u,
578                                 isDepthStencilFormat ? DE_NULL : &srcAttachmentRef,
579                                 DE_NULL,
580
581                                 isDepthStencilFormat ? &srcAttachmentRef : DE_NULL,
582                                 0u,
583                                 DE_NULL
584                         };
585
586                         subpasses.push_back(subpass);
587                 }
588
589                 for (deUint32 splitSubpassIndex = 0; splitSubpassIndex < splitSubpassCount; splitSubpassIndex++)
590                 {
591                         {
592                                 const VkSubpassDescription      subpass =
593                                 {
594                                         (VkSubpassDescriptionFlags)0,
595                                         VK_PIPELINE_BIND_POINT_GRAPHICS,
596
597                                         1u,
598                                         &srcAttachmentInputRef,
599
600                                         (deUint32)dstAttachmentRefs[splitSubpassIndex].size(),
601                                         &dstAttachmentRefs[splitSubpassIndex][0],
602                                         &dstResolveAttachmentRefs[splitSubpassIndex][0],
603
604                                         DE_NULL,
605                                         0u,
606                                         DE_NULL
607                                 };
608                                 subpasses.push_back(subpass);
609                         }
610                         {
611                                 const VkSubpassDependency               dependency      =
612                                 {
613                                         0u, splitSubpassIndex + 1,
614                                         VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
615                                         VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
616
617                                         VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
618                                         VK_ACCESS_INPUT_ATTACHMENT_READ_BIT,
619
620                                         VK_DEPENDENCY_BY_REGION_BIT
621                                 };
622
623                                 dependencies.push_back(dependency);
624                         }
625                 };
626                 const VkRenderPassCreateInfo    createInfo      =
627                 {
628                         VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
629                         DE_NULL,
630                         (VkRenderPassCreateFlags)0u,
631
632                         (deUint32)attachments.size(),
633                         &attachments[0],
634
635                         (deUint32)subpasses.size(),
636                         &subpasses[0],
637
638                         (deUint32)dependencies.size(),
639                         &dependencies[0]
640                 };
641
642                 return createRenderPass(vkd, device, &createInfo);
643         }
644 }
645
646 Move<VkFramebuffer> createFramebuffer (const DeviceInterface&                           vkd,
647                                                                            VkDevice                                                             device,
648                                                                            VkRenderPass                                                 renderPass,
649                                                                            VkImageView                                                  srcImageView,
650                                                                            const std::vector<VkImageViewSp>&    dstMultisampleImageViews,
651                                                                            const std::vector<VkImageViewSp>&    dstSinglesampleImageViews,
652                                                                            deUint32                                                             width,
653                                                                            deUint32                                                             height)
654 {
655         std::vector<VkImageView> attachments;
656
657         attachments.reserve(dstMultisampleImageViews.size() + dstSinglesampleImageViews.size() + 1u);
658
659         attachments.push_back(srcImageView);
660
661         DE_ASSERT(dstMultisampleImageViews.size() == dstSinglesampleImageViews.size());
662
663         for (size_t ndx = 0; ndx < dstMultisampleImageViews.size(); ndx++)
664         {
665                 attachments.push_back(**dstMultisampleImageViews[ndx]);
666                 attachments.push_back(**dstSinglesampleImageViews[ndx]);
667         }
668
669         const VkFramebufferCreateInfo createInfo =
670         {
671                 VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
672                 DE_NULL,
673                 0u,
674
675                 renderPass,
676                 (deUint32)attachments.size(),
677                 &attachments[0],
678
679                 width,
680                 height,
681                 1u
682         };
683
684         return createFramebuffer(vkd, device, &createInfo);
685 }
686
687 Move<VkPipelineLayout> createRenderPipelineLayout (const DeviceInterface&       vkd,
688                                                                                                    VkDevice                                     device)
689 {
690         const VkPushConstantRange                       pushConstant                    =
691         {
692                 VK_SHADER_STAGE_FRAGMENT_BIT,
693                 0u,
694                 4u
695         };
696         const VkPipelineLayoutCreateInfo        createInfo      =
697         {
698                 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
699                 DE_NULL,
700                 (vk::VkPipelineLayoutCreateFlags)0,
701
702                 0u,
703                 DE_NULL,
704
705                 1u,
706                 &pushConstant
707         };
708
709         return createPipelineLayout(vkd, device, &createInfo);
710 }
711
712 Move<VkPipeline> createRenderPipeline (const DeviceInterface&                                                   vkd,
713                                                                            VkDevice                                                                                     device,
714                                                                            VkFormat                                                                                     srcFormat,
715                                                                            VkRenderPass                                                                         renderPass,
716                                                                            VkPipelineLayout                                                                     pipelineLayout,
717                                                                            const vk::ProgramCollection<vk::ProgramBinary>&      binaryCollection,
718                                                                            deUint32                                                                                     width,
719                                                                            deUint32                                                                                     height,
720                                                                            deUint32                                                                                     sampleCount)
721 {
722         const tcu::TextureFormat                format                                          (mapVkFormat(srcFormat));
723         const bool                                              isDepthStencilFormat            (tcu::hasDepthComponent(format.order) || tcu::hasStencilComponent(format.order));
724
725         const Unique<VkShaderModule>    vertexShaderModule                      (createShaderModule(vkd, device, binaryCollection.get("quad-vert"), 0u));
726         const Unique<VkShaderModule>    fragmentShaderModule            (createShaderModule(vkd, device, binaryCollection.get("quad-frag"), 0u));
727         const VkSpecializationInfo              emptyShaderSpecializations      =
728         {
729                 0u,
730                 DE_NULL,
731
732                 0u,
733                 DE_NULL
734         };
735         // Disable blending
736         const VkPipelineColorBlendAttachmentState attachmentBlendState =
737         {
738                 VK_FALSE,
739                 VK_BLEND_FACTOR_SRC_ALPHA,
740                 VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,
741                 VK_BLEND_OP_ADD,
742                 VK_BLEND_FACTOR_ONE,
743                 VK_BLEND_FACTOR_ONE,
744                 VK_BLEND_OP_ADD,
745                 VK_COLOR_COMPONENT_R_BIT|VK_COLOR_COMPONENT_G_BIT|VK_COLOR_COMPONENT_B_BIT|VK_COLOR_COMPONENT_A_BIT
746         };
747         const VkPipelineShaderStageCreateInfo shaderStages[2] =
748         {
749                 {
750                         VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
751                         DE_NULL,
752                         (VkPipelineShaderStageCreateFlags)0u,
753                         VK_SHADER_STAGE_VERTEX_BIT,
754                         *vertexShaderModule,
755                         "main",
756                         &emptyShaderSpecializations
757                 },
758                 {
759                         VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
760                         DE_NULL,
761                         (VkPipelineShaderStageCreateFlags)0u,
762                         VK_SHADER_STAGE_FRAGMENT_BIT,
763                         *fragmentShaderModule,
764                         "main",
765                         &emptyShaderSpecializations
766                 }
767         };
768         const VkPipelineVertexInputStateCreateInfo vertexInputState =
769         {
770                 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
771                 DE_NULL,
772                 (VkPipelineVertexInputStateCreateFlags)0u,
773
774                 0u,
775                 DE_NULL,
776
777                 0u,
778                 DE_NULL
779         };
780         const VkPipelineInputAssemblyStateCreateInfo inputAssemblyState =
781         {
782                 VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
783                 DE_NULL,
784
785                 (VkPipelineInputAssemblyStateCreateFlags)0u,
786                 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
787                 VK_FALSE
788         };
789         const VkViewport viewport =
790         {
791                 0.0f,  0.0f,
792                 (float)width, (float)height,
793
794                 0.0f, 1.0f
795         };
796         const VkRect2D scissor =
797         {
798                 { 0u, 0u },
799                 { width, height }
800         };
801         const VkPipelineViewportStateCreateInfo viewportState =
802         {
803                 VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
804                 DE_NULL,
805                 (VkPipelineViewportStateCreateFlags)0u,
806
807                 1u,
808                 &viewport,
809
810                 1u,
811                 &scissor
812         };
813         const VkPipelineRasterizationStateCreateInfo rasterState =
814         {
815                 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
816                 DE_NULL,
817                 (VkPipelineRasterizationStateCreateFlags)0u,
818                 VK_TRUE,
819                 VK_FALSE,
820                 VK_POLYGON_MODE_FILL,
821                 VK_CULL_MODE_NONE,
822                 VK_FRONT_FACE_COUNTER_CLOCKWISE,
823                 VK_FALSE,
824                 0.0f,
825                 0.0f,
826                 0.0f,
827                 1.0f
828         };
829         const VkPipelineMultisampleStateCreateInfo multisampleState =
830         {
831                 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
832                 DE_NULL,
833                 (VkPipelineMultisampleStateCreateFlags)0u,
834
835                 sampleCountBitFromomSampleCount(sampleCount),
836                 VK_FALSE,
837                 0.0f,
838                 DE_NULL,
839                 VK_FALSE,
840                 VK_FALSE,
841         };
842         const VkPipelineDepthStencilStateCreateInfo depthStencilState =
843         {
844                 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
845                 DE_NULL,
846                 (VkPipelineDepthStencilStateCreateFlags)0u,
847
848                 VK_TRUE,
849                 VK_TRUE,
850                 VK_COMPARE_OP_ALWAYS,
851                 VK_FALSE,
852                 VK_TRUE,
853                 {
854                         VK_STENCIL_OP_KEEP,
855                         VK_STENCIL_OP_INCREMENT_AND_WRAP,
856                         VK_STENCIL_OP_KEEP,
857                         VK_COMPARE_OP_ALWAYS,
858                         ~0u,
859                         ~0u,
860                         0xFFu / (sampleCount + 1)
861                 },
862                 {
863                         VK_STENCIL_OP_KEEP,
864                         VK_STENCIL_OP_INCREMENT_AND_WRAP,
865                         VK_STENCIL_OP_KEEP,
866                         VK_COMPARE_OP_ALWAYS,
867                         ~0u,
868                         ~0u,
869                         0xFFu / (sampleCount + 1)
870                 },
871
872                 0.0f,
873                 1.0f
874         };
875         const VkPipelineColorBlendStateCreateInfo blendState =
876         {
877                 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
878                 DE_NULL,
879                 (VkPipelineColorBlendStateCreateFlags)0u,
880
881                 VK_FALSE,
882                 VK_LOGIC_OP_COPY,
883                 (isDepthStencilFormat ? 0u : 1u),
884                 (isDepthStencilFormat ? DE_NULL : &attachmentBlendState),
885                 { 0.0f, 0.0f, 0.0f, 0.0f }
886         };
887         const VkGraphicsPipelineCreateInfo createInfo =
888         {
889                 VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
890                 DE_NULL,
891                 (VkPipelineCreateFlags)0u,
892
893                 2,
894                 shaderStages,
895
896                 &vertexInputState,
897                 &inputAssemblyState,
898                 DE_NULL,
899                 &viewportState,
900                 &rasterState,
901                 &multisampleState,
902                 &depthStencilState,
903                 &blendState,
904                 (const VkPipelineDynamicStateCreateInfo*)DE_NULL,
905                 pipelineLayout,
906
907                 renderPass,
908                 0u,
909                 DE_NULL,
910                 0u
911         };
912
913         return createGraphicsPipeline(vkd, device, DE_NULL, &createInfo);
914 }
915
916 Move<VkDescriptorSetLayout> createSplitDescriptorSetLayout (const DeviceInterface&      vkd,
917                                                                                                                         VkDevice                                device,
918                                                                                                                         VkFormat                                vkFormat)
919 {
920         const tcu::TextureFormat                                format          (mapVkFormat(vkFormat));
921         const bool                                                              hasDepth        (tcu::hasDepthComponent(format.order));
922         const bool                                                              hasStencil      (tcu::hasStencilComponent(format.order));
923         const VkDescriptorSetLayoutBinding              bindings[]      =
924         {
925                 {
926                         0u,
927                         VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,
928                         1u,
929                         VK_SHADER_STAGE_FRAGMENT_BIT,
930                         DE_NULL
931                 },
932                 {
933                         1u,
934                         VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,
935                         1u,
936                         VK_SHADER_STAGE_FRAGMENT_BIT,
937                         DE_NULL
938                 }
939         };
940         const VkDescriptorSetLayoutCreateInfo   createInfo      =
941         {
942                 VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
943                 DE_NULL,
944                 0u,
945
946                 hasDepth && hasStencil ? 2u : 1u,
947                 bindings
948         };
949
950         return createDescriptorSetLayout(vkd, device, &createInfo);
951 }
952
953 Move<VkPipelineLayout> createSplitPipelineLayout (const DeviceInterface&        vkd,
954                                                                                                   VkDevice                                      device,
955                                                                                                   VkDescriptorSetLayout         descriptorSetLayout)
956 {
957         const VkPushConstantRange                       pushConstant                    =
958         {
959                 VK_SHADER_STAGE_FRAGMENT_BIT,
960                 0u,
961                 4u
962         };
963         const VkPipelineLayoutCreateInfo        createInfo      =
964         {
965                 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
966                 DE_NULL,
967                 (vk::VkPipelineLayoutCreateFlags)0,
968
969                 1u,
970                 &descriptorSetLayout,
971
972                 1u,
973                 &pushConstant
974         };
975
976         return createPipelineLayout(vkd, device, &createInfo);
977 }
978
979 Move<VkPipeline> createSplitPipeline (const DeviceInterface&                                                    vkd,
980                                                                           VkDevice                                                                                      device,
981                                                                           VkRenderPass                                                                          renderPass,
982                                                                           deUint32                                                                                      subpassIndex,
983                                                                           VkPipelineLayout                                                                      pipelineLayout,
984                                                                           const vk::ProgramCollection<vk::ProgramBinary>&       binaryCollection,
985                                                                           deUint32                                                                                      width,
986                                                                           deUint32                                                                                      height,
987                                                                           deUint32                                                                                      sampleCount)
988 {
989         const Unique<VkShaderModule>    vertexShaderModule                      (createShaderModule(vkd, device, binaryCollection.get("quad-vert"), 0u));
990         const Unique<VkShaderModule>    fragmentShaderModule            (createShaderModule(vkd, device, binaryCollection.get("quad-split-frag"), 0u));
991         const VkSpecializationInfo              emptyShaderSpecializations      =
992         {
993                 0u,
994                 DE_NULL,
995
996                 0u,
997                 DE_NULL
998         };
999         // Disable blending
1000         const VkPipelineColorBlendAttachmentState attachmentBlendState =
1001         {
1002                 VK_FALSE,
1003                 VK_BLEND_FACTOR_SRC_ALPHA,
1004                 VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,
1005                 VK_BLEND_OP_ADD,
1006                 VK_BLEND_FACTOR_ONE,
1007                 VK_BLEND_FACTOR_ONE,
1008                 VK_BLEND_OP_ADD,
1009                 VK_COLOR_COMPONENT_R_BIT|VK_COLOR_COMPONENT_G_BIT|VK_COLOR_COMPONENT_B_BIT|VK_COLOR_COMPONENT_A_BIT
1010         };
1011         const std::vector<VkPipelineColorBlendAttachmentState> attachmentBlendStates (de::min((deUint32)MAX_COLOR_ATTACHMENT_COUNT, sampleCount), attachmentBlendState);
1012         const VkPipelineShaderStageCreateInfo shaderStages[2] =
1013         {
1014                 {
1015                         VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
1016                         DE_NULL,
1017                         (VkPipelineShaderStageCreateFlags)0u,
1018                         VK_SHADER_STAGE_VERTEX_BIT,
1019                         *vertexShaderModule,
1020                         "main",
1021                         &emptyShaderSpecializations
1022                 },
1023                 {
1024                         VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
1025                         DE_NULL,
1026                         (VkPipelineShaderStageCreateFlags)0u,
1027                         VK_SHADER_STAGE_FRAGMENT_BIT,
1028                         *fragmentShaderModule,
1029                         "main",
1030                         &emptyShaderSpecializations
1031                 }
1032         };
1033         const VkPipelineVertexInputStateCreateInfo vertexInputState =
1034         {
1035                 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
1036                 DE_NULL,
1037                 (VkPipelineVertexInputStateCreateFlags)0u,
1038
1039                 0u,
1040                 DE_NULL,
1041
1042                 0u,
1043                 DE_NULL
1044         };
1045         const VkPipelineInputAssemblyStateCreateInfo inputAssemblyState =
1046         {
1047                 VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
1048                 DE_NULL,
1049
1050                 (VkPipelineInputAssemblyStateCreateFlags)0u,
1051                 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
1052                 VK_FALSE
1053         };
1054         const VkViewport viewport =
1055         {
1056                 0.0f,  0.0f,
1057                 (float)width, (float)height,
1058
1059                 0.0f, 1.0f
1060         };
1061         const VkRect2D scissor =
1062         {
1063                 { 0u, 0u },
1064                 { width, height }
1065         };
1066         const VkPipelineViewportStateCreateInfo viewportState =
1067         {
1068                 VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
1069                 DE_NULL,
1070                 (VkPipelineViewportStateCreateFlags)0u,
1071
1072                 1u,
1073                 &viewport,
1074
1075                 1u,
1076                 &scissor
1077         };
1078         const VkPipelineRasterizationStateCreateInfo rasterState =
1079         {
1080                 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
1081                 DE_NULL,
1082                 (VkPipelineRasterizationStateCreateFlags)0u,
1083                 VK_TRUE,
1084                 VK_FALSE,
1085                 VK_POLYGON_MODE_FILL,
1086                 VK_CULL_MODE_NONE,
1087                 VK_FRONT_FACE_COUNTER_CLOCKWISE,
1088                 VK_FALSE,
1089                 0.0f,
1090                 0.0f,
1091                 0.0f,
1092                 1.0f
1093         };
1094         const VkPipelineMultisampleStateCreateInfo multisampleState =
1095         {
1096                 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
1097                 DE_NULL,
1098                 (VkPipelineMultisampleStateCreateFlags)0u,
1099
1100                 sampleCountBitFromomSampleCount(sampleCount),
1101                 VK_FALSE,
1102                 0.0f,
1103                 DE_NULL,
1104                 VK_FALSE,
1105                 VK_FALSE,
1106         };
1107         const VkPipelineDepthStencilStateCreateInfo depthStencilState =
1108         {
1109                 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
1110                 DE_NULL,
1111                 (VkPipelineDepthStencilStateCreateFlags)0u,
1112
1113                 VK_FALSE,
1114                 VK_FALSE,
1115                 VK_COMPARE_OP_ALWAYS,
1116                 VK_FALSE,
1117                 VK_FALSE,
1118                 {
1119                         VK_STENCIL_OP_REPLACE,
1120                         VK_STENCIL_OP_REPLACE,
1121                         VK_STENCIL_OP_REPLACE,
1122                         VK_COMPARE_OP_ALWAYS,
1123                         ~0u,
1124                         ~0u,
1125                         0x0u
1126                 },
1127                 {
1128                         VK_STENCIL_OP_REPLACE,
1129                         VK_STENCIL_OP_REPLACE,
1130                         VK_STENCIL_OP_REPLACE,
1131                         VK_COMPARE_OP_ALWAYS,
1132                         ~0u,
1133                         ~0u,
1134                         0x0u
1135                 },
1136
1137                 0.0f,
1138                 1.0f
1139         };
1140         const VkPipelineColorBlendStateCreateInfo blendState =
1141         {
1142                 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
1143                 DE_NULL,
1144                 (VkPipelineColorBlendStateCreateFlags)0u,
1145
1146                 VK_FALSE,
1147                 VK_LOGIC_OP_COPY,
1148
1149                 (deUint32)attachmentBlendStates.size(),
1150                 &attachmentBlendStates[0],
1151
1152                 { 0.0f, 0.0f, 0.0f, 0.0f }
1153         };
1154         const VkGraphicsPipelineCreateInfo createInfo =
1155         {
1156                 VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
1157                 DE_NULL,
1158                 (VkPipelineCreateFlags)0u,
1159
1160                 2,
1161                 shaderStages,
1162
1163                 &vertexInputState,
1164                 &inputAssemblyState,
1165                 DE_NULL,
1166                 &viewportState,
1167                 &rasterState,
1168                 &multisampleState,
1169                 &depthStencilState,
1170                 &blendState,
1171                 (const VkPipelineDynamicStateCreateInfo*)DE_NULL,
1172                 pipelineLayout,
1173
1174                 renderPass,
1175                 subpassIndex,
1176                 DE_NULL,
1177                 0u
1178         };
1179
1180         return createGraphicsPipeline(vkd, device, DE_NULL, &createInfo);
1181 }
1182
1183 vector<VkPipelineSp> createSplitPipelines (const DeviceInterface&                                                       vkd,
1184                                                                                  VkDevice                                                                                       device,
1185                                                                                  VkRenderPass                                                                           renderPass,
1186                                                                                  VkPipelineLayout                                                                       pipelineLayout,
1187                                                                                  const vk::ProgramCollection<vk::ProgramBinary>&        binaryCollection,
1188                                                                                  deUint32                                                                                       width,
1189                                                                                  deUint32                                                                                       height,
1190                                                                                  deUint32                                                                                       sampleCount)
1191 {
1192         std::vector<VkPipelineSp> pipelines (deDivRoundUp32(sampleCount, MAX_COLOR_ATTACHMENT_COUNT), (VkPipelineSp)0u);
1193
1194         for (size_t ndx = 0; ndx < pipelines.size(); ndx++)
1195                 pipelines[ndx] = safeSharedPtr(new Unique<VkPipeline>(createSplitPipeline(vkd, device, renderPass, (deUint32)(ndx + 1), pipelineLayout, binaryCollection, width, height, sampleCount)));
1196
1197         return pipelines;
1198 }
1199
1200 Move<VkDescriptorPool> createSplitDescriptorPool (const DeviceInterface&        vkd,
1201                                                                                                   VkDevice                                      device)
1202 {
1203         const VkDescriptorPoolSize                      size            =
1204         {
1205                 VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 2u
1206         };
1207         const VkDescriptorPoolCreateInfo        createInfo      =
1208         {
1209                 VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
1210                 DE_NULL,
1211                 VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
1212
1213
1214                 2u,
1215                 1u,
1216                 &size
1217         };
1218
1219         return createDescriptorPool(vkd, device, &createInfo);
1220 }
1221
1222 Move<VkDescriptorSet> createSplitDescriptorSet (const DeviceInterface&  vkd,
1223                                                                                                 VkDevice                                device,
1224                                                                                                 VkDescriptorPool                pool,
1225                                                                                                 VkDescriptorSetLayout   layout,
1226                                                                                                 VkImageView                             primaryImageView,
1227                                                                                                 VkImageView                             secondaryImageView)
1228 {
1229         const VkDescriptorSetAllocateInfo       allocateInfo    =
1230         {
1231                 VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
1232                 DE_NULL,
1233
1234                 pool,
1235                 1u,
1236                 &layout
1237         };
1238         Move<VkDescriptorSet> set (allocateDescriptorSet(vkd, device, &allocateInfo));
1239
1240         {
1241                 const VkDescriptorImageInfo     imageInfos[]    =
1242                 {
1243                         {
1244                                 (VkSampler)0u,
1245                                 primaryImageView,
1246                                 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
1247                         },
1248                         {
1249                                 (VkSampler)0u,
1250                                 secondaryImageView,
1251                                 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
1252                         }
1253                 };
1254                 const VkWriteDescriptorSet      writes[]        =
1255                 {
1256                         {
1257                                 VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
1258                                 DE_NULL,
1259
1260                                 *set,
1261                                 0u,
1262                                 0u,
1263                                 1u,
1264                                 VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,
1265                                 &imageInfos[0],
1266                                 DE_NULL,
1267                                 DE_NULL
1268                         },
1269                         {
1270                                 VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
1271                                 DE_NULL,
1272
1273                                 *set,
1274                                 1u,
1275                                 0u,
1276                                 1u,
1277                                 VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,
1278                                 &imageInfos[1],
1279                                 DE_NULL,
1280                                 DE_NULL
1281                         }
1282                 };
1283                 const deUint32  count   = secondaryImageView != (VkImageView)0
1284                                                                 ? 2u
1285                                                                 : 1u;
1286
1287                 vkd.updateDescriptorSets(device, count, writes, 0u, DE_NULL);
1288         }
1289         return set;
1290 }
1291
1292 struct TestConfig
1293 {
1294                                 TestConfig              (VkFormat       format_,
1295                                                                  deUint32       sampleCount_)
1296                 : format                (format_)
1297                 , sampleCount   (sampleCount_)
1298         {
1299         }
1300
1301         VkFormat        format;
1302         deUint32        sampleCount;
1303 };
1304
1305 VkImageUsageFlags getSrcImageUsage (VkFormat vkFormat)
1306 {
1307         const tcu::TextureFormat        format          (mapVkFormat(vkFormat));
1308         const bool                                      hasDepth        (tcu::hasDepthComponent(format.order));
1309         const bool                                      hasStencil      (tcu::hasStencilComponent(format.order));
1310
1311         if (hasDepth || hasStencil)
1312                 return VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
1313         else
1314                 return VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
1315 }
1316
1317 VkFormat getDstFormat (VkFormat vkFormat)
1318 {
1319         const tcu::TextureFormat        format          (mapVkFormat(vkFormat));
1320         const bool                                      hasDepth        (tcu::hasDepthComponent(format.order));
1321         const bool                                      hasStencil      (tcu::hasStencilComponent(format.order));
1322
1323         if (hasDepth && hasStencil)
1324                 return VK_FORMAT_R32G32_SFLOAT;
1325         else if (hasDepth || hasStencil)
1326                 return VK_FORMAT_R32_SFLOAT;
1327         else
1328                 return vkFormat;
1329 }
1330
1331
1332 class MultisampleRenderPassTestInstance : public TestInstance
1333 {
1334 public:
1335                                         MultisampleRenderPassTestInstance       (Context& context, TestConfig config);
1336                                         ~MultisampleRenderPassTestInstance      (void);
1337
1338         tcu::TestStatus iterate                                                         (void);
1339
1340 private:
1341         const VkFormat                                                                  m_srcFormat;
1342         const VkFormat                                                                  m_dstFormat;
1343         const deUint32                                                                  m_sampleCount;
1344         const deUint32                                                                  m_width;
1345         const deUint32                                                                  m_height;
1346
1347         const VkImageAspectFlags                                                m_srcImageAspect;
1348         const VkImageUsageFlags                                                 m_srcImageUsage;
1349         const Unique<VkImage>                                                   m_srcImage;
1350         const de::UniquePtr<Allocation>                                 m_srcImageMemory;
1351         const Unique<VkImageView>                                               m_srcImageView;
1352         const Unique<VkImageView>                                               m_srcPrimaryInputImageView;
1353         const Unique<VkImageView>                                               m_srcSecondaryInputImageView;
1354
1355         const std::vector<VkImageSp>                                    m_dstMultisampleImages;
1356         const std::vector<de::SharedPtr<Allocation> >   m_dstMultisampleImageMemory;
1357         const std::vector<VkImageViewSp>                                m_dstMultisampleImageViews;
1358
1359         const std::vector<VkImageSp>                                    m_dstSinglesampleImages;
1360         const std::vector<de::SharedPtr<Allocation> >   m_dstSinglesampleImageMemory;
1361         const std::vector<VkImageViewSp>                                m_dstSinglesampleImageViews;
1362
1363         const std::vector<VkBufferSp>                                   m_dstBuffers;
1364         const std::vector<de::SharedPtr<Allocation> >   m_dstBufferMemory;
1365
1366         const Unique<VkRenderPass>                                              m_renderPass;
1367         const Unique<VkFramebuffer>                                             m_framebuffer;
1368
1369         const Unique<VkPipelineLayout>                                  m_renderPipelineLayout;
1370         const Unique<VkPipeline>                                                m_renderPipeline;
1371
1372         const Unique<VkDescriptorSetLayout>                             m_splitDescriptorSetLayout;
1373         const Unique<VkPipelineLayout>                                  m_splitPipelineLayout;
1374         const std::vector<VkPipelineSp>                                 m_splitPipelines;
1375         const Unique<VkDescriptorPool>                                  m_splitDescriptorPool;
1376         const Unique<VkDescriptorSet>                                   m_splitDescriptorSet;
1377
1378         const Unique<VkCommandPool>                                             m_commandPool;
1379         tcu::ResultCollector                                                    m_resultCollector;
1380 };
1381
1382 MultisampleRenderPassTestInstance::MultisampleRenderPassTestInstance (Context& context, TestConfig config)
1383         : TestInstance                                  (context)
1384         , m_srcFormat                                   (config.format)
1385         , m_dstFormat                                   (getDstFormat(config.format))
1386         , m_sampleCount                                 (config.sampleCount)
1387         , m_width                                               (32u)
1388         , m_height                                              (32u)
1389
1390         , m_srcImageAspect                              (getImageAspectFlags(m_srcFormat))
1391         , m_srcImageUsage                               (getSrcImageUsage(m_srcFormat))
1392         , m_srcImage                                    (createImage(context.getInstanceInterface(), context.getPhysicalDevice(), context.getDeviceInterface(), context.getDevice(), m_srcFormat, sampleCountBitFromomSampleCount(m_sampleCount), m_srcImageUsage, m_width, m_height))
1393         , m_srcImageMemory                              (createImageMemory(context.getDeviceInterface(), context.getDevice(), context.getDefaultAllocator(), *m_srcImage))
1394         , m_srcImageView                                (createImageAttachmentView(context.getDeviceInterface(), context.getDevice(), *m_srcImage, m_srcFormat, m_srcImageAspect))
1395         , m_srcPrimaryInputImageView    (createSrcPrimaryInputImageView(context.getDeviceInterface(), context.getDevice(), *m_srcImage, m_srcFormat, m_srcImageAspect))
1396         , m_srcSecondaryInputImageView  (createSrcSecondaryInputImageView(context.getDeviceInterface(), context.getDevice(), *m_srcImage, m_srcFormat, m_srcImageAspect))
1397
1398         , m_dstMultisampleImages                (createMultisampleImages(context.getInstanceInterface(), context.getPhysicalDevice(), context.getDeviceInterface(), context.getDevice(), m_dstFormat, m_sampleCount, m_width, m_height))
1399         , m_dstMultisampleImageMemory   (createImageMemory(context.getDeviceInterface(), context.getDevice(), context.getDefaultAllocator(), m_dstMultisampleImages))
1400         , m_dstMultisampleImageViews    (createImageAttachmentViews(context.getDeviceInterface(), context.getDevice(), m_dstMultisampleImages, m_dstFormat, VK_IMAGE_ASPECT_COLOR_BIT))
1401
1402         , m_dstSinglesampleImages               (createSingleSampleImages(context.getInstanceInterface(), context.getPhysicalDevice(), context.getDeviceInterface(), context.getDevice(), m_dstFormat, m_sampleCount, m_width, m_height))
1403         , m_dstSinglesampleImageMemory  (createImageMemory(context.getDeviceInterface(), context.getDevice(), context.getDefaultAllocator(), m_dstSinglesampleImages))
1404         , m_dstSinglesampleImageViews   (createImageAttachmentViews(context.getDeviceInterface(), context.getDevice(), m_dstSinglesampleImages, m_dstFormat, VK_IMAGE_ASPECT_COLOR_BIT))
1405
1406         , m_dstBuffers                                  (createBuffers(context.getDeviceInterface(), context.getDevice(), m_dstFormat, m_sampleCount, m_width, m_height))
1407         , m_dstBufferMemory                             (createBufferMemory(context.getDeviceInterface(), context.getDevice(), context.getDefaultAllocator(), m_dstBuffers))
1408
1409         , m_renderPass                                  (createRenderPass(context.getDeviceInterface(), context.getDevice(), m_srcFormat, m_dstFormat, m_sampleCount))
1410         , m_framebuffer                                 (createFramebuffer(context.getDeviceInterface(), context.getDevice(), *m_renderPass, *m_srcImageView, m_dstMultisampleImageViews, m_dstSinglesampleImageViews, m_width, m_height))
1411
1412         , m_renderPipelineLayout                (createRenderPipelineLayout(context.getDeviceInterface(), context.getDevice()))
1413         , m_renderPipeline                              (createRenderPipeline(context.getDeviceInterface(), context.getDevice(), m_srcFormat, *m_renderPass, *m_renderPipelineLayout, context.getBinaryCollection(), m_width, m_height, m_sampleCount))
1414
1415         , m_splitDescriptorSetLayout    (createSplitDescriptorSetLayout(context.getDeviceInterface(), context.getDevice(), m_srcFormat))
1416         , m_splitPipelineLayout                 (createSplitPipelineLayout(context.getDeviceInterface(), context.getDevice(), *m_splitDescriptorSetLayout))
1417         , m_splitPipelines                              (createSplitPipelines(context.getDeviceInterface(), context.getDevice(), *m_renderPass, *m_splitPipelineLayout, context.getBinaryCollection(), m_width, m_height, m_sampleCount))
1418         , m_splitDescriptorPool                 (createSplitDescriptorPool(context.getDeviceInterface(), context.getDevice()))
1419         , m_splitDescriptorSet                  (createSplitDescriptorSet(context.getDeviceInterface(), context.getDevice(), *m_splitDescriptorPool, *m_splitDescriptorSetLayout, *m_srcPrimaryInputImageView, *m_srcSecondaryInputImageView))
1420         , m_commandPool                                 (createCommandPool(context.getDeviceInterface(), context.getDevice(), VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, context.getUniversalQueueFamilyIndex()))
1421 {
1422 }
1423
1424 MultisampleRenderPassTestInstance::~MultisampleRenderPassTestInstance (void)
1425 {
1426 }
1427
1428 tcu::TestStatus MultisampleRenderPassTestInstance::iterate (void)
1429 {
1430         const DeviceInterface&                  vkd                             (m_context.getDeviceInterface());
1431         const VkDevice                                  device                  (m_context.getDevice());
1432         const Unique<VkCommandBuffer>   commandBuffer   (allocateCommandBuffer(vkd, device, *m_commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
1433
1434         {
1435                 const VkCommandBufferBeginInfo beginInfo =
1436                 {
1437                         VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
1438                         DE_NULL,
1439
1440                         VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
1441                         DE_NULL
1442                 };
1443
1444                 VK_CHECK(vkd.beginCommandBuffer(*commandBuffer, &beginInfo));
1445         }
1446
1447         {
1448                 const VkRenderPassBeginInfo beginInfo =
1449                 {
1450                         VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
1451                         DE_NULL,
1452
1453                         *m_renderPass,
1454                         *m_framebuffer,
1455
1456                         {
1457                                 { 0u, 0u },
1458                                 { m_width, m_height }
1459                         },
1460
1461                         0u,
1462                         DE_NULL
1463                 };
1464                 vkd.cmdBeginRenderPass(*commandBuffer, &beginInfo, VK_SUBPASS_CONTENTS_INLINE);
1465         }
1466
1467         vkd.cmdBindPipeline(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_renderPipeline);
1468
1469         for (deUint32 sampleNdx = 0; sampleNdx < m_sampleCount; sampleNdx++)
1470         {
1471                 vkd.cmdPushConstants(*commandBuffer, *m_renderPipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, 0u, sizeof(sampleNdx), &sampleNdx);
1472                 vkd.cmdDraw(*commandBuffer, 6u, 1u, 0u, 0u);
1473         }
1474
1475         for (deUint32 splitPipelineNdx = 0; splitPipelineNdx < m_splitPipelines.size(); splitPipelineNdx++)
1476         {
1477                 vkd.cmdNextSubpass(*commandBuffer, VK_SUBPASS_CONTENTS_INLINE);
1478
1479                 vkd.cmdBindPipeline(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, **m_splitPipelines[splitPipelineNdx]);
1480                 vkd.cmdBindDescriptorSets(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_splitPipelineLayout, 0u, 1u,  &*m_splitDescriptorSet, 0u, DE_NULL);
1481                 vkd.cmdPushConstants(*commandBuffer, *m_splitPipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, 0u, sizeof(splitPipelineNdx), &splitPipelineNdx);
1482                 vkd.cmdDraw(*commandBuffer, 6u, 1u, 0u, 0u);
1483         }
1484
1485         vkd.cmdEndRenderPass(*commandBuffer);
1486
1487         // Memory barriers between rendering and copies
1488         {
1489                 std::vector<VkImageMemoryBarrier> barriers;
1490
1491                 for (size_t dstNdx = 0; dstNdx < m_dstSinglesampleImages.size(); dstNdx++)
1492                 {
1493                         const VkImageMemoryBarrier barrier =
1494                         {
1495                                 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
1496                                 DE_NULL,
1497
1498                                 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
1499                                 VK_ACCESS_TRANSFER_READ_BIT,
1500
1501                                 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
1502                                 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
1503
1504                                 VK_QUEUE_FAMILY_IGNORED,
1505                                 VK_QUEUE_FAMILY_IGNORED,
1506
1507                                 **m_dstSinglesampleImages[dstNdx],
1508                                 {
1509                                         VK_IMAGE_ASPECT_COLOR_BIT,
1510                                         0u,
1511                                         1u,
1512                                         0u,
1513                                         1u
1514                                 }
1515                         };
1516
1517                         barriers.push_back(barrier);
1518                 }
1519
1520                 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]);
1521         }
1522
1523         // Copy image memory to buffers
1524         for (size_t dstNdx = 0; dstNdx < m_dstSinglesampleImages.size(); dstNdx++)
1525         {
1526                 const VkBufferImageCopy region =
1527                 {
1528                         0u,
1529                         0u,
1530                         0u,
1531                         {
1532                                 VK_IMAGE_ASPECT_COLOR_BIT,
1533                                 0u,
1534                                 0u,
1535                                 1u,
1536                         },
1537                         { 0u, 0u, 0u },
1538                         { m_width, m_height, 1u }
1539                 };
1540
1541                 vkd.cmdCopyImageToBuffer(*commandBuffer, **m_dstSinglesampleImages[dstNdx], VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, **m_dstBuffers[dstNdx], 1u, &region);
1542         }
1543
1544         // Memory barriers between copies and host access
1545         {
1546                 std::vector<VkBufferMemoryBarrier> barriers;
1547
1548                 for (size_t dstNdx = 0; dstNdx < m_dstBuffers.size(); dstNdx++)
1549                 {
1550                         const VkBufferMemoryBarrier barrier =
1551                         {
1552                                 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
1553                                 DE_NULL,
1554
1555                                 VK_ACCESS_TRANSFER_WRITE_BIT,
1556                                 VK_ACCESS_HOST_READ_BIT,
1557
1558                                 VK_QUEUE_FAMILY_IGNORED,
1559                                 VK_QUEUE_FAMILY_IGNORED,
1560
1561                                 **m_dstBuffers[dstNdx],
1562                                 0u,
1563                                 VK_WHOLE_SIZE
1564                         };
1565
1566                         barriers.push_back(barrier);
1567                 }
1568
1569                 vkd.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, (deUint32)barriers.size(), &barriers[0], 0u, DE_NULL);
1570         }
1571
1572         VK_CHECK(vkd.endCommandBuffer(*commandBuffer));
1573
1574         {
1575                 const VkSubmitInfo submitInfo =
1576                 {
1577                         VK_STRUCTURE_TYPE_SUBMIT_INFO,
1578                         DE_NULL,
1579
1580                         0u,
1581                         DE_NULL,
1582                         DE_NULL,
1583
1584                         1u,
1585                         &*commandBuffer,
1586
1587                         0u,
1588                         DE_NULL
1589                 };
1590
1591                 VK_CHECK(vkd.queueSubmit(m_context.getUniversalQueue(), 1u, &submitInfo, (VkFence)0u));
1592
1593                 VK_CHECK(vkd.queueWaitIdle(m_context.getUniversalQueue()));
1594         }
1595
1596         {
1597                 const tcu::TextureFormat                format                  (mapVkFormat(m_dstFormat));
1598                 const tcu::TextureFormat                srcFormat               (mapVkFormat(m_srcFormat));
1599                 const bool                                              hasDepth                (tcu::hasDepthComponent(srcFormat.order));
1600                 const bool                                              hasStencil              (tcu::hasStencilComponent(srcFormat.order));
1601
1602                 for (deUint32 sampleNdx = 0; sampleNdx < m_sampleCount; sampleNdx++)
1603                 {
1604                         const std::string                                       name            ("Sample" + de::toString(sampleNdx));
1605                         const void* const                                       ptr                     (m_dstBufferMemory[sampleNdx]->getHostPtr());
1606                         const tcu::ConstPixelBufferAccess       access          (format, m_width, m_height, 1, ptr);
1607                         tcu::TextureLevel                                       reference       (format, m_width, m_height);
1608
1609                         if (hasDepth || hasStencil)
1610                         {
1611                                 if (hasDepth)
1612                                 {
1613                                         for (deUint32 y = 0; y < m_height; y++)
1614                                         for (deUint32 x = 0; x < m_width; x++)
1615                                         {
1616                                                 const deUint32  x1                              = x ^ sampleNdx;
1617                                                 const deUint32  y1                              = y ^ sampleNdx;
1618                                                 const float             range                   = 1.0f;
1619                                                 float                   depth                   = 0.0f;
1620                                                 deUint32                divider                 = 2;
1621
1622                                                 // \note Limited to ten bits since the target is 32x32, so there are 10 input bits
1623                                                 for (size_t bitNdx = 0; bitNdx < 10; bitNdx++)
1624                                                 {
1625                                                         depth += (range / (float)divider)
1626                                                                         * (((bitNdx % 2 == 0 ? x1 : y1) & (0x1u << (bitNdx / 2u))) == 0u ? 0u : 1u);
1627                                                         divider *= 2;
1628                                                 }
1629
1630                                                 reference.getAccess().setPixel(Vec4(depth, 0.0f, 0.0f, 0.0f), x, y);
1631                                         }
1632                                 }
1633                                 if (hasStencil)
1634                                 {
1635                                         for (deUint32 y = 0; y < m_height; y++)
1636                                         for (deUint32 x = 0; x < m_width; x++)
1637                                         {
1638                                                 const deUint32  stencil = sampleNdx + 1u;
1639
1640                                                 if (hasDepth)
1641                                                 {
1642                                                         const Vec4 src (reference.getAccess().getPixel(x, y));
1643
1644                                                         reference.getAccess().setPixel(Vec4(src.x(), (float)stencil, 0.0f, 0.0f), x, y);
1645                                                 }
1646                                                 else
1647                                                         reference.getAccess().setPixel(Vec4((float)stencil, 0.0f, 0.0f, 0.0f), x, y);
1648                                         }
1649                                 }
1650                                 {
1651                                         const Vec4 threshold (hasDepth ? (1.0f / 1024.0f) : 0.0f, 0.0f, 0.0f, 0.0f);
1652
1653                                         if (!tcu::floatThresholdCompare(m_context.getTestContext().getLog(), name.c_str(), name.c_str(), reference.getAccess(), access, threshold, tcu::COMPARE_LOG_ON_ERROR))
1654                                                 m_resultCollector.fail("Compare failed for sample " + de::toString(sampleNdx));
1655                                 }
1656                         }
1657                         else
1658                         {
1659                                 const tcu::TextureChannelClass  channelClass    (tcu::getTextureChannelClass(format.type));
1660
1661                                 switch (channelClass)
1662                                 {
1663                                         case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
1664                                         {
1665                                                 const UVec4             bits                    (tcu::getTextureFormatBitDepth(format).cast<deUint32>());
1666                                                 const UVec4             minValue                (0);
1667                                                 const UVec4             range                   (UVec4(1u) << tcu::min(bits, UVec4(31)));
1668                                                 const int               componentCount  (tcu::getNumUsedChannels(format.order));
1669                                                 const deUint32  bitSize                 (bits[0] + bits[1] + bits[2] + bits[3]);
1670
1671                                                 for (deUint32 y = 0; y < m_height; y++)
1672                                                 for (deUint32 x = 0; x < m_width; x++)
1673                                                 {
1674                                                         const deUint32  x1                              = x ^ sampleNdx;
1675                                                         const deUint32  y1                              = y ^ sampleNdx;
1676                                                         UVec4                   color                   (minValue);
1677                                                         deUint32                dstBitsUsed[4]  = { 0u, 0u, 0u, 0u };
1678                                                         deUint32                nextSrcBit              = 0;
1679                                                         deUint32                divider                 = 2;
1680
1681                                                         // \note Limited to ten bits since the target is 32x32, so there are 10 input bits
1682                                                         while (nextSrcBit < de::min(bitSize, 10u))
1683                                                         {
1684                                                                 for (int compNdx = 0; compNdx < componentCount; compNdx++)
1685                                                                 {
1686                                                                         if (dstBitsUsed[compNdx] > bits[compNdx])
1687                                                                                 continue;
1688
1689                                                                         color[compNdx] += (range[compNdx] / divider)
1690                                                                                                         * (((nextSrcBit % 2 == 0 ? x1 : y1) & (0x1u << (nextSrcBit / 2u))) == 0u ? 0u : 1u);
1691
1692                                                                         nextSrcBit++;
1693                                                                         dstBitsUsed[compNdx]++;
1694                                                                 }
1695
1696                                                                 divider *= 2;
1697                                                         }
1698
1699                                                         reference.getAccess().setPixel(color, x, y);
1700                                                 }
1701
1702                                                 if (!tcu::intThresholdCompare(m_context.getTestContext().getLog(), name.c_str(), name.c_str(), reference.getAccess(), access, UVec4(0u), tcu::COMPARE_LOG_ON_ERROR))
1703                                                         m_resultCollector.fail("Compare failed for sample " + de::toString(sampleNdx));
1704
1705                                                 break;
1706                                         }
1707
1708                                         case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
1709                                         {
1710                                                 const UVec4             bits                    (tcu::getTextureFormatBitDepth(format).cast<deUint32>());
1711                                                 const IVec4             minValue                (0);
1712                                                 const IVec4             range                   ((UVec4(1u) << tcu::min(bits, UVec4(30))).cast<deInt32>());
1713                                                 const int               componentCount  (tcu::getNumUsedChannels(format.order));
1714                                                 const deUint32  bitSize                 (bits[0] + bits[1] + bits[2] + bits[3]);
1715
1716                                                 for (deUint32 y = 0; y < m_height; y++)
1717                                                 for (deUint32 x = 0; x < m_width; x++)
1718                                                 {
1719                                                         const deUint32  x1                              = x ^ sampleNdx;
1720                                                         const deUint32  y1                              = y ^ sampleNdx;
1721                                                         IVec4                   color                   (minValue);
1722                                                         deUint32                dstBitsUsed[4]  = { 0u, 0u, 0u, 0u };
1723                                                         deUint32                nextSrcBit              = 0;
1724                                                         deUint32                divider                 = 2;
1725
1726                                                         // \note Limited to ten bits since the target is 32x32, so there are 10 input bits
1727                                                         while (nextSrcBit < de::min(bitSize, 10u))
1728                                                         {
1729                                                                 for (int compNdx = 0; compNdx < componentCount; compNdx++)
1730                                                                 {
1731                                                                         if (dstBitsUsed[compNdx] > bits[compNdx])
1732                                                                                 continue;
1733
1734                                                                         color[compNdx] += (range[compNdx] / divider)
1735                                                                                                         * (((nextSrcBit % 2 == 0 ? x1 : y1) & (0x1u << (nextSrcBit / 2u))) == 0u ? 0u : 1u);
1736
1737                                                                         nextSrcBit++;
1738                                                                         dstBitsUsed[compNdx]++;
1739                                                                 }
1740
1741                                                                 divider *= 2;
1742                                                         }
1743
1744                                                         reference.getAccess().setPixel(color, x, y);
1745                                                 }
1746
1747                                                 if (!tcu::intThresholdCompare(m_context.getTestContext().getLog(), name.c_str(), name.c_str(), reference.getAccess(), access, UVec4(0u), tcu::COMPARE_LOG_ON_ERROR))
1748                                                         m_resultCollector.fail("Compare failed for sample " + de::toString(sampleNdx));
1749
1750                                                 break;
1751                                         }
1752
1753                                         case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
1754                                         case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
1755                                         case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
1756                                         {
1757                                                 const tcu::TextureFormatInfo    info                    (tcu::getTextureFormatInfo(format));
1758                                                 const UVec4                                             bits                    (tcu::getTextureFormatBitDepth(format).cast<deUint32>());
1759                                                 const Vec4                                              minLimit                (-65536.0);
1760                                                 const Vec4                                              maxLimit                (65536.0);
1761                                                 const Vec4                                              minValue                (tcu::max(info.valueMin, minLimit));
1762                                                 const Vec4                                              range                   (tcu::min(info.valueMax, maxLimit) - minValue);
1763                                                 const int                                               componentCount  (tcu::getNumUsedChannels(format.order));
1764                                                 const deUint32                                  bitSize                 (bits[0] + bits[1] + bits[2] + bits[3]);
1765
1766                                                 for (deUint32 y = 0; y < m_height; y++)
1767                                                 for (deUint32 x = 0; x < m_width; x++)
1768                                                 {
1769                                                         const deUint32  x1                              = x ^ sampleNdx;
1770                                                         const deUint32  y1                              = y ^ sampleNdx;
1771                                                         Vec4                    color                   (minValue);
1772                                                         deUint32                dstBitsUsed[4]  = { 0u, 0u, 0u, 0u };
1773                                                         deUint32                nextSrcBit              = 0;
1774                                                         deUint32                divider                 = 2;
1775
1776                                                         // \note Limited to ten bits since the target is 32x32, so there are 10 input bits
1777                                                         while (nextSrcBit < de::min(bitSize, 10u))
1778                                                         {
1779                                                                 for (int compNdx = 0; compNdx < componentCount; compNdx++)
1780                                                                 {
1781                                                                         if (dstBitsUsed[compNdx] > bits[compNdx])
1782                                                                                 continue;
1783
1784                                                                         color[compNdx] += (range[compNdx] / (float)divider)
1785                                                                                                         * (((nextSrcBit % 2 == 0 ? x1 : y1) & (0x1u << (nextSrcBit / 2u))) == 0u ? 0u : 1u);
1786
1787                                                                         nextSrcBit++;
1788                                                                         dstBitsUsed[compNdx]++;
1789                                                                 }
1790
1791                                                                 divider *= 2;
1792                                                         }
1793
1794                                                         if (tcu::isSRGB(format))
1795                                                                 reference.getAccess().setPixel(tcu::linearToSRGB(color), x, y);
1796                                                         else
1797                                                                 reference.getAccess().setPixel(color, x, y);
1798                                                 }
1799
1800                                                 if (channelClass == tcu::TEXTURECHANNELCLASS_FLOATING_POINT)
1801                                                 {
1802                                                         // Convert target format ulps to float ulps and allow 64ulp differences
1803                                                         const UVec4 threshold (64u * (UVec4(1u) << (UVec4(23) - tcu::getTextureFormatMantissaBitDepth(format).cast<deUint32>())));
1804
1805                                                         if (!tcu::floatUlpThresholdCompare(m_context.getTestContext().getLog(), name.c_str(), name.c_str(), reference.getAccess(), access, threshold, tcu::COMPARE_LOG_ON_ERROR))
1806                                                                 m_resultCollector.fail("Compare failed for sample " + de::toString(sampleNdx));
1807                                                 }
1808                                                 else
1809                                                 {
1810                                                         // Allow error of 4 times the minimum presentable difference
1811                                                         const Vec4 threshold (4.0f * 1.0f / ((UVec4(1u) << tcu::getTextureFormatMantissaBitDepth(format).cast<deUint32>()) - 1u).cast<float>());
1812
1813                                                         if (!tcu::floatThresholdCompare(m_context.getTestContext().getLog(), name.c_str(), name.c_str(), reference.getAccess(), access, threshold, tcu::COMPARE_LOG_ON_ERROR))
1814                                                                 m_resultCollector.fail("Compare failed for sample " + de::toString(sampleNdx));
1815                                                 }
1816
1817                                                 break;
1818                                         }
1819
1820                                         default:
1821                                                 DE_FATAL("Unknown channel class");
1822                                 }
1823                         }
1824                 }
1825         }
1826
1827         return tcu::TestStatus(m_resultCollector.getResult(), m_resultCollector.getMessage());
1828 }
1829
1830 struct Programs
1831 {
1832         void init (vk::SourceCollections& dst, TestConfig config) const
1833         {
1834                 const tcu::TextureFormat                format                  (mapVkFormat(config.format));
1835                 const tcu::TextureChannelClass  channelClass    (tcu::getTextureChannelClass(format.type));
1836
1837                 dst.glslSources.add("quad-vert") << glu::VertexSource(
1838                         "#version 450\n"
1839                         "out gl_PerVertex {\n"
1840                         "\tvec4 gl_Position;\n"
1841                         "};\n"
1842                         "highp float;\n"
1843                         "void main (void) {\n"
1844                         "\tgl_Position = vec4(((gl_VertexIndex + 2) / 3) % 2 == 0 ? -1.0 : 1.0,\n"
1845                         "\t                   ((gl_VertexIndex + 1) / 3) % 2 == 0 ? -1.0 : 1.0, 0.0, 1.0);\n"
1846                         "}\n");
1847
1848                 if (tcu::hasDepthComponent(format.order))
1849                 {
1850                         const Vec4                      minValue                (0.0f);
1851                         const Vec4                      range                   (1.0f);
1852                         std::ostringstream      fragmentShader;
1853
1854                         fragmentShader <<
1855                                 "#version 450\n"
1856                                 "layout(push_constant) uniform PushConstant {\n"
1857                                 "\thighp uint sampleIndex;\n"
1858                                 "} pushConstants;\n"
1859                                 "void main (void)\n"
1860                                 "{\n"
1861                                 "\thighp uint sampleIndex = pushConstants.sampleIndex;\n"
1862                                 "\tgl_SampleMask[0] = int((~0x0u) << sampleIndex);\n"
1863                                 "\thighp float depth;\n"
1864                                 "\thighp uint x = sampleIndex ^ uint(gl_FragCoord.x);\n"
1865                                 "\thighp uint y = sampleIndex ^ uint(gl_FragCoord.y);\n";
1866
1867                         fragmentShader << "\tdepth = "  << minValue[0] << ";\n";
1868
1869                         {
1870                                 deUint32 divider = 2;
1871
1872                                 // \note Limited to ten bits since the target is 32x32, so there are 10 input bits
1873                                 for (size_t bitNdx = 0; bitNdx < 10; bitNdx++)
1874                                 {
1875                                         fragmentShader <<
1876                                                         "\tdepth += " << (range[0] / (float)divider)
1877                                                         << " * float(bitfieldExtract(" << (bitNdx % 2 == 0 ? "x" : "y") << ", " << (bitNdx / 2) << ", 1));\n";
1878
1879                                         divider *= 2;
1880                                 }
1881                         }
1882
1883                         fragmentShader <<
1884                                 "\tgl_FragDepth = depth;\n"
1885                                 "}\n";
1886
1887                         dst.glslSources.add("quad-frag") << glu::FragmentSource(fragmentShader.str());
1888                 }
1889                 else if (tcu::hasStencilComponent(format.order))
1890                 {
1891                         dst.glslSources.add("quad-frag") << glu::FragmentSource(
1892                                 "#version 450\n"
1893                                 "layout(push_constant) uniform PushConstant {\n"
1894                                 "\thighp uint sampleIndex;\n"
1895                                 "} pushConstants;\n"
1896                                 "void main (void)\n"
1897                                 "{\n"
1898                                 "\thighp uint sampleIndex = pushConstants.sampleIndex;\n"
1899                                 "\tgl_SampleMask[0] = int((~0x0u) << sampleIndex);\n"
1900                                 "}\n");
1901                 }
1902                 else
1903                 {
1904                         switch (channelClass)
1905                         {
1906                                 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
1907                                 {
1908                                         const UVec4     bits            (tcu::getTextureFormatBitDepth(format).cast<deUint32>());
1909                                         const UVec4 minValue    (0);
1910                                         const UVec4 range               (UVec4(1u) << tcu::min(bits, UVec4(31)));
1911                                         std::ostringstream              fragmentShader;
1912
1913                                         fragmentShader <<
1914                                                 "#version 450\n"
1915                                                 "layout(location = 0) out highp uvec4 o_color;\n"
1916                                                 "layout(push_constant) uniform PushConstant {\n"
1917                                                 "\thighp uint sampleIndex;\n"
1918                                                 "} pushConstants;\n"
1919                                                 "void main (void)\n"
1920                                                 "{\n"
1921                                                 "\thighp uint sampleIndex = pushConstants.sampleIndex;\n"
1922                                                 "\tgl_SampleMask[0] = int(0x1u << sampleIndex);\n"
1923                                                 "\thighp uint color[4];\n"
1924                                                 "\thighp uint x = sampleIndex ^ uint(gl_FragCoord.x);\n"
1925                                                 "\thighp uint y = sampleIndex ^ uint(gl_FragCoord.y);\n";
1926
1927                                         for (int ndx = 0; ndx < 4; ndx++)
1928                                                 fragmentShader << "\tcolor[" << ndx << "] = "  << minValue[ndx] << ";\n";
1929
1930                                         {
1931                                                 const int               componentCount  = tcu::getNumUsedChannels(format.order);
1932                                                 const deUint32  bitSize                 (bits[0] + bits[1] + bits[2] + bits[3]);
1933                                                 deUint32                dstBitsUsed[4]  = { 0u, 0u, 0u, 0u };
1934                                                 deUint32                nextSrcBit              = 0;
1935                                                 deUint32                divider                 = 2;
1936
1937                                                 // \note Limited to ten bits since the target is 32x32, so there are 10 input bits
1938                                                 while (nextSrcBit < de::min(bitSize, 10u))
1939                                                 {
1940                                                         for (int compNdx = 0; compNdx < componentCount; compNdx++)
1941                                                         {
1942                                                                 if (dstBitsUsed[compNdx] > bits[compNdx])
1943                                                                         continue;
1944
1945                                                                 fragmentShader <<
1946                                                                                 "\tcolor[" << compNdx << "] += " << (range[compNdx] / divider)
1947                                                                                 << " * bitfieldExtract(" << (nextSrcBit % 2 == 0 ? "x" : "y") << ", " << (nextSrcBit / 2) << ", 1);\n";
1948
1949                                                                 nextSrcBit++;
1950                                                                 dstBitsUsed[compNdx]++;
1951                                                         }
1952
1953                                                         divider *= 2;
1954                                                 }
1955                                         }
1956
1957                                         fragmentShader <<
1958                                                 "\to_color = uvec4(color[0], color[1], color[2], color[3]);\n"
1959                                                 "}\n";
1960
1961                                         dst.glslSources.add("quad-frag") << glu::FragmentSource(fragmentShader.str());
1962                                         break;
1963                                 }
1964
1965                                 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
1966                                 {
1967                                         const UVec4     bits            (tcu::getTextureFormatBitDepth(format).cast<deUint32>());
1968                                         const IVec4 minValue    (0);
1969                                         const IVec4 range               ((UVec4(1u) << tcu::min(bits, UVec4(30))).cast<deInt32>());
1970                                         const IVec4 maxV                ((UVec4(1u) << (bits - UVec4(1u))).cast<deInt32>());
1971                                         const IVec4 clampMax    (maxV - 1);
1972                                         const IVec4 clampMin    (-maxV);
1973                                         std::ostringstream              fragmentShader;
1974
1975                                         fragmentShader <<
1976                                                 "#version 450\n"
1977                                                 "layout(location = 0) out highp ivec4 o_color;\n"
1978                                                 "layout(push_constant) uniform PushConstant {\n"
1979                                                 "\thighp uint sampleIndex;\n"
1980                                                 "} pushConstants;\n"
1981                                                 "void main (void)\n"
1982                                                 "{\n"
1983                                                 "\thighp uint sampleIndex = pushConstants.sampleIndex;\n"
1984                                                 "\tgl_SampleMask[0] = int(0x1u << sampleIndex);\n"
1985                                                 "\thighp int color[4];\n"
1986                                                 "\thighp uint x = sampleIndex ^ uint(gl_FragCoord.x);\n"
1987                                                 "\thighp uint y = sampleIndex ^ uint(gl_FragCoord.y);\n";
1988
1989                                         for (int ndx = 0; ndx < 4; ndx++)
1990                                                 fragmentShader << "\tcolor[" << ndx << "] = "  << minValue[ndx] << ";\n";
1991
1992                                         {
1993                                                 const int               componentCount  = tcu::getNumUsedChannels(format.order);
1994                                                 const deUint32  bitSize                 (bits[0] + bits[1] + bits[2] + bits[3]);
1995                                                 deUint32                dstBitsUsed[4]  = { 0u, 0u, 0u, 0u };
1996                                                 deUint32                nextSrcBit              = 0;
1997                                                 deUint32                divider                 = 2;
1998
1999                                                 // \note Limited to ten bits since the target is 32x32, so there are 10 input bits
2000                                                 while (nextSrcBit < de::min(bitSize, 10u))
2001                                                 {
2002                                                         for (int compNdx = 0; compNdx < componentCount; compNdx++)
2003                                                         {
2004                                                                 if (dstBitsUsed[compNdx] > bits[compNdx])
2005                                                                         continue;
2006
2007                                                                 fragmentShader <<
2008                                                                                 "\tcolor[" << compNdx << "] += " << (range[compNdx] / divider)
2009                                                                                 << " * int(bitfieldExtract(" << (nextSrcBit % 2 == 0 ? "x" : "y") << ", " << (nextSrcBit / 2) << ", 1));\n";
2010
2011                                                                 nextSrcBit++;
2012                                                                 dstBitsUsed[compNdx]++;
2013                                                         }
2014
2015                                                         divider *= 2;
2016                                                 }
2017                                         }
2018
2019                                         // The spec doesn't define whether signed-integers are clamped on output,
2020                                         // so we'll clamp them explicitly to have well-defined outputs.
2021                                         fragmentShader <<
2022                                                 "\to_color = clamp(ivec4(color[0], color[1], color[2], color[3]), " <<
2023                                                 "ivec4" << clampMin << ", ivec4" << clampMax << ");\n" <<
2024                                                 "}\n";
2025
2026                                         dst.glslSources.add("quad-frag") << glu::FragmentSource(fragmentShader.str());
2027                                         break;
2028                                 }
2029
2030                                 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
2031                                 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
2032                                 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
2033                                 {
2034                                         const tcu::TextureFormatInfo    info                    (tcu::getTextureFormatInfo(format));
2035                                         const UVec4                                             bits                    (tcu::getTextureFormatMantissaBitDepth(format).cast<deUint32>());
2036                                         const Vec4                                              minLimit                (-65536.0);
2037                                         const Vec4                                              maxLimit                (65536.0);
2038                                         const Vec4                                              minValue                (tcu::max(info.valueMin, minLimit));
2039                                         const Vec4                                              range                   (tcu::min(info.valueMax, maxLimit) - minValue);
2040                                         std::ostringstream                              fragmentShader;
2041
2042                                         fragmentShader <<
2043                                                 "#version 450\n"
2044                                                 "layout(location = 0) out highp vec4 o_color;\n"
2045                                                 "layout(push_constant) uniform PushConstant {\n"
2046                                                 "\thighp uint sampleIndex;\n"
2047                                                 "} pushConstants;\n"
2048                                                 "void main (void)\n"
2049                                                 "{\n"
2050                                                 "\thighp uint sampleIndex = pushConstants.sampleIndex;\n"
2051                                                 "\tgl_SampleMask[0] = int(0x1u << sampleIndex);\n"
2052                                                 "\thighp float color[4];\n"
2053                                                 "\thighp uint x = sampleIndex ^ uint(gl_FragCoord.x);\n"
2054                                                 "\thighp uint y = sampleIndex ^ uint(gl_FragCoord.y);\n";
2055
2056                                         for (int ndx = 0; ndx < 4; ndx++)
2057                                                 fragmentShader << "\tcolor[" << ndx << "] = "  << minValue[ndx] << ";\n";
2058
2059                                         {
2060                                                 const int               componentCount  = tcu::getNumUsedChannels(format.order);
2061                                                 const deUint32  bitSize                 (bits[0] + bits[1] + bits[2] + bits[3]);
2062                                                 deUint32                dstBitsUsed[4]  = { 0u, 0u, 0u, 0u };
2063                                                 deUint32                nextSrcBit              = 0;
2064                                                 deUint32                divider                 = 2;
2065
2066                                                 // \note Limited to ten bits since the target is 32x32, so there are 10 input bits
2067                                                 while (nextSrcBit < de::min(bitSize, 10u))
2068                                                 {
2069                                                         for (int compNdx = 0; compNdx < componentCount; compNdx++)
2070                                                         {
2071                                                                 if (dstBitsUsed[compNdx] > bits[compNdx])
2072                                                                         continue;
2073
2074                                                                 fragmentShader <<
2075                                                                                 "\tcolor[" << compNdx << "] += " << (range[compNdx] / (float)divider)
2076                                                                                 << " * float(bitfieldExtract(" << (nextSrcBit % 2 == 0 ? "x" : "y") << ", " << (nextSrcBit / 2) << ", 1));\n";
2077
2078                                                                 nextSrcBit++;
2079                                                                 dstBitsUsed[compNdx]++;
2080                                                         }
2081
2082                                                         divider *= 2;
2083                                                 }
2084                                         }
2085
2086                                         fragmentShader <<
2087                                                 "\to_color = vec4(color[0], color[1], color[2], color[3]);\n"
2088                                                 "}\n";
2089
2090                                         dst.glslSources.add("quad-frag") << glu::FragmentSource(fragmentShader.str());
2091                                         break;
2092                                 }
2093
2094                                 default:
2095                                         DE_FATAL("Unknown channel class");
2096                         }
2097                 }
2098
2099                 if (tcu::hasDepthComponent(format.order) || tcu::hasStencilComponent(format.order))
2100                 {
2101                         std::ostringstream splitShader;
2102
2103                         splitShader <<
2104                                 "#version 450\n";
2105
2106                         if (tcu::hasDepthComponent(format.order) && tcu::hasStencilComponent(format.order))
2107                         {
2108                                 splitShader << "layout(input_attachment_index = 0, set = 0, binding = 0) uniform highp subpassInputMS i_depth;\n"
2109                                                         << "layout(input_attachment_index = 0, set = 0, binding = 1) uniform highp usubpassInputMS i_stencil;\n";
2110                         }
2111                         else if (tcu::hasDepthComponent(format.order))
2112                                 splitShader << "layout(input_attachment_index = 0, set = 0, binding = 0) uniform highp subpassInputMS i_depth;\n";
2113                         else if (tcu::hasStencilComponent(format.order))
2114                                 splitShader << "layout(input_attachment_index = 0, set = 0, binding = 0) uniform highp usubpassInputMS i_stencil;\n";
2115
2116                         splitShader <<
2117                                 "layout(push_constant) uniform PushConstant {\n"
2118                                 "\thighp uint splitSubpassIndex;\n"
2119                                 "} pushConstants;\n";
2120
2121                         for (deUint32 attachmentNdx = 0; attachmentNdx < de::min((deUint32)MAX_COLOR_ATTACHMENT_COUNT, config.sampleCount); attachmentNdx++)
2122                         {
2123                                 if (tcu::hasDepthComponent(format.order) && tcu::hasStencilComponent(format.order))
2124                                         splitShader << "layout(location = " << attachmentNdx << ") out highp vec2 o_color" << attachmentNdx << ";\n";
2125                                 else
2126                                         splitShader << "layout(location = " << attachmentNdx << ") out highp float o_color" << attachmentNdx << ";\n";
2127                         }
2128
2129                         splitShader <<
2130                                 "void main (void)\n"
2131                                 "{\n";
2132
2133                         for (deUint32 attachmentNdx = 0; attachmentNdx < de::min((deUint32)MAX_COLOR_ATTACHMENT_COUNT, config.sampleCount); attachmentNdx++)
2134                         {
2135                                 if (tcu::hasDepthComponent(format.order))
2136                                         splitShader << "\thighp float depth" << attachmentNdx << " = subpassLoad(i_depth, int(" << MAX_COLOR_ATTACHMENT_COUNT << " * pushConstants.splitSubpassIndex + " << attachmentNdx << "u)).x;\n";
2137
2138                                 if (tcu::hasStencilComponent(format.order))
2139                                         splitShader << "\thighp uint stencil" << attachmentNdx << " = subpassLoad(i_stencil, int(" << MAX_COLOR_ATTACHMENT_COUNT << " * pushConstants.splitSubpassIndex + " << attachmentNdx << "u)).x;\n";
2140
2141                                 if (tcu::hasDepthComponent(format.order) && tcu::hasStencilComponent(format.order))
2142                                         splitShader << "\to_color" << attachmentNdx << " = vec2(depth" << attachmentNdx << ", float(stencil" << attachmentNdx << "));\n";
2143                                 else if (tcu::hasDepthComponent(format.order))
2144                                         splitShader << "\to_color" << attachmentNdx << " = float(depth" << attachmentNdx << ");\n";
2145                                 else if (tcu::hasStencilComponent(format.order))
2146                                         splitShader << "\to_color" << attachmentNdx << " = float(stencil" << attachmentNdx << ");\n";
2147                         }
2148
2149                         splitShader <<
2150                                 "}\n";
2151
2152                         dst.glslSources.add("quad-split-frag") << glu::FragmentSource(splitShader.str());
2153                 }
2154                 else
2155                 {
2156                         std::string subpassType;
2157                         std::string outputType;
2158
2159                         switch (channelClass)
2160                         {
2161                                 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
2162                                         subpassType     = "usubpassInputMS";
2163                                         outputType      = "uvec4";
2164                                         break;
2165
2166                                 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
2167                                         subpassType     = "isubpassInputMS";
2168                                         outputType      = "ivec4";
2169                                         break;
2170
2171                                 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
2172                                 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
2173                                 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
2174                                         subpassType     = "subpassInputMS";
2175                                         outputType      = "vec4";
2176                                         break;
2177
2178                                 default:
2179                                         DE_FATAL("Unknown channel class");
2180                         }
2181
2182                         std::ostringstream splitShader;
2183                         splitShader <<
2184                                 "#version 450\n"
2185                                 "layout(input_attachment_index = 0, set = 0, binding = 0) uniform highp " << subpassType << " i_color;\n"
2186                                 "layout(push_constant) uniform PushConstant {\n"
2187                                 "\thighp uint splitSubpassIndex;\n"
2188                                 "} pushConstants;\n";
2189
2190                         for (deUint32 attachmentNdx = 0; attachmentNdx < de::min((deUint32)MAX_COLOR_ATTACHMENT_COUNT, config.sampleCount); attachmentNdx++)
2191                                 splitShader << "layout(location = " << attachmentNdx << ") out highp " << outputType << " o_color" << attachmentNdx << ";\n";
2192
2193                         splitShader <<
2194                                 "void main (void)\n"
2195                                 "{\n";
2196
2197                         for (deUint32 attachmentNdx = 0; attachmentNdx < de::min((deUint32)MAX_COLOR_ATTACHMENT_COUNT, config.sampleCount); attachmentNdx++)
2198                                 splitShader << "\to_color" << attachmentNdx << " = subpassLoad(i_color, int(" << MAX_COLOR_ATTACHMENT_COUNT << " * pushConstants.splitSubpassIndex + " << attachmentNdx << "u));\n";
2199
2200                         splitShader <<
2201                                 "}\n";
2202
2203                         dst.glslSources.add("quad-split-frag") << glu::FragmentSource(splitShader.str());
2204                 }
2205         }
2206 };
2207
2208 std::string formatToName (VkFormat format)
2209 {
2210         const std::string       formatStr       = de::toString(format);
2211         const std::string       prefix          = "VK_FORMAT_";
2212
2213         DE_ASSERT(formatStr.substr(0, prefix.length()) == prefix);
2214
2215         return de::toLower(formatStr.substr(prefix.length()));
2216 }
2217
2218 void initTests (tcu::TestCaseGroup* group)
2219 {
2220         static const VkFormat   formats[]       =
2221         {
2222                 VK_FORMAT_R5G6B5_UNORM_PACK16,
2223                 VK_FORMAT_R8_UNORM,
2224                 VK_FORMAT_R8_SNORM,
2225                 VK_FORMAT_R8_UINT,
2226                 VK_FORMAT_R8_SINT,
2227                 VK_FORMAT_R8G8_UNORM,
2228                 VK_FORMAT_R8G8_SNORM,
2229                 VK_FORMAT_R8G8_UINT,
2230                 VK_FORMAT_R8G8_SINT,
2231                 VK_FORMAT_R8G8B8A8_UNORM,
2232                 VK_FORMAT_R8G8B8A8_SNORM,
2233                 VK_FORMAT_R8G8B8A8_UINT,
2234                 VK_FORMAT_R8G8B8A8_SINT,
2235                 VK_FORMAT_R8G8B8A8_SRGB,
2236                 VK_FORMAT_A8B8G8R8_UNORM_PACK32,
2237                 VK_FORMAT_A8B8G8R8_SNORM_PACK32,
2238                 VK_FORMAT_A8B8G8R8_UINT_PACK32,
2239                 VK_FORMAT_A8B8G8R8_SINT_PACK32,
2240                 VK_FORMAT_A8B8G8R8_SRGB_PACK32,
2241                 VK_FORMAT_B8G8R8A8_UNORM,
2242                 VK_FORMAT_B8G8R8A8_SRGB,
2243                 VK_FORMAT_A2R10G10B10_UNORM_PACK32,
2244                 VK_FORMAT_A2B10G10R10_UNORM_PACK32,
2245                 VK_FORMAT_A2B10G10R10_UINT_PACK32,
2246                 VK_FORMAT_R16_UNORM,
2247                 VK_FORMAT_R16_SNORM,
2248                 VK_FORMAT_R16_UINT,
2249                 VK_FORMAT_R16_SINT,
2250                 VK_FORMAT_R16_SFLOAT,
2251                 VK_FORMAT_R16G16_UNORM,
2252                 VK_FORMAT_R16G16_SNORM,
2253                 VK_FORMAT_R16G16_UINT,
2254                 VK_FORMAT_R16G16_SINT,
2255                 VK_FORMAT_R16G16_SFLOAT,
2256                 VK_FORMAT_R16G16B16A16_UNORM,
2257                 VK_FORMAT_R16G16B16A16_SNORM,
2258                 VK_FORMAT_R16G16B16A16_UINT,
2259                 VK_FORMAT_R16G16B16A16_SINT,
2260                 VK_FORMAT_R16G16B16A16_SFLOAT,
2261                 VK_FORMAT_R32_UINT,
2262                 VK_FORMAT_R32_SINT,
2263                 VK_FORMAT_R32_SFLOAT,
2264                 VK_FORMAT_R32G32_UINT,
2265                 VK_FORMAT_R32G32_SINT,
2266                 VK_FORMAT_R32G32_SFLOAT,
2267                 VK_FORMAT_R32G32B32A32_UINT,
2268                 VK_FORMAT_R32G32B32A32_SINT,
2269                 VK_FORMAT_R32G32B32A32_SFLOAT,
2270
2271                 VK_FORMAT_D16_UNORM,
2272                 VK_FORMAT_X8_D24_UNORM_PACK32,
2273                 VK_FORMAT_D32_SFLOAT,
2274                 VK_FORMAT_S8_UINT,
2275                 VK_FORMAT_D16_UNORM_S8_UINT,
2276                 VK_FORMAT_D24_UNORM_S8_UINT,
2277                 VK_FORMAT_D32_SFLOAT_S8_UINT
2278         };
2279         const deUint32                  sampleCounts[] =
2280         {
2281                 2u, 4u, 8u, 16u, 32u
2282         };
2283         tcu::TestContext&               testCtx         (group->getTestContext());
2284
2285         for (size_t formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); formatNdx++)
2286         {
2287                 const VkFormat                                  format          (formats[formatNdx]);
2288                 const std::string                               formatName      (formatToName(format));
2289                 de::MovePtr<tcu::TestCaseGroup> formatGroup     (new tcu::TestCaseGroup(testCtx, formatName.c_str(), formatName.c_str()));
2290
2291                 for (size_t sampleCountNdx = 0; sampleCountNdx < DE_LENGTH_OF_ARRAY(sampleCounts); sampleCountNdx++)
2292                 {
2293                         const deUint32          sampleCount     (sampleCounts[sampleCountNdx]);
2294                         const std::string       testName        ("samples_" + de::toString(sampleCount));
2295
2296                         formatGroup->addChild(new InstanceFactory1<MultisampleRenderPassTestInstance, TestConfig, Programs>(testCtx, tcu::NODETYPE_SELF_VALIDATE, testName.c_str(), testName.c_str(), TestConfig(format, sampleCount)));
2297                 }
2298
2299                 group->addChild(formatGroup.release());
2300         }
2301 }
2302
2303 } // anonymous
2304
2305 tcu::TestCaseGroup* createRenderPassMultisampleTests (tcu::TestContext& testCtx)
2306 {
2307         return createTestGroup(testCtx, "multisample", "Multisample render pass tests", initTests);
2308 }
2309
2310 } // vkt