Clear the stencil attachment if it exists
[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                 // Stencil needs to be cleared if it exists.
1467                 if (tcu::hasStencilComponent(mapVkFormat(m_srcFormat).order))
1468                 {
1469                         const VkClearAttachment clearAttachment =
1470                         {
1471                                 VK_IMAGE_ASPECT_STENCIL_BIT,                                            // VkImageAspectFlags   aspectMask;
1472                                 0,                                                                                                      // deUint32                             colorAttachment;
1473                                 makeClearValueDepthStencil(0, 0)                                        // VkClearValue                 clearValue;
1474                         };
1475
1476                         const VkClearRect clearRect =
1477                         {
1478                                 {
1479                                         { 0u, 0u },
1480                                         { m_width, m_height }
1481                                 },
1482                                 0,                                                                                                      // deUint32     baseArrayLayer;
1483                                 1                                                                                                       // deUint32     layerCount;
1484                         };
1485
1486                         vkd.cmdClearAttachments(*commandBuffer, 1, &clearAttachment, 1, &clearRect);
1487                 }
1488         }
1489
1490         vkd.cmdBindPipeline(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_renderPipeline);
1491
1492         for (deUint32 sampleNdx = 0; sampleNdx < m_sampleCount; sampleNdx++)
1493         {
1494                 vkd.cmdPushConstants(*commandBuffer, *m_renderPipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, 0u, sizeof(sampleNdx), &sampleNdx);
1495                 vkd.cmdDraw(*commandBuffer, 6u, 1u, 0u, 0u);
1496         }
1497
1498         for (deUint32 splitPipelineNdx = 0; splitPipelineNdx < m_splitPipelines.size(); splitPipelineNdx++)
1499         {
1500                 vkd.cmdNextSubpass(*commandBuffer, VK_SUBPASS_CONTENTS_INLINE);
1501
1502                 vkd.cmdBindPipeline(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, **m_splitPipelines[splitPipelineNdx]);
1503                 vkd.cmdBindDescriptorSets(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_splitPipelineLayout, 0u, 1u,  &*m_splitDescriptorSet, 0u, DE_NULL);
1504                 vkd.cmdPushConstants(*commandBuffer, *m_splitPipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, 0u, sizeof(splitPipelineNdx), &splitPipelineNdx);
1505                 vkd.cmdDraw(*commandBuffer, 6u, 1u, 0u, 0u);
1506         }
1507
1508         vkd.cmdEndRenderPass(*commandBuffer);
1509
1510         // Memory barriers between rendering and copies
1511         {
1512                 std::vector<VkImageMemoryBarrier> barriers;
1513
1514                 for (size_t dstNdx = 0; dstNdx < m_dstSinglesampleImages.size(); dstNdx++)
1515                 {
1516                         const VkImageMemoryBarrier barrier =
1517                         {
1518                                 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
1519                                 DE_NULL,
1520
1521                                 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
1522                                 VK_ACCESS_TRANSFER_READ_BIT,
1523
1524                                 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
1525                                 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
1526
1527                                 VK_QUEUE_FAMILY_IGNORED,
1528                                 VK_QUEUE_FAMILY_IGNORED,
1529
1530                                 **m_dstSinglesampleImages[dstNdx],
1531                                 {
1532                                         VK_IMAGE_ASPECT_COLOR_BIT,
1533                                         0u,
1534                                         1u,
1535                                         0u,
1536                                         1u
1537                                 }
1538                         };
1539
1540                         barriers.push_back(barrier);
1541                 }
1542
1543                 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]);
1544         }
1545
1546         // Copy image memory to buffers
1547         for (size_t dstNdx = 0; dstNdx < m_dstSinglesampleImages.size(); dstNdx++)
1548         {
1549                 const VkBufferImageCopy region =
1550                 {
1551                         0u,
1552                         0u,
1553                         0u,
1554                         {
1555                                 VK_IMAGE_ASPECT_COLOR_BIT,
1556                                 0u,
1557                                 0u,
1558                                 1u,
1559                         },
1560                         { 0u, 0u, 0u },
1561                         { m_width, m_height, 1u }
1562                 };
1563
1564                 vkd.cmdCopyImageToBuffer(*commandBuffer, **m_dstSinglesampleImages[dstNdx], VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, **m_dstBuffers[dstNdx], 1u, &region);
1565         }
1566
1567         // Memory barriers between copies and host access
1568         {
1569                 std::vector<VkBufferMemoryBarrier> barriers;
1570
1571                 for (size_t dstNdx = 0; dstNdx < m_dstBuffers.size(); dstNdx++)
1572                 {
1573                         const VkBufferMemoryBarrier barrier =
1574                         {
1575                                 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
1576                                 DE_NULL,
1577
1578                                 VK_ACCESS_TRANSFER_WRITE_BIT,
1579                                 VK_ACCESS_HOST_READ_BIT,
1580
1581                                 VK_QUEUE_FAMILY_IGNORED,
1582                                 VK_QUEUE_FAMILY_IGNORED,
1583
1584                                 **m_dstBuffers[dstNdx],
1585                                 0u,
1586                                 VK_WHOLE_SIZE
1587                         };
1588
1589                         barriers.push_back(barrier);
1590                 }
1591
1592                 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);
1593         }
1594
1595         VK_CHECK(vkd.endCommandBuffer(*commandBuffer));
1596
1597         {
1598                 const VkSubmitInfo submitInfo =
1599                 {
1600                         VK_STRUCTURE_TYPE_SUBMIT_INFO,
1601                         DE_NULL,
1602
1603                         0u,
1604                         DE_NULL,
1605                         DE_NULL,
1606
1607                         1u,
1608                         &*commandBuffer,
1609
1610                         0u,
1611                         DE_NULL
1612                 };
1613
1614                 VK_CHECK(vkd.queueSubmit(m_context.getUniversalQueue(), 1u, &submitInfo, (VkFence)0u));
1615
1616                 VK_CHECK(vkd.queueWaitIdle(m_context.getUniversalQueue()));
1617         }
1618
1619         {
1620                 const tcu::TextureFormat                format                  (mapVkFormat(m_dstFormat));
1621                 const tcu::TextureFormat                srcFormat               (mapVkFormat(m_srcFormat));
1622                 const bool                                              hasDepth                (tcu::hasDepthComponent(srcFormat.order));
1623                 const bool                                              hasStencil              (tcu::hasStencilComponent(srcFormat.order));
1624
1625                 for (deUint32 sampleNdx = 0; sampleNdx < m_sampleCount; sampleNdx++)
1626                 {
1627                         const std::string                                       name            ("Sample" + de::toString(sampleNdx));
1628                         const void* const                                       ptr                     (m_dstBufferMemory[sampleNdx]->getHostPtr());
1629                         const tcu::ConstPixelBufferAccess       access          (format, m_width, m_height, 1, ptr);
1630                         tcu::TextureLevel                                       reference       (format, m_width, m_height);
1631
1632                         if (hasDepth || hasStencil)
1633                         {
1634                                 if (hasDepth)
1635                                 {
1636                                         for (deUint32 y = 0; y < m_height; y++)
1637                                         for (deUint32 x = 0; x < m_width; x++)
1638                                         {
1639                                                 const deUint32  x1                              = x ^ sampleNdx;
1640                                                 const deUint32  y1                              = y ^ sampleNdx;
1641                                                 const float             range                   = 1.0f;
1642                                                 float                   depth                   = 0.0f;
1643                                                 deUint32                divider                 = 2;
1644
1645                                                 // \note Limited to ten bits since the target is 32x32, so there are 10 input bits
1646                                                 for (size_t bitNdx = 0; bitNdx < 10; bitNdx++)
1647                                                 {
1648                                                         depth += (range / (float)divider)
1649                                                                         * (((bitNdx % 2 == 0 ? x1 : y1) & (0x1u << (bitNdx / 2u))) == 0u ? 0u : 1u);
1650                                                         divider *= 2;
1651                                                 }
1652
1653                                                 reference.getAccess().setPixel(Vec4(depth, 0.0f, 0.0f, 0.0f), x, y);
1654                                         }
1655                                 }
1656                                 if (hasStencil)
1657                                 {
1658                                         for (deUint32 y = 0; y < m_height; y++)
1659                                         for (deUint32 x = 0; x < m_width; x++)
1660                                         {
1661                                                 const deUint32  stencil = sampleNdx + 1u;
1662
1663                                                 if (hasDepth)
1664                                                 {
1665                                                         const Vec4 src (reference.getAccess().getPixel(x, y));
1666
1667                                                         reference.getAccess().setPixel(Vec4(src.x(), (float)stencil, 0.0f, 0.0f), x, y);
1668                                                 }
1669                                                 else
1670                                                         reference.getAccess().setPixel(Vec4((float)stencil, 0.0f, 0.0f, 0.0f), x, y);
1671                                         }
1672                                 }
1673                                 {
1674                                         const Vec4 threshold (hasDepth ? (1.0f / 1024.0f) : 0.0f, 0.0f, 0.0f, 0.0f);
1675
1676                                         if (!tcu::floatThresholdCompare(m_context.getTestContext().getLog(), name.c_str(), name.c_str(), reference.getAccess(), access, threshold, tcu::COMPARE_LOG_ON_ERROR))
1677                                                 m_resultCollector.fail("Compare failed for sample " + de::toString(sampleNdx));
1678                                 }
1679                         }
1680                         else
1681                         {
1682                                 const tcu::TextureChannelClass  channelClass    (tcu::getTextureChannelClass(format.type));
1683
1684                                 switch (channelClass)
1685                                 {
1686                                         case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
1687                                         {
1688                                                 const UVec4             bits                    (tcu::getTextureFormatBitDepth(format).cast<deUint32>());
1689                                                 const UVec4             minValue                (0);
1690                                                 const UVec4             range                   (UVec4(1u) << tcu::min(bits, UVec4(31)));
1691                                                 const int               componentCount  (tcu::getNumUsedChannels(format.order));
1692                                                 const deUint32  bitSize                 (bits[0] + bits[1] + bits[2] + bits[3]);
1693
1694                                                 for (deUint32 y = 0; y < m_height; y++)
1695                                                 for (deUint32 x = 0; x < m_width; x++)
1696                                                 {
1697                                                         const deUint32  x1                              = x ^ sampleNdx;
1698                                                         const deUint32  y1                              = y ^ sampleNdx;
1699                                                         UVec4                   color                   (minValue);
1700                                                         deUint32                dstBitsUsed[4]  = { 0u, 0u, 0u, 0u };
1701                                                         deUint32                nextSrcBit              = 0;
1702                                                         deUint32                divider                 = 2;
1703
1704                                                         // \note Limited to ten bits since the target is 32x32, so there are 10 input bits
1705                                                         while (nextSrcBit < de::min(bitSize, 10u))
1706                                                         {
1707                                                                 for (int compNdx = 0; compNdx < componentCount; compNdx++)
1708                                                                 {
1709                                                                         if (dstBitsUsed[compNdx] > bits[compNdx])
1710                                                                                 continue;
1711
1712                                                                         color[compNdx] += (range[compNdx] / divider)
1713                                                                                                         * (((nextSrcBit % 2 == 0 ? x1 : y1) & (0x1u << (nextSrcBit / 2u))) == 0u ? 0u : 1u);
1714
1715                                                                         nextSrcBit++;
1716                                                                         dstBitsUsed[compNdx]++;
1717                                                                 }
1718
1719                                                                 divider *= 2;
1720                                                         }
1721
1722                                                         reference.getAccess().setPixel(color, x, y);
1723                                                 }
1724
1725                                                 if (!tcu::intThresholdCompare(m_context.getTestContext().getLog(), name.c_str(), name.c_str(), reference.getAccess(), access, UVec4(0u), tcu::COMPARE_LOG_ON_ERROR))
1726                                                         m_resultCollector.fail("Compare failed for sample " + de::toString(sampleNdx));
1727
1728                                                 break;
1729                                         }
1730
1731                                         case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
1732                                         {
1733                                                 const UVec4             bits                    (tcu::getTextureFormatBitDepth(format).cast<deUint32>());
1734                                                 const IVec4             minValue                (0);
1735                                                 const IVec4             range                   ((UVec4(1u) << tcu::min(bits, UVec4(30))).cast<deInt32>());
1736                                                 const int               componentCount  (tcu::getNumUsedChannels(format.order));
1737                                                 const deUint32  bitSize                 (bits[0] + bits[1] + bits[2] + bits[3]);
1738
1739                                                 for (deUint32 y = 0; y < m_height; y++)
1740                                                 for (deUint32 x = 0; x < m_width; x++)
1741                                                 {
1742                                                         const deUint32  x1                              = x ^ sampleNdx;
1743                                                         const deUint32  y1                              = y ^ sampleNdx;
1744                                                         IVec4                   color                   (minValue);
1745                                                         deUint32                dstBitsUsed[4]  = { 0u, 0u, 0u, 0u };
1746                                                         deUint32                nextSrcBit              = 0;
1747                                                         deUint32                divider                 = 2;
1748
1749                                                         // \note Limited to ten bits since the target is 32x32, so there are 10 input bits
1750                                                         while (nextSrcBit < de::min(bitSize, 10u))
1751                                                         {
1752                                                                 for (int compNdx = 0; compNdx < componentCount; compNdx++)
1753                                                                 {
1754                                                                         if (dstBitsUsed[compNdx] > bits[compNdx])
1755                                                                                 continue;
1756
1757                                                                         color[compNdx] += (range[compNdx] / divider)
1758                                                                                                         * (((nextSrcBit % 2 == 0 ? x1 : y1) & (0x1u << (nextSrcBit / 2u))) == 0u ? 0u : 1u);
1759
1760                                                                         nextSrcBit++;
1761                                                                         dstBitsUsed[compNdx]++;
1762                                                                 }
1763
1764                                                                 divider *= 2;
1765                                                         }
1766
1767                                                         reference.getAccess().setPixel(color, x, y);
1768                                                 }
1769
1770                                                 if (!tcu::intThresholdCompare(m_context.getTestContext().getLog(), name.c_str(), name.c_str(), reference.getAccess(), access, UVec4(0u), tcu::COMPARE_LOG_ON_ERROR))
1771                                                         m_resultCollector.fail("Compare failed for sample " + de::toString(sampleNdx));
1772
1773                                                 break;
1774                                         }
1775
1776                                         case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
1777                                         case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
1778                                         case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
1779                                         {
1780                                                 const tcu::TextureFormatInfo    info                    (tcu::getTextureFormatInfo(format));
1781                                                 const UVec4                                             bits                    (tcu::getTextureFormatBitDepth(format).cast<deUint32>());
1782                                                 const Vec4                                              minLimit                (-65536.0);
1783                                                 const Vec4                                              maxLimit                (65536.0);
1784                                                 const Vec4                                              minValue                (tcu::max(info.valueMin, minLimit));
1785                                                 const Vec4                                              range                   (tcu::min(info.valueMax, maxLimit) - minValue);
1786                                                 const int                                               componentCount  (tcu::getNumUsedChannels(format.order));
1787                                                 const deUint32                                  bitSize                 (bits[0] + bits[1] + bits[2] + bits[3]);
1788
1789                                                 for (deUint32 y = 0; y < m_height; y++)
1790                                                 for (deUint32 x = 0; x < m_width; x++)
1791                                                 {
1792                                                         const deUint32  x1                              = x ^ sampleNdx;
1793                                                         const deUint32  y1                              = y ^ sampleNdx;
1794                                                         Vec4                    color                   (minValue);
1795                                                         deUint32                dstBitsUsed[4]  = { 0u, 0u, 0u, 0u };
1796                                                         deUint32                nextSrcBit              = 0;
1797                                                         deUint32                divider                 = 2;
1798
1799                                                         // \note Limited to ten bits since the target is 32x32, so there are 10 input bits
1800                                                         while (nextSrcBit < de::min(bitSize, 10u))
1801                                                         {
1802                                                                 for (int compNdx = 0; compNdx < componentCount; compNdx++)
1803                                                                 {
1804                                                                         if (dstBitsUsed[compNdx] > bits[compNdx])
1805                                                                                 continue;
1806
1807                                                                         color[compNdx] += (range[compNdx] / (float)divider)
1808                                                                                                         * (((nextSrcBit % 2 == 0 ? x1 : y1) & (0x1u << (nextSrcBit / 2u))) == 0u ? 0u : 1u);
1809
1810                                                                         nextSrcBit++;
1811                                                                         dstBitsUsed[compNdx]++;
1812                                                                 }
1813
1814                                                                 divider *= 2;
1815                                                         }
1816
1817                                                         if (tcu::isSRGB(format))
1818                                                                 reference.getAccess().setPixel(tcu::linearToSRGB(color), x, y);
1819                                                         else
1820                                                                 reference.getAccess().setPixel(color, x, y);
1821                                                 }
1822
1823                                                 if (channelClass == tcu::TEXTURECHANNELCLASS_FLOATING_POINT)
1824                                                 {
1825                                                         // Convert target format ulps to float ulps and allow 64ulp differences
1826                                                         const UVec4 threshold (64u * (UVec4(1u) << (UVec4(23) - tcu::getTextureFormatMantissaBitDepth(format).cast<deUint32>())));
1827
1828                                                         if (!tcu::floatUlpThresholdCompare(m_context.getTestContext().getLog(), name.c_str(), name.c_str(), reference.getAccess(), access, threshold, tcu::COMPARE_LOG_ON_ERROR))
1829                                                                 m_resultCollector.fail("Compare failed for sample " + de::toString(sampleNdx));
1830                                                 }
1831                                                 else
1832                                                 {
1833                                                         // Allow error of 4 times the minimum presentable difference
1834                                                         const Vec4 threshold (4.0f * 1.0f / ((UVec4(1u) << tcu::getTextureFormatMantissaBitDepth(format).cast<deUint32>()) - 1u).cast<float>());
1835
1836                                                         if (!tcu::floatThresholdCompare(m_context.getTestContext().getLog(), name.c_str(), name.c_str(), reference.getAccess(), access, threshold, tcu::COMPARE_LOG_ON_ERROR))
1837                                                                 m_resultCollector.fail("Compare failed for sample " + de::toString(sampleNdx));
1838                                                 }
1839
1840                                                 break;
1841                                         }
1842
1843                                         default:
1844                                                 DE_FATAL("Unknown channel class");
1845                                 }
1846                         }
1847                 }
1848         }
1849
1850         return tcu::TestStatus(m_resultCollector.getResult(), m_resultCollector.getMessage());
1851 }
1852
1853 struct Programs
1854 {
1855         void init (vk::SourceCollections& dst, TestConfig config) const
1856         {
1857                 const tcu::TextureFormat                format                  (mapVkFormat(config.format));
1858                 const tcu::TextureChannelClass  channelClass    (tcu::getTextureChannelClass(format.type));
1859
1860                 dst.glslSources.add("quad-vert") << glu::VertexSource(
1861                         "#version 450\n"
1862                         "out gl_PerVertex {\n"
1863                         "\tvec4 gl_Position;\n"
1864                         "};\n"
1865                         "highp float;\n"
1866                         "void main (void) {\n"
1867                         "\tgl_Position = vec4(((gl_VertexIndex + 2) / 3) % 2 == 0 ? -1.0 : 1.0,\n"
1868                         "\t                   ((gl_VertexIndex + 1) / 3) % 2 == 0 ? -1.0 : 1.0, 0.0, 1.0);\n"
1869                         "}\n");
1870
1871                 if (tcu::hasDepthComponent(format.order))
1872                 {
1873                         const Vec4                      minValue                (0.0f);
1874                         const Vec4                      range                   (1.0f);
1875                         std::ostringstream      fragmentShader;
1876
1877                         fragmentShader <<
1878                                 "#version 450\n"
1879                                 "layout(push_constant) uniform PushConstant {\n"
1880                                 "\thighp uint sampleIndex;\n"
1881                                 "} pushConstants;\n"
1882                                 "void main (void)\n"
1883                                 "{\n"
1884                                 "\thighp uint sampleIndex = pushConstants.sampleIndex;\n"
1885                                 "\tgl_SampleMask[0] = int((~0x0u) << sampleIndex);\n"
1886                                 "\thighp float depth;\n"
1887                                 "\thighp uint x = sampleIndex ^ uint(gl_FragCoord.x);\n"
1888                                 "\thighp uint y = sampleIndex ^ uint(gl_FragCoord.y);\n";
1889
1890                         fragmentShader << "\tdepth = "  << minValue[0] << ";\n";
1891
1892                         {
1893                                 deUint32 divider = 2;
1894
1895                                 // \note Limited to ten bits since the target is 32x32, so there are 10 input bits
1896                                 for (size_t bitNdx = 0; bitNdx < 10; bitNdx++)
1897                                 {
1898                                         fragmentShader <<
1899                                                         "\tdepth += " << (range[0] / (float)divider)
1900                                                         << " * float(bitfieldExtract(" << (bitNdx % 2 == 0 ? "x" : "y") << ", " << (bitNdx / 2) << ", 1));\n";
1901
1902                                         divider *= 2;
1903                                 }
1904                         }
1905
1906                         fragmentShader <<
1907                                 "\tgl_FragDepth = depth;\n"
1908                                 "}\n";
1909
1910                         dst.glslSources.add("quad-frag") << glu::FragmentSource(fragmentShader.str());
1911                 }
1912                 else if (tcu::hasStencilComponent(format.order))
1913                 {
1914                         dst.glslSources.add("quad-frag") << glu::FragmentSource(
1915                                 "#version 450\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((~0x0u) << sampleIndex);\n"
1923                                 "}\n");
1924                 }
1925                 else
1926                 {
1927                         switch (channelClass)
1928                         {
1929                                 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
1930                                 {
1931                                         const UVec4     bits            (tcu::getTextureFormatBitDepth(format).cast<deUint32>());
1932                                         const UVec4 minValue    (0);
1933                                         const UVec4 range               (UVec4(1u) << tcu::min(bits, UVec4(31)));
1934                                         std::ostringstream              fragmentShader;
1935
1936                                         fragmentShader <<
1937                                                 "#version 450\n"
1938                                                 "layout(location = 0) out highp uvec4 o_color;\n"
1939                                                 "layout(push_constant) uniform PushConstant {\n"
1940                                                 "\thighp uint sampleIndex;\n"
1941                                                 "} pushConstants;\n"
1942                                                 "void main (void)\n"
1943                                                 "{\n"
1944                                                 "\thighp uint sampleIndex = pushConstants.sampleIndex;\n"
1945                                                 "\tgl_SampleMask[0] = int(0x1u << sampleIndex);\n"
1946                                                 "\thighp uint color[4];\n"
1947                                                 "\thighp uint x = sampleIndex ^ uint(gl_FragCoord.x);\n"
1948                                                 "\thighp uint y = sampleIndex ^ uint(gl_FragCoord.y);\n";
1949
1950                                         for (int ndx = 0; ndx < 4; ndx++)
1951                                                 fragmentShader << "\tcolor[" << ndx << "] = "  << minValue[ndx] << ";\n";
1952
1953                                         {
1954                                                 const int               componentCount  = tcu::getNumUsedChannels(format.order);
1955                                                 const deUint32  bitSize                 (bits[0] + bits[1] + bits[2] + bits[3]);
1956                                                 deUint32                dstBitsUsed[4]  = { 0u, 0u, 0u, 0u };
1957                                                 deUint32                nextSrcBit              = 0;
1958                                                 deUint32                divider                 = 2;
1959
1960                                                 // \note Limited to ten bits since the target is 32x32, so there are 10 input bits
1961                                                 while (nextSrcBit < de::min(bitSize, 10u))
1962                                                 {
1963                                                         for (int compNdx = 0; compNdx < componentCount; compNdx++)
1964                                                         {
1965                                                                 if (dstBitsUsed[compNdx] > bits[compNdx])
1966                                                                         continue;
1967
1968                                                                 fragmentShader <<
1969                                                                                 "\tcolor[" << compNdx << "] += " << (range[compNdx] / divider)
1970                                                                                 << " * bitfieldExtract(" << (nextSrcBit % 2 == 0 ? "x" : "y") << ", " << (nextSrcBit / 2) << ", 1);\n";
1971
1972                                                                 nextSrcBit++;
1973                                                                 dstBitsUsed[compNdx]++;
1974                                                         }
1975
1976                                                         divider *= 2;
1977                                                 }
1978                                         }
1979
1980                                         fragmentShader <<
1981                                                 "\to_color = uvec4(color[0], color[1], color[2], color[3]);\n"
1982                                                 "}\n";
1983
1984                                         dst.glslSources.add("quad-frag") << glu::FragmentSource(fragmentShader.str());
1985                                         break;
1986                                 }
1987
1988                                 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
1989                                 {
1990                                         const UVec4     bits            (tcu::getTextureFormatBitDepth(format).cast<deUint32>());
1991                                         const IVec4 minValue    (0);
1992                                         const IVec4 range               ((UVec4(1u) << tcu::min(bits, UVec4(30))).cast<deInt32>());
1993                                         const IVec4 maxV                ((UVec4(1u) << (bits - UVec4(1u))).cast<deInt32>());
1994                                         const IVec4 clampMax    (maxV - 1);
1995                                         const IVec4 clampMin    (-maxV);
1996                                         std::ostringstream              fragmentShader;
1997
1998                                         fragmentShader <<
1999                                                 "#version 450\n"
2000                                                 "layout(location = 0) out highp ivec4 o_color;\n"
2001                                                 "layout(push_constant) uniform PushConstant {\n"
2002                                                 "\thighp uint sampleIndex;\n"
2003                                                 "} pushConstants;\n"
2004                                                 "void main (void)\n"
2005                                                 "{\n"
2006                                                 "\thighp uint sampleIndex = pushConstants.sampleIndex;\n"
2007                                                 "\tgl_SampleMask[0] = int(0x1u << sampleIndex);\n"
2008                                                 "\thighp int color[4];\n"
2009                                                 "\thighp uint x = sampleIndex ^ uint(gl_FragCoord.x);\n"
2010                                                 "\thighp uint y = sampleIndex ^ uint(gl_FragCoord.y);\n";
2011
2012                                         for (int ndx = 0; ndx < 4; ndx++)
2013                                                 fragmentShader << "\tcolor[" << ndx << "] = "  << minValue[ndx] << ";\n";
2014
2015                                         {
2016                                                 const int               componentCount  = tcu::getNumUsedChannels(format.order);
2017                                                 const deUint32  bitSize                 (bits[0] + bits[1] + bits[2] + bits[3]);
2018                                                 deUint32                dstBitsUsed[4]  = { 0u, 0u, 0u, 0u };
2019                                                 deUint32                nextSrcBit              = 0;
2020                                                 deUint32                divider                 = 2;
2021
2022                                                 // \note Limited to ten bits since the target is 32x32, so there are 10 input bits
2023                                                 while (nextSrcBit < de::min(bitSize, 10u))
2024                                                 {
2025                                                         for (int compNdx = 0; compNdx < componentCount; compNdx++)
2026                                                         {
2027                                                                 if (dstBitsUsed[compNdx] > bits[compNdx])
2028                                                                         continue;
2029
2030                                                                 fragmentShader <<
2031                                                                                 "\tcolor[" << compNdx << "] += " << (range[compNdx] / divider)
2032                                                                                 << " * int(bitfieldExtract(" << (nextSrcBit % 2 == 0 ? "x" : "y") << ", " << (nextSrcBit / 2) << ", 1));\n";
2033
2034                                                                 nextSrcBit++;
2035                                                                 dstBitsUsed[compNdx]++;
2036                                                         }
2037
2038                                                         divider *= 2;
2039                                                 }
2040                                         }
2041
2042                                         // The spec doesn't define whether signed-integers are clamped on output,
2043                                         // so we'll clamp them explicitly to have well-defined outputs.
2044                                         fragmentShader <<
2045                                                 "\to_color = clamp(ivec4(color[0], color[1], color[2], color[3]), " <<
2046                                                 "ivec4" << clampMin << ", ivec4" << clampMax << ");\n" <<
2047                                                 "}\n";
2048
2049                                         dst.glslSources.add("quad-frag") << glu::FragmentSource(fragmentShader.str());
2050                                         break;
2051                                 }
2052
2053                                 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
2054                                 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
2055                                 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
2056                                 {
2057                                         const tcu::TextureFormatInfo    info                    (tcu::getTextureFormatInfo(format));
2058                                         const UVec4                                             bits                    (tcu::getTextureFormatMantissaBitDepth(format).cast<deUint32>());
2059                                         const Vec4                                              minLimit                (-65536.0);
2060                                         const Vec4                                              maxLimit                (65536.0);
2061                                         const Vec4                                              minValue                (tcu::max(info.valueMin, minLimit));
2062                                         const Vec4                                              range                   (tcu::min(info.valueMax, maxLimit) - minValue);
2063                                         std::ostringstream                              fragmentShader;
2064
2065                                         fragmentShader <<
2066                                                 "#version 450\n"
2067                                                 "layout(location = 0) out highp vec4 o_color;\n"
2068                                                 "layout(push_constant) uniform PushConstant {\n"
2069                                                 "\thighp uint sampleIndex;\n"
2070                                                 "} pushConstants;\n"
2071                                                 "void main (void)\n"
2072                                                 "{\n"
2073                                                 "\thighp uint sampleIndex = pushConstants.sampleIndex;\n"
2074                                                 "\tgl_SampleMask[0] = int(0x1u << sampleIndex);\n"
2075                                                 "\thighp float color[4];\n"
2076                                                 "\thighp uint x = sampleIndex ^ uint(gl_FragCoord.x);\n"
2077                                                 "\thighp uint y = sampleIndex ^ uint(gl_FragCoord.y);\n";
2078
2079                                         for (int ndx = 0; ndx < 4; ndx++)
2080                                                 fragmentShader << "\tcolor[" << ndx << "] = "  << minValue[ndx] << ";\n";
2081
2082                                         {
2083                                                 const int               componentCount  = tcu::getNumUsedChannels(format.order);
2084                                                 const deUint32  bitSize                 (bits[0] + bits[1] + bits[2] + bits[3]);
2085                                                 deUint32                dstBitsUsed[4]  = { 0u, 0u, 0u, 0u };
2086                                                 deUint32                nextSrcBit              = 0;
2087                                                 deUint32                divider                 = 2;
2088
2089                                                 // \note Limited to ten bits since the target is 32x32, so there are 10 input bits
2090                                                 while (nextSrcBit < de::min(bitSize, 10u))
2091                                                 {
2092                                                         for (int compNdx = 0; compNdx < componentCount; compNdx++)
2093                                                         {
2094                                                                 if (dstBitsUsed[compNdx] > bits[compNdx])
2095                                                                         continue;
2096
2097                                                                 fragmentShader <<
2098                                                                                 "\tcolor[" << compNdx << "] += " << (range[compNdx] / (float)divider)
2099                                                                                 << " * float(bitfieldExtract(" << (nextSrcBit % 2 == 0 ? "x" : "y") << ", " << (nextSrcBit / 2) << ", 1));\n";
2100
2101                                                                 nextSrcBit++;
2102                                                                 dstBitsUsed[compNdx]++;
2103                                                         }
2104
2105                                                         divider *= 2;
2106                                                 }
2107                                         }
2108
2109                                         fragmentShader <<
2110                                                 "\to_color = vec4(color[0], color[1], color[2], color[3]);\n"
2111                                                 "}\n";
2112
2113                                         dst.glslSources.add("quad-frag") << glu::FragmentSource(fragmentShader.str());
2114                                         break;
2115                                 }
2116
2117                                 default:
2118                                         DE_FATAL("Unknown channel class");
2119                         }
2120                 }
2121
2122                 if (tcu::hasDepthComponent(format.order) || tcu::hasStencilComponent(format.order))
2123                 {
2124                         std::ostringstream splitShader;
2125
2126                         splitShader <<
2127                                 "#version 450\n";
2128
2129                         if (tcu::hasDepthComponent(format.order) && tcu::hasStencilComponent(format.order))
2130                         {
2131                                 splitShader << "layout(input_attachment_index = 0, set = 0, binding = 0) uniform highp subpassInputMS i_depth;\n"
2132                                                         << "layout(input_attachment_index = 0, set = 0, binding = 1) uniform highp usubpassInputMS i_stencil;\n";
2133                         }
2134                         else if (tcu::hasDepthComponent(format.order))
2135                                 splitShader << "layout(input_attachment_index = 0, set = 0, binding = 0) uniform highp subpassInputMS i_depth;\n";
2136                         else if (tcu::hasStencilComponent(format.order))
2137                                 splitShader << "layout(input_attachment_index = 0, set = 0, binding = 0) uniform highp usubpassInputMS i_stencil;\n";
2138
2139                         splitShader <<
2140                                 "layout(push_constant) uniform PushConstant {\n"
2141                                 "\thighp uint splitSubpassIndex;\n"
2142                                 "} pushConstants;\n";
2143
2144                         for (deUint32 attachmentNdx = 0; attachmentNdx < de::min((deUint32)MAX_COLOR_ATTACHMENT_COUNT, config.sampleCount); attachmentNdx++)
2145                         {
2146                                 if (tcu::hasDepthComponent(format.order) && tcu::hasStencilComponent(format.order))
2147                                         splitShader << "layout(location = " << attachmentNdx << ") out highp vec2 o_color" << attachmentNdx << ";\n";
2148                                 else
2149                                         splitShader << "layout(location = " << attachmentNdx << ") out highp float o_color" << attachmentNdx << ";\n";
2150                         }
2151
2152                         splitShader <<
2153                                 "void main (void)\n"
2154                                 "{\n";
2155
2156                         for (deUint32 attachmentNdx = 0; attachmentNdx < de::min((deUint32)MAX_COLOR_ATTACHMENT_COUNT, config.sampleCount); attachmentNdx++)
2157                         {
2158                                 if (tcu::hasDepthComponent(format.order))
2159                                         splitShader << "\thighp float depth" << attachmentNdx << " = subpassLoad(i_depth, int(" << MAX_COLOR_ATTACHMENT_COUNT << " * pushConstants.splitSubpassIndex + " << attachmentNdx << "u)).x;\n";
2160
2161                                 if (tcu::hasStencilComponent(format.order))
2162                                         splitShader << "\thighp uint stencil" << attachmentNdx << " = subpassLoad(i_stencil, int(" << MAX_COLOR_ATTACHMENT_COUNT << " * pushConstants.splitSubpassIndex + " << attachmentNdx << "u)).x;\n";
2163
2164                                 if (tcu::hasDepthComponent(format.order) && tcu::hasStencilComponent(format.order))
2165                                         splitShader << "\to_color" << attachmentNdx << " = vec2(depth" << attachmentNdx << ", float(stencil" << attachmentNdx << "));\n";
2166                                 else if (tcu::hasDepthComponent(format.order))
2167                                         splitShader << "\to_color" << attachmentNdx << " = float(depth" << attachmentNdx << ");\n";
2168                                 else if (tcu::hasStencilComponent(format.order))
2169                                         splitShader << "\to_color" << attachmentNdx << " = float(stencil" << attachmentNdx << ");\n";
2170                         }
2171
2172                         splitShader <<
2173                                 "}\n";
2174
2175                         dst.glslSources.add("quad-split-frag") << glu::FragmentSource(splitShader.str());
2176                 }
2177                 else
2178                 {
2179                         std::string subpassType;
2180                         std::string outputType;
2181
2182                         switch (channelClass)
2183                         {
2184                                 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
2185                                         subpassType     = "usubpassInputMS";
2186                                         outputType      = "uvec4";
2187                                         break;
2188
2189                                 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
2190                                         subpassType     = "isubpassInputMS";
2191                                         outputType      = "ivec4";
2192                                         break;
2193
2194                                 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
2195                                 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
2196                                 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
2197                                         subpassType     = "subpassInputMS";
2198                                         outputType      = "vec4";
2199                                         break;
2200
2201                                 default:
2202                                         DE_FATAL("Unknown channel class");
2203                         }
2204
2205                         std::ostringstream splitShader;
2206                         splitShader <<
2207                                 "#version 450\n"
2208                                 "layout(input_attachment_index = 0, set = 0, binding = 0) uniform highp " << subpassType << " i_color;\n"
2209                                 "layout(push_constant) uniform PushConstant {\n"
2210                                 "\thighp uint splitSubpassIndex;\n"
2211                                 "} pushConstants;\n";
2212
2213                         for (deUint32 attachmentNdx = 0; attachmentNdx < de::min((deUint32)MAX_COLOR_ATTACHMENT_COUNT, config.sampleCount); attachmentNdx++)
2214                                 splitShader << "layout(location = " << attachmentNdx << ") out highp " << outputType << " o_color" << attachmentNdx << ";\n";
2215
2216                         splitShader <<
2217                                 "void main (void)\n"
2218                                 "{\n";
2219
2220                         for (deUint32 attachmentNdx = 0; attachmentNdx < de::min((deUint32)MAX_COLOR_ATTACHMENT_COUNT, config.sampleCount); attachmentNdx++)
2221                                 splitShader << "\to_color" << attachmentNdx << " = subpassLoad(i_color, int(" << MAX_COLOR_ATTACHMENT_COUNT << " * pushConstants.splitSubpassIndex + " << attachmentNdx << "u));\n";
2222
2223                         splitShader <<
2224                                 "}\n";
2225
2226                         dst.glslSources.add("quad-split-frag") << glu::FragmentSource(splitShader.str());
2227                 }
2228         }
2229 };
2230
2231 std::string formatToName (VkFormat format)
2232 {
2233         const std::string       formatStr       = de::toString(format);
2234         const std::string       prefix          = "VK_FORMAT_";
2235
2236         DE_ASSERT(formatStr.substr(0, prefix.length()) == prefix);
2237
2238         return de::toLower(formatStr.substr(prefix.length()));
2239 }
2240
2241 void initTests (tcu::TestCaseGroup* group)
2242 {
2243         static const VkFormat   formats[]       =
2244         {
2245                 VK_FORMAT_R5G6B5_UNORM_PACK16,
2246                 VK_FORMAT_R8_UNORM,
2247                 VK_FORMAT_R8_SNORM,
2248                 VK_FORMAT_R8_UINT,
2249                 VK_FORMAT_R8_SINT,
2250                 VK_FORMAT_R8G8_UNORM,
2251                 VK_FORMAT_R8G8_SNORM,
2252                 VK_FORMAT_R8G8_UINT,
2253                 VK_FORMAT_R8G8_SINT,
2254                 VK_FORMAT_R8G8B8A8_UNORM,
2255                 VK_FORMAT_R8G8B8A8_SNORM,
2256                 VK_FORMAT_R8G8B8A8_UINT,
2257                 VK_FORMAT_R8G8B8A8_SINT,
2258                 VK_FORMAT_R8G8B8A8_SRGB,
2259                 VK_FORMAT_A8B8G8R8_UNORM_PACK32,
2260                 VK_FORMAT_A8B8G8R8_SNORM_PACK32,
2261                 VK_FORMAT_A8B8G8R8_UINT_PACK32,
2262                 VK_FORMAT_A8B8G8R8_SINT_PACK32,
2263                 VK_FORMAT_A8B8G8R8_SRGB_PACK32,
2264                 VK_FORMAT_B8G8R8A8_UNORM,
2265                 VK_FORMAT_B8G8R8A8_SRGB,
2266                 VK_FORMAT_A2R10G10B10_UNORM_PACK32,
2267                 VK_FORMAT_A2B10G10R10_UNORM_PACK32,
2268                 VK_FORMAT_A2B10G10R10_UINT_PACK32,
2269                 VK_FORMAT_R16_UNORM,
2270                 VK_FORMAT_R16_SNORM,
2271                 VK_FORMAT_R16_UINT,
2272                 VK_FORMAT_R16_SINT,
2273                 VK_FORMAT_R16_SFLOAT,
2274                 VK_FORMAT_R16G16_UNORM,
2275                 VK_FORMAT_R16G16_SNORM,
2276                 VK_FORMAT_R16G16_UINT,
2277                 VK_FORMAT_R16G16_SINT,
2278                 VK_FORMAT_R16G16_SFLOAT,
2279                 VK_FORMAT_R16G16B16A16_UNORM,
2280                 VK_FORMAT_R16G16B16A16_SNORM,
2281                 VK_FORMAT_R16G16B16A16_UINT,
2282                 VK_FORMAT_R16G16B16A16_SINT,
2283                 VK_FORMAT_R16G16B16A16_SFLOAT,
2284                 VK_FORMAT_R32_UINT,
2285                 VK_FORMAT_R32_SINT,
2286                 VK_FORMAT_R32_SFLOAT,
2287                 VK_FORMAT_R32G32_UINT,
2288                 VK_FORMAT_R32G32_SINT,
2289                 VK_FORMAT_R32G32_SFLOAT,
2290                 VK_FORMAT_R32G32B32A32_UINT,
2291                 VK_FORMAT_R32G32B32A32_SINT,
2292                 VK_FORMAT_R32G32B32A32_SFLOAT,
2293
2294                 VK_FORMAT_D16_UNORM,
2295                 VK_FORMAT_X8_D24_UNORM_PACK32,
2296                 VK_FORMAT_D32_SFLOAT,
2297                 VK_FORMAT_S8_UINT,
2298                 VK_FORMAT_D16_UNORM_S8_UINT,
2299                 VK_FORMAT_D24_UNORM_S8_UINT,
2300                 VK_FORMAT_D32_SFLOAT_S8_UINT
2301         };
2302         const deUint32                  sampleCounts[] =
2303         {
2304                 2u, 4u, 8u, 16u, 32u
2305         };
2306         tcu::TestContext&               testCtx         (group->getTestContext());
2307
2308         for (size_t formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); formatNdx++)
2309         {
2310                 const VkFormat                                  format          (formats[formatNdx]);
2311                 const std::string                               formatName      (formatToName(format));
2312                 de::MovePtr<tcu::TestCaseGroup> formatGroup     (new tcu::TestCaseGroup(testCtx, formatName.c_str(), formatName.c_str()));
2313
2314                 for (size_t sampleCountNdx = 0; sampleCountNdx < DE_LENGTH_OF_ARRAY(sampleCounts); sampleCountNdx++)
2315                 {
2316                         const deUint32          sampleCount     (sampleCounts[sampleCountNdx]);
2317                         const std::string       testName        ("samples_" + de::toString(sampleCount));
2318
2319                         formatGroup->addChild(new InstanceFactory1<MultisampleRenderPassTestInstance, TestConfig, Programs>(testCtx, tcu::NODETYPE_SELF_VALIDATE, testName.c_str(), testName.c_str(), TestConfig(format, sampleCount)));
2320                 }
2321
2322                 group->addChild(formatGroup.release());
2323         }
2324 }
2325
2326 } // anonymous
2327
2328 tcu::TestCaseGroup* createRenderPassMultisampleTests (tcu::TestContext& testCtx)
2329 {
2330         return createTestGroup(testCtx, "multisample", "Multisample render pass tests", initTests);
2331 }
2332
2333 } // vkt