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