• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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::__anon0c42d1a50111::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     for (size_t dstNdx = 0; dstNdx < m_singlesampleImages.size(); dstNdx++)
803     {
804         // assume that buffer(s) have enough memory to store desired amount of mipmaps
805         copyImageToBuffer(vkd, *commandBuffer, **m_singlesampleImages[dstNdx], **m_buffers[dstNdx], m_format,
806                           tcu::IVec2((1u << m_renderLevel) * m_width, (1u << m_renderLevel) * m_height), m_renderLevel,
807                           VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, totalLayers());
808     }
809 
810     endCommandBuffer(vkd, *commandBuffer);
811 
812     submitCommandsAndWait(vkd, device, m_context.getUniversalQueue(), *commandBuffer);
813 
814     for (size_t memoryBufferNdx = 0; memoryBufferNdx < m_bufferMemory.size(); memoryBufferNdx++)
815         invalidateMappedMemoryRange(vkd, device, m_bufferMemory[memoryBufferNdx]->getMemory(), 0u, VK_WHOLE_SIZE);
816 }
817 
submitDynamicRendering(void)818 void MultisampleRenderPassTestInstance::submitDynamicRendering(void)
819 {
820 #ifndef CTS_USES_VULKANSC
821 
822     const DeviceInterface &vkd(m_context.getDeviceInterface());
823     const VkDevice device(m_context.getDevice());
824     const Unique<VkCommandBuffer> cmdBuffer(
825         allocateCommandBuffer(vkd, device, *m_commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
826     Move<VkCommandBuffer> secCmdBuffer;
827 
828     // Memory barriers between previous copies and rendering
829     std::vector<VkImageMemoryBarrier> singlesampleImageBarriers(
830         m_singlesampleImages.size(), {VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
831                                       DE_NULL,
832 
833                                       VK_ACCESS_TRANSFER_READ_BIT,
834                                       VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
835 
836                                       VK_IMAGE_LAYOUT_UNDEFINED,
837                                       VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
838 
839                                       VK_QUEUE_FAMILY_IGNORED,
840                                       VK_QUEUE_FAMILY_IGNORED,
841 
842                                       DE_NULL,
843                                       {VK_IMAGE_ASPECT_COLOR_BIT, m_renderLevel, 1u, 0u, totalLayers()}});
844     for (size_t dstNdx = 0; dstNdx < m_singlesampleImages.size(); dstNdx++)
845         singlesampleImageBarriers[dstNdx].image = **m_singlesampleImages[dstNdx];
846 
847     // Memory barriers to set multisample image layout to COLOR_ATTACHMENT_OPTIMAL
848     std::vector<VkImageMemoryBarrier> multisampleImageBarriers(m_multisampleImages.size(),
849                                                                {VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
850                                                                 DE_NULL,
851 
852                                                                 0,
853                                                                 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
854 
855                                                                 VK_IMAGE_LAYOUT_UNDEFINED,
856                                                                 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
857 
858                                                                 VK_QUEUE_FAMILY_IGNORED,
859                                                                 VK_QUEUE_FAMILY_IGNORED,
860 
861                                                                 DE_NULL,
862                                                                 {VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, m_layerCount}});
863     for (size_t dstNdx = 0; dstNdx < m_multisampleImages.size(); dstNdx++)
864         multisampleImageBarriers[dstNdx].image = **m_multisampleImages[dstNdx];
865 
866     VkRect2D renderArea           = makeRect2D(m_width, m_height);
867     const VkClearValue clearValue = makeClearValueColor({0.0f, 0.0f, 0.0f, 1.0f});
868     std::vector<vk::VkRenderingAttachmentInfoKHR> colorAttachments(
869         m_attachmentsCount,
870         {
871             vk::VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR, // VkStructureType sType;
872             DE_NULL,                                             // const void* pNext;
873             DE_NULL,                                             // VkImageView imageView;
874             vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,        // VkImageLayout imageLayout;
875             vk::VK_RESOLVE_MODE_NONE,                            // VkResolveModeFlagBits resolveMode;
876             DE_NULL,                                             // VkImageView resolveImageView;
877             vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,        // VkImageLayout resolveImageLayout;
878             vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE,                 // VkAttachmentLoadOp loadOp;
879             vk::VK_ATTACHMENT_STORE_OP_DONT_CARE,                // VkAttachmentStoreOp storeOp;
880             clearValue                                           // VkClearValue clearValue;
881         });
882 
883     for (uint32_t i = 0; i < m_attachmentsCount; ++i)
884     {
885         colorAttachments[i].imageView        = **m_multisampleImageViews[i];
886         colorAttachments[i].resolveImageView = **m_singlesampleImageViews[i];
887         if (isIntFormat(m_format) || isUintFormat(m_format))
888             colorAttachments[i].resolveMode = vk::VK_RESOLVE_MODE_SAMPLE_ZERO_BIT;
889         else
890             colorAttachments[i].resolveMode = vk::VK_RESOLVE_MODE_AVERAGE_BIT;
891     }
892 
893     vk::VkRenderingInfoKHR renderingInfo{
894         vk::VK_STRUCTURE_TYPE_RENDERING_INFO_KHR,
895         DE_NULL,
896         0,                       // VkRenderingFlagsKHR flags;
897         renderArea,              // VkRect2D renderArea;
898         m_layerCount,            // uint32_t layerCount;
899         0u,                      // uint32_t viewMask;
900         m_attachmentsCount,      // uint32_t colorAttachmentCount;
901         colorAttachments.data(), // const VkRenderingAttachmentInfoKHR* pColorAttachments;
902         DE_NULL,                 // const VkRenderingAttachmentInfoKHR* pDepthAttachment;
903         DE_NULL,                 // const VkRenderingAttachmentInfoKHR* pStencilAttachment;
904     };
905 
906     if (m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
907     {
908         secCmdBuffer = allocateCommandBuffer(vkd, device, *m_commandPool, VK_COMMAND_BUFFER_LEVEL_SECONDARY);
909 
910         // record secondary command buffer
911         beginSecondaryCmdBuffer(*secCmdBuffer);
912         vkd.cmdBeginRendering(*secCmdBuffer, &renderingInfo);
913         drawCommands(*secCmdBuffer, *m_renderPipeline, *m_renderPipelineLayout);
914         vkd.cmdEndRendering(*secCmdBuffer);
915 
916         endCommandBuffer(vkd, *secCmdBuffer);
917 
918         // record primary command buffer
919         beginCommandBuffer(vkd, *cmdBuffer);
920 
921         vkd.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT,
922                                VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL,
923                                (uint32_t)singlesampleImageBarriers.size(), &singlesampleImageBarriers[0]);
924         vkd.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
925                                VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL,
926                                (uint32_t)multisampleImageBarriers.size(), &multisampleImageBarriers[0]);
927 
928         vkd.cmdExecuteCommands(*cmdBuffer, 1u, &*secCmdBuffer);
929     }
930     else
931     {
932         beginCommandBuffer(vkd, *cmdBuffer);
933 
934         vkd.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT,
935                                VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL,
936                                (uint32_t)singlesampleImageBarriers.size(), &singlesampleImageBarriers[0]);
937         vkd.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
938                                VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL,
939                                (uint32_t)multisampleImageBarriers.size(), &multisampleImageBarriers[0]);
940 
941         vkd.cmdBeginRendering(*cmdBuffer, &renderingInfo);
942         drawCommands(*cmdBuffer, *m_renderPipeline, *m_renderPipelineLayout);
943         vkd.cmdEndRendering(*cmdBuffer);
944     }
945 
946     // Memory barriers to set single-sample image layout to TRANSFER_SRC_OPTIMAL
947     {
948         std::vector<VkImageMemoryBarrier> barriers;
949 
950         for (size_t dstNdx = 0; dstNdx < m_singlesampleImages.size(); dstNdx++)
951         {
952             const VkImageMemoryBarrier barrier = {VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
953                                                   DE_NULL,
954 
955                                                   VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
956                                                   VK_ACCESS_TRANSFER_READ_BIT,
957 
958                                                   VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
959                                                   VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
960 
961                                                   VK_QUEUE_FAMILY_IGNORED,
962                                                   VK_QUEUE_FAMILY_IGNORED,
963 
964                                                   **m_singlesampleImages[dstNdx],
965                                                   {VK_IMAGE_ASPECT_COLOR_BIT, m_renderLevel, 1u, 0u, totalLayers()}};
966 
967             barriers.push_back(barrier);
968         }
969 
970         vkd.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
971                                VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, (uint32_t)barriers.size(),
972                                &barriers[0]);
973     }
974 
975     for (size_t dstNdx = 0; dstNdx < m_singlesampleImages.size(); dstNdx++)
976     {
977         // assume that buffer(s) have enough memory to store desired amount of mipmaps
978         copyImageToBuffer(vkd, *cmdBuffer, **m_singlesampleImages[dstNdx], **m_buffers[dstNdx], m_format,
979                           tcu::IVec2((1u << m_renderLevel) * m_width, (1u << m_renderLevel) * m_height), m_renderLevel,
980                           VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, totalLayers());
981     }
982 
983     endCommandBuffer(vkd, *cmdBuffer);
984 
985     submitCommandsAndWait(vkd, device, m_context.getUniversalQueue(), *cmdBuffer);
986 
987     for (size_t memoryBufferNdx = 0; memoryBufferNdx < m_bufferMemory.size(); memoryBufferNdx++)
988         invalidateMappedMemoryRange(vkd, device, m_bufferMemory[memoryBufferNdx]->getMemory(), 0u, VK_WHOLE_SIZE);
989 
990 #endif // CTS_USES_VULKANSC
991 }
992 
submitSwitch(const SharedGroupParams groupParams)993 void MultisampleRenderPassTestInstance::submitSwitch(const SharedGroupParams groupParams)
994 {
995     switch (groupParams->renderingType)
996     {
997     case RENDERING_TYPE_RENDERPASS_LEGACY:
998         submit<RenderpassSubpass1>();
999         break;
1000     case RENDERING_TYPE_RENDERPASS2:
1001         submit<RenderpassSubpass2>();
1002         break;
1003     case RENDERING_TYPE_DYNAMIC_RENDERING:
1004         submitDynamicRendering();
1005         break;
1006     default:
1007         TCU_THROW(InternalError, "Impossible");
1008     }
1009 }
1010 
verify(void)1011 void MultisampleRenderPassTestInstance::verify(void)
1012 {
1013     const Vec4 errorColor(1.0f, 0.0f, 0.0f, 1.0f);
1014     const Vec4 okColor(0.0f, 1.0f, 0.0f, 1.0f);
1015     const tcu::TextureFormat format(mapVkFormat(m_format));
1016     const tcu::TextureChannelClass channelClass(tcu::getTextureChannelClass(format.type));
1017 
1018     uint32_t offset(0u);
1019     uint32_t width((1u << m_renderLevel) * m_width);
1020     uint32_t height((1u << m_renderLevel) * m_height);
1021     uint32_t pixelSize(static_cast<uint32_t>(getPixelSize()));
1022     for (uint32_t level = 0; level < m_renderLevel; ++level)
1023     {
1024         offset += (width * height * pixelSize);
1025         height /= 2;
1026         width /= 2;
1027     }
1028 
1029     std::vector<tcu::ConstPixelBufferAccess> accesses;
1030     for (uint32_t attachmentIdx = 0; attachmentIdx < m_attachmentsCount; ++attachmentIdx)
1031     {
1032         void *const ptr = static_cast<uint8_t *>(m_bufferMemory[attachmentIdx]->getHostPtr()) + offset;
1033         accesses.push_back(tcu::ConstPixelBufferAccess(format, m_width, m_height, totalLayers(), ptr));
1034     }
1035 
1036     tcu::TextureLevel errorMask(tcu::TextureFormat(tcu::TextureFormat::RGB, tcu::TextureFormat::UNORM_INT8), m_width,
1037                                 m_height, totalLayers());
1038     tcu::TestLog &log(m_context.getTestContext().getLog());
1039 
1040     switch (channelClass)
1041     {
1042     case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
1043     case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
1044     case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
1045     {
1046         const bool isAlphaOnly = isAlphaOnlyFormat(m_format);
1047         const int componentCount(isAlphaOnly ? 4 : tcu::getNumUsedChannels(format.order));
1048         bool isOk = true;
1049         float clearValue;
1050         float renderValue;
1051 
1052         switch (channelClass)
1053         {
1054         case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
1055         case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
1056             clearValue  = -1.0f;
1057             renderValue = 1.0f;
1058             break;
1059 
1060         case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
1061             clearValue  = 0.0f;
1062             renderValue = 1.0f;
1063             break;
1064 
1065         default:
1066             clearValue  = 0.0f;
1067             renderValue = 0.0f;
1068             DE_FATAL("Unknown channel class");
1069         }
1070 
1071         for (uint32_t z = m_baseLayer; z < totalLayers(); z++)
1072             for (uint32_t y = 0; y < m_height; y++)
1073                 for (uint32_t x = 0; x < m_width; x++)
1074                 {
1075                     // Color has to be black if no samples were covered, white if all samples were covered or same in every attachment
1076                     const Vec4 firstColor(accesses[0].getPixel(x, y, z));
1077                     const Vec4 refColor(m_sampleMask == 0x0u ?
1078                                             Vec4((isAlphaOnly ? 0.0f : clearValue),
1079                                                  componentCount > 1 && !isAlphaOnly ? clearValue : 0.0f,
1080                                                  componentCount > 2 && !isAlphaOnly ? clearValue : 0.0f,
1081                                                  componentCount > 3 ? clearValue : 1.0f) :
1082                                         m_sampleMask == ((0x1u << m_sampleCount) - 1u) ?
1083                                             Vec4((isAlphaOnly ? 0.0f : renderValue),
1084                                                  componentCount > 1 && !isAlphaOnly ? renderValue : 0.0f,
1085                                                  componentCount > 2 && !isAlphaOnly ? renderValue : 0.0f,
1086                                                  componentCount > 3 ? renderValue : 1.0f) :
1087                                             firstColor);
1088 
1089                     errorMask.getAccess().setPixel(okColor, x, y, z);
1090 
1091                     for (size_t attachmentNdx = 0; attachmentNdx < m_attachmentsCount; attachmentNdx++)
1092                     {
1093                         const Vec4 color(accesses[attachmentNdx].getPixel(x, y, z));
1094 
1095                         if (refColor != color)
1096                         {
1097                             isOk = false;
1098                             errorMask.getAccess().setPixel(errorColor, x, y, z);
1099                             break;
1100                         }
1101                     }
1102 
1103                     {
1104                         const Vec4 old = m_sum.getAccess().getPixel(x, y, z);
1105                         m_sum.getAccess().setPixel(
1106                             old + (tcu::isSRGB(format) ? tcu::sRGBToLinear(firstColor) : firstColor), x, y, z);
1107 
1108                         const Vec4 oldSrgb = m_sumSrgb.getAccess().getPixel(x, y, z);
1109                         m_sumSrgb.getAccess().setPixel(oldSrgb + firstColor, x, y, z);
1110                     }
1111                 }
1112 
1113         if (!isOk)
1114         {
1115             const std::string sectionName("ResolveVerifyWithMask" + de::toString(m_sampleMask));
1116             const tcu::ScopedLogSection section(log, sectionName, sectionName);
1117 
1118             for (size_t attachmentNdx = 0; attachmentNdx < m_attachmentsCount; attachmentNdx++)
1119                 logImage(std::string("Attachment") + de::toString(attachmentNdx), accesses[attachmentNdx]);
1120 
1121             logImage("ErrorMask", errorMask.getAccess());
1122 
1123             if (m_sampleMask == 0x0u)
1124             {
1125                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Empty sample mask didn't produce all "
1126                                                     << clearValue << " pixels" << tcu::TestLog::EndMessage;
1127                 m_resultCollector.fail("Empty sample mask didn't produce correct pixel values");
1128             }
1129             else if (m_sampleMask == ((0x1u << m_sampleCount) - 1u))
1130             {
1131                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Full sample mask didn't produce all "
1132                                                     << renderValue << " pixels" << tcu::TestLog::EndMessage;
1133                 m_resultCollector.fail("Full sample mask didn't produce correct pixel values");
1134             }
1135             else
1136             {
1137                 m_context.getTestContext().getLog()
1138                     << tcu::TestLog::Message << "Resolve is inconsistent between attachments"
1139                     << tcu::TestLog::EndMessage;
1140                 m_resultCollector.fail("Resolve is inconsistent between attachments");
1141             }
1142         }
1143         break;
1144     }
1145 
1146     case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
1147     {
1148         const int componentCount(tcu::getNumUsedChannels(format.order));
1149         const UVec4 bitDepth(tcu::getTextureFormatBitDepth(format).cast<uint32_t>());
1150         const UVec4 renderValue(tcu::select((UVec4(1u) << tcu::min(UVec4(8u), bitDepth)) - UVec4(1u),
1151                                             UVec4(0u, 0u, 0u, 1u),
1152                                             tcu::lessThan(IVec4(0, 1, 2, 3), IVec4(componentCount))));
1153         const UVec4 clearValue(
1154             tcu::select(UVec4(0u), UVec4(0u, 0u, 0u, 1u), tcu::lessThan(IVec4(0, 1, 2, 3), IVec4(componentCount))));
1155         bool unexpectedValues        = false;
1156         bool inconsistentComponents  = false;
1157         bool inconsistentAttachments = false;
1158 
1159         for (uint32_t z = m_baseLayer; z < totalLayers(); z++)
1160             for (uint32_t y = 0; y < m_height; y++)
1161                 for (uint32_t x = 0; x < m_width; x++)
1162                 {
1163                     // Color has to be all zeros if no samples were covered, all 255 if all samples were covered or consistent across all attachments
1164                     const UVec4 refColor(m_sampleMask == 0x0u ? clearValue :
1165                                          m_sampleMask == ((0x1u << m_sampleCount) - 1u) ?
1166                                                                 renderValue :
1167                                                                 accesses[0].getPixelUint(x, y, z));
1168                     bool isOk = true;
1169 
1170                     // If reference value was taken from first attachment, check that it is valid value i.e. clear or render value
1171                     if (m_sampleMask != 0x0u && m_sampleMask != ((0x1u << m_sampleCount) - 1u))
1172                     {
1173                         // Each component must be resolved same way
1174                         const BVec4 isRenderValue(refColor == renderValue);
1175                         const BVec4 isClearValue(refColor == clearValue);
1176                         const bool unexpectedValue(
1177                             tcu::anyNotEqual(tcu::logicalOr(isRenderValue, isClearValue), BVec4(true)));
1178                         const bool inconsistentComponent(
1179                             !(tcu::allEqual(isRenderValue, BVec4(true)) || tcu::allEqual(isClearValue, BVec4(true))));
1180 
1181                         unexpectedValues |= unexpectedValue;
1182                         inconsistentComponents |= inconsistentComponent;
1183 
1184                         if (unexpectedValue || inconsistentComponent)
1185                             isOk = false;
1186                     }
1187 
1188                     for (size_t attachmentNdx = 0; attachmentNdx < m_attachmentsCount; attachmentNdx++)
1189                     {
1190                         const UVec4 color(accesses[attachmentNdx].getPixelUint(x, y, z));
1191 
1192                         if (refColor != color)
1193                         {
1194                             isOk                    = false;
1195                             inconsistentAttachments = true;
1196                             break;
1197                         }
1198                     }
1199 
1200                     errorMask.getAccess().setPixel((isOk ? okColor : errorColor), x, y, z);
1201                 }
1202 
1203         if (unexpectedValues || inconsistentComponents || inconsistentAttachments)
1204         {
1205             const std::string sectionName("ResolveVerifyWithMask" + de::toString(m_sampleMask));
1206             const tcu::ScopedLogSection section(log, sectionName, sectionName);
1207 
1208             for (size_t attachmentNdx = 0; attachmentNdx < m_attachmentsCount; attachmentNdx++)
1209                 logImage(std::string("Attachment") + de::toString(attachmentNdx), accesses[attachmentNdx]);
1210 
1211             logImage("ErrorMask", errorMask.getAccess());
1212 
1213             if (m_sampleMask == 0x0u)
1214             {
1215                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Empty sample mask didn't produce all "
1216                                                     << clearValue << " pixels" << tcu::TestLog::EndMessage;
1217                 m_resultCollector.fail("Empty sample mask didn't produce correct pixels");
1218             }
1219             else if (m_sampleMask == ((0x1u << m_sampleCount) - 1u))
1220             {
1221                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Full sample mask didn't produce all "
1222                                                     << renderValue << " pixels" << tcu::TestLog::EndMessage;
1223                 m_resultCollector.fail("Full sample mask didn't produce correct pixels");
1224             }
1225             else
1226             {
1227                 if (unexpectedValues)
1228                 {
1229                     m_context.getTestContext().getLog()
1230                         << tcu::TestLog::Message << "Resolve produced unexpected values i.e. not " << clearValue
1231                         << " or " << renderValue << tcu::TestLog::EndMessage;
1232                     m_resultCollector.fail("Resolve produced unexpected values");
1233                 }
1234 
1235                 if (inconsistentComponents)
1236                 {
1237                     m_context.getTestContext().getLog()
1238                         << tcu::TestLog::Message
1239                         << "Different components of attachment were resolved to different values."
1240                         << tcu::TestLog::EndMessage;
1241                     m_resultCollector.fail("Different components of attachment were resolved to different values.");
1242                 }
1243 
1244                 if (inconsistentAttachments)
1245                 {
1246                     m_context.getTestContext().getLog()
1247                         << tcu::TestLog::Message << "Different attachments were resolved to different values."
1248                         << tcu::TestLog::EndMessage;
1249                     m_resultCollector.fail("Different attachments were resolved to different values.");
1250                 }
1251             }
1252         }
1253         break;
1254     }
1255 
1256     case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
1257     {
1258         const int componentCount(tcu::getNumUsedChannels(format.order));
1259         const IVec4 bitDepth(tcu::getTextureFormatBitDepth(format));
1260         const IVec4 renderValue(tcu::select((IVec4(1) << (tcu::min(IVec4(8), bitDepth) - IVec4(1))) - IVec4(1),
1261                                             IVec4(0, 0, 0, 1),
1262                                             tcu::lessThan(IVec4(0, 1, 2, 3), IVec4(componentCount))));
1263         const IVec4 clearValue(tcu::select(-(IVec4(1) << (tcu::min(IVec4(8), bitDepth) - IVec4(1))), IVec4(0, 0, 0, 1),
1264                                            tcu::lessThan(IVec4(0, 1, 2, 3), IVec4(componentCount))));
1265         bool unexpectedValues        = false;
1266         bool inconsistentComponents  = false;
1267         bool inconsistentAttachments = false;
1268 
1269         for (uint32_t z = m_baseLayer; z < totalLayers(); z++)
1270             for (uint32_t y = 0; y < m_height; y++)
1271                 for (uint32_t x = 0; x < m_width; x++)
1272                 {
1273                     // Color has to be all zeros if no samples were covered, all 255 if all samples were covered or consistent across all attachments
1274                     const IVec4 refColor(m_sampleMask == 0x0u ? clearValue :
1275                                          m_sampleMask == ((0x1u << m_sampleCount) - 1u) ?
1276                                                                 renderValue :
1277                                                                 accesses[0].getPixelInt(x, y, z));
1278                     bool isOk = true;
1279 
1280                     // If reference value was taken from first attachment, check that it is valid value i.e. clear or render value
1281                     if (m_sampleMask != 0x0u && m_sampleMask != ((0x1u << m_sampleCount) - 1u))
1282                     {
1283                         // Each component must be resolved same way
1284                         const BVec4 isRenderValue(refColor == renderValue);
1285                         const BVec4 isClearValue(refColor == clearValue);
1286                         const bool unexpectedValue(
1287                             tcu::anyNotEqual(tcu::logicalOr(isRenderValue, isClearValue), BVec4(true)));
1288                         const bool inconsistentComponent(
1289                             !(tcu::allEqual(isRenderValue, BVec4(true)) || tcu::allEqual(isClearValue, BVec4(true))));
1290 
1291                         unexpectedValues |= unexpectedValue;
1292                         inconsistentComponents |= inconsistentComponent;
1293 
1294                         if (unexpectedValue || inconsistentComponent)
1295                             isOk = false;
1296                     }
1297 
1298                     for (size_t attachmentNdx = 0; attachmentNdx < m_attachmentsCount; attachmentNdx++)
1299                     {
1300                         const IVec4 color(accesses[attachmentNdx].getPixelInt(x, y, z));
1301 
1302                         if (refColor != color)
1303                         {
1304                             isOk                    = false;
1305                             inconsistentAttachments = true;
1306                             break;
1307                         }
1308                     }
1309 
1310                     errorMask.getAccess().setPixel((isOk ? okColor : errorColor), x, y, z);
1311                 }
1312 
1313         if (unexpectedValues || inconsistentComponents || inconsistentAttachments)
1314         {
1315             const std::string sectionName("ResolveVerifyWithMask" + de::toString(m_sampleMask));
1316             const tcu::ScopedLogSection section(log, sectionName, sectionName);
1317 
1318             for (size_t attachmentNdx = 0; attachmentNdx < m_attachmentsCount; attachmentNdx++)
1319                 logImage(std::string("Attachment") + de::toString(attachmentNdx), accesses[attachmentNdx]);
1320 
1321             logImage("ErrorMask", errorMask.getAccess());
1322 
1323             if (m_sampleMask == 0x0u)
1324             {
1325                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Empty sample mask didn't produce all "
1326                                                     << clearValue << " pixels" << tcu::TestLog::EndMessage;
1327                 m_resultCollector.fail("Empty sample mask didn't produce correct pixels");
1328             }
1329             else if (m_sampleMask == ((0x1u << m_sampleCount) - 1u))
1330             {
1331                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Full sample mask didn't produce all "
1332                                                     << renderValue << " pixels" << tcu::TestLog::EndMessage;
1333                 m_resultCollector.fail("Full sample mask didn't produce correct pixels");
1334             }
1335             else
1336             {
1337                 if (unexpectedValues)
1338                 {
1339                     m_context.getTestContext().getLog()
1340                         << tcu::TestLog::Message << "Resolve produced unexpected values i.e. not " << clearValue
1341                         << " or " << renderValue << tcu::TestLog::EndMessage;
1342                     m_resultCollector.fail("Resolve produced unexpected values");
1343                 }
1344 
1345                 if (inconsistentComponents)
1346                 {
1347                     m_context.getTestContext().getLog()
1348                         << tcu::TestLog::Message
1349                         << "Different components of attachment were resolved to different values."
1350                         << tcu::TestLog::EndMessage;
1351                     m_resultCollector.fail("Different components of attachment were resolved to different values.");
1352                 }
1353 
1354                 if (inconsistentAttachments)
1355                 {
1356                     m_context.getTestContext().getLog()
1357                         << tcu::TestLog::Message << "Different attachments were resolved to different values."
1358                         << tcu::TestLog::EndMessage;
1359                     m_resultCollector.fail("Different attachments were resolved to different values.");
1360                 }
1361             }
1362         }
1363         break;
1364     }
1365 
1366     default:
1367         DE_FATAL("Unknown channel class");
1368     }
1369 }
1370 
iterate(void)1371 tcu::TestStatus MultisampleRenderPassTestInstance::iterate(void)
1372 {
1373     if (m_sampleMask == 0u)
1374     {
1375         const tcu::TextureFormat format(mapVkFormat(m_format));
1376         const tcu::TextureChannelClass channelClass(tcu::getTextureChannelClass(format.type));
1377         tcu::TestLog &log(m_context.getTestContext().getLog());
1378 
1379         switch (channelClass)
1380         {
1381         case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
1382             log << TestLog::Message
1383                 << "Clearing target to zero and rendering 255 pixels with every possible sample mask"
1384                 << TestLog::EndMessage;
1385             break;
1386 
1387         case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
1388             log << TestLog::Message
1389                 << "Clearing target to -128 and rendering 127 pixels with every possible sample mask"
1390                 << TestLog::EndMessage;
1391             break;
1392 
1393         case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
1394         case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
1395         case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
1396             log << TestLog::Message
1397                 << "Clearing target to black and rendering white pixels with every possible sample mask"
1398                 << TestLog::EndMessage;
1399             break;
1400 
1401         default:
1402             DE_FATAL("Unknown channel class");
1403         }
1404     }
1405 
1406     submitSwitch(m_groupParams);
1407     verify();
1408 
1409     if (m_sampleMask == ((0x1u << m_sampleCount) - 1u))
1410     {
1411         const tcu::TextureFormat format(mapVkFormat(m_format));
1412         const tcu::TextureChannelClass channelClass(tcu::getTextureChannelClass(format.type));
1413         const Vec4 threshold(getFormatThreshold());
1414         tcu::TestLog &log(m_context.getTestContext().getLog());
1415 
1416         if (channelClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT ||
1417             channelClass == tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT ||
1418             channelClass == tcu::TEXTURECHANNELCLASS_FLOATING_POINT)
1419         {
1420             const bool isAlphaOnly = isAlphaOnlyFormat(m_format);
1421             const int componentCount(isAlphaOnly ? 4 : tcu::getNumUsedChannels(format.order));
1422             const Vec4 errorColor(1.0f, 0.0f, 0.0f, 1.0f);
1423             const Vec4 okColor(0.0f, 1.0f, 0.0f, 1.0f);
1424             tcu::TextureLevel errorMask(tcu::TextureFormat(tcu::TextureFormat::RGB, tcu::TextureFormat::UNORM_INT8),
1425                                         m_width, m_height, totalLayers());
1426             bool isOk = true;
1427             Vec4 maxDiff(0.0f);
1428             Vec4 expectedAverage;
1429 
1430             switch (channelClass)
1431             {
1432             case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
1433             {
1434                 expectedAverage =
1435                     Vec4((isAlphaOnly ? 0.0f : 0.5f), componentCount > 1 && !isAlphaOnly ? 0.5f : 0.0f,
1436                          componentCount > 2 && !isAlphaOnly ? 0.5f : 0.0f, componentCount > 3 ? 0.5f : 1.0f);
1437                 break;
1438             }
1439 
1440             case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
1441             case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
1442             {
1443                 expectedAverage = Vec4(0.0f, 0.0f, 0.0f, componentCount > 3 ? 0.0f : 1.0f);
1444                 break;
1445             }
1446 
1447             default:
1448                 DE_FATAL("Unknown channel class");
1449             }
1450 
1451             for (uint32_t z = m_baseLayer; z < totalLayers(); z++)
1452                 for (uint32_t y = 0; y < m_height; y++)
1453                     for (uint32_t x = 0; x < m_width; x++)
1454                     {
1455                         const Vec4 sum(m_sum.getAccess().getPixel(x, y, z));
1456                         const Vec4 average(sum / Vec4((float)(0x1u << m_sampleCount)));
1457                         const Vec4 diff(tcu::abs(average - expectedAverage));
1458 
1459                         m_sum.getAccess().setPixel(average, x, y, z);
1460                         errorMask.getAccess().setPixel(okColor, x, y, z);
1461 
1462                         bool failThreshold;
1463 
1464                         if (!tcu::isSRGB(format))
1465                         {
1466                             failThreshold = (diff[0] > threshold.x() || diff[1] > threshold.y() ||
1467                                              diff[2] > threshold.z() || diff[3] > threshold.w());
1468                         }
1469                         else
1470                         {
1471                             const Vec4 sumSrgb(m_sumSrgb.getAccess().getPixel(x, y, z));
1472                             const Vec4 averageSrgb(sumSrgb / Vec4((float)(0x1u << m_sampleCount)));
1473                             const Vec4 diffSrgb(tcu::abs(averageSrgb - expectedAverage));
1474 
1475                             m_sumSrgb.getAccess().setPixel(averageSrgb, x, y, z);
1476 
1477                             // Spec doesn't restrict implementation to downsample in linear color space. So, comparing both non linear and
1478                             // linear diff's in case of srgb formats.
1479                             failThreshold = ((diff[0] > threshold.x() || diff[1] > threshold.y() ||
1480                                               diff[2] > threshold.z() || diff[3] > threshold.w()) &&
1481                                              (diffSrgb[0] > threshold.x() || diffSrgb[1] > threshold.y() ||
1482                                               diffSrgb[2] > threshold.z() || diffSrgb[3] > threshold.w()));
1483                         }
1484 
1485                         if (failThreshold)
1486                         {
1487                             isOk    = false;
1488                             maxDiff = tcu::max(maxDiff, diff);
1489                             errorMask.getAccess().setPixel(errorColor, x, y, z);
1490                         }
1491                     }
1492 
1493             log << TestLog::Image("Average resolved values in attachment 0", "Average resolved values in attachment 0",
1494                                   m_sum);
1495 
1496             if (!isOk)
1497             {
1498                 std::stringstream message;
1499 
1500                 m_context.getTestContext().getLog() << tcu::LogImage("ErrorMask", "ErrorMask", errorMask.getAccess());
1501 
1502                 message << "Average resolved values differ from expected average values by more than ";
1503 
1504                 switch (componentCount)
1505                 {
1506                 case 1:
1507                     message << threshold.x();
1508                     break;
1509                 case 2:
1510                     message << "vec2" << Vec2(threshold.x(), threshold.y());
1511                     break;
1512                 case 3:
1513                     message << "vec3" << Vec3(threshold.x(), threshold.y(), threshold.z());
1514                     break;
1515                 default:
1516                     message << "vec4" << threshold;
1517                 }
1518 
1519                 message << ". Max diff " << maxDiff;
1520                 log << TestLog::Message << message.str() << TestLog::EndMessage;
1521 
1522                 m_resultCollector.fail("Average resolved values differ from expected average values");
1523             }
1524         }
1525 
1526         return tcu::TestStatus(m_resultCollector.getResult(), m_resultCollector.getMessage());
1527     }
1528     else
1529     {
1530         m_sampleMask++;
1531         return tcu::TestStatus::incomplete();
1532     }
1533 }
1534 
1535 template <typename RenderPassTrait>
createRenderPass(bool usedResolveAttachment)1536 Move<VkRenderPass> MultisampleRenderPassTestInstance::createRenderPass(bool usedResolveAttachment)
1537 {
1538     // make name for RenderPass1Trait or RenderPass2Trait shorter
1539     typedef RenderPassTrait RPT;
1540     typedef typename RPT::AttDesc AttDesc;
1541     typedef typename RPT::AttRef AttRef;
1542     typedef typename RPT::SubpassDesc SubpassDesc;
1543     typedef typename RPT::RenderPassCreateInfo RenderPassCreateInfo;
1544 
1545     const DeviceInterface &vkd = m_context.getDeviceInterface();
1546     VkDevice device            = m_context.getDevice();
1547     std::vector<AttDesc> attachments;
1548     std::vector<AttRef> colorAttachmentRefs;
1549     std::vector<AttRef> resolveAttachmentRefs;
1550 
1551     for (size_t attachmentNdx = 0; attachmentNdx < m_attachmentsCount; attachmentNdx++)
1552     {
1553         {
1554             const AttDesc multisampleAttachment(
1555                 // sType
1556                 DE_NULL,                                 // pNext
1557                 0u,                                      // flags
1558                 m_format,                                // format
1559                 m_sampleCount,                           // samples
1560                 VK_ATTACHMENT_LOAD_OP_DONT_CARE,         // loadOp
1561                 VK_ATTACHMENT_STORE_OP_DONT_CARE,        // storeOp
1562                 VK_ATTACHMENT_LOAD_OP_DONT_CARE,         // stencilLoadOp
1563                 VK_ATTACHMENT_STORE_OP_DONT_CARE,        // stencilStoreOp
1564                 VK_IMAGE_LAYOUT_UNDEFINED,               // initialLayout
1565                 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // finalLayout
1566             );
1567             const AttRef attachmentRef(
1568                 // sType
1569                 DE_NULL,                                  // pNext
1570                 (uint32_t)attachments.size(),             // attachment
1571                 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // layout
1572                 0u                                        // aspectMask
1573             );
1574             colorAttachmentRefs.push_back(attachmentRef);
1575             attachments.push_back(multisampleAttachment);
1576         }
1577         {
1578             const AttDesc singlesampleAttachment(
1579                 // sType
1580                 DE_NULL,                             // pNext
1581                 0u,                                  // flags
1582                 m_format,                            // format
1583                 VK_SAMPLE_COUNT_1_BIT,               // samples
1584                 VK_ATTACHMENT_LOAD_OP_DONT_CARE,     // loadOp
1585                 VK_ATTACHMENT_STORE_OP_STORE,        // storeOp
1586                 VK_ATTACHMENT_LOAD_OP_DONT_CARE,     // stencilLoadOp
1587                 VK_ATTACHMENT_STORE_OP_DONT_CARE,    // stencilStoreOp
1588                 VK_IMAGE_LAYOUT_UNDEFINED,           // initialLayout
1589                 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL // finalLayout
1590             );
1591             const auto attachmentId =
1592                 (usedResolveAttachment ? static_cast<uint32_t>(attachments.size()) : VK_ATTACHMENT_UNUSED);
1593             const AttRef attachmentRef(
1594                 // sType
1595                 DE_NULL,                                  // pNext
1596                 attachmentId,                             // attachment
1597                 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // layout
1598                 0u                                        // aspectMask
1599             );
1600             resolveAttachmentRefs.push_back(attachmentRef);
1601             attachments.push_back(singlesampleAttachment);
1602         }
1603     }
1604 
1605     DE_ASSERT(colorAttachmentRefs.size() == resolveAttachmentRefs.size());
1606     DE_ASSERT(attachments.size() == colorAttachmentRefs.size() + resolveAttachmentRefs.size());
1607 
1608     const SubpassDesc subpass(
1609         // sType
1610         DE_NULL,                              // pNext
1611         (VkSubpassDescriptionFlags)0,         // flags
1612         VK_PIPELINE_BIND_POINT_GRAPHICS,      // pipelineBindPoint
1613         0u,                                   // viewMask
1614         0u,                                   // inputAttachmentCount
1615         DE_NULL,                              // pInputAttachments
1616         (uint32_t)colorAttachmentRefs.size(), // colorAttachmentCount
1617         &colorAttachmentRefs[0],              // pColorAttachments
1618         &resolveAttachmentRefs[0],            // pResolveAttachments
1619         DE_NULL,                              // pDepthStencilAttachment
1620         0u,                                   // preserveAttachmentCount
1621         DE_NULL                               // pPreserveAttachments
1622     );
1623     const RenderPassCreateInfo renderPassCreator(
1624         // sType
1625         DE_NULL,                      // pNext
1626         (VkRenderPassCreateFlags)0u,  // flags
1627         (uint32_t)attachments.size(), // attachmentCount
1628         &attachments[0],              // pAttachments
1629         1u,                           // subpassCount
1630         &subpass,                     // pSubpasses
1631         0u,                           // dependencyCount
1632         DE_NULL,                      // pDependencies
1633         0u,                           // correlatedViewMaskCount
1634         DE_NULL                       // pCorrelatedViewMasks
1635     );
1636 
1637     return renderPassCreator.createRenderPass(vkd, device);
1638 }
1639 
createRenderPassSwitch(bool usedResolveAttachment)1640 Move<VkRenderPass> MultisampleRenderPassTestInstance::createRenderPassSwitch(bool usedResolveAttachment)
1641 {
1642     switch (m_groupParams->renderingType)
1643     {
1644     case RENDERING_TYPE_RENDERPASS_LEGACY:
1645         return createRenderPass<RenderPass1Trait>(usedResolveAttachment);
1646     case RENDERING_TYPE_RENDERPASS2:
1647         return createRenderPass<RenderPass2Trait>(usedResolveAttachment);
1648     case RENDERING_TYPE_DYNAMIC_RENDERING:
1649         return Move<VkRenderPass>();
1650     default:
1651         TCU_THROW(InternalError, "Impossible");
1652     }
1653 }
1654 
createRenderPassCompatible(void)1655 Move<VkRenderPass> MultisampleRenderPassTestInstance::createRenderPassCompatible(void)
1656 {
1657     if (m_testCompatibility)
1658     {
1659         // The compatible render pass is always created with a used resolve attachment.
1660         return createRenderPassSwitch(true);
1661     }
1662     else
1663     {
1664         return {};
1665     }
1666 }
1667 
createRenderPipelineLayout(void)1668 Move<VkPipelineLayout> MultisampleRenderPassTestInstance::createRenderPipelineLayout(void)
1669 {
1670     const DeviceInterface &vkd = m_context.getDeviceInterface();
1671     VkDevice device            = m_context.getDevice();
1672 
1673     const VkPushConstantRange pushConstant      = {VK_SHADER_STAGE_FRAGMENT_BIT, 0u, 4u};
1674     const VkPipelineLayoutCreateInfo createInfo = {VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
1675                                                    DE_NULL,
1676                                                    (vk::VkPipelineLayoutCreateFlags)0,
1677 
1678                                                    0u,
1679                                                    DE_NULL,
1680 
1681                                                    1u,
1682                                                    &pushConstant};
1683 
1684     return createPipelineLayout(vkd, device, &createInfo);
1685 }
1686 
createRenderPipeline(void)1687 Move<VkPipeline> MultisampleRenderPassTestInstance::createRenderPipeline(void)
1688 {
1689     const DeviceInterface &vkd                   = m_context.getDeviceInterface();
1690     VkDevice device                              = m_context.getDevice();
1691     const vk::BinaryCollection &binaryCollection = m_context.getBinaryCollection();
1692     const Unique<VkShaderModule> vertexShaderModule(
1693         createShaderModule(vkd, device, binaryCollection.get("quad-vert"), 0u));
1694     const Unique<VkShaderModule> fragmentShaderModule(
1695         createShaderModule(vkd, device, binaryCollection.get("quad-frag"), 0u));
1696     const Move<VkShaderModule> geometryShaderModule(
1697         m_layerCount == 1 ? Move<VkShaderModule>() : createShaderModule(vkd, device, binaryCollection.get("geom"), 0u));
1698     // Disable blending
1699     const VkPipelineColorBlendAttachmentState attachmentBlendState{
1700         VK_FALSE,
1701         VK_BLEND_FACTOR_SRC_ALPHA,
1702         VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,
1703         VK_BLEND_OP_ADD,
1704         VK_BLEND_FACTOR_ONE,
1705         VK_BLEND_FACTOR_ONE,
1706         VK_BLEND_OP_ADD,
1707         VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT};
1708     std::vector<VkPipelineColorBlendAttachmentState> attachmentBlendStates(m_attachmentsCount, attachmentBlendState);
1709     const VkPipelineVertexInputStateCreateInfo vertexInputState = {
1710         VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
1711         DE_NULL,
1712         (VkPipelineVertexInputStateCreateFlags)0u,
1713 
1714         0u,
1715         DE_NULL,
1716 
1717         0u,
1718         DE_NULL};
1719     const tcu::UVec2 renderArea(m_width, m_height);
1720     const std::vector<VkViewport> viewports(1, makeViewport(renderArea));
1721     const std::vector<VkRect2D> scissors(1, makeRect2D(renderArea));
1722 
1723     const VkPipelineMultisampleStateCreateInfo multisampleState = {
1724         VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
1725         DE_NULL,
1726         (VkPipelineMultisampleStateCreateFlags)0u,
1727 
1728         sampleCountBitFromSampleCount(m_sampleCount),
1729         VK_FALSE,
1730         0.0f,
1731         DE_NULL,
1732         VK_FALSE,
1733         VK_FALSE,
1734     };
1735     const VkPipelineDepthStencilStateCreateInfo depthStencilState = {
1736         VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
1737         DE_NULL,
1738         (VkPipelineDepthStencilStateCreateFlags)0u,
1739 
1740         VK_FALSE,
1741         VK_TRUE,
1742         VK_COMPARE_OP_ALWAYS,
1743         VK_FALSE,
1744         VK_TRUE,
1745         {VK_STENCIL_OP_KEEP, VK_STENCIL_OP_INCREMENT_AND_WRAP, VK_STENCIL_OP_KEEP, VK_COMPARE_OP_ALWAYS, ~0u, ~0u,
1746          0xFFu / (m_sampleCount + 1)},
1747         {VK_STENCIL_OP_KEEP, VK_STENCIL_OP_INCREMENT_AND_WRAP, VK_STENCIL_OP_KEEP, VK_COMPARE_OP_ALWAYS, ~0u, ~0u,
1748          0xFFu / (m_sampleCount + 1)},
1749 
1750         0.0f,
1751         1.0f};
1752     const VkPipelineColorBlendStateCreateInfo blendState = {VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
1753                                                             DE_NULL,
1754                                                             (VkPipelineColorBlendStateCreateFlags)0u,
1755 
1756                                                             VK_FALSE,
1757                                                             VK_LOGIC_OP_COPY,
1758                                                             uint32_t(attachmentBlendStates.size()),
1759                                                             &attachmentBlendStates[0],
1760                                                             {0.0f, 0.0f, 0.0f, 0.0f}};
1761 
1762     void *pNext = DE_NULL;
1763 
1764 #ifndef CTS_USES_VULKANSC
1765     std::vector<VkFormat> attachmentFormats(m_attachmentsCount, m_format);
1766     VkPipelineRenderingCreateInfoKHR renderingCreateInfo{VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR,
1767                                                          DE_NULL,
1768                                                          0u,
1769                                                          m_attachmentsCount,
1770                                                          attachmentFormats.data(),
1771                                                          VK_FORMAT_UNDEFINED,
1772                                                          VK_FORMAT_UNDEFINED};
1773     if (m_groupParams->renderingType == RENDERING_TYPE_DYNAMIC_RENDERING)
1774         pNext = &renderingCreateInfo;
1775 #endif // CTS_USES_VULKANSC
1776 
1777     return makeGraphicsPipeline(
1778         vkd,                     // const DeviceInterface&                        vk
1779         device,                  // const VkDevice                                device
1780         *m_renderPipelineLayout, // const VkPipelineLayout                        pipelineLayout
1781         *vertexShaderModule,     // const VkShaderModule                          vertexShaderModule
1782         DE_NULL,                 // const VkShaderModule                          tessellationControlShaderModule
1783         DE_NULL,                 // const VkShaderModule                          tessellationEvalShaderModule
1784         m_layerCount != 1 ? *geometryShaderModule :
1785                             DE_NULL,         // const VkShaderModule                          geometryShaderModule
1786         *fragmentShaderModule,               // const VkShaderModule                          fragmentShaderModule
1787         *m_renderPass,                       // const VkRenderPass                            renderPass
1788         viewports,                           // const std::vector<VkViewport>&                viewports
1789         scissors,                            // const std::vector<VkRect2D>&                  scissors
1790         VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, // const VkPrimitiveTopology                     topology
1791         0u,                                  // const uint32_t                                subpass
1792         0u,                                  // const uint32_t                                patchControlPoints
1793         &vertexInputState,                   // const VkPipelineVertexInputStateCreateInfo*   vertexInputStateCreateInfo
1794         DE_NULL,            // const VkPipelineRasterizationStateCreateInfo* rasterizationStateCreateInfo
1795         &multisampleState,  // const VkPipelineMultisampleStateCreateInfo*   multisampleStateCreateInfo
1796         &depthStencilState, // const VkPipelineDepthStencilStateCreateInfo*  depthStencilStateCreateInfo
1797         &blendState,        // const VkPipelineColorBlendStateCreateInfo*    colorBlendStateCreateInfo
1798         DE_NULL,            // const VkPipelineDynamicStateCreateInfo*       dynamicStateCreateInfo
1799         pNext);             // const void*                                   pNext
1800 }
1801 
1802 #ifndef CTS_USES_VULKANSC
beginSecondaryCmdBuffer(VkCommandBuffer cmdBuffer) const1803 void MultisampleRenderPassTestInstance::beginSecondaryCmdBuffer(VkCommandBuffer cmdBuffer) const
1804 {
1805     const DeviceInterface &vkd = m_context.getDeviceInterface();
1806     std::vector<VkFormat> formats(m_attachmentsCount, m_format);
1807 
1808     VkCommandBufferInheritanceRenderingInfoKHR inheritanceRenderingInfo{
1809         VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_RENDERING_INFO_KHR, // VkStructureType sType;
1810         DE_NULL,                                                         // const void* pNext;
1811         0u,                                                              // VkRenderingFlagsKHR flags;
1812         0u,                                                              // uint32_t viewMask;
1813         m_attachmentsCount,                                              // uint32_t colorAttachmentCount;
1814         formats.data(),                                                  // const VkFormat* pColorAttachmentFormats;
1815         VK_FORMAT_UNDEFINED,                                             // VkFormat depthAttachmentFormat;
1816         VK_FORMAT_UNDEFINED,                                             // VkFormat stencilAttachmentFormat;
1817         m_sampleCount,                                                   // VkSampleCountFlagBits rasterizationSamples;
1818     };
1819 
1820     const VkCommandBufferInheritanceInfo bufferInheritanceInfo = initVulkanStructure(&inheritanceRenderingInfo);
1821     VkCommandBufferUsageFlags usageFlags                       = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
1822     if (!m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
1823         usageFlags |= VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT;
1824 
1825     const VkCommandBufferBeginInfo commandBufBeginParams{
1826         VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType;
1827         DE_NULL,                                     // const void* pNext;
1828         usageFlags,                                  // VkCommandBufferUsageFlags flags;
1829         &bufferInheritanceInfo};
1830 
1831     VK_CHECK(vkd.beginCommandBuffer(cmdBuffer, &commandBufBeginParams));
1832 }
1833 #endif // CTS_USES_VULKANSC
1834 
1835 class MaxAttachmenstsRenderPassTestInstance : public MultisampleRenderPassTestBase
1836 {
1837 public:
1838     MaxAttachmenstsRenderPassTestInstance(Context &context, TestConfig config);
1839     ~MaxAttachmenstsRenderPassTestInstance(void) = default;
1840 
1841     tcu::TestStatus iterate(void);
1842 
1843 private:
1844     template <typename RenderpassSubpass>
1845     void submit(void);
1846     void submitDynamicRendering(void);
1847 
1848 #ifndef CTS_USES_VULKANSC
1849     void preRenderCommands(const DeviceInterface &vk, VkCommandBuffer cmdBuffer);
1850     void inbetweenRenderCommands(const DeviceInterface &vk, VkCommandBuffer cmdBuffer);
1851 #endif // CTS_USES_VULKANSC
1852     void drawFirstSubpass(const DeviceInterface &vk, VkCommandBuffer cmdBuffer);
1853     void drawSecondSubpass(const DeviceInterface &vk, VkCommandBuffer cmdBuffer);
1854     void postRenderCommands(const DeviceInterface &vk, VkCommandBuffer cmdBuffer);
1855 
1856     void submitSwitch(RenderingType renderingType);
1857     void verify(void);
1858 
1859     Move<VkDescriptorSetLayout> createDescriptorSetLayout(void);
1860     Move<VkDescriptorPool> createDescriptorPool(void);
1861     Move<VkDescriptorSet> createDescriptorSet(void);
1862 
1863     template <typename RenderPassTrait>
1864     Move<VkRenderPass> createRenderPass(void);
1865     Move<VkRenderPass> createRenderPassSwitch(const RenderingType renderingType);
1866     void createRenderPipeline(GraphicsPipelineWrapper &graphicsPipeline, bool secondSubpass);
1867 
1868 private:
1869     const std::vector<VkImageSp> m_multisampleImages;
1870     const std::vector<AllocationSp> m_multisampleImageMemory;
1871     const std::vector<VkImageViewSp> m_multisampleImageViews;
1872 
1873     const std::vector<VkImageSp> m_singlesampleImages;
1874     const std::vector<AllocationSp> m_singlesampleImageMemory;
1875     const std::vector<VkImageViewSp> m_singlesampleImageViews;
1876 
1877     const Unique<VkDescriptorSetLayout> m_descriptorSetLayout;
1878     const Unique<VkDescriptorPool> m_descriptorPool;
1879     const Unique<VkDescriptorSet> m_descriptorSet;
1880 
1881     const Unique<VkRenderPass> m_renderPass;
1882     const Unique<VkFramebuffer> m_framebuffer;
1883 
1884     PipelineLayoutWrapper m_pipelineLayoutPass0;
1885     GraphicsPipelineWrapper m_pipelinePass0;
1886     PipelineLayoutWrapper m_pipelineLayoutPass1;
1887     GraphicsPipelineWrapper m_pipelinePass1;
1888 
1889     const std::vector<VkBufferSp> m_buffers;
1890     const std::vector<AllocationSp> m_bufferMemory;
1891 
1892     const Unique<VkCommandPool> m_commandPool;
1893     tcu::ResultCollector m_resultCollector;
1894 };
1895 
MaxAttachmenstsRenderPassTestInstance(Context & context,TestConfig config)1896 MaxAttachmenstsRenderPassTestInstance::MaxAttachmenstsRenderPassTestInstance(Context &context, TestConfig config)
1897     : MultisampleRenderPassTestBase(context, config)
1898 
1899     , m_multisampleImages(createImages(m_sampleCount, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT))
1900     , m_multisampleImageMemory(createImageMemory(m_multisampleImages))
1901     , m_multisampleImageViews(createImageViews(m_multisampleImages))
1902 
1903     , m_singlesampleImages(createImages(VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
1904                                                                    VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT |
1905                                                                    VK_IMAGE_USAGE_TRANSFER_SRC_BIT))
1906     , m_singlesampleImageMemory(createImageMemory(m_singlesampleImages))
1907     , m_singlesampleImageViews(createImageViews(m_singlesampleImages, m_baseLayer))
1908 
1909     , m_descriptorSetLayout(createDescriptorSetLayout())
1910     , m_descriptorPool(createDescriptorPool())
1911     , m_descriptorSet(createDescriptorSet())
1912 
1913     , m_renderPass(createRenderPassSwitch(config.groupParams->renderingType))
1914     , m_framebuffer(createFramebuffer(m_multisampleImageViews, m_singlesampleImageViews, *m_renderPass))
1915 
1916     , m_pipelineLayoutPass0(config.groupParams->pipelineConstructionType, context.getDeviceInterface(),
1917                             context.getDevice())
1918     , m_pipelinePass0(context.getInstanceInterface(), context.getDeviceInterface(), context.getPhysicalDevice(),
1919                       context.getDevice(), context.getDeviceExtensions(), m_groupParams->pipelineConstructionType)
1920     , m_pipelineLayoutPass1(config.groupParams->pipelineConstructionType, context.getDeviceInterface(),
1921                             context.getDevice(), *m_descriptorSetLayout)
1922     , m_pipelinePass1(context.getInstanceInterface(), context.getDeviceInterface(), context.getPhysicalDevice(),
1923                       context.getDevice(), context.getDeviceExtensions(), m_groupParams->pipelineConstructionType)
1924 
1925     , m_buffers(createBuffers())
1926     , m_bufferMemory(createBufferMemory(m_buffers))
1927 
1928     , m_commandPool(createCommandPool(context.getDeviceInterface(), context.getDevice(),
1929                                       VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, context.getUniversalQueueFamilyIndex()))
1930 {
1931     createRenderPipeline(m_pipelinePass0, 0);
1932     createRenderPipeline(m_pipelinePass1, 1);
1933 }
1934 
1935 template <typename RenderpassSubpass>
submit(void)1936 void MaxAttachmenstsRenderPassTestInstance::submit(void)
1937 {
1938     const DeviceInterface &vkd(m_context.getDeviceInterface());
1939     const VkDevice device(m_context.getDevice());
1940     const Unique<VkCommandBuffer> commandBuffer(
1941         allocateCommandBuffer(vkd, device, *m_commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
1942     const typename RenderpassSubpass::SubpassBeginInfo subpassBeginInfo(DE_NULL, VK_SUBPASS_CONTENTS_INLINE);
1943     const typename RenderpassSubpass::SubpassEndInfo subpassEndInfo(DE_NULL);
1944 
1945     beginCommandBuffer(vkd, *commandBuffer);
1946 
1947     // Memory barriers between previous copies and rendering
1948     {
1949         std::vector<VkImageMemoryBarrier> barriers;
1950 
1951         for (size_t dstNdx = 0; dstNdx < m_singlesampleImages.size(); dstNdx++)
1952         {
1953             const VkImageMemoryBarrier barrier = {VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
1954                                                   DE_NULL,
1955 
1956                                                   VK_ACCESS_TRANSFER_READ_BIT,
1957                                                   VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
1958 
1959                                                   VK_IMAGE_LAYOUT_UNDEFINED,
1960                                                   VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
1961 
1962                                                   VK_QUEUE_FAMILY_IGNORED,
1963                                                   VK_QUEUE_FAMILY_IGNORED,
1964 
1965                                                   **m_singlesampleImages[dstNdx],
1966                                                   {VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, m_baseLayer, m_layerCount}};
1967 
1968             barriers.push_back(barrier);
1969         }
1970 
1971         vkd.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT,
1972                                VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL,
1973                                (uint32_t)barriers.size(), &barriers[0]);
1974     }
1975 
1976     {
1977         const VkRenderPassBeginInfo beginInfo = {VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
1978                                                  DE_NULL,
1979 
1980                                                  *m_renderPass,
1981                                                  *m_framebuffer,
1982 
1983                                                  {{0u, 0u}, {m_width, m_height}},
1984 
1985                                                  0u,
1986                                                  DE_NULL};
1987         RenderpassSubpass::cmdBeginRenderPass(vkd, *commandBuffer, &beginInfo, &subpassBeginInfo);
1988     }
1989 
1990     // Clear everything to black
1991     clearAttachments(*commandBuffer);
1992 
1993     // First subpass - render black samples
1994     drawFirstSubpass(vkd, *commandBuffer);
1995 
1996     // Second subpasss - merge attachments
1997     RenderpassSubpass::cmdNextSubpass(vkd, *commandBuffer, &subpassBeginInfo, &subpassEndInfo);
1998     drawSecondSubpass(vkd, *commandBuffer);
1999 
2000     RenderpassSubpass::cmdEndRenderPass(vkd, *commandBuffer, &subpassEndInfo);
2001 
2002     postRenderCommands(vkd, *commandBuffer);
2003 
2004     endCommandBuffer(vkd, *commandBuffer);
2005 
2006     submitCommandsAndWait(vkd, device, m_context.getUniversalQueue(), *commandBuffer);
2007 
2008     for (size_t memoryBufferNdx = 0; memoryBufferNdx < m_bufferMemory.size(); memoryBufferNdx++)
2009         invalidateMappedMemoryRange(vkd, device, m_bufferMemory[memoryBufferNdx]->getMemory(), 0u, VK_WHOLE_SIZE);
2010 }
2011 
submitDynamicRendering()2012 void MaxAttachmenstsRenderPassTestInstance::submitDynamicRendering()
2013 {
2014 #ifndef CTS_USES_VULKANSC
2015     const DeviceInterface &vk(m_context.getDeviceInterface());
2016     const VkDevice device(m_context.getDevice());
2017     const Unique<VkCommandBuffer> cmdBuffer(
2018         allocateCommandBuffer(vk, device, *m_commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
2019     Move<VkCommandBuffer> secCmdBuffers[2];
2020 
2021     const tcu::TextureFormat format(mapVkFormat(m_format));
2022     const tcu::TextureChannelClass channelClass = tcu::getTextureChannelClass(format.type);
2023     const bool isIntClass                       = (channelClass == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER) ||
2024                             (channelClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER);
2025     VkResolveModeFlagBits resolveMode = isIntClass ? VK_RESOLVE_MODE_SAMPLE_ZERO_BIT : VK_RESOLVE_MODE_AVERAGE_BIT;
2026 
2027     std::vector<VkRenderingAttachmentInfo> firstColorAttachments(
2028         m_multisampleImages.size(),
2029         {
2030             VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO, // VkStructureType sType;
2031             DE_NULL,                                     // const void* pNext;
2032             VK_NULL_HANDLE,                              // VkImageView imageView;
2033             VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,    // VkImageLayout imageLayout;
2034             resolveMode,                                 // VkResolveModeFlagBits resolveMode;
2035             VK_NULL_HANDLE,                              // VkImageView resolveImageView;
2036             m_inputImageReadLayout,                      // VkImageLayout resolveImageLayout;
2037             VK_ATTACHMENT_LOAD_OP_CLEAR,                 // VkAttachmentLoadOp loadOp;
2038             VK_ATTACHMENT_STORE_OP_STORE,                // VkAttachmentStoreOp storeOp;
2039             getClearValue()                              // VkClearValue clearValue;
2040         });
2041     std::vector<VkRenderingAttachmentInfo> secondColorAttachments(m_multisampleImages.size(), firstColorAttachments[0]);
2042     for (size_t i = 0; i < m_multisampleImages.size(); ++i)
2043     {
2044         firstColorAttachments[i].imageView        = **m_multisampleImageViews[i];
2045         firstColorAttachments[i].resolveImageView = **m_singlesampleImageViews[i];
2046 
2047         secondColorAttachments[i].imageView   = **m_singlesampleImageViews[i];
2048         secondColorAttachments[i].imageLayout = m_inputImageReadLayout;
2049         secondColorAttachments[i].resolveMode = VK_RESOLVE_MODE_NONE;
2050         secondColorAttachments[i].loadOp      = VK_ATTACHMENT_LOAD_OP_LOAD;
2051     }
2052 
2053     VkRenderingInfo firstRenderingInfo{
2054         VK_STRUCTURE_TYPE_RENDERING_INFO,
2055         DE_NULL,
2056         0,                                      // VkRenderingFlagsKHR flags;
2057         makeRect2D(m_width, m_height),          // VkRect2D renderArea;
2058         1u,                                     // uint32_t layerCount;
2059         0u,                                     // uint32_t viewMask;
2060         (uint32_t)firstColorAttachments.size(), // uint32_t colorAttachmentCount;
2061         firstColorAttachments.data(),           // const VkRenderingAttachmentInfoKHR* pColorAttachments;
2062         DE_NULL,                                // const VkRenderingAttachmentInfoKHR* pDepthAttachment;
2063         DE_NULL,                                // const VkRenderingAttachmentInfoKHR* pStencilAttachment;
2064     };
2065     VkRenderingInfo secondRenderingInfo   = firstRenderingInfo;
2066     secondRenderingInfo.pColorAttachments = secondColorAttachments.data();
2067 
2068     std::vector<uint32_t> colorAttachmentLocationsAndInputs(firstColorAttachments.size());
2069     std::iota(colorAttachmentLocationsAndInputs.begin(), colorAttachmentLocationsAndInputs.end(), 0);
2070 
2071     VkRenderingAttachmentLocationInfoKHR renderingAttachmentLocationInfo = initVulkanStructure();
2072     renderingAttachmentLocationInfo.colorAttachmentCount      = (uint32_t)colorAttachmentLocationsAndInputs.size();
2073     renderingAttachmentLocationInfo.pColorAttachmentLocations = colorAttachmentLocationsAndInputs.data();
2074 
2075     VkRenderingInputAttachmentIndexInfoKHR renderingInputAttachmentIndexInfo = initVulkanStructure();
2076     renderingInputAttachmentIndexInfo.colorAttachmentCount         = (uint32_t)colorAttachmentLocationsAndInputs.size();
2077     renderingInputAttachmentIndexInfo.pColorAttachmentInputIndices = colorAttachmentLocationsAndInputs.data();
2078 
2079     if (m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
2080     {
2081         secCmdBuffers[0] = allocateCommandBuffer(vk, device, *m_commandPool, VK_COMMAND_BUFFER_LEVEL_SECONDARY);
2082         secCmdBuffers[1] = allocateCommandBuffer(vk, device, *m_commandPool, VK_COMMAND_BUFFER_LEVEL_SECONDARY);
2083 
2084         // record secondary command buffer for first subpass
2085         beginSecondaryCmdBuffer(vk, *secCmdBuffers[0], (uint32_t)m_multisampleImages.size(), m_sampleCount);
2086         vk.cmdBeginRendering(*secCmdBuffers[0], &firstRenderingInfo);
2087         drawFirstSubpass(vk, *secCmdBuffers[0]);
2088         vk.cmdEndRendering(*secCmdBuffers[0]);
2089         endCommandBuffer(vk, *secCmdBuffers[0]);
2090 
2091         // record secondary command buffer for second subpass
2092         beginSecondaryCmdBuffer(vk, *secCmdBuffers[1], (uint32_t)m_multisampleImages.size(), VK_SAMPLE_COUNT_1_BIT);
2093         vk.cmdBeginRendering(*secCmdBuffers[1], &secondRenderingInfo);
2094         vk.cmdSetRenderingAttachmentLocationsKHR(*secCmdBuffers[1], &renderingAttachmentLocationInfo);
2095         vk.cmdSetRenderingInputAttachmentIndicesKHR(*secCmdBuffers[1], &renderingInputAttachmentIndexInfo);
2096         drawSecondSubpass(vk, *secCmdBuffers[1]);
2097         vk.cmdEndRendering(*secCmdBuffers[1]);
2098         endCommandBuffer(vk, *secCmdBuffers[1]);
2099 
2100         renderingInputAttachmentIndexInfo.pNext = DE_NULL;
2101 
2102         // record primary command buffer
2103         beginCommandBuffer(vk, *cmdBuffer);
2104         preRenderCommands(vk, *cmdBuffer);
2105         vk.cmdExecuteCommands(*cmdBuffer, 1u, &*secCmdBuffers[0]);
2106         inbetweenRenderCommands(vk, *cmdBuffer);
2107         vk.cmdExecuteCommands(*cmdBuffer, 1u, &*secCmdBuffers[1]);
2108         postRenderCommands(vk, *cmdBuffer);
2109         endCommandBuffer(vk, *cmdBuffer);
2110     }
2111     else
2112     {
2113         beginCommandBuffer(vk, *cmdBuffer);
2114 
2115         preRenderCommands(vk, *cmdBuffer);
2116 
2117         // First dynamic render pass - render black samples
2118         vk.cmdBeginRendering(*cmdBuffer, &firstRenderingInfo);
2119         drawFirstSubpass(vk, *cmdBuffer);
2120         vk.cmdEndRendering(*cmdBuffer);
2121 
2122         inbetweenRenderCommands(vk, *cmdBuffer);
2123 
2124         // Second dynamic render pass - merge resolved attachments
2125         vk.cmdBeginRendering(*cmdBuffer, &secondRenderingInfo);
2126         vk.cmdSetRenderingAttachmentLocationsKHR(*cmdBuffer, &renderingAttachmentLocationInfo);
2127         vk.cmdSetRenderingInputAttachmentIndicesKHR(*cmdBuffer, &renderingInputAttachmentIndexInfo);
2128         drawSecondSubpass(vk, *cmdBuffer);
2129         vk.cmdEndRendering(*cmdBuffer);
2130 
2131         postRenderCommands(vk, *cmdBuffer);
2132         endCommandBuffer(vk, *cmdBuffer);
2133     }
2134 
2135     submitCommandsAndWait(vk, device, m_context.getUniversalQueue(), *cmdBuffer);
2136 
2137     for (size_t memoryBufferNdx = 0; memoryBufferNdx < m_bufferMemory.size(); memoryBufferNdx++)
2138         invalidateMappedMemoryRange(vk, device, m_bufferMemory[memoryBufferNdx]->getMemory(), 0u, VK_WHOLE_SIZE);
2139 #endif
2140 }
2141 
2142 #ifndef CTS_USES_VULKANSC
preRenderCommands(const DeviceInterface & vk,VkCommandBuffer cmdBuffer)2143 void MaxAttachmenstsRenderPassTestInstance::preRenderCommands(const DeviceInterface &vk, VkCommandBuffer cmdBuffer)
2144 {
2145     const VkImageSubresourceRange subresourceRange{VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, m_layerCount};
2146     std::vector<VkImageMemoryBarrier> barriers(
2147         m_multisampleImages.size() + m_singlesampleImages.size(),
2148         makeImageMemoryBarrier(VK_ACCESS_TRANSFER_READ_BIT, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
2149                                VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, 0,
2150                                subresourceRange));
2151 
2152     for (size_t i = 0; i < m_multisampleImages.size(); ++i)
2153         barriers[i].image = **m_multisampleImages[i];
2154     for (size_t i = m_multisampleImages.size(); i < barriers.size(); ++i)
2155     {
2156         barriers[i].image     = **m_singlesampleImages[i - m_multisampleImages.size()];
2157         barriers[i].newLayout = m_inputImageReadLayout;
2158     }
2159 
2160     vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u,
2161                           0u, DE_NULL, 0u, DE_NULL, (uint32_t)barriers.size(), barriers.data());
2162 }
2163 
inbetweenRenderCommands(const DeviceInterface & vk,VkCommandBuffer cmdBuffer)2164 void MaxAttachmenstsRenderPassTestInstance::inbetweenRenderCommands(const DeviceInterface &vk,
2165                                                                     VkCommandBuffer cmdBuffer)
2166 {
2167     VkMemoryBarrier memoryBarrier =
2168         makeMemoryBarrier(VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_COLOR_ATTACHMENT_READ_BIT);
2169     vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
2170                           VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_DEPENDENCY_BY_REGION_BIT, 1u, &memoryBarrier, 0u,
2171                           DE_NULL, 0, DE_NULL);
2172 }
2173 #endif // CTS_USES_VULKANSC
2174 
drawFirstSubpass(const DeviceInterface & vk,VkCommandBuffer cmdBuffer)2175 void MaxAttachmenstsRenderPassTestInstance::drawFirstSubpass(const DeviceInterface &vk, VkCommandBuffer cmdBuffer)
2176 {
2177     vk.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipelinePass0.getPipeline());
2178     vk.cmdDraw(cmdBuffer, 6u, 1u, 0u, 0u);
2179 }
2180 
drawSecondSubpass(const DeviceInterface & vk,VkCommandBuffer cmdBuffer)2181 void MaxAttachmenstsRenderPassTestInstance::drawSecondSubpass(const DeviceInterface &vk, VkCommandBuffer cmdBuffer)
2182 {
2183     vk.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipelinePass1.getPipeline());
2184     vk.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayoutPass1, 0, 1u,
2185                              &*m_descriptorSet, 0, NULL);
2186     vk.cmdDraw(cmdBuffer, 6u, 1u, 0u, 0u);
2187 }
2188 
postRenderCommands(const DeviceInterface & vk,VkCommandBuffer cmdBuffer)2189 void MaxAttachmenstsRenderPassTestInstance::postRenderCommands(const DeviceInterface &vk, VkCommandBuffer cmdBuffer)
2190 {
2191     const VkImageSubresourceRange subresourceRange{VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, m_layerCount};
2192 
2193     // Memory barriers between rendering and copies
2194     std::vector<VkImageMemoryBarrier> imageBarriers(
2195         m_singlesampleImages.size(),
2196         makeImageMemoryBarrier(VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
2197                                m_inputImageReadLayout, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, 0u, subresourceRange));
2198 
2199     for (size_t dstNdx = 0; dstNdx < m_singlesampleImages.size(); dstNdx++)
2200         imageBarriers[dstNdx].image = **m_singlesampleImages[dstNdx];
2201 
2202     vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
2203                           0u, DE_NULL, 0u, DE_NULL, (uint32_t)imageBarriers.size(), imageBarriers.data());
2204 
2205     // Copy image memory to buffers
2206     const VkBufferImageCopy region =
2207         makeBufferImageCopy({m_width, m_height, 1u}, {VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, m_layerCount});
2208     for (size_t dstNdx = 0; dstNdx < m_singlesampleImages.size(); dstNdx++)
2209         vk.cmdCopyImageToBuffer(cmdBuffer, **m_singlesampleImages[dstNdx], VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
2210                                 **m_buffers[dstNdx], 1u, &region);
2211 
2212     // Memory barriers between copies and host access
2213     std::vector<VkBufferMemoryBarrier> bufferBarriers(
2214         m_buffers.size(),
2215         makeBufferMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, 0u, 0u, VK_WHOLE_SIZE));
2216     for (size_t i = 0u; i < bufferBarriers.size(); ++i)
2217         bufferBarriers[i].buffer = **m_buffers[i];
2218 
2219     vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u, DE_NULL,
2220                           (uint32_t)bufferBarriers.size(), bufferBarriers.data(), 0u, DE_NULL);
2221 }
2222 
submitSwitch(RenderingType renderingType)2223 void MaxAttachmenstsRenderPassTestInstance::submitSwitch(RenderingType renderingType)
2224 {
2225     switch (renderingType)
2226     {
2227     case RENDERING_TYPE_RENDERPASS_LEGACY:
2228         submit<RenderpassSubpass1>();
2229         break;
2230     case RENDERING_TYPE_RENDERPASS2:
2231         submit<RenderpassSubpass2>();
2232         break;
2233     case RENDERING_TYPE_DYNAMIC_RENDERING:
2234         submitDynamicRendering();
2235         break;
2236     default:
2237         TCU_THROW(InternalError, "Impossible");
2238     }
2239 }
2240 
2241 template <typename VecType>
isValueAboveThreshold1(const VecType & vale,const VecType & threshold)2242 bool isValueAboveThreshold1(const VecType &vale, const VecType &threshold)
2243 {
2244     return (vale[0] > threshold[0]);
2245 }
2246 
2247 template <typename VecType>
isValueAboveThreshold2(const VecType & vale,const VecType & threshold)2248 bool isValueAboveThreshold2(const VecType &vale, const VecType &threshold)
2249 {
2250     return (vale[0] > threshold[0]) || (vale[1] > threshold[1]);
2251 }
2252 
2253 template <typename VecType>
isValueAboveThreshold3(const VecType & vale,const VecType & threshold)2254 bool isValueAboveThreshold3(const VecType &vale, const VecType &threshold)
2255 {
2256     return (vale[0] > threshold[0]) || (vale[1] > threshold[1]) || (vale[2] > threshold[2]);
2257 }
2258 
2259 template <typename VecType>
isValueAboveThreshold4(const VecType & vale,const VecType & threshold)2260 bool isValueAboveThreshold4(const VecType &vale, const VecType &threshold)
2261 {
2262     return (vale[0] > threshold[0]) || (vale[1] > threshold[1]) || (vale[2] > threshold[2]) || (vale[3] > threshold[3]);
2263 }
2264 
verify(void)2265 void MaxAttachmenstsRenderPassTestInstance::verify(void)
2266 {
2267     const Vec4 errorColor(1.0f, 0.0f, 0.0f, 1.0f);
2268     const Vec4 okColor(0.0f, 1.0f, 0.0f, 1.0f);
2269     const tcu::TextureFormat format(mapVkFormat(m_format));
2270     const tcu::TextureChannelClass channelClass(tcu::getTextureChannelClass(format.type));
2271     const int componentCount(tcu::getNumUsedChannels(format.order));
2272     const int outputsCount = m_attachmentsCount / 2;
2273 
2274     DE_ASSERT((componentCount >= 0) && (componentCount < 5));
2275 
2276     std::vector<tcu::ConstPixelBufferAccess> accesses;
2277     for (int outputNdx = 0; outputNdx < outputsCount; ++outputNdx)
2278     {
2279         void *const ptr = m_bufferMemory[outputNdx]->getHostPtr();
2280         accesses.push_back(tcu::ConstPixelBufferAccess(format, m_width, m_height, 1, ptr));
2281     }
2282 
2283     tcu::TextureLevel errorMask(tcu::TextureFormat(tcu::TextureFormat::RGB, tcu::TextureFormat::UNORM_INT8), m_width,
2284                                 m_height, outputsCount);
2285     tcu::TestLog &log(m_context.getTestContext().getLog());
2286     bool isOk = true;
2287 
2288     switch (channelClass)
2289     {
2290     case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
2291     case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
2292     case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
2293     {
2294         const Vec4 refColor(0.0f, 0.3f, 0.6f, 0.75f);
2295         const Vec4 threshold(getFormatThreshold());
2296 
2297         typedef bool (*ValueAboveThresholdFn)(const Vec4 &, const Vec4 &);
2298         ValueAboveThresholdFn componentToFnMap[4]   = {isValueAboveThreshold1<Vec4>, isValueAboveThreshold2<Vec4>,
2299                                                        isValueAboveThreshold3<Vec4>, isValueAboveThreshold4<Vec4>};
2300         ValueAboveThresholdFn isValueAboveThreshold = componentToFnMap[componentCount - 1];
2301         bool isSRGBFormat                           = tcu::isSRGB(format);
2302 
2303         for (int outputNdx = 0; outputNdx < outputsCount; outputNdx++)
2304             for (int y = 0; y < (int)m_height; y++)
2305                 for (int x = 0; x < (int)m_width; x++)
2306                 {
2307                     Vec4 color = accesses[outputNdx].getPixel(x, y);
2308                     if (isSRGBFormat)
2309                         color = tcu::sRGBToLinear(color);
2310 
2311                     const Vec4 diff(tcu::abs(color - refColor));
2312 
2313                     if (isValueAboveThreshold(diff, threshold))
2314                     {
2315                         isOk = false;
2316                         errorMask.getAccess().setPixel(errorColor, x, y, outputNdx);
2317                         break;
2318                     }
2319                     else
2320                         errorMask.getAccess().setPixel(okColor, x, y, outputNdx);
2321                 }
2322         break;
2323     }
2324 
2325     case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
2326     {
2327         const UVec4 refColor(0, 48, 144, 189);
2328         UVec4 threshold(1, 1, 1, 1);
2329 
2330         if (m_format == VK_FORMAT_A2B10G10R10_UINT_PACK32)
2331             threshold[3] = 200;
2332 
2333         typedef bool (*ValueAboveThresholdFn)(const UVec4 &, const UVec4 &);
2334         ValueAboveThresholdFn componentToFnMap[4]   = {isValueAboveThreshold1<UVec4>, isValueAboveThreshold2<UVec4>,
2335                                                        isValueAboveThreshold3<UVec4>, isValueAboveThreshold4<UVec4>};
2336         ValueAboveThresholdFn isValueAboveThreshold = componentToFnMap[componentCount - 1];
2337 
2338         for (int outputNdx = 0; outputNdx < outputsCount; outputNdx++)
2339             for (int y = 0; y < (int)m_height; y++)
2340                 for (int x = 0; x < (int)m_width; x++)
2341                 {
2342                     const UVec4 color(accesses[outputNdx].getPixelUint(x, y));
2343                     const UVec4 diff(
2344                         std::abs(int(color.x()) - int(refColor.x())), std::abs(int(color.y()) - int(refColor.y())),
2345                         std::abs(int(color.z()) - int(refColor.z())), std::abs(int(color.w()) - int(refColor.w())));
2346 
2347                     if (isValueAboveThreshold(diff, threshold))
2348                     {
2349                         isOk = false;
2350                         errorMask.getAccess().setPixel(errorColor, x, y, outputNdx);
2351                         break;
2352                     }
2353                     else
2354                         errorMask.getAccess().setPixel(okColor, x, y, outputNdx);
2355                 }
2356         break;
2357     }
2358 
2359     case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
2360     {
2361         const IVec4 refColor(0, 24, 75, 93);
2362         const IVec4 threshold(1, 1, 1, 1);
2363 
2364         typedef bool (*ValueAboveThresholdFn)(const IVec4 &, const IVec4 &);
2365         ValueAboveThresholdFn componentToFnMap[4]   = {isValueAboveThreshold1<IVec4>, isValueAboveThreshold2<IVec4>,
2366                                                        isValueAboveThreshold3<IVec4>, isValueAboveThreshold4<IVec4>};
2367         ValueAboveThresholdFn isValueAboveThreshold = componentToFnMap[componentCount - 1];
2368 
2369         for (int outputNdx = 0; outputNdx < outputsCount; outputNdx++)
2370             for (int y = 0; y < (int)m_height; y++)
2371                 for (int x = 0; x < (int)m_width; x++)
2372                 {
2373                     const IVec4 color(accesses[outputNdx].getPixelInt(x, y));
2374                     const IVec4 diff(std::abs(color.x() - refColor.x()), std::abs(color.y() - refColor.y()),
2375                                      std::abs(color.z() - refColor.z()), std::abs(color.w() - 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     default:
2390         DE_FATAL("Unknown channel class");
2391     }
2392 
2393     if (!isOk)
2394     {
2395         const std::string sectionName("MaxAttachmentsVerify");
2396         const tcu::ScopedLogSection section(log, sectionName, sectionName);
2397 
2398         logImage("ErrorMask", errorMask.getAccess());
2399         m_resultCollector.fail("Fail");
2400     }
2401 }
2402 
iterate(void)2403 tcu::TestStatus MaxAttachmenstsRenderPassTestInstance::iterate(void)
2404 {
2405     submitSwitch(m_groupParams->renderingType);
2406     verify();
2407 
2408     return tcu::TestStatus(m_resultCollector.getResult(), m_resultCollector.getMessage());
2409 }
2410 
createDescriptorSetLayout()2411 Move<VkDescriptorSetLayout> MaxAttachmenstsRenderPassTestInstance::createDescriptorSetLayout()
2412 {
2413     const VkDescriptorSetLayoutBinding bindingTemplate = {
2414         0,                                   // binding
2415         VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, // descriptorType
2416         1u,                                  // descriptorCount
2417         VK_SHADER_STAGE_FRAGMENT_BIT,        // stageFlags
2418         DE_NULL                              // pImmutableSamplers
2419     };
2420 
2421     std::vector<VkDescriptorSetLayoutBinding> bindings(m_attachmentsCount, bindingTemplate);
2422     for (uint32_t idx = 0; idx < m_attachmentsCount; ++idx)
2423         bindings[idx].binding = idx;
2424 
2425     const VkDescriptorSetLayoutCreateInfo createInfo = {
2426         VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, // sType
2427         DE_NULL,                                             // pNext
2428         0u,                                                  // flags
2429         m_attachmentsCount,                                  // bindingCount
2430         &bindings[0]                                         // pBindings
2431     };
2432 
2433     return ::createDescriptorSetLayout(m_context.getDeviceInterface(), m_context.getDevice(), &createInfo);
2434 }
2435 
createDescriptorPool()2436 Move<VkDescriptorPool> MaxAttachmenstsRenderPassTestInstance::createDescriptorPool()
2437 {
2438     const VkDescriptorPoolSize size = {
2439         VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, // type
2440         m_attachmentsCount                   // descriptorCount
2441     };
2442 
2443     const VkDescriptorPoolCreateInfo createInfo = {
2444         VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,     // sType
2445         DE_NULL,                                           // pNext
2446         VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, // flags
2447         1u,                                                // maxSets
2448         1u,                                                // poolSizeCount
2449         &size                                              // pPoolSizes
2450     };
2451 
2452     return ::createDescriptorPool(m_context.getDeviceInterface(), m_context.getDevice(), &createInfo);
2453 }
2454 
createDescriptorSet()2455 Move<VkDescriptorSet> MaxAttachmenstsRenderPassTestInstance::createDescriptorSet()
2456 {
2457     const VkDescriptorSetAllocateInfo allocateInfo = {
2458         VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, // sType
2459         DE_NULL,                                        // pNext
2460         *m_descriptorPool,                              // descriptorPool
2461         1u,                                             // descriptorSetCount
2462         &*m_descriptorSetLayout                         // pSetLayouts
2463     };
2464 
2465     const vk::DeviceInterface &vkd      = m_context.getDeviceInterface();
2466     vk::VkDevice device                 = m_context.getDevice();
2467     Move<VkDescriptorSet> descriptorSet = allocateDescriptorSet(vkd, device, &allocateInfo);
2468     vector<VkDescriptorImageInfo> descriptorImageInfo(m_attachmentsCount);
2469     vector<VkWriteDescriptorSet> descriptorWrites(m_attachmentsCount);
2470 
2471     for (uint32_t idx = 0; idx < m_attachmentsCount; ++idx)
2472     {
2473         descriptorImageInfo[idx] = {
2474             DE_NULL,                         // VkSampler        sampler
2475             **m_singlesampleImageViews[idx], // VkImageView        imageView
2476             m_inputImageReadLayout           // VkImageLayout    imageLayout
2477         };
2478 
2479         descriptorWrites[idx] = {
2480             VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, // VkStructureType                    sType
2481             DE_NULL,                                // const void*                        pNext
2482             *descriptorSet,                         // VkDescriptorSet                    dstSet
2483             (uint32_t)idx,                          // uint32_t                            dstBinding
2484             0u,                                     // uint32_t                            dstArrayElement
2485             1u,                                     // uint32_t                            descriptorCount
2486             VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,    // VkDescriptorType                    descriptorType
2487             &descriptorImageInfo[idx],              // const VkDescriptorImageInfo*        pImageInfo
2488             DE_NULL,                                // const VkDescriptorBufferInfo*    pBufferInfo
2489             DE_NULL                                 // const VkBufferView*                pTexelBufferView
2490         };
2491     }
2492 
2493     vkd.updateDescriptorSets(device, (uint32_t)descriptorWrites.size(), &descriptorWrites[0], 0u, DE_NULL);
2494     return descriptorSet;
2495 }
2496 
2497 template <typename RenderPassTrait>
createRenderPass(void)2498 Move<VkRenderPass> MaxAttachmenstsRenderPassTestInstance::createRenderPass(void)
2499 {
2500     // make name for RenderPass1Trait or RenderPass2Trait shorter
2501     typedef RenderPassTrait RPT;
2502 
2503     typedef typename RPT::AttDesc AttDesc;
2504     typedef typename RPT::AttRef AttRef;
2505     typedef typename RPT::SubpassDep SubpassDep;
2506     typedef typename RPT::SubpassDesc SubpassDesc;
2507     typedef typename RPT::RenderPassCreateInfo RenderPassCreateInfo;
2508 
2509     const DeviceInterface &vkd = m_context.getDeviceInterface();
2510     VkDevice device            = m_context.getDevice();
2511     std::vector<AttDesc> attachments;
2512     std::vector<AttRef> sp0colorAttachmentRefs;
2513     std::vector<AttRef> sp0resolveAttachmentRefs;
2514     std::vector<AttRef> sp1inAttachmentRefs;
2515     std::vector<AttRef> sp1colorAttachmentRefs;
2516 
2517     for (size_t attachmentNdx = 0; attachmentNdx < m_attachmentsCount; attachmentNdx++)
2518     {
2519         // define first subpass outputs
2520         {
2521             const AttDesc multisampleAttachment(DE_NULL,                                 // pNext
2522                                                 0u,                                      // flags
2523                                                 m_format,                                // format
2524                                                 m_sampleCount,                           // samples
2525                                                 VK_ATTACHMENT_LOAD_OP_DONT_CARE,         // loadOp
2526                                                 VK_ATTACHMENT_STORE_OP_STORE,            // storeOp
2527                                                 VK_ATTACHMENT_LOAD_OP_DONT_CARE,         // stencilLoadOp
2528                                                 VK_ATTACHMENT_STORE_OP_DONT_CARE,        // stencilStoreOp
2529                                                 VK_IMAGE_LAYOUT_UNDEFINED,               // initialLayout
2530                                                 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // finalLayout
2531             );
2532             const AttRef attachmentRef(DE_NULL,
2533                                        (uint32_t)attachments.size(),             // attachment
2534                                        VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // layout
2535                                        0u                                        // aspectMask
2536             );
2537             sp0colorAttachmentRefs.push_back(attachmentRef);
2538             attachments.push_back(multisampleAttachment);
2539         }
2540         // define first subpass resolve attachments
2541         {
2542             const AttDesc singlesampleAttachment(DE_NULL,                          // pNext
2543                                                  0u,                               // flags
2544                                                  m_format,                         // format
2545                                                  VK_SAMPLE_COUNT_1_BIT,            // samples
2546                                                  VK_ATTACHMENT_LOAD_OP_DONT_CARE,  // loadOp
2547                                                  VK_ATTACHMENT_STORE_OP_STORE,     // storeOp
2548                                                  VK_ATTACHMENT_LOAD_OP_DONT_CARE,  // stencilLoadOp
2549                                                  VK_ATTACHMENT_STORE_OP_DONT_CARE, // stencilStoreOp
2550                                                  VK_IMAGE_LAYOUT_UNDEFINED,        // initialLayout
2551                                                  VK_IMAGE_LAYOUT_GENERAL           // finalLayout
2552             );
2553             const AttRef attachmentRef(DE_NULL,                      // pNext
2554                                        (uint32_t)attachments.size(), // attachment
2555                                        VK_IMAGE_LAYOUT_GENERAL,      // layout
2556                                        0u                            // aspectMask
2557             );
2558             sp0resolveAttachmentRefs.push_back(attachmentRef);
2559             attachments.push_back(singlesampleAttachment);
2560         }
2561         // define second subpass inputs
2562         {
2563             const AttRef attachmentRef(DE_NULL,                          // pNext
2564                                        (uint32_t)attachments.size() - 1, // attachment
2565                                        VK_IMAGE_LAYOUT_GENERAL,          // layout
2566                                        VK_IMAGE_ASPECT_COLOR_BIT         // aspectMask
2567             );
2568             sp1inAttachmentRefs.push_back(attachmentRef);
2569         }
2570         // define second subpass outputs - it merges pairs of
2571         // results that were produced by the first subpass
2572         if (attachmentNdx < (m_attachmentsCount / 2))
2573         {
2574             const AttRef colorAttachmentRef(DE_NULL,                          // pNext
2575                                             (uint32_t)attachments.size() - 1, // attachment
2576                                             VK_IMAGE_LAYOUT_GENERAL,          // layout
2577                                             0u                                // aspectMask
2578             );
2579             sp1colorAttachmentRefs.push_back(colorAttachmentRef);
2580         }
2581     }
2582 
2583     DE_ASSERT(sp0colorAttachmentRefs.size() == sp0resolveAttachmentRefs.size());
2584     DE_ASSERT(attachments.size() == sp0colorAttachmentRefs.size() + sp0resolveAttachmentRefs.size());
2585 
2586     {
2587         const SubpassDesc subpass0(
2588             // sType
2589             DE_NULL,                                 // pNext
2590             (VkSubpassDescriptionFlags)0,            // flags
2591             VK_PIPELINE_BIND_POINT_GRAPHICS,         // pipelineBindPoint
2592             0u,                                      // viewMask
2593             0u,                                      // inputAttachmentCount
2594             DE_NULL,                                 // pInputAttachments
2595             (uint32_t)sp0colorAttachmentRefs.size(), // colorAttachmentCount
2596             &sp0colorAttachmentRefs[0],              // pColorAttachments
2597             &sp0resolveAttachmentRefs[0],            // pResolveAttachments
2598             DE_NULL,                                 // pDepthStencilAttachment
2599             0u,                                      // preserveAttachmentCount
2600             DE_NULL                                  // pPreserveAttachments
2601         );
2602         const SubpassDesc subpass1(
2603             // sType
2604             DE_NULL,                                 // pNext
2605             (VkSubpassDescriptionFlags)0,            // flags
2606             VK_PIPELINE_BIND_POINT_GRAPHICS,         // pipelineBindPoint
2607             0u,                                      // viewMask
2608             (uint32_t)sp1inAttachmentRefs.size(),    // inputAttachmentCount
2609             &sp1inAttachmentRefs[0],                 // pInputAttachments
2610             (uint32_t)sp1colorAttachmentRefs.size(), // colorAttachmentCount
2611             &sp1colorAttachmentRefs[0],              // pColorAttachments
2612             DE_NULL,                                 // pResolveAttachments
2613             DE_NULL,                                 // pDepthStencilAttachment
2614             0u,                                      // preserveAttachmentCount
2615             DE_NULL                                  // pPreserveAttachments
2616         );
2617         SubpassDesc subpasses[] = {subpass0, subpass1};
2618         const SubpassDep subpassDependency(DE_NULL,                                       // pNext
2619                                            0u,                                            // srcSubpass
2620                                            1u,                                            // dstSubpass
2621                                            VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, // srcStageMask
2622                                            VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,         // dstStageMask
2623                                            VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,          // srcAccessMask
2624                                            VK_ACCESS_INPUT_ATTACHMENT_READ_BIT,           // dstAccessMask
2625                                            0u,                                            // dependencyFlags
2626                                            0u                                             // viewOffset
2627         );
2628         const RenderPassCreateInfo renderPassCreator(
2629             // sType
2630             DE_NULL,                      // pNext
2631             (VkRenderPassCreateFlags)0u,  // flags
2632             (uint32_t)attachments.size(), // attachmentCount
2633             &attachments[0],              // pAttachments
2634             2u,                           // subpassCount
2635             subpasses,                    // pSubpasses
2636             1u,                           // dependencyCount
2637             &subpassDependency,           // pDependencies
2638             0u,                           // correlatedViewMaskCount
2639             DE_NULL                       // pCorrelatedViewMasks
2640         );
2641 
2642         return renderPassCreator.createRenderPass(vkd, device);
2643     }
2644 }
2645 
createRenderPassSwitch(const RenderingType renderingType)2646 Move<VkRenderPass> MaxAttachmenstsRenderPassTestInstance::createRenderPassSwitch(const RenderingType renderingType)
2647 {
2648     switch (renderingType)
2649     {
2650     case RENDERING_TYPE_RENDERPASS_LEGACY:
2651         return createRenderPass<RenderPass1Trait>();
2652     case RENDERING_TYPE_RENDERPASS2:
2653         return createRenderPass<RenderPass2Trait>();
2654     case RENDERING_TYPE_DYNAMIC_RENDERING:
2655         return Move<VkRenderPass>();
2656     default:
2657         TCU_THROW(InternalError, "Impossible");
2658     }
2659 }
2660 
createRenderPipeline(GraphicsPipelineWrapper & graphicsPipeline,bool secondSubpass)2661 void MaxAttachmenstsRenderPassTestInstance::createRenderPipeline(GraphicsPipelineWrapper &graphicsPipeline,
2662                                                                  bool secondSubpass)
2663 {
2664     const DeviceInterface &vkd                   = m_context.getDeviceInterface();
2665     VkDevice device                              = m_context.getDevice();
2666     const vk::BinaryCollection &binaryCollection = m_context.getBinaryCollection();
2667     VkSampleCountFlagBits sampleCount            = sampleCountBitFromSampleCount(m_sampleCount);
2668     uint32_t blendStatesCount                    = m_attachmentsCount;
2669     std::string fragShaderNameBase               = "quad-frag-sp0-";
2670 
2671     if (secondSubpass)
2672     {
2673         sampleCount = VK_SAMPLE_COUNT_1_BIT;
2674         blendStatesCount /= 2;
2675         fragShaderNameBase = "quad-frag-sp1-";
2676     }
2677 
2678     if (*m_renderPass == DE_NULL)
2679         blendStatesCount = m_attachmentsCount;
2680 
2681     std::string fragShaderName = fragShaderNameBase + de::toString(m_attachmentsCount);
2682     ShaderWrapper vertexShaderModule(vkd, device, binaryCollection.get("quad-vert"), 0u);
2683     ShaderWrapper fragmentShaderModule(vkd, device, binaryCollection.get(fragShaderName), 0u);
2684     ShaderWrapper geometryShaderModule;
2685 
2686     if (m_layerCount != 1)
2687         geometryShaderModule = ShaderWrapper(vkd, device, binaryCollection.get("geom"), 0u);
2688 
2689     // Disable blending
2690     const VkPipelineColorBlendAttachmentState attachmentBlendState{
2691         VK_FALSE,
2692         VK_BLEND_FACTOR_SRC_ALPHA,
2693         VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,
2694         VK_BLEND_OP_ADD,
2695         VK_BLEND_FACTOR_ONE,
2696         VK_BLEND_FACTOR_ONE,
2697         VK_BLEND_OP_ADD,
2698         VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT};
2699     std::vector<VkPipelineColorBlendAttachmentState> attachmentBlendStates(blendStatesCount, attachmentBlendState);
2700     const VkPipelineVertexInputStateCreateInfo vertexInputState = initVulkanStructure();
2701 
2702     PipelineRenderingCreateInfoWrapper renderingCreateInfoWrapper;
2703     RenderingAttachmentLocationInfoWrapper renderingAttachmentLocationInfoWrapper;
2704     RenderingInputAttachmentIndexInfoWrapper renderingInputAttachmentIndexInfoWrapper;
2705     const tcu::UVec2 renderArea(m_width, m_height);
2706     const std::vector<VkViewport> viewports{makeViewport(renderArea)};
2707     const std::vector<VkRect2D> scissors{makeRect2D(renderArea)};
2708 
2709     const VkPipelineMultisampleStateCreateInfo multisampleState = {
2710         VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
2711         DE_NULL,
2712         (VkPipelineMultisampleStateCreateFlags)0u,
2713 
2714         sampleCount,
2715         VK_FALSE,
2716         0.0f,
2717         DE_NULL,
2718         VK_FALSE,
2719         VK_FALSE,
2720     };
2721     const VkPipelineDepthStencilStateCreateInfo depthStencilState = {
2722         VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
2723         DE_NULL,
2724         (VkPipelineDepthStencilStateCreateFlags)0u,
2725 
2726         VK_FALSE,
2727         VK_TRUE,
2728         VK_COMPARE_OP_ALWAYS,
2729         VK_FALSE,
2730         VK_TRUE,
2731         {VK_STENCIL_OP_KEEP, VK_STENCIL_OP_INCREMENT_AND_WRAP, VK_STENCIL_OP_KEEP, VK_COMPARE_OP_ALWAYS, ~0u, ~0u,
2732          0xFFu / (m_sampleCount + 1)},
2733         {VK_STENCIL_OP_KEEP, VK_STENCIL_OP_INCREMENT_AND_WRAP, VK_STENCIL_OP_KEEP, VK_COMPARE_OP_ALWAYS, ~0u, ~0u,
2734          0xFFu / (m_sampleCount + 1)},
2735 
2736         0.0f,
2737         1.0f};
2738     const VkPipelineColorBlendStateCreateInfo blendState{VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
2739                                                          DE_NULL,
2740                                                          (VkPipelineColorBlendStateCreateFlags)0u,
2741 
2742                                                          VK_FALSE,
2743                                                          VK_LOGIC_OP_COPY,
2744                                                          uint32_t(attachmentBlendStates.size()),
2745                                                          attachmentBlendStates.data(),
2746                                                          {0.0f, 0.0f, 0.0f, 0.0f}};
2747 
2748 #ifndef CTS_USES_VULKANSC
2749     const std::vector<VkFormat> colorAttachmentFormats(m_attachmentsCount, m_format);
2750     VkPipelineRenderingCreateInfo renderingCreateInfo{VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO,
2751                                                       DE_NULL,
2752                                                       0u,
2753                                                       (uint32_t)colorAttachmentFormats.size(),
2754                                                       colorAttachmentFormats.data(),
2755                                                       VK_FORMAT_UNDEFINED,
2756                                                       VK_FORMAT_UNDEFINED};
2757 
2758     std::vector<uint32_t> colorAttachmentLocationsAndInputs(colorAttachmentFormats.size());
2759     std::iota(colorAttachmentLocationsAndInputs.begin(), colorAttachmentLocationsAndInputs.end(), 0);
2760 
2761     VkRenderingAttachmentLocationInfoKHR renderingAttachmentLocationInfo = initVulkanStructure();
2762     renderingAttachmentLocationInfo.colorAttachmentCount                 = (uint32_t)colorAttachmentFormats.size();
2763     renderingAttachmentLocationInfo.pColorAttachmentLocations            = colorAttachmentLocationsAndInputs.data();
2764 
2765     VkRenderingInputAttachmentIndexInfoKHR renderingInputAttachmentIndexInfo =
2766         initVulkanStructure(&renderingAttachmentLocationInfo);
2767     renderingInputAttachmentIndexInfo.colorAttachmentCount         = (uint32_t)colorAttachmentLocationsAndInputs.size();
2768     renderingInputAttachmentIndexInfo.pColorAttachmentInputIndices = colorAttachmentLocationsAndInputs.data();
2769 
2770     if (*m_renderPass == DE_NULL)
2771     {
2772         renderingCreateInfoWrapper.ptr             = &renderingCreateInfo;
2773         renderingAttachmentLocationInfoWrapper.ptr = &renderingAttachmentLocationInfo;
2774         if (secondSubpass)
2775             renderingInputAttachmentIndexInfoWrapper.ptr = &renderingInputAttachmentIndexInfo;
2776     }
2777 #endif // CTS_USES_VULKANSC
2778 
2779     PipelineLayoutWrapper &pipelineLayout(secondSubpass ? m_pipelineLayoutPass1 : m_pipelineLayoutPass0);
2780     graphicsPipeline.setDefaultRasterizationState()
2781         .setupVertexInputState(&vertexInputState)
2782         .setupPreRasterizationShaderState(viewports, scissors, pipelineLayout, *m_renderPass, secondSubpass,
2783                                           vertexShaderModule, 0u, ShaderWrapper(), ShaderWrapper(),
2784                                           geometryShaderModule, DE_NULL, DE_NULL, renderingCreateInfoWrapper)
2785         .setupFragmentShaderState(pipelineLayout, *m_renderPass, secondSubpass, fragmentShaderModule,
2786                                   &depthStencilState, &multisampleState, 0, 0, {},
2787                                   renderingInputAttachmentIndexInfoWrapper)
2788         .setupFragmentOutputState(*m_renderPass, secondSubpass, &blendState, &multisampleState, 0, {},
2789                                   renderingAttachmentLocationInfoWrapper)
2790         .setMonolithicPipelineLayout(pipelineLayout)
2791         .buildPipeline();
2792 }
2793 
2794 class MultisampleRenderPassResolveLevelTestInstance : public MultisampleRenderPassTestInstance
2795 {
2796 public:
2797     MultisampleRenderPassResolveLevelTestInstance(Context &context, TestConfig2 config);
2798     ~MultisampleRenderPassResolveLevelTestInstance(void) = default;
2799 };
2800 
MultisampleRenderPassResolveLevelTestInstance(Context & context,TestConfig2 config)2801 MultisampleRenderPassResolveLevelTestInstance::MultisampleRenderPassResolveLevelTestInstance(Context &context,
2802                                                                                              TestConfig2 config)
2803     : MultisampleRenderPassTestInstance(context, config, config.resolveLevel)
2804 {
2805 }
2806 
2807 struct Programs
2808 {
initvkt::__anon0c42d1a50111::Programs2809     void init(vk::SourceCollections &dst, TestConfig config) const
2810     {
2811         const tcu::TextureFormat format(mapVkFormat(config.format));
2812         const tcu::TextureChannelClass channelClass(tcu::getTextureChannelClass(format.type));
2813 
2814         dst.glslSources.add("quad-vert") << glu::VertexSource(
2815             "#version 450\n"
2816             "out gl_PerVertex {\n"
2817             "\tvec4 gl_Position;\n"
2818             "};\n"
2819             "highp float;\n"
2820             "void main (void) {\n"
2821             "\tgl_Position = vec4(((gl_VertexIndex + 2) / 3) % 2 == 0 ? -1.0 : 1.0,\n"
2822             "\t                   ((gl_VertexIndex + 1) / 3) % 2 == 0 ? -1.0 : 1.0, 0.0, 1.0);\n"
2823             "}\n");
2824 
2825         if (config.layerCount > 1)
2826         {
2827             std::ostringstream src;
2828 
2829             src << "#version 450\n"
2830                 << "highp float;\n"
2831                 << "\n"
2832                 << "layout(triangles) in;\n"
2833                 << "layout(triangle_strip, max_vertices = " << 3 * 2 * config.layerCount << ") out;\n"
2834                 << "\n"
2835                 << "in gl_PerVertex {\n"
2836                 << "    vec4 gl_Position;\n"
2837                 << "} gl_in[];\n"
2838                 << "\n"
2839                 << "out gl_PerVertex {\n"
2840                 << "    vec4 gl_Position;\n"
2841                 << "};\n"
2842                 << "\n"
2843                 << "void main (void) {\n"
2844                 << "    for (int layerNdx = 0; layerNdx < " << config.layerCount << "; ++layerNdx) {\n"
2845                 << "        for(int vertexNdx = 0; vertexNdx < gl_in.length(); vertexNdx++) {\n"
2846                 << "            gl_Position = gl_in[vertexNdx].gl_Position;\n"
2847                 << "            gl_Layer    = layerNdx;\n"
2848                 << "            EmitVertex();\n"
2849                 << "        };\n"
2850                 << "        EndPrimitive();\n"
2851                 << "    };\n"
2852                 << "}\n";
2853 
2854             dst.glslSources.add("geom") << glu::GeometrySource(src.str());
2855         }
2856 
2857         const tcu::StringTemplate genericLayoutTemplate(
2858             "layout(location = ${INDEX}) out ${TYPE_PREFIX}vec4 o_color${INDEX};\n");
2859         const tcu::StringTemplate genericBodyTemplate("\to_color${INDEX} = ${TYPE_PREFIX}vec4(${COLOR_VAL});\n");
2860 
2861         if (config.testType == RESOLVE || config.testType == COMPATIBILITY)
2862         {
2863             const tcu::StringTemplate fragTemplate("#version 450\n"
2864                                                    "layout(push_constant) uniform PushConstant {\n"
2865                                                    "\thighp uint sampleMask;\n"
2866                                                    "} pushConstants;\n"
2867                                                    "${LAYOUT}"
2868                                                    "void main (void)\n"
2869                                                    "{\n"
2870                                                    "${BODY}"
2871                                                    "}\n");
2872 
2873             std::map<std::string, std::string> parameters;
2874             switch (channelClass)
2875             {
2876             case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
2877                 parameters["TYPE_PREFIX"] = "u";
2878                 parameters["COLOR_VAL"]   = "255";
2879                 break;
2880 
2881             case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
2882                 parameters["TYPE_PREFIX"] = "i";
2883                 parameters["COLOR_VAL"]   = "127";
2884                 break;
2885 
2886             case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
2887             case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
2888             case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
2889                 parameters["TYPE_PREFIX"] = "";
2890                 parameters["COLOR_VAL"]   = "1.0";
2891                 break;
2892 
2893             default:
2894                 DE_FATAL("Unknown channel class");
2895             }
2896 
2897             std::string layoutDefinitions = "";
2898             std::string shaderBody        = "\tgl_SampleMask[0] = int(pushConstants.sampleMask);\n";
2899 
2900             for (uint32_t attIdx = 0; attIdx < config.attachmentCount; ++attIdx)
2901             {
2902                 parameters["INDEX"] = de::toString(attIdx);
2903                 layoutDefinitions += genericLayoutTemplate.specialize(parameters);
2904                 shaderBody += genericBodyTemplate.specialize(parameters);
2905             }
2906 
2907             parameters["LAYOUT"] = layoutDefinitions;
2908             parameters["BODY"]   = shaderBody;
2909             dst.glslSources.add("quad-frag") << glu::FragmentSource(fragTemplate.specialize(parameters));
2910         }
2911         else // MAX_ATTACMENTS
2912         {
2913             const tcu::StringTemplate fragTemplate("#version 450\n"
2914                                                    "${LAYOUT}"
2915                                                    "void main (void)\n"
2916                                                    "{\n"
2917                                                    "${BODY}"
2918                                                    "}\n");
2919 
2920             std::map<std::string, std::string> parameters;
2921             switch (channelClass)
2922             {
2923             case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
2924                 parameters["TYPE_PREFIX"] = "u";
2925                 parameters["COLOR_VAL"]   = "0, 64, 192, 252";
2926                 break;
2927 
2928             case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
2929                 parameters["TYPE_PREFIX"] = "i";
2930                 parameters["COLOR_VAL"]   = "0, 32, 100, 124";
2931                 break;
2932 
2933             case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
2934             case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
2935             case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
2936                 parameters["TYPE_PREFIX"] = "";
2937                 parameters["COLOR_VAL"]   = "0.0, 0.4, 0.8, 1.0";
2938                 break;
2939 
2940             default:
2941                 DE_FATAL("Unknown channel class");
2942             }
2943 
2944             // parts of fragment shader for second subpass - Vulkan introduced a new uniform type and syntax to glsl for input attachments
2945             const tcu::StringTemplate subpassLayoutTemplate(
2946                 "layout (input_attachment_index = ${INDEX}, set = 0, binding = ${INDEX}) uniform "
2947                 "${TYPE_PREFIX}subpassInput i_color${INDEX};\n");
2948             const tcu::StringTemplate subpassFBodyTemplate(
2949                 "\to_color${INDEX} = subpassLoad(i_color${INDEX})*0.5 + subpassLoad(i_color${MIX_INDEX})*0.25;\n");
2950             const tcu::StringTemplate subpassIBodyTemplate(
2951                 "\to_color${INDEX} = subpassLoad(i_color${INDEX}) / 2 + subpassLoad(i_color${MIX_INDEX}) / 4;\n");
2952 
2953             bool selectIBody                               = isIntFormat(config.format) || isUintFormat(config.format);
2954             const tcu::StringTemplate &subpassBodyTemplate = selectIBody ? subpassIBodyTemplate : subpassFBodyTemplate;
2955 
2956             std::string sp0layoutDefinitions    = "";
2957             std::string sp0shaderBody           = "";
2958             std::string sp1inLayoutDefinitions  = "";
2959             std::string sp1outLayoutDefinitions = "";
2960             std::string sp1shaderBody           = "";
2961 
2962             uint32_t halfAttachments = config.attachmentCount / 2;
2963             for (uint32_t attIdx = 0; attIdx < config.attachmentCount; ++attIdx)
2964             {
2965                 parameters["INDEX"] = de::toString(attIdx);
2966 
2967                 sp0layoutDefinitions += genericLayoutTemplate.specialize(parameters);
2968                 sp0shaderBody += genericBodyTemplate.specialize(parameters);
2969 
2970                 sp1inLayoutDefinitions += subpassLayoutTemplate.specialize(parameters);
2971                 if (attIdx < halfAttachments)
2972                 {
2973                     // we are combining pairs of input attachments to produce half the number of outputs
2974                     parameters["MIX_INDEX"] = de::toString(halfAttachments + attIdx);
2975                     sp1outLayoutDefinitions += genericLayoutTemplate.specialize(parameters);
2976                     sp1shaderBody += subpassBodyTemplate.specialize(parameters);
2977                 }
2978             }
2979 
2980             // construct fragment shaders for subpass1 and subpass2; note that there
2981             // is different shader definition depending on number of attachments
2982             std::string nameBase    = "quad-frag-sp";
2983             std::string namePostfix = de::toString(config.attachmentCount);
2984             parameters["LAYOUT"]    = sp0layoutDefinitions;
2985             parameters["BODY"]      = sp0shaderBody;
2986             dst.glslSources.add(nameBase + "0-" + namePostfix)
2987                 << glu::FragmentSource(fragTemplate.specialize(parameters));
2988             parameters["LAYOUT"] = sp1inLayoutDefinitions + sp1outLayoutDefinitions;
2989             parameters["BODY"]   = sp1shaderBody;
2990             dst.glslSources.add(nameBase + "1-" + namePostfix)
2991                 << glu::FragmentSource(fragTemplate.specialize(parameters));
2992         }
2993     }
2994 };
2995 
2996 template <class TestConfigType>
checkSupport(Context & context,TestConfigType config)2997 void checkSupport(Context &context, TestConfigType config)
2998 {
2999 #ifndef CTS_USES_VULKANSC
3000     if (config.format == VK_FORMAT_A8_UNORM_KHR)
3001         context.requireDeviceFunctionality("VK_KHR_maintenance5");
3002 #endif // CTS_USES_VULKANSC
3003 
3004     if (config.layerCount > 1)
3005         context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_GEOMETRY_SHADER);
3006 
3007     if (config.groupParams->renderingType == RENDERING_TYPE_RENDERPASS2)
3008         context.requireDeviceFunctionality("VK_KHR_create_renderpass2");
3009 
3010     const InstanceInterface &vki                    = context.getInstanceInterface();
3011     vk::VkPhysicalDevice physicalDevice             = context.getPhysicalDevice();
3012     const vk::VkPhysicalDeviceProperties properties = vk::getPhysicalDeviceProperties(vki, physicalDevice);
3013 
3014     checkPipelineConstructionRequirements(vki, physicalDevice, config.groupParams->pipelineConstructionType);
3015     if (config.groupParams->renderingType == RENDERING_TYPE_DYNAMIC_RENDERING)
3016     {
3017         context.requireDeviceFunctionality("VK_KHR_dynamic_rendering");
3018         if (config.testType == MAX_ATTACHMENTS)
3019         {
3020             context.requireDeviceFunctionality("VK_KHR_dynamic_rendering_local_read");
3021             if (config.attachmentCount > properties.limits.maxColorAttachments)
3022                 TCU_THROW(NotSupportedError, "Required number of color attachments not supported.");
3023         }
3024     }
3025 
3026 #ifndef CTS_USES_VULKANSC
3027     if (context.isDeviceFunctionalitySupported("VK_KHR_portability_subset") &&
3028         !context.getPortabilitySubsetFeatures().multisampleArrayImage &&
3029         (config.sampleCount != VK_SAMPLE_COUNT_1_BIT) && (config.layerCount != 1))
3030     {
3031         TCU_THROW(
3032             NotSupportedError,
3033             "VK_KHR_portability_subset: Implementation does not support image array with multiple samples per texel");
3034     }
3035 #endif // CTS_USES_VULKANSC
3036 
3037     if (config.attachmentCount > properties.limits.maxColorAttachments)
3038         TCU_THROW(NotSupportedError, "Required number of color attachments not supported.");
3039 
3040     if (config.testType == MAX_ATTACHMENTS &&
3041         config.attachmentCount > properties.limits.maxPerStageDescriptorInputAttachments)
3042         TCU_THROW(NotSupportedError, "Required number of per stage descriptor input attachments not supported.");
3043 }
3044 
formatToName(VkFormat format)3045 std::string formatToName(VkFormat format)
3046 {
3047     const std::string formatStr = de::toString(format);
3048     const std::string prefix    = "VK_FORMAT_";
3049 
3050     DE_ASSERT(formatStr.substr(0, prefix.length()) == prefix);
3051 
3052     return de::toLower(formatStr.substr(prefix.length()));
3053 }
3054 
initTests(tcu::TestCaseGroup * group,const SharedGroupParams groupParams)3055 void initTests(tcu::TestCaseGroup *group, const SharedGroupParams groupParams)
3056 {
3057     static const VkFormat formats[] = {
3058         VK_FORMAT_R5G6B5_UNORM_PACK16,
3059         VK_FORMAT_R8_UNORM,
3060         VK_FORMAT_R8_SNORM,
3061         VK_FORMAT_R8_UINT,
3062         VK_FORMAT_R8_SINT,
3063 #ifndef CTS_USES_VULKANSC
3064         VK_FORMAT_A8_UNORM_KHR,
3065 #endif // CTS_USES_VULKANSC
3066         VK_FORMAT_R8G8_UNORM,
3067         VK_FORMAT_R8G8_SNORM,
3068         VK_FORMAT_R8G8_UINT,
3069         VK_FORMAT_R8G8_SINT,
3070         VK_FORMAT_R8G8B8A8_UNORM,
3071         VK_FORMAT_R8G8B8A8_SNORM,
3072         VK_FORMAT_R8G8B8A8_UINT,
3073         VK_FORMAT_R8G8B8A8_SINT,
3074         VK_FORMAT_R8G8B8A8_SRGB,
3075         VK_FORMAT_A8B8G8R8_UNORM_PACK32,
3076         VK_FORMAT_A8B8G8R8_SNORM_PACK32,
3077         VK_FORMAT_A8B8G8R8_UINT_PACK32,
3078         VK_FORMAT_A8B8G8R8_SINT_PACK32,
3079         VK_FORMAT_A8B8G8R8_SRGB_PACK32,
3080         VK_FORMAT_B8G8R8A8_UNORM,
3081         VK_FORMAT_B8G8R8A8_SRGB,
3082         VK_FORMAT_A2R10G10B10_UNORM_PACK32,
3083         VK_FORMAT_A2B10G10R10_UNORM_PACK32,
3084         VK_FORMAT_A2B10G10R10_UINT_PACK32,
3085         VK_FORMAT_R16_UNORM,
3086         VK_FORMAT_R16_SNORM,
3087         VK_FORMAT_R16_UINT,
3088         VK_FORMAT_R16_SINT,
3089         VK_FORMAT_R16_SFLOAT,
3090         VK_FORMAT_R16G16_UNORM,
3091         VK_FORMAT_R16G16_SNORM,
3092         VK_FORMAT_R16G16_UINT,
3093         VK_FORMAT_R16G16_SINT,
3094         VK_FORMAT_R16G16_SFLOAT,
3095         VK_FORMAT_R16G16B16A16_UNORM,
3096         VK_FORMAT_R16G16B16A16_SNORM,
3097         VK_FORMAT_R16G16B16A16_UINT,
3098         VK_FORMAT_R16G16B16A16_SINT,
3099         VK_FORMAT_R16G16B16A16_SFLOAT,
3100         VK_FORMAT_R32_UINT,
3101         VK_FORMAT_R32_SINT,
3102         VK_FORMAT_R32_SFLOAT,
3103         VK_FORMAT_R32G32_UINT,
3104         VK_FORMAT_R32G32_SINT,
3105         VK_FORMAT_R32G32_SFLOAT,
3106         VK_FORMAT_R32G32B32A32_UINT,
3107         VK_FORMAT_R32G32B32A32_SINT,
3108         VK_FORMAT_R32G32B32A32_SFLOAT,
3109         VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16,
3110     };
3111     const uint32_t sampleCounts[]  = {2u, 4u, 8u};
3112     const uint32_t layerCounts[]   = {1u, 3u, 6u};
3113     const uint32_t resolveLevels[] = {2u, 3u, 4u};
3114     tcu::TestContext &testCtx(group->getTestContext());
3115 
3116     for (size_t layerCountNdx = 0; layerCountNdx < DE_LENGTH_OF_ARRAY(layerCounts); layerCountNdx++)
3117     {
3118         const uint32_t layerCount(layerCounts[layerCountNdx]);
3119         const std::string layerGroupName("layers_" + de::toString(layerCount));
3120         de::MovePtr<tcu::TestCaseGroup> layerGroup(new tcu::TestCaseGroup(testCtx, layerGroupName.c_str()));
3121 
3122         for (size_t formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); formatNdx++)
3123         {
3124             const VkFormat format(formats[formatNdx]);
3125             const std::string formatName(formatToName(format));
3126             de::MovePtr<tcu::TestCaseGroup> formatGroup(new tcu::TestCaseGroup(testCtx, formatName.c_str()));
3127 
3128             for (size_t sampleCountNdx = 0; sampleCountNdx < DE_LENGTH_OF_ARRAY(sampleCounts); sampleCountNdx++)
3129             {
3130                 const uint32_t sampleCount(sampleCounts[sampleCountNdx]);
3131 
3132                 // Skip this test as it is rather slow
3133                 if (layerCount == 6 && sampleCount == 8)
3134                     continue;
3135 
3136                 // Reduce number of tests for dynamic rendering cases where secondary command buffer is used
3137                 if (groupParams->useSecondaryCmdBuffer && ((sampleCount > 2u) || (layerCount > 3u)))
3138                     continue;
3139 
3140                 std::string testName("samples_" + de::toString(sampleCount));
3141                 const TestConfig testConfig{RESOLVE, format, sampleCount, layerCount, 0, 4u, 32u, 32u, groupParams};
3142 
3143                 // repeat only dynamic_rendering_local_read tests for GPL
3144                 if (groupParams->pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC)
3145                 {
3146                     formatGroup->addChild(new InstanceFactory1WithSupport<MultisampleRenderPassTestInstance, TestConfig,
3147                                                                           FunctionSupport1<TestConfig>, Programs>(
3148                         testCtx, testName.c_str(), testConfig,
3149                         typename FunctionSupport1<TestConfig>::Args(checkSupport, testConfig)));
3150 
3151                     const TestConfig testConfigBaseLayer{RESOLVE, format, sampleCount, layerCount, 1,
3152                                                          4u,      32u,    32u,         groupParams};
3153                     std::string testNameBaseLayer("samples_" + de::toString(sampleCount) + "_baseLayer1");
3154 
3155                     formatGroup->addChild(new InstanceFactory1WithSupport<MultisampleRenderPassTestInstance, TestConfig,
3156                                                                           FunctionSupport1<TestConfig>, Programs>(
3157                         testCtx, testNameBaseLayer.c_str(), testConfigBaseLayer,
3158                         typename FunctionSupport1<TestConfig>::Args(checkSupport, testConfigBaseLayer)));
3159 
3160                     for (uint32_t resolveLevel : resolveLevels)
3161                     {
3162                         const TestConfig2 testConfig2(testConfig, resolveLevel);
3163                         std::string resolveLevelTestNameStr(testName + "_resolve_level_" + de::toString(resolveLevel));
3164                         const char *resolveLevelTestName = resolveLevelTestNameStr.c_str();
3165 
3166                         formatGroup->addChild(
3167                             new InstanceFactory1WithSupport<MultisampleRenderPassResolveLevelTestInstance, TestConfig2,
3168                                                             FunctionSupport1<TestConfig2>, Programs>(
3169                                 testCtx, resolveLevelTestName, testConfig2,
3170                                 typename FunctionSupport1<TestConfig2>::Args(checkSupport, testConfig2)));
3171 
3172                         // Reduce number of tests for dynamic rendering cases where secondary command buffer is used
3173                         if (groupParams->useSecondaryCmdBuffer)
3174                             break;
3175                     }
3176                 }
3177 
3178                 // MaxAttachmenstsRenderPassTest is ment to test extreme cases where applications might consume all available on-chip
3179                 // memory. This is achieved by using maxColorAttachments attachments and two subpasses, but during test creation we
3180                 // dont know what is the maximal number of attachments (spirv tools are not available on all platforms) so we cant
3181                 // construct shaders during test execution. To be able to test this we need to execute tests for all available
3182                 // numbers of attachments despite the fact that we are only interested in the maximal number; test construction code
3183                 // assumes that the number of attachments is power of two
3184                 if ((layerCount == 1) && (groupParams->useSecondaryCmdBuffer ==
3185                                           groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass))
3186                 {
3187                     for (uint32_t power = 2; power < 5; ++power)
3188                     {
3189                         uint32_t attachmentCount = 1 << power;
3190                         std::string maxAttName   = "max_attachments_" + de::toString(attachmentCount) + "_" + testName;
3191 
3192                         TestConfig maxAttachmentsTestConfig      = testConfig;
3193                         maxAttachmentsTestConfig.testType        = MAX_ATTACHMENTS;
3194                         maxAttachmentsTestConfig.attachmentCount = attachmentCount;
3195 
3196                         formatGroup->addChild(
3197                             new InstanceFactory1WithSupport<MaxAttachmenstsRenderPassTestInstance, TestConfig,
3198                                                             FunctionSupport1<TestConfig>, Programs>(
3199                                 testCtx, maxAttName.c_str(), maxAttachmentsTestConfig,
3200                                 typename FunctionSupport1<TestConfig>::Args(checkSupport, maxAttachmentsTestConfig)));
3201                     }
3202 
3203                     if (groupParams->renderingType != RENDERING_TYPE_DYNAMIC_RENDERING)
3204                     {
3205                         std::string compatibilityTestName = "compatibility_" + testName;
3206 
3207                         TestConfig compatibilityTestConfig      = testConfig;
3208                         compatibilityTestConfig.testType        = COMPATIBILITY;
3209                         compatibilityTestConfig.attachmentCount = 1;
3210 
3211                         formatGroup->addChild(
3212                             new InstanceFactory1WithSupport<MultisampleRenderPassTestInstance, TestConfig,
3213                                                             FunctionSupport1<TestConfig>, Programs>(
3214                                 testCtx, compatibilityTestName.c_str(), compatibilityTestConfig,
3215                                 typename FunctionSupport1<TestConfig>::Args(checkSupport, compatibilityTestConfig)));
3216                     }
3217                 }
3218             }
3219 
3220             if (layerCount == 1)
3221                 group->addChild(formatGroup.release());
3222             else
3223                 layerGroup->addChild(formatGroup.release());
3224         }
3225 
3226         if (layerCount != 1)
3227             group->addChild(layerGroup.release());
3228     }
3229 }
3230 
3231 } // namespace
3232 
createRenderPassMultisampleResolveTests(tcu::TestContext & testCtx,const renderpass::SharedGroupParams groupParams)3233 tcu::TestCaseGroup *createRenderPassMultisampleResolveTests(tcu::TestContext &testCtx,
3234                                                             const renderpass::SharedGroupParams groupParams)
3235 {
3236     return createTestGroup(testCtx, "multisample_resolve", initTests, groupParams);
3237 }
3238 
3239 } // namespace vkt
3240