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