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