1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2019 The Khronos Group Inc.
6  * Copyright (c) 2019 Valve Corporation.
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  *//*!
21  * \file
22  * \brief Tests vkCmdClearAttachments with unused attachments.
23  *//*--------------------------------------------------------------------*/
24 
25 #include "vktRenderPassUnusedClearAttachmentTests.hpp"
26 #include "pipeline/vktPipelineImageUtil.hpp"
27 #include "vktRenderPassTestsUtil.hpp"
28 #include "vkQueryUtil.hpp"
29 #include "vkRefUtil.hpp"
30 #include "vkCmdUtil.hpp"
31 #include "vkObjUtil.hpp"
32 #include "vkImageUtil.hpp"
33 #include "tcuTextureUtil.hpp"
34 #include <sstream>
35 #include <functional>
36 #include <vector>
37 #include <string>
38 #include <memory>
39 
40 namespace vkt
41 {
42 namespace renderpass
43 {
44 
45 namespace
46 {
47 
48 constexpr size_t COLOR_ATTACHMENTS_NUMBER = 4; // maxColorAttachments is guaranteed to be at least 4.
49 constexpr VkFormat FORMAT_COLOR           = VK_FORMAT_R8G8B8A8_UNORM;
50 constexpr VkFormat FORMAT_DEPTH           = VK_FORMAT_D32_SFLOAT;
51 constexpr VkFormat FORMAT_STENCIL         = VK_FORMAT_S8_UINT;
52 constexpr VkFormat FORMAT_DEPTH_STENCIL   = VK_FORMAT_D32_SFLOAT_S8_UINT;
53 const bool DE_BOOL_VALUES[]               = {false, true};
54 
55 enum DepthStencilType
56 {
57     DEPTH_STENCIL_NONE         = 0,
58     DEPTH_STENCIL_DEPTH_ONLY   = 1,
59     DEPTH_STENCIL_STENCIL_ONLY = 2,
60     DEPTH_STENCIL_BOTH         = 3,
61     DEPTH_STENCIL_MAX_ENUM     = 4
62 };
63 
getFormatBriefName(VkFormat format)64 std::string getFormatBriefName(VkFormat format)
65 {
66     switch (format)
67     {
68     case VK_FORMAT_D32_SFLOAT:
69         return "d32";
70     case VK_FORMAT_S8_UINT:
71         return "s8";
72     case VK_FORMAT_D32_SFLOAT_S8_UINT:
73         return "d32s8";
74     default:
75         break;
76     }
77 
78     return "";
79 }
80 
depthStencilTypeName(DepthStencilType type,VkFormat format)81 std::string depthStencilTypeName(DepthStencilType type, VkFormat format)
82 {
83     DE_ASSERT(type >= DEPTH_STENCIL_NONE && type < DEPTH_STENCIL_MAX_ENUM);
84 
85     const std::string formatName = getFormatBriefName(format);
86 
87     switch (type)
88     {
89     case DEPTH_STENCIL_NONE:
90         return "nods";
91     case DEPTH_STENCIL_DEPTH_ONLY:
92         return "depthonly_" + formatName;
93     case DEPTH_STENCIL_STENCIL_ONLY:
94         return "stencilonly_" + formatName;
95     case DEPTH_STENCIL_BOTH:
96         return "depthstencil_" + formatName;
97     default:
98         return "UNKNOWN"; // Unreachable.
99     }
100 
101     return "UNKNOWN"; // Unreachable.
102 }
103 
getClearAspectMask(DepthStencilType type)104 VkImageAspectFlags getClearAspectMask(DepthStencilType type)
105 {
106     VkImageAspectFlags aspectMask = 0u;
107 
108     if (type == DEPTH_STENCIL_DEPTH_ONLY || type == DEPTH_STENCIL_BOTH)
109         aspectMask |= VK_IMAGE_ASPECT_DEPTH_BIT;
110 
111     if (type == DEPTH_STENCIL_STENCIL_ONLY || type == DEPTH_STENCIL_BOTH)
112         aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT;
113 
114     return aspectMask;
115 }
116 
getFormatAspectMask(VkFormat format)117 VkImageAspectFlags getFormatAspectMask(VkFormat format)
118 {
119     const auto order              = mapVkFormat(format).order;
120     VkImageAspectFlags aspectMask = 0u;
121 
122     if (tcu::hasDepthComponent(order))
123         aspectMask |= VK_IMAGE_ASPECT_DEPTH_BIT;
124 
125     if (tcu::hasStencilComponent(order))
126         aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT;
127 
128     if (!aspectMask)
129         aspectMask |= VK_IMAGE_ASPECT_COLOR_BIT;
130 
131     return aspectMask;
132 }
133 
getFormats(DepthStencilType type)134 std::vector<VkFormat> getFormats(DepthStencilType type)
135 {
136     DE_ASSERT(type >= DEPTH_STENCIL_NONE && type < DEPTH_STENCIL_MAX_ENUM);
137 
138     std::vector<VkFormat> formats;
139 
140     if (type != DEPTH_STENCIL_NONE)
141         formats.push_back(FORMAT_DEPTH_STENCIL);
142     else
143         formats.push_back(VK_FORMAT_UNDEFINED);
144 
145     if (type == DEPTH_STENCIL_DEPTH_ONLY)
146         formats.push_back(FORMAT_DEPTH);
147     else if (type == DEPTH_STENCIL_STENCIL_ONLY)
148         formats.push_back(FORMAT_STENCIL);
149 
150     return formats;
151 }
152 
isDepthOnly(DepthStencilType type)153 bool isDepthOnly(DepthStencilType type)
154 {
155     return (type == DEPTH_STENCIL_DEPTH_ONLY);
156 }
157 
isStencilOnly(DepthStencilType type)158 bool isStencilOnly(DepthStencilType type)
159 {
160     return (type == DEPTH_STENCIL_STENCIL_ONLY);
161 }
162 
hasDepthStencil(DepthStencilType type)163 bool hasDepthStencil(DepthStencilType type)
164 {
165     return (type != DEPTH_STENCIL_NONE);
166 }
167 
168 struct TestParams
169 {
TestParamsvkt::renderpass::__anon0918147e0111::TestParams170     TestParams(size_t numColorAttachments, DepthStencilType depthStencilType_, bool depthStencilUsed_,
171                VkFormat depthStencilFormat_, const SharedGroupParams groupParams_)
172         : colorUsed(numColorAttachments, false)
173         , depthStencilType(depthStencilType_)
174         , depthStencilUsed(depthStencilUsed_)
175         , depthStencilFormat(depthStencilFormat_)
176         , groupParams(groupParams_)
177     {
178     }
179 
180     std::vector<bool> colorUsed;
181     DepthStencilType depthStencilType;
182     bool depthStencilUsed;
183     VkFormat depthStencilFormat;
184     const SharedGroupParams groupParams;
185 };
186 
187 class UnusedClearAttachmentTestInstance : public vkt::TestInstance
188 {
189 public:
190     UnusedClearAttachmentTestInstance(Context &context, const TestParams &testParams);
~UnusedClearAttachmentTestInstance(void)191     virtual ~UnusedClearAttachmentTestInstance(void)
192     {
193     }
194     virtual tcu::TestStatus iterate(void);
195     template <typename RenderpassSubpass>
196     void createCommandBuffer(const DeviceInterface &vk, VkDevice vkDevice);
197 
198 #ifndef CTS_USES_VULKANSC
199     void createCommandBufferDynamicRendering(const DeviceInterface &vk, VkDevice vkDevice);
200 #endif // CTS_USES_VULKANSC
201 
202 private:
203     static constexpr uint32_t kImageWidth  = 32;
204     static constexpr uint32_t kImageHeight = 32;
205     const tcu::UVec2 m_renderSize          = {kImageWidth, kImageHeight};
206 
207     VkClearValue m_initialColor;
208     VkClearValue m_initialColorDepth;
209     VkClearValue m_clearColor;
210     VkClearValue m_clearColorDepth;
211 
212     const TestParams m_testParams;
213 
214     std::vector<Move<VkImage>> m_colorImages;
215     std::vector<de::MovePtr<Allocation>> m_colorImageAllocs;
216     std::vector<Move<VkImageView>> m_colorAttachmentViews;
217 
218     Move<VkImage> m_depthImage;
219     de::MovePtr<Allocation> m_depthImageAlloc;
220     Move<VkImageView> m_depthAttachmentView;
221 
222     Move<VkRenderPass> m_renderPass;
223     Move<VkFramebuffer> m_framebuffer;
224     Move<VkShaderModule> m_vertexShaderModule;
225     Move<VkShaderModule> m_fragmentShaderModule;
226     Move<VkDescriptorSetLayout> m_descriptorSetLayout;
227     Move<VkPipelineLayout> m_pipelineLayout;
228     Move<VkPipeline> m_graphicsPipeline;
229     Move<VkCommandPool> m_cmdPool;
230     Move<VkCommandBuffer> m_cmdBuffer;
231     Move<VkCommandBuffer> m_secCmdBuffer;
232 };
233 
234 class UnusedClearAttachmentTest : public vkt::TestCase
235 {
236 public:
UnusedClearAttachmentTest(tcu::TestContext & testContext,const std::string & name,const TestParams & testParams)237     UnusedClearAttachmentTest(tcu::TestContext &testContext, const std::string &name, const TestParams &testParams)
238         : vkt::TestCase(testContext, name)
239         , m_testParams(testParams)
240     {
241     }
~UnusedClearAttachmentTest(void)242     virtual ~UnusedClearAttachmentTest(void)
243     {
244     }
245     virtual void initPrograms(SourceCollections &sourceCollections) const;
246     virtual TestInstance *createInstance(Context &context) const;
247     virtual void checkSupport(Context &context) const;
248 
249 private:
250     const TestParams m_testParams;
251 };
252 
checkFormatSupported(Context & context,VkFormat format,VkImageUsageFlags usage)253 void checkFormatSupported(Context &context, VkFormat format, VkImageUsageFlags usage)
254 {
255     VkResult result;
256     VkImageFormatProperties properties;
257 
258     result = context.getInstanceInterface().getPhysicalDeviceImageFormatProperties(
259         context.getPhysicalDevice(), format, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL, usage, 0, &properties);
260 
261     if (result == VK_ERROR_FORMAT_NOT_SUPPORTED)
262     {
263         std::ostringstream msg;
264         msg << "Format " << format << " not supported for usage flags 0x" << std::hex << usage;
265         TCU_THROW(NotSupportedError, msg.str());
266     }
267 
268     VK_CHECK(result);
269 }
270 
checkSupport(Context & context) const271 void UnusedClearAttachmentTest::checkSupport(Context &context) const
272 {
273     // Check for renderpass2 extension if used
274     if (m_testParams.groupParams->renderingType == RENDERING_TYPE_RENDERPASS2)
275         context.requireDeviceFunctionality("VK_KHR_create_renderpass2");
276 
277     // Check for dynamic_rendering extension if used
278     if (m_testParams.groupParams->renderingType == RENDERING_TYPE_DYNAMIC_RENDERING)
279         context.requireDeviceFunctionality("VK_KHR_dynamic_rendering");
280 
281     // Check support for the needed color, depth and stencil formats.
282     if (!m_testParams.colorUsed.empty())
283         checkFormatSupported(context, FORMAT_COLOR, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
284 
285     if (hasDepthStencil(m_testParams.depthStencilType))
286         checkFormatSupported(context, m_testParams.depthStencilFormat, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT);
287 }
288 
createInstance(Context & context) const289 TestInstance *UnusedClearAttachmentTest::createInstance(Context &context) const
290 {
291     return new UnusedClearAttachmentTestInstance(context, m_testParams);
292 }
293 
294 // These shaders are needed to create the graphics pipeline, but they will not be actually used because we will not draw anything.
initPrograms(SourceCollections & sourceCollections) const295 void UnusedClearAttachmentTest::initPrograms(SourceCollections &sourceCollections) const
296 {
297     // Vertex shader.
298     sourceCollections.glslSources.add("vert_shader") << glu::VertexSource("#version 450\n"
299                                                                           "precision highp float;\n"
300                                                                           "layout(location = 0) in vec4 position;\n"
301                                                                           "layout(location = 0) out vec4 vtxColor;\n"
302                                                                           "void main (void)\n"
303                                                                           "{\n"
304                                                                           "\tgl_Position = position;\n"
305                                                                           "\tvtxColor = vec4(0.5, 0.5, 0.5, 1.0);\n"
306                                                                           "}\n");
307 
308     // Fragment shader.
309     std::ostringstream fragmentSource;
310 
311     fragmentSource << "#version 450\n"
312                    << "precision highp float;\n"
313                    << "layout(location = 0) in vec4 vtxColor;\n";
314 
315     for (size_t i = 0; i < m_testParams.colorUsed.size(); ++i)
316     {
317         if (m_testParams.colorUsed[i])
318             fragmentSource << "layout(location = " << i << ") out vec4 fragColor" << i << ";\n";
319     }
320 
321     fragmentSource << "void main (void)\n"
322                    << "{\n";
323 
324     for (size_t i = 0; i < m_testParams.colorUsed.size(); ++i)
325     {
326         if (m_testParams.colorUsed[i])
327             fragmentSource << "\tfragColor" << i << " = vtxColor;\n";
328     }
329 
330     fragmentSource << "}\n";
331 
332     sourceCollections.glslSources.add("frag_shader") << glu::FragmentSource(fragmentSource.str());
333 }
334 
335 // Create a render pass for this use case.
336 template <typename AttachmentDesc, typename AttachmentRef, typename SubpassDesc, typename SubpassDep,
337           typename RenderPassCreateInfo>
createRenderPass(const DeviceInterface & vk,VkDevice vkDevice,const TestParams testParams)338 Move<VkRenderPass> createRenderPass(const DeviceInterface &vk, VkDevice vkDevice, const TestParams testParams)
339 {
340     const VkImageAspectFlags colorAspectMask   = VK_IMAGE_ASPECT_COLOR_BIT;
341     const VkImageAspectFlags dsClearAspectMask = getClearAspectMask(testParams.depthStencilType);
342     const bool isDepthStencil                  = hasDepthStencil(testParams.depthStencilType);
343 
344     // Create attachment descriptions.
345     const AttachmentDesc attachmentDescription(
346         DE_NULL,                                  // const void*                        pNext
347         (VkAttachmentDescriptionFlags)0,          // VkAttachmentDescriptionFlags        flags
348         FORMAT_COLOR,                             // VkFormat                            format
349         VK_SAMPLE_COUNT_1_BIT,                    // VkSampleCountFlagBits            samples
350         VK_ATTACHMENT_LOAD_OP_LOAD,               // VkAttachmentLoadOp                loadOp
351         VK_ATTACHMENT_STORE_OP_STORE,             // VkAttachmentStoreOp                storeOp
352         VK_ATTACHMENT_LOAD_OP_DONT_CARE,          // VkAttachmentLoadOp                stencilLoadOp
353         VK_ATTACHMENT_STORE_OP_DONT_CARE,         // VkAttachmentStoreOp                stencilStoreOp
354         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout                    initialLayout
355         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL  // VkImageLayout                    finalLayout
356     );
357     std::vector<AttachmentDesc> attachmentDescriptions(testParams.colorUsed.size(), attachmentDescription);
358 
359     if (isDepthStencil)
360     {
361         const bool depthOnly   = isDepthOnly(testParams.depthStencilType);
362         const bool stencilOnly = isStencilOnly(testParams.depthStencilType);
363         const VkAttachmentLoadOp depthLoadOp =
364             (stencilOnly ? VK_ATTACHMENT_LOAD_OP_DONT_CARE : VK_ATTACHMENT_LOAD_OP_LOAD);
365         const VkAttachmentStoreOp depthStoreOp =
366             (stencilOnly ? VK_ATTACHMENT_STORE_OP_DONT_CARE : VK_ATTACHMENT_STORE_OP_STORE);
367         const VkAttachmentLoadOp stencilLoadOp =
368             (depthOnly ? VK_ATTACHMENT_LOAD_OP_DONT_CARE : VK_ATTACHMENT_LOAD_OP_LOAD);
369         const VkAttachmentStoreOp stencilStoreOp =
370             (depthOnly ? VK_ATTACHMENT_STORE_OP_DONT_CARE : VK_ATTACHMENT_STORE_OP_STORE);
371 
372         attachmentDescriptions.emplace_back(
373             nullptr,                                          // const void*                        pNext
374             (VkAttachmentDescriptionFlags)0,                  // VkAttachmentDescriptionFlags        flags
375             testParams.depthStencilFormat,                    // VkFormat                            format
376             VK_SAMPLE_COUNT_1_BIT,                            // VkSampleCountFlagBits            samples
377             depthLoadOp,                                      // VkAttachmentLoadOp                loadOp
378             depthStoreOp,                                     // VkAttachmentStoreOp                storeOp
379             stencilLoadOp,                                    // VkAttachmentLoadOp                stencilLoadOp
380             stencilStoreOp,                                   // VkAttachmentStoreOp                stencilStoreOp
381             VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, // VkImageLayout                    initialLayout
382             VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL  // VkImageLayout                    finalLayout
383         );
384     }
385 
386     // Mark attachments as used or not depending on the test parameters.
387     std::vector<AttachmentRef> attachmentReferences;
388     for (size_t i = 0; i < testParams.colorUsed.size(); ++i)
389     {
390         attachmentReferences.push_back(
391             AttachmentRef(DE_NULL, // const void*            pNext
392                           (testParams.colorUsed[i] ? static_cast<uint32_t>(i) :
393                                                      VK_ATTACHMENT_UNUSED), // uint32_t                attachment
394                           VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,         // VkImageLayout        layout
395                           colorAspectMask                                   // VkImageAspectFlags    aspectMask
396                           ));
397     }
398 
399     std::unique_ptr<AttachmentRef> depthAttachmentRef;
400     if (isDepthStencil)
401     {
402         depthAttachmentRef.reset(new AttachmentRef(
403             DE_NULL,
404             (testParams.depthStencilUsed ? static_cast<uint32_t>(testParams.colorUsed.size()) : VK_ATTACHMENT_UNUSED),
405             VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, dsClearAspectMask));
406     }
407 
408     // Create subpass description with the previous color attachment references.
409     const SubpassDesc subpassDescription(
410         DE_NULL,
411         (VkSubpassDescriptionFlags)0,                       // VkSubpassDescriptionFlags        flags
412         VK_PIPELINE_BIND_POINT_GRAPHICS,                    // VkPipelineBindPoint                pipelineBindPoint
413         0u,                                                 // uint32_t                            viewMask
414         0u,                                                 // uint32_t                            inputAttachmentCount
415         DE_NULL,                                            // const VkAttachmentReference*        pInputAttachments
416         static_cast<uint32_t>(attachmentReferences.size()), // uint32_t                            colorAttachmentCount
417         (attachmentReferences.empty() ?
418              DE_NULL :
419              attachmentReferences.data()), // const VkAttachmentReference*        pColorAttachments
420         DE_NULL,                           // const VkAttachmentReference*        pResolveAttachments
421         (depthAttachmentRef ? depthAttachmentRef.get() :
422                               DE_NULL), // const VkAttachmentReference*        pDepthStencilAttachment
423         0u,                             // uint32_t                            preserveAttachmentCount
424         DE_NULL                         // const uint32_t*                    pPreserveAttachments
425     );
426 
427     const RenderPassCreateInfo renderPassInfo(
428         DE_NULL,                                              // const void*                        pNext
429         (VkRenderPassCreateFlags)0,                           // VkRenderPassCreateFlags            flags
430         static_cast<uint32_t>(attachmentDescriptions.size()), // uint32_t                            attachmentCount
431         (attachmentDescriptions.empty() ?
432              DE_NULL :
433              attachmentDescriptions.data()), // const VkAttachmentDescription*    pAttachments
434         1u,                                  // uint32_t                            subpassCount
435         &subpassDescription,                 // const VkSubpassDescription*        pSubpasses
436         0u,                                  // uint32_t                            dependencyCount
437         DE_NULL,                             // const VkSubpassDependency*        pDependencies
438         0u,                                  // uint32_t                            correlatedViewMaskCount
439         DE_NULL                              // const uint32_t*                    pCorrelatedViewMasks
440     );
441 
442     return renderPassInfo.createRenderPass(vk, vkDevice);
443 }
444 
UnusedClearAttachmentTestInstance(Context & context,const TestParams & testParams)445 UnusedClearAttachmentTestInstance::UnusedClearAttachmentTestInstance(Context &context, const TestParams &testParams)
446     : vkt::TestInstance(context)
447     , m_testParams(testParams)
448 {
449     // Initial color for all images.
450     m_initialColor.color.float32[0] = 0.0f;
451     m_initialColor.color.float32[1] = 0.0f;
452     m_initialColor.color.float32[2] = 0.0f;
453     m_initialColor.color.float32[3] = 1.0f;
454 
455     m_initialColorDepth.depthStencil.depth   = 1.0f;
456     m_initialColorDepth.depthStencil.stencil = 0u;
457 
458     // Clear color for used attachments.
459     m_clearColor.color.float32[0] = 1.0f;
460     m_clearColor.color.float32[1] = 1.0f;
461     m_clearColor.color.float32[2] = 1.0f;
462     m_clearColor.color.float32[3] = 1.0f;
463 
464     m_clearColorDepth.depthStencil.depth   = 0.0f;
465     m_clearColorDepth.depthStencil.stencil = 255u;
466 
467     const DeviceInterface &vk       = m_context.getDeviceInterface();
468     const VkDevice vkDevice         = m_context.getDevice();
469     const uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
470     SimpleAllocator memAlloc(
471         vk, vkDevice,
472         getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
473     const VkComponentMapping componentMapping = {VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY,
474                                                  VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY};
475 
476     // Create color images.
477     {
478         const VkImageCreateInfo colorImageParams = {
479             VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
480             DE_NULL,                             // const void* pNext;
481             0u,                                  // VkImageCreateFlags flags;
482             VK_IMAGE_TYPE_2D,                    // VkImageType imageType;
483             FORMAT_COLOR,                        // VkFormat format;
484             {kImageWidth, kImageHeight, 1u},     // VkExtent3D extent;
485             1u,                                  // uint32_t mipLevels;
486             1u,                                  // uint32_t arrayLayers;
487             VK_SAMPLE_COUNT_1_BIT,               // VkSampleCountFlagBits samples;
488             VK_IMAGE_TILING_OPTIMAL,             // VkImageTiling tiling;
489             VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
490                 VK_IMAGE_USAGE_TRANSFER_DST_BIT, // VkImageUsageFlags usage;
491             VK_SHARING_MODE_EXCLUSIVE,           // VkSharingMode sharingMode;
492             1u,                                  // uint32_t queueFamilyIndexCount;
493             &queueFamilyIndex,                   // const uint32_t* pQueueFamilyIndices;
494             VK_IMAGE_LAYOUT_UNDEFINED            // VkImageLayout initialLayout;
495         };
496 
497         const VkImageCreateInfo depthImageParams = {
498             VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
499             DE_NULL,                             // const void* pNext;
500             0u,                                  // VkImageCreateFlags flags;
501             VK_IMAGE_TYPE_2D,                    // VkImageType imageType;
502             m_testParams.depthStencilFormat,     // VkFormat format;
503             {kImageWidth, kImageHeight, 1u},     // VkExtent3D extent;
504             1u,                                  // uint32_t mipLevels;
505             1u,                                  // uint32_t arrayLayers;
506             VK_SAMPLE_COUNT_1_BIT,               // VkSampleCountFlagBits samples;
507             VK_IMAGE_TILING_OPTIMAL,             // VkImageTiling tiling;
508             VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
509                 VK_IMAGE_USAGE_TRANSFER_DST_BIT, // VkImageUsageFlags usage;
510             VK_SHARING_MODE_EXCLUSIVE,           // VkSharingMode sharingMode;
511             1u,                                  // uint32_t queueFamilyIndexCount;
512             &queueFamilyIndex,                   // const uint32_t* pQueueFamilyIndices;
513             VK_IMAGE_LAYOUT_UNDEFINED            // VkImageLayout initialLayout;
514         };
515 
516         for (size_t i = 0; i < testParams.colorUsed.size(); ++i)
517         {
518             // Create, allocate and bind image memory.
519             m_colorImages.emplace_back(createImage(vk, vkDevice, &colorImageParams));
520             m_colorImageAllocs.emplace_back(memAlloc.allocate(
521                 getImageMemoryRequirements(vk, vkDevice, *m_colorImages.back()), MemoryRequirement::Any));
522             VK_CHECK(vk.bindImageMemory(vkDevice, *m_colorImages.back(), m_colorImageAllocs.back()->getMemory(),
523                                         m_colorImageAllocs.back()->getOffset()));
524 
525             // Create image view.
526             {
527                 const VkImageViewCreateInfo colorAttachmentViewParams = {
528                     VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,   // VkStructureType sType;
529                     DE_NULL,                                    // const void* pNext;
530                     0u,                                         // VkImageViewCreateFlags flags;
531                     *m_colorImages.back(),                      // VkImage image;
532                     VK_IMAGE_VIEW_TYPE_2D,                      // VkImageViewType viewType;
533                     FORMAT_COLOR,                               // VkFormat format;
534                     componentMapping,                           // VkChannelMapping channels;
535                     {VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u} // VkImageSubresourceRange subresourceRange;
536                 };
537 
538                 m_colorAttachmentViews.emplace_back(createImageView(vk, vkDevice, &colorAttachmentViewParams));
539             }
540 
541             // Clear image and leave it prepared to be used as a color attachment.
542             {
543                 const VkImageAspectFlags aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
544                 Move<VkCommandPool> cmdPool;
545                 Move<VkCommandBuffer> cmdBuffer;
546 
547                 // Create command pool and buffer
548                 cmdPool   = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
549                 cmdBuffer = allocateCommandBuffer(vk, vkDevice, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
550 
551                 // From undefined layout to VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL.
552                 const VkImageMemoryBarrier preImageBarrier = {
553                     VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
554                     DE_NULL,                                // const void* pNext;
555                     0u,                                     // VkAccessFlags srcAccessMask;
556                     VK_ACCESS_TRANSFER_WRITE_BIT,           // VkAccessFlags dstAccessMask;
557                     VK_IMAGE_LAYOUT_UNDEFINED,              // VkImageLayout oldLayout;
558                     VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,   // VkImageLayout newLayout;
559                     VK_QUEUE_FAMILY_IGNORED,                // uint32_t srcQueueFamilyIndex;
560                     VK_QUEUE_FAMILY_IGNORED,                // uint32_t dstQueueFamilyIndex;
561                     *m_colorImages.back(),                  // VkImage image;
562                     {
563                         // VkImageSubresourceRange subresourceRange;
564                         aspectMask, // VkImageAspect aspect;
565                         0u,         // uint32_t baseMipLevel;
566                         1u,         // uint32_t mipLevels;
567                         0u,         // uint32_t baseArraySlice;
568                         1u          // uint32_t arraySize;
569                     }};
570 
571                 // From VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL to VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL.
572                 const VkImageMemoryBarrier postImageBarrier = {
573                     VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,   // VkStructureType sType;
574                     DE_NULL,                                  // const void* pNext;
575                     VK_ACCESS_TRANSFER_WRITE_BIT,             // VkAccessFlags srcAccessMask;
576                     VK_ACCESS_SHADER_READ_BIT,                // VkAccessFlags dstAccessMask;
577                     VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,     // VkImageLayout oldLayout;
578                     VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout newLayout;
579                     VK_QUEUE_FAMILY_IGNORED,                  // uint32_t srcQueueFamilyIndex;
580                     VK_QUEUE_FAMILY_IGNORED,                  // uint32_t dstQueueFamilyIndex;
581                     *m_colorImages.back(),                    // VkImage image;
582                     {
583                         // VkImageSubresourceRange subresourceRange;
584                         aspectMask, // VkImageAspect aspect;
585                         0u,         // uint32_t baseMipLevel;
586                         1u,         // uint32_t mipLevels;
587                         0u,         // uint32_t baseArraySlice;
588                         1u          // uint32_t arraySize;
589                     }};
590 
591                 const VkImageSubresourceRange clearRange = {
592                     aspectMask, // VkImageAspectFlags aspectMask;
593                     0u,         // uint32_t baseMipLevel;
594                     1u,         // uint32_t levelCount;
595                     0u,         // uint32_t baseArrayLayer;
596                     1u          // uint32_t layerCount;
597                 };
598 
599                 // Clear image and transfer layout.
600                 beginCommandBuffer(vk, *cmdBuffer);
601                 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
602                                       (VkDependencyFlags)0, 0, (const VkMemoryBarrier *)DE_NULL, 0,
603                                       (const VkBufferMemoryBarrier *)DE_NULL, 1, &preImageBarrier);
604                 vk.cmdClearColorImage(*cmdBuffer, *m_colorImages.back(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
605                                       &m_initialColor.color, 1, &clearRange);
606                 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT,
607                                       (VkDependencyFlags)0, 0, (const VkMemoryBarrier *)DE_NULL, 0,
608                                       (const VkBufferMemoryBarrier *)DE_NULL, 1, &postImageBarrier);
609                 endCommandBuffer(vk, *cmdBuffer);
610 
611                 submitCommandsAndWait(vk, vkDevice, m_context.getUniversalQueue(), cmdBuffer.get());
612             }
613         }
614 
615         if (hasDepthStencil(m_testParams.depthStencilType))
616         {
617             const VkImageAspectFlags clearAspectMask  = getClearAspectMask(m_testParams.depthStencilType);
618             const VkImageAspectFlags formatAspectMask = getFormatAspectMask(m_testParams.depthStencilFormat);
619 
620             // Create, allocate and bind image memory.
621             m_depthImage = createImage(vk, vkDevice, &depthImageParams);
622             m_depthImageAlloc =
623                 memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *m_depthImage), MemoryRequirement::Any);
624             VK_CHECK(vk.bindImageMemory(vkDevice, *m_depthImage, m_depthImageAlloc->getMemory(),
625                                         m_depthImageAlloc->getOffset()));
626 
627             // Create image view.
628             {
629                 const VkImageViewCreateInfo depthAttachmentViewParams = {
630                     VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType;
631                     DE_NULL,                                  // const void* pNext;
632                     0u,                                       // VkImageViewCreateFlags flags;
633                     *m_depthImage,                            // VkImage image;
634                     VK_IMAGE_VIEW_TYPE_2D,                    // VkImageViewType viewType;
635                     m_testParams.depthStencilFormat,          // VkFormat format;
636                     componentMapping,                         // VkChannelMapping channels;
637                     {clearAspectMask, 0u, 1u, 0u, 1u}         // VkImageSubresourceRange subresourceRange;
638                 };
639 
640                 m_depthAttachmentView = createImageView(vk, vkDevice, &depthAttachmentViewParams);
641             }
642 
643             // Clear image and leave it prepared to be used as a depth/stencil attachment.
644             {
645                 Move<VkCommandPool> cmdPool;
646                 Move<VkCommandBuffer> cmdBuffer;
647 
648                 // Create command pool and buffer
649                 cmdPool   = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
650                 cmdBuffer = allocateCommandBuffer(vk, vkDevice, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
651 
652                 // From undefined layout to VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL.
653                 const VkImageMemoryBarrier preImageBarrier = {
654                     VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
655                     DE_NULL,                                // const void* pNext;
656                     0u,                                     // VkAccessFlags srcAccessMask;
657                     VK_ACCESS_TRANSFER_WRITE_BIT,           // VkAccessFlags dstAccessMask;
658                     VK_IMAGE_LAYOUT_UNDEFINED,              // VkImageLayout oldLayout;
659                     VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,   // VkImageLayout newLayout;
660                     VK_QUEUE_FAMILY_IGNORED,                // uint32_t srcQueueFamilyIndex;
661                     VK_QUEUE_FAMILY_IGNORED,                // uint32_t dstQueueFamilyIndex;
662                     *m_depthImage,                          // VkImage image;
663                     {
664                         // VkImageSubresourceRange subresourceRange;
665                         formatAspectMask, // VkImageAspect aspect;
666                         0u,               // uint32_t baseMipLevel;
667                         1u,               // uint32_t mipLevels;
668                         0u,               // uint32_t baseArraySlice;
669                         1u                // uint32_t arraySize;
670                     }};
671 
672                 // From VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL to VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL.
673                 const VkImageMemoryBarrier postImageBarrier = {
674                     VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,           // VkStructureType sType;
675                     DE_NULL,                                          // const void* pNext;
676                     VK_ACCESS_TRANSFER_WRITE_BIT,                     // VkAccessFlags srcAccessMask;
677                     VK_ACCESS_SHADER_READ_BIT,                        // VkAccessFlags dstAccessMask;
678                     VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,             // VkImageLayout oldLayout;
679                     VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, // VkImageLayout newLayout;
680                     VK_QUEUE_FAMILY_IGNORED,                          // uint32_t srcQueueFamilyIndex;
681                     VK_QUEUE_FAMILY_IGNORED,                          // uint32_t dstQueueFamilyIndex;
682                     *m_depthImage,                                    // VkImage image;
683                     {
684                         // VkImageSubresourceRange subresourceRange;
685                         formatAspectMask, // VkImageAspect aspect;
686                         0u,               // uint32_t baseMipLevel;
687                         1u,               // uint32_t mipLevels;
688                         0u,               // uint32_t baseArraySlice;
689                         1u                // uint32_t arraySize;
690                     }};
691 
692                 const VkImageSubresourceRange clearRange = {
693                     clearAspectMask, // VkImageAspectFlags aspectMask;
694                     0u,              // uint32_t baseMipLevel;
695                     1u,              // uint32_t levelCount;
696                     0u,              // uint32_t baseArrayLayer;
697                     1u               // uint32_t layerCount;
698                 };
699 
700                 // Clear image and transfer layout.
701                 beginCommandBuffer(vk, *cmdBuffer);
702                 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
703                                       (VkDependencyFlags)0, 0, (const VkMemoryBarrier *)DE_NULL, 0,
704                                       (const VkBufferMemoryBarrier *)DE_NULL, 1, &preImageBarrier);
705                 vk.cmdClearDepthStencilImage(*cmdBuffer, *m_depthImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
706                                              &m_initialColorDepth.depthStencil, 1, &clearRange);
707                 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT,
708                                       (VkDependencyFlags)0, 0, (const VkMemoryBarrier *)DE_NULL, 0,
709                                       (const VkBufferMemoryBarrier *)DE_NULL, 1, &postImageBarrier);
710                 endCommandBuffer(vk, *cmdBuffer);
711 
712                 submitCommandsAndWait(vk, vkDevice, m_context.getUniversalQueue(), cmdBuffer.get());
713             }
714         }
715     }
716 
717     // Create render pass when dynamic_rendering is not tested
718     if (testParams.groupParams->renderingType == RENDERING_TYPE_RENDERPASS_LEGACY)
719         m_renderPass = createRenderPass<AttachmentDescription1, AttachmentReference1, SubpassDescription1,
720                                         SubpassDependency1, RenderPassCreateInfo1>(vk, vkDevice, testParams);
721     else if (testParams.groupParams->renderingType == RENDERING_TYPE_RENDERPASS2)
722         m_renderPass = createRenderPass<AttachmentDescription2, AttachmentReference2, SubpassDescription2,
723                                         SubpassDependency2, RenderPassCreateInfo2>(vk, vkDevice, testParams);
724 
725     // Create framebuffer
726     if (testParams.groupParams->renderingType != RENDERING_TYPE_DYNAMIC_RENDERING)
727     {
728         std::vector<VkImageView> imageViews;
729 
730         for (auto &movePtr : m_colorAttachmentViews)
731             imageViews.push_back(movePtr.get());
732 
733         if (hasDepthStencil(m_testParams.depthStencilType))
734             imageViews.push_back(m_depthAttachmentView.get());
735 
736         const VkFramebufferCreateInfo framebufferParams = {
737             VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,          // VkStructureType sType;
738             DE_NULL,                                            // const void* pNext;
739             0u,                                                 // VkFramebufferCreateFlags flags;
740             *m_renderPass,                                      // VkRenderPass renderPass;
741             static_cast<uint32_t>(imageViews.size()),           // uint32_t attachmentCount;
742             (imageViews.empty() ? DE_NULL : imageViews.data()), // const VkImageView* pAttachments;
743             kImageWidth,                                        // uint32_t width;
744             kImageHeight,                                       // uint32_t height;
745             1u                                                  // uint32_t layers;
746         };
747 
748         m_framebuffer = createFramebuffer(vk, vkDevice, &framebufferParams);
749     }
750 
751     // Create pipeline layout for subpass 0.
752     {
753         const VkDescriptorSetLayoutCreateInfo descriptorSetLayoutParams = {
754             VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, // VkStructureType                        sType
755             DE_NULL,                                             // const void*                            pNext
756             0u,                                                  // VkDescriptorSetLayoutCreateFlags        flags
757             0u,                                                  // uint32_t                                bindingCount
758             DE_NULL                                              // const VkDescriptorSetLayoutBinding*    pBindings
759         };
760         m_descriptorSetLayout = createDescriptorSetLayout(vk, vkDevice, &descriptorSetLayoutParams);
761 
762         const VkPipelineLayoutCreateInfo pipelineLayoutParams = {
763             VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType;
764             DE_NULL,                                       // const void* pNext;
765             0u,                                            // VkPipelineLayoutCreateFlags flags;
766             1u,                                            // uint32_t setLayoutCount;
767             &m_descriptorSetLayout.get(),                  // const VkDescriptorSetLayout* pSetLayouts;
768             0u,                                            // uint32_t pushConstantRangeCount;
769             DE_NULL                                        // const VkPushConstantRange* pPushConstantRanges;
770         };
771 
772         m_pipelineLayout = createPipelineLayout(vk, vkDevice, &pipelineLayoutParams);
773     }
774 
775     m_vertexShaderModule   = createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("vert_shader"), 0);
776     m_fragmentShaderModule = createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("frag_shader"), 0);
777 
778     // Create pipeline.
779     {
780         const std::vector<VkViewport> viewports(1, makeViewport(m_renderSize));
781         const std::vector<VkRect2D> scissors(1, makeRect2D(m_renderSize));
782 
783         const VkPipelineColorBlendAttachmentState colorBlendAttachmentState = {
784             VK_FALSE,                // VkBool32                    blendEnable
785             VK_BLEND_FACTOR_ZERO,    // VkBlendFactor            srcColorBlendFactor
786             VK_BLEND_FACTOR_ZERO,    // VkBlendFactor            dstColorBlendFactor
787             VK_BLEND_OP_ADD,         // VkBlendOp                colorBlendOp
788             VK_BLEND_FACTOR_ZERO,    // VkBlendFactor            srcAlphaBlendFactor
789             VK_BLEND_FACTOR_ZERO,    // VkBlendFactor            dstAlphaBlendFactor
790             VK_BLEND_OP_ADD,         // VkBlendOp                alphaBlendOp
791             VK_COLOR_COMPONENT_R_BIT // VkColorComponentFlags    colorWriteMask
792                 | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT};
793 
794         std::vector<VkPipelineColorBlendAttachmentState> colorBlendAttachmentStates;
795         for (size_t i = 0; i < testParams.colorUsed.size(); ++i)
796             colorBlendAttachmentStates.push_back(colorBlendAttachmentState);
797 
798         const VkPipelineColorBlendStateCreateInfo colorBlendStateCreateInfo = {
799             VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType                                sType
800             DE_NULL,           // const void*                                    pNext
801             0u,                // VkPipelineColorBlendStateCreateFlags            flags
802             VK_FALSE,          // VkBool32                                        logicOpEnable
803             VK_LOGIC_OP_CLEAR, // VkLogicOp                                    logicOp
804             static_cast<uint32_t>(
805                 colorBlendAttachmentStates.size()), // uint32_t                                        attachmentCount
806             (colorBlendAttachmentStates.empty() ?
807                  DE_NULL :
808                  colorBlendAttachmentStates.data()), // const VkPipelineColorBlendAttachmentState*    pAttachments
809             {0.0f, 0.0f, 0.0f, 0.0f}                 // float                                        blendConstants[4]
810         };
811 
812         void *pNext = DE_NULL;
813 #ifndef CTS_USES_VULKANSC
814         const std::vector<VkFormat> colorAttachmentFormats(testParams.colorUsed.size(), FORMAT_COLOR);
815         const bool hasDepth = m_testParams.depthStencilType == DEPTH_STENCIL_BOTH ||
816                               m_testParams.depthStencilType == DEPTH_STENCIL_DEPTH_ONLY;
817         const bool hasStencil = m_testParams.depthStencilType == DEPTH_STENCIL_BOTH ||
818                                 m_testParams.depthStencilType == DEPTH_STENCIL_STENCIL_ONLY;
819         VkPipelineRenderingCreateInfoKHR renderingCreateInfo{
820             VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR,
821             DE_NULL,
822             0u,
823             static_cast<uint32_t>(colorAttachmentFormats.size()),
824             colorAttachmentFormats.data(),
825             (hasDepth ? m_testParams.depthStencilFormat : vk::VK_FORMAT_UNDEFINED),
826             (hasStencil ? m_testParams.depthStencilFormat : vk::VK_FORMAT_UNDEFINED),
827         };
828 
829         if (testParams.groupParams->renderingType == RENDERING_TYPE_DYNAMIC_RENDERING)
830             pNext = &renderingCreateInfo;
831 #endif // CTS_USES_VULKANSC
832 
833         m_graphicsPipeline = makeGraphicsPipeline(
834             vk,                      // const DeviceInterface&                            vk
835             vkDevice,                // const VkDevice                                    device
836             *m_pipelineLayout,       // const VkPipelineLayout                            pipelineLayout
837             *m_vertexShaderModule,   // const VkShaderModule                                vertexShaderModule
838             DE_NULL,                 // const VkShaderModule                                tessellationControlModule
839             DE_NULL,                 // const VkShaderModule                                tessellationEvalModule
840             DE_NULL,                 // const VkShaderModule                                geometryShaderModule
841             *m_fragmentShaderModule, // const VkShaderModule                                fragmentShaderModule
842             *m_renderPass,           // const VkRenderPass                                renderPass
843             viewports,               // const std::vector<VkViewport>&                    viewports
844             scissors,                // const std::vector<VkRect2D>&                        scissors
845             VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, // const VkPrimitiveTopology                        topology
846             0u,                                  // const uint32_t                                    subpass
847             0u,                                  // const uint32_t                                    patchControlPoints
848             DE_NULL, // const VkPipelineVertexInputStateCreateInfo*        vertexInputStateCreateInfo
849             DE_NULL, // const VkPipelineRasterizationStateCreateInfo*    rasterizationStateCreateInfo
850             DE_NULL, // const VkPipelineMultisampleStateCreateInfo*        multisampleStateCreateInfo
851             DE_NULL, // const VkPipelineDepthStencilStateCreateInfo*        depthStencilStateCreateInfo
852             &colorBlendStateCreateInfo, // const VkPipelineColorBlendStateCreateInfo*        colorBlendStateCreateInfo
853             DE_NULL,                    // const VkPipelineDynamicStateCreateInfo*            dynamicStateCreateInfo
854             pNext);                     // const void*                                        pNext
855     }
856 
857     // Create command pool
858     m_cmdPool = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
859 
860     // Create command buffer
861     if (testParams.groupParams->renderingType == RENDERING_TYPE_RENDERPASS_LEGACY)
862         createCommandBuffer<RenderpassSubpass1>(vk, vkDevice);
863     else if (testParams.groupParams->renderingType == RENDERING_TYPE_RENDERPASS2)
864         createCommandBuffer<RenderpassSubpass2>(vk, vkDevice);
865     else
866     {
867 #ifndef CTS_USES_VULKANSC
868         createCommandBufferDynamicRendering(vk, vkDevice);
869 #endif // CTS_USES_VULKANSC
870     }
871 }
872 
873 template <typename RenderpassSubpass>
createCommandBuffer(const DeviceInterface & vk,VkDevice vkDevice)874 void UnusedClearAttachmentTestInstance::createCommandBuffer(const DeviceInterface &vk, VkDevice vkDevice)
875 {
876     m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
877 
878     const VkClearRect clearRect = {
879         {
880             // VkRect2D rect;
881             {
882                 0,
883                 0,
884             },                          // VkOffset2D offset;
885             {kImageWidth, kImageHeight} // VkExtent2D extent;
886         },
887         0u, // uint32_t baseArrayLayer;
888         1u  // uint32_t layerCount;
889     };
890 
891     std::vector<VkClearAttachment> clearAttachments;
892     for (size_t i = 0; i < m_testParams.colorUsed.size(); ++i)
893     {
894         const VkClearAttachment clearAttachment = {
895             VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask;
896             static_cast<uint32_t>(i),  // uint32_t colorAttachment;
897             m_clearColor               // VkClearValue clearValue;
898         };
899         clearAttachments.push_back(clearAttachment);
900     }
901 
902     if (hasDepthStencil(m_testParams.depthStencilType))
903     {
904         const VkClearAttachment clearAttachment = {
905             getClearAspectMask(m_testParams.depthStencilType), // VkImageAspectFlags aspectMask;
906             0u,                                                // uint32_t colorAttachment;
907             m_clearColorDepth                                  // VkClearValue clearValue;
908         };
909         clearAttachments.push_back(clearAttachment);
910     }
911 
912     beginCommandBuffer(vk, *m_cmdBuffer, 0u);
913 
914     VkRect2D renderArea = makeRect2D(m_renderSize);
915 
916     const VkRenderPassBeginInfo renderPassBeginInfo{
917         VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType;
918         DE_NULL,                                  // const void* pNext;
919         *m_renderPass,                            // VkRenderPass renderPass;
920         *m_framebuffer,                           // VkFramebuffer framebuffer;
921         renderArea,                               // VkRect2D renderArea;
922         0u,                                       // uint32_t clearValueCount;
923         DE_NULL                                   // const VkClearValue* pClearValues;
924     };
925 
926     const typename RenderpassSubpass::SubpassBeginInfo subpassBeginInfo(DE_NULL, VK_SUBPASS_CONTENTS_INLINE);
927     RenderpassSubpass::cmdBeginRenderPass(vk, *m_cmdBuffer, &renderPassBeginInfo, &subpassBeginInfo);
928 
929     vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_graphicsPipeline);
930     if (!clearAttachments.empty())
931     {
932         vk.cmdClearAttachments(*m_cmdBuffer, static_cast<uint32_t>(clearAttachments.size()), clearAttachments.data(),
933                                1u, &clearRect);
934     }
935 
936     const typename RenderpassSubpass::SubpassEndInfo subpassEndInfo(DE_NULL);
937     RenderpassSubpass::cmdEndRenderPass(vk, *m_cmdBuffer, &subpassEndInfo);
938 
939     endCommandBuffer(vk, *m_cmdBuffer);
940 }
941 
942 #ifndef CTS_USES_VULKANSC
createCommandBufferDynamicRendering(const DeviceInterface & vk,VkDevice vkDevice)943 void UnusedClearAttachmentTestInstance::createCommandBufferDynamicRendering(const DeviceInterface &vk,
944                                                                             VkDevice vkDevice)
945 {
946     const VkClearRect clearRect{
947         {
948             // VkRect2D rect;
949             {
950                 0,
951                 0,
952             },                          // VkOffset2D offset;
953             {kImageWidth, kImageHeight} // VkExtent2D extent;
954         },
955         0u, // uint32_t baseArrayLayer;
956         1u  // uint32_t layerCount;
957     };
958 
959     std::vector<VkClearAttachment> clearAttachments;
960     for (size_t i = 0; i < m_testParams.colorUsed.size(); ++i)
961     {
962         const VkClearAttachment clearAttachment = {
963             VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask;
964             static_cast<uint32_t>(i),  // uint32_t colorAttachment;
965             m_clearColor               // VkClearValue clearValue;
966         };
967         clearAttachments.push_back(clearAttachment);
968     }
969 
970     if (m_testParams.depthStencilUsed)
971     {
972         const VkClearAttachment clearAttachment = {
973             getClearAspectMask(m_testParams.depthStencilType), // VkImageAspectFlags aspectMask;
974             0u,                                                // uint32_t colorAttachment;
975             m_clearColorDepth                                  // VkClearValue clearValue;
976         };
977         clearAttachments.push_back(clearAttachment);
978     }
979 
980     VkRect2D renderArea = makeRect2D(m_renderSize);
981     std::vector<VkRenderingAttachmentInfoKHR> colorAttachments;
982     for (size_t i = 0; i < m_colorAttachmentViews.size(); ++i)
983     {
984         colorAttachments.push_back({
985             VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR,              // VkStructureType sType;
986             DE_NULL,                                                      // const void* pNext;
987             (m_testParams.colorUsed[i]) ? *m_colorAttachmentViews[i] : 0, // VkImageView imageView;
988             VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,                     // VkImageLayout imageLayout;
989             VK_RESOLVE_MODE_NONE,                                         // VkResolveModeFlagBits resolveMode;
990             DE_NULL,                                                      // VkImageView resolveImageView;
991             VK_IMAGE_LAYOUT_UNDEFINED,                                    // VkImageLayout resolveImageLayout;
992             VK_ATTACHMENT_LOAD_OP_LOAD,                                   // VkAttachmentLoadOp loadOp;
993             VK_ATTACHMENT_STORE_OP_STORE,                                 // VkAttachmentStoreOp storeOp;
994             m_clearColor                                                  // VkClearValue clearValue;
995         });
996     }
997 
998     VkRenderingAttachmentInfoKHR depthAttachment{
999         VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR,              // VkStructureType sType;
1000         DE_NULL,                                                      // const void* pNext;
1001         (m_testParams.depthStencilUsed) ? *m_depthAttachmentView : 0, // VkImageView imageView;
1002         VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,             // VkImageLayout imageLayout;
1003         VK_RESOLVE_MODE_NONE,                                         // VkResolveModeFlagBits resolveMode;
1004         DE_NULL,                                                      // VkImageView resolveImageView;
1005         VK_IMAGE_LAYOUT_UNDEFINED,                                    // VkImageLayout resolveImageLayout;
1006         VK_ATTACHMENT_LOAD_OP_LOAD,                                   // VkAttachmentLoadOp loadOp;
1007         VK_ATTACHMENT_STORE_OP_STORE,                                 // VkAttachmentStoreOp storeOp;
1008         m_clearColorDepth                                             // VkClearValue clearValue;
1009     };
1010 
1011     const bool hasDepth = (m_testParams.depthStencilType == DEPTH_STENCIL_BOTH ||
1012                            m_testParams.depthStencilType == DEPTH_STENCIL_DEPTH_ONLY) &&
1013                           m_testParams.depthStencilUsed;
1014     const bool hasStencil = (m_testParams.depthStencilType == DEPTH_STENCIL_BOTH ||
1015                              m_testParams.depthStencilType == DEPTH_STENCIL_STENCIL_ONLY) &&
1016                             m_testParams.depthStencilUsed;
1017 
1018     std::vector<VkFormat> colorAttachmentFormats(m_testParams.colorUsed.size(), VK_FORMAT_UNDEFINED);
1019     for (size_t i = 0; i < m_testParams.colorUsed.size(); ++i)
1020         if (m_testParams.colorUsed[i])
1021             colorAttachmentFormats[i] = FORMAT_COLOR;
1022 
1023     VkCommandBufferInheritanceRenderingInfoKHR inheritanceRenderingInfo{
1024         VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_RENDERING_INFO_KHR,    // VkStructureType sType;
1025         DE_NULL,                                                            // const void* pNext;
1026         0u,                                                                 // VkRenderingFlagsKHR flags;
1027         0u,                                                                 // uint32_t viewMask;
1028         static_cast<uint32_t>(colorAttachmentFormats.size()),               // uint32_t colorAttachmentCount;
1029         colorAttachmentFormats.data(),                                      // const VkFormat* pColorAttachmentFormats;
1030         hasDepth ? m_testParams.depthStencilFormat : VK_FORMAT_UNDEFINED,   // VkFormat depthAttachmentFormat;
1031         hasStencil ? m_testParams.depthStencilFormat : VK_FORMAT_UNDEFINED, // VkFormat stencilAttachmentFormat;
1032         VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits rasterizationSamples;
1033     };
1034 
1035     const VkCommandBufferInheritanceInfo bufferInheritanceInfo = initVulkanStructure(&inheritanceRenderingInfo);
1036     VkCommandBufferBeginInfo commandBufBeginParams{
1037         VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType;
1038         DE_NULL,                                     // const void* pNext;
1039         VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, // VkCommandBufferUsageFlags flags;
1040         &bufferInheritanceInfo};
1041 
1042     VkRenderingInfoKHR renderingInfo{
1043         VK_STRUCTURE_TYPE_RENDERING_INFO_KHR,
1044         DE_NULL,
1045         0u,                                             // VkRenderingFlagsKHR flags;
1046         renderArea,                                     // VkRect2D renderArea;
1047         1u,                                             // uint32_t layerCount;
1048         0u,                                             // uint32_t viewMask;
1049         static_cast<uint32_t>(colorAttachments.size()), // uint32_t colorAttachmentCount;
1050         colorAttachments.empty() ? DE_NULL :
1051                                    colorAttachments.data(), // const VkRenderingAttachmentInfoKHR* pColorAttachments;
1052         hasDepth ? &depthAttachment : DE_NULL,              // const VkRenderingAttachmentInfoKHR* pDepthAttachment;
1053         hasStencil ? &depthAttachment : DE_NULL,            // const VkRenderingAttachmentInfoKHR* pStencilAttachment;
1054     };
1055 
1056     m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
1057 
1058     if (m_testParams.groupParams->useSecondaryCmdBuffer)
1059     {
1060         m_secCmdBuffer = allocateCommandBuffer(vk, vkDevice, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_SECONDARY);
1061 
1062         // record secondary command buffer
1063         if (m_testParams.groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
1064         {
1065             inheritanceRenderingInfo.flags = VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT;
1066             vk.beginCommandBuffer(*m_secCmdBuffer, &commandBufBeginParams);
1067             vk.cmdBeginRendering(*m_secCmdBuffer, &renderingInfo);
1068         }
1069         else
1070         {
1071             commandBufBeginParams.flags |= VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT;
1072             vk.beginCommandBuffer(*m_secCmdBuffer, &commandBufBeginParams);
1073         }
1074 
1075         vk.cmdBindPipeline(*m_secCmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_graphicsPipeline);
1076         if (!clearAttachments.empty())
1077         {
1078             vk.cmdClearAttachments(*m_secCmdBuffer, static_cast<uint32_t>(clearAttachments.size()),
1079                                    clearAttachments.data(), 1u, &clearRect);
1080         }
1081 
1082         if (m_testParams.groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
1083             vk.cmdEndRendering(*m_secCmdBuffer);
1084         endCommandBuffer(vk, *m_secCmdBuffer);
1085 
1086         // record primary command buffer
1087         beginCommandBuffer(vk, *m_cmdBuffer, 0u);
1088         if (!m_testParams.groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
1089         {
1090             renderingInfo.flags = vk::VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS;
1091             vk.cmdBeginRendering(*m_cmdBuffer, &renderingInfo);
1092         }
1093         vk.cmdExecuteCommands(*m_cmdBuffer, 1u, &*m_secCmdBuffer);
1094         if (!m_testParams.groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
1095             vk.cmdEndRendering(*m_cmdBuffer);
1096         endCommandBuffer(vk, *m_cmdBuffer);
1097     }
1098     else
1099     {
1100         beginCommandBuffer(vk, *m_cmdBuffer, 0u);
1101         vk.cmdBeginRendering(*m_cmdBuffer, &renderingInfo);
1102 
1103         vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_graphicsPipeline);
1104         if (!clearAttachments.empty())
1105         {
1106             vk.cmdClearAttachments(*m_cmdBuffer, static_cast<uint32_t>(clearAttachments.size()),
1107                                    clearAttachments.data(), 1u, &clearRect);
1108         }
1109 
1110         vk.cmdEndRendering(*m_cmdBuffer);
1111         endCommandBuffer(vk, *m_cmdBuffer);
1112     }
1113 }
1114 #endif // CTS_USES_VULKANSC
1115 
iterate(void)1116 tcu::TestStatus UnusedClearAttachmentTestInstance::iterate(void)
1117 {
1118     const DeviceInterface &vk       = m_context.getDeviceInterface();
1119     const VkDevice vkDevice         = m_context.getDevice();
1120     const VkQueue queue             = m_context.getUniversalQueue();
1121     const uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
1122     SimpleAllocator allocator(
1123         vk, vkDevice,
1124         getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
1125 
1126     submitCommandsAndWait(vk, vkDevice, queue, m_cmdBuffer.get());
1127 
1128     // Read result images.
1129     std::vector<de::MovePtr<tcu::TextureLevel>> imagePixels;
1130     for (size_t i = 0; i < m_testParams.colorUsed.size(); ++i)
1131         imagePixels.emplace_back(pipeline::readColorAttachment(vk, vkDevice, queue, queueFamilyIndex, allocator,
1132                                                                *m_colorImages[i], FORMAT_COLOR, m_renderSize)
1133                                      .release());
1134 
1135     // Verify pixel colors match.
1136     for (size_t i = 0; i < imagePixels.size(); ++i)
1137     {
1138         const tcu::ConstPixelBufferAccess &imageAccess = imagePixels[i]->getAccess();
1139         const float *refColor = (m_testParams.colorUsed[i] ? m_clearColor.color.float32 : m_initialColor.color.float32);
1140 
1141 #ifdef CTS_USES_VULKANSC
1142         if (m_context.getTestContext().getCommandLine().isSubProcess())
1143 #endif // CTS_USES_VULKANSC
1144         {
1145             for (int y = 0; y < imageAccess.getHeight(); ++y)
1146                 for (int x = 0; x < imageAccess.getWidth(); ++x)
1147                 {
1148                     const tcu::Vec4 color = imageAccess.getPixel(x, y);
1149 
1150                     for (uint32_t cpnt = 0; cpnt < 4; ++cpnt)
1151                         if (de::abs(color[cpnt] - refColor[cpnt]) > 0.01f)
1152                         {
1153                             std::ostringstream msg;
1154 
1155                             msg << "Attachment " << i << " with mismatched pixel (" << x << ", " << y
1156                                 << "): expecting pixel value [";
1157                             for (uint32_t j = 0; j < 4; ++j)
1158                                 msg << ((j == 0) ? "" : ", ") << refColor[j];
1159                             msg << "] and found [";
1160                             for (uint32_t j = 0; j < 4; ++j)
1161                                 msg << ((j == 0) ? "" : ", ") << color[j];
1162                             msg << "]";
1163 
1164                             return tcu::TestStatus::fail(msg.str());
1165                         }
1166                 }
1167         }
1168     }
1169 
1170     if (hasDepthStencil(m_testParams.depthStencilType))
1171     {
1172         const bool depthOnly   = isDepthOnly(m_testParams.depthStencilType);
1173         const bool stencilOnly = isStencilOnly(m_testParams.depthStencilType);
1174 
1175         if (!stencilOnly)
1176         {
1177             de::MovePtr<tcu::TextureLevel> depthPixels =
1178                 pipeline::readDepthAttachment(vk, vkDevice, queue, queueFamilyIndex, allocator, *m_depthImage,
1179                                               m_testParams.depthStencilFormat, m_renderSize);
1180             const tcu::ConstPixelBufferAccess &depthAccess = depthPixels->getAccess();
1181             const float refDepth = (m_testParams.depthStencilUsed ? m_clearColorDepth.depthStencil.depth :
1182                                                                     m_initialColorDepth.depthStencil.depth);
1183 
1184 #ifdef CTS_USES_VULKANSC
1185             if (m_context.getTestContext().getCommandLine().isSubProcess())
1186 #endif // CTS_USES_VULKANSC
1187             {
1188                 for (int y = 0; y < depthAccess.getHeight(); ++y)
1189                     for (int x = 0; x < depthAccess.getWidth(); ++x)
1190                     {
1191                         const float value = depthAccess.getPixDepth(x, y);
1192                         if (de::abs(value - refDepth) > 0.001f)
1193                         {
1194                             std::ostringstream msg;
1195 
1196                             msg << "Depth/stencil attachment with mismatched depth value at pixel (" << x << ", " << y
1197                                 << "): expected value " << refDepth << " and found " << value;
1198                             return tcu::TestStatus::fail(msg.str());
1199                         }
1200                     }
1201             }
1202         }
1203 
1204         if (!depthOnly)
1205         {
1206             // Note read*Attachment leaves the attachment in the VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL layout, so the current layout
1207             // depends on if we have previously read the depth aspect or not.
1208             const VkImageLayout currentLayout =
1209                 (stencilOnly ? VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL : VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
1210             de::MovePtr<tcu::TextureLevel> stencilPixels =
1211                 pipeline::readStencilAttachment(vk, vkDevice, queue, queueFamilyIndex, allocator, *m_depthImage,
1212                                                 m_testParams.depthStencilFormat, m_renderSize, currentLayout);
1213             const tcu::ConstPixelBufferAccess &stencilAccess = stencilPixels->getAccess();
1214             const uint32_t refStencil = (m_testParams.depthStencilUsed ? m_clearColorDepth.depthStencil.stencil :
1215                                                                          m_initialColorDepth.depthStencil.stencil);
1216 
1217 #ifdef CTS_USES_VULKANSC
1218             if (m_context.getTestContext().getCommandLine().isSubProcess())
1219 #endif // CTS_USES_VULKANSC
1220             {
1221                 for (int y = 0; y < stencilAccess.getHeight(); ++y)
1222                     for (int x = 0; x < stencilAccess.getWidth(); ++x)
1223                     {
1224                         const int value = stencilAccess.getPixStencil(x, y);
1225                         if (value < 0 || static_cast<uint32_t>(value) != refStencil)
1226                         {
1227                             std::ostringstream msg;
1228 
1229                             msg << "Depth/stencil attachment with mismatched stencil value at pixel (" << x << ", " << y
1230                                 << "): expected value " << refStencil << " and found " << value;
1231                             return tcu::TestStatus::fail(msg.str());
1232                         }
1233                     }
1234             }
1235         }
1236     }
1237 
1238     return tcu::TestStatus::pass("Pass");
1239 }
1240 
1241 using CallbackFunction = std::function<void(const std::vector<bool> &)>;
1242 
runCallbackOnCombination(std::vector<bool> & array,size_t current_index,CallbackFunction callback)1243 void runCallbackOnCombination(std::vector<bool> &array, size_t current_index, CallbackFunction callback)
1244 {
1245     DE_ASSERT(current_index < array.size());
1246     for (size_t i = 0; i < DE_LENGTH_OF_ARRAY(DE_BOOL_VALUES); ++i)
1247     {
1248         array[current_index] = DE_BOOL_VALUES[i];
1249         if (current_index == array.size() - 1)
1250             callback(array);
1251         else
1252             runCallbackOnCombination(array, current_index + 1, callback);
1253     }
1254 }
1255 
runCallbackOnCombination(std::vector<bool> & array,CallbackFunction callback)1256 void runCallbackOnCombination(std::vector<bool> &array, CallbackFunction callback)
1257 {
1258     runCallbackOnCombination(array, 0, callback);
1259 }
1260 
getUsed(bool value)1261 std::string getUsed(bool value)
1262 {
1263     return (value ? "used" : "unused");
1264 }
1265 
getCombName(const std::vector<bool> & array)1266 std::string getCombName(const std::vector<bool> &array)
1267 {
1268     std::ostringstream name;
1269     for (size_t i = 0; i < array.size(); ++i)
1270         name << ((i == 0) ? "" : "_") << "color" << getUsed(array[i]);
1271     return name.str();
1272 }
1273 
1274 } // namespace
1275 
createRenderPassUnusedClearAttachmentTests(tcu::TestContext & testCtx,const SharedGroupParams groupParams)1276 tcu::TestCaseGroup *createRenderPassUnusedClearAttachmentTests(tcu::TestContext &testCtx,
1277                                                                const SharedGroupParams groupParams)
1278 {
1279     // Unused attachments with vkCmdClearAttachments
1280     de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "unused_clear_attachments"));
1281 
1282     for (int depthStencilType = 0; depthStencilType < DEPTH_STENCIL_MAX_ENUM; ++depthStencilType)
1283     {
1284         const DepthStencilType dsType = static_cast<DepthStencilType>(depthStencilType);
1285         const auto dsFormats          = getFormats(dsType);
1286 
1287         for (const auto dsFormat : dsFormats)
1288         {
1289             for (size_t i = 0; i < DE_LENGTH_OF_ARRAY(DE_BOOL_VALUES); ++i)
1290             {
1291                 const bool depthStencilUse = DE_BOOL_VALUES[i];
1292 
1293                 if (groupParams->renderingType == RENDERING_TYPE_DYNAMIC_RENDERING && dsType != DEPTH_STENCIL_NONE &&
1294                     !depthStencilUse && groupParams->useSecondaryCmdBuffer &&
1295                     !groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
1296                 {
1297                     // In dynamic rendering, we cannot have D/S format set for attachment in secondary command buffer,
1298                     // while having no attachment in rendering info in primary command buffer.
1299                     //
1300                     // Spec:
1301                     // If vkCmdExecuteCommands is being called within a render pass instance begun with vkCmdBeginRendering and
1302                     // the VkRenderingInfo::pDepthAttachment->imageView parameter to vkCmdBeginRendering was VK_NULL_HANDLE,
1303                     // the value of the depthAttachmentFormat member of the VkCommandBufferInheritanceRenderingInfo structure included
1304                     // in the pNext chain of VkCommandBufferBeginInfo::pInheritanceInfo used to begin recording each element of
1305                     // pCommandBuffers must be VK_FORMAT_UNDEFINED
1306                     continue;
1307                 }
1308 
1309                 const std::string dsCase = depthStencilTypeName(dsType, dsFormat);
1310                 std::vector<TestParams> testTypes;
1311 
1312                 if (hasDepthStencil(dsType))
1313                     testTypes.emplace_back(0, dsType, depthStencilUse, dsFormat, groupParams); // No color attachments.
1314                 testTypes.emplace_back(1, dsType, depthStencilUse, dsFormat, groupParams); // Single color attachment.
1315                 testTypes.emplace_back(COLOR_ATTACHMENTS_NUMBER, dsType, depthStencilUse, dsFormat,
1316                                        groupParams); // Multiple color attachments.
1317 
1318                 for (auto &params : testTypes)
1319                 {
1320                     if (!params.colorUsed.empty())
1321                     {
1322                         runCallbackOnCombination(params.colorUsed,
1323                                                  [&](const std::vector<bool> &array)
1324                                                  {
1325                                                      std::string name = getCombName(array) + "_" + dsCase;
1326                                                      if (hasDepthStencil(dsType))
1327                                                          name += std::string("_") + getUsed(depthStencilUse);
1328                                                      testGroup->addChild(
1329                                                          new UnusedClearAttachmentTest(testCtx, name, params));
1330                                                  });
1331                     }
1332                     else
1333                     {
1334                         std::string name = dsCase + "_" + getUsed(depthStencilUse);
1335                         testGroup->addChild(new UnusedClearAttachmentTest(testCtx, name, params));
1336                     }
1337                 }
1338 
1339                 if (!hasDepthStencil(dsType))
1340                     break;
1341             }
1342         }
1343     }
1344 
1345     return testGroup.release();
1346 }
1347 
1348 } // namespace renderpass
1349 } // namespace vkt
1350