1 /*-------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * -----------------------------
4  *
5  * Copyright (c) 2020 Google Inc.
6  * Copyright (c) 2020 The Khronos Group Inc.
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 for multiple color or depth clears within a render pass
23  *//*--------------------------------------------------------------------*/
24 
25 #include "vktDrawMultipleClearsWithinRenderPass.hpp"
26 
27 #include "vktTestGroupUtil.hpp"
28 #include "vktTestCaseUtil.hpp"
29 #include "vktDrawCreateInfoUtil.hpp"
30 #include "vktDrawBufferObjectUtil.hpp"
31 #include "vktDrawImageObjectUtil.hpp"
32 #include "vkPrograms.hpp"
33 #include "vkTypeUtil.hpp"
34 #include "vkRefUtil.hpp"
35 #include "vkCmdUtil.hpp"
36 #include "vkBuilderUtil.hpp"
37 #include "vkImageUtil.hpp"
38 #include "vkQueryUtil.hpp"
39 #include "tcuTextureUtil.hpp"
40 #include "tcuCommandLine.hpp"
41 #include "vktDrawTestCaseUtil.hpp"
42 
43 #include "deStringUtil.hpp"
44 
45 #include <cmath>
46 #include <vector>
47 #include <string>
48 #include <sstream>
49 
50 namespace vkt
51 {
52 namespace Draw
53 {
54 namespace
55 {
56 using namespace vk;
57 using de::SharedPtr;
58 using std::abs;
59 using std::ostringstream;
60 using std::string;
61 using std::vector;
62 using tcu::Vec4;
63 
64 const uint32_t WIDTH  = 400;
65 const uint32_t HEIGHT = 300;
66 
67 enum struct Topology
68 {
69     TRIANGLE_STRIP = 0,
70     TRIANGLES,
71     TRIANGLE
72 };
73 
74 const Topology topologiesToTest[] = {Topology::TRIANGLE_STRIP, Topology::TRIANGLES, Topology::TRIANGLE};
75 
76 struct FormatPair
77 {
78     VkFormat colorFormat;
79     VkFormat depthFormat;
80 };
81 
82 const FormatPair formatsToTest[] = {
83     {VK_FORMAT_R8G8B8A8_UNORM, VK_FORMAT_UNDEFINED},  {VK_FORMAT_R8G8B8A8_SNORM, VK_FORMAT_UNDEFINED},
84     {VK_FORMAT_UNDEFINED, VK_FORMAT_D32_SFLOAT},      {VK_FORMAT_UNDEFINED, VK_FORMAT_D16_UNORM},
85     {VK_FORMAT_R8G8B8A8_UNORM, VK_FORMAT_D32_SFLOAT}, {VK_FORMAT_R8G8B8A8_UNORM, VK_FORMAT_D16_UNORM},
86     {VK_FORMAT_R8G8B8A8_SNORM, VK_FORMAT_D32_SFLOAT}, {VK_FORMAT_R8G8B8A8_SNORM, VK_FORMAT_D16_UNORM},
87 };
88 
89 const Vec4 verticesTriangleStrip[] = {
90     Vec4(-1.0f, -1.0f, 0.0f, 1.0f), // 0 -- 2
91     Vec4(-1.0f, 1.0f, 0.0f, 1.0f),  // |  / |
92     Vec4(1.0f, -1.0f, 0.0f, 1.0f),  // | /    |
93     Vec4(1.0f, 1.0f, 0.0f, 1.0f)    // 1 -- 3
94 };
95 const Vec4 verticesTriangles[] = {
96     Vec4(-1.0f, -1.0f, 0.0f, 1.0f), // 0 - 1
97     Vec4(-1.0f, 1.0f, 0.0f, 1.0f),  // | /
98     Vec4(1.0f, -1.0f, 0.0f, 1.0f),  // 2
99     Vec4(1.0f, -1.0f, 0.0f, 1.0f),  //       4
100     Vec4(-1.0f, 1.0f, 0.0f, 1.0f),  //     / |
101     Vec4(1.0f, 1.0f, 0.0f, 1.0f)    // 3 - 5
102 };
103 const Vec4 verticesBigTriangle[] = {
104     Vec4(-1.0f, -1.0f, 0.0f, 1.0f), // 0 - 2
105     Vec4(-1.0f, 3.0f, 0.0f, 1.0f),  // | /
106     Vec4(3.0f, -1.0f, 0.0f, 1.0f),  // 1
107 };
108 
109 const uint32_t TOPOLOGY_MAX_VERTICES_COUNT = 6;
110 const uint32_t TEST_MAX_STEPS_COUNT        = 3;
111 
112 struct Vertices
113 {
114     const char *testNameSuffix;
115     VkPrimitiveTopology topology;
116     uint32_t verticesCount;
117     const Vec4 *vertices;
118 };
119 
120 const Vertices verticesByTopology[] = {
121     {"_triangle_strip", VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, DE_LENGTH_OF_ARRAY(verticesTriangleStrip),
122      verticesTriangleStrip},
123     {"_triangles", VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, DE_LENGTH_OF_ARRAY(verticesTriangles), verticesTriangles},
124     {"_big_triangle", VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, DE_LENGTH_OF_ARRAY(verticesBigTriangle),
125      verticesBigTriangle}};
126 
127 enum struct ClearOp
128 {
129     LOAD = 0,
130     DRAW,
131     CLEAR
132 };
133 
134 struct ClearStep
135 {
136     ClearOp clearOp;
137     Vec4 color;
138     float depth;
139 };
140 
141 struct TestParams
142 {
143     VkFormat colorFormat;
144     VkFormat depthFormat;
145     Topology topology;
146     Vec4 expectedColor;
147     float colorEpsilon;
148     float expectedDepth;
149     float depthEpsilon;
150     uint32_t repeatCount;
151     bool enableBlend;
152     const SharedGroupParams groupParams;
153     vector<ClearStep> steps;
154 };
155 
156 class MultipleClearsTest : public TestInstance
157 {
158 public:
159     MultipleClearsTest(Context &context, const TestParams &params);
160     virtual tcu::TestStatus iterate(void);
161 
162 private:
163     void preRenderCommands(VkCommandBuffer cmdBuffer) const;
164     void beginLegacyRender(VkCommandBuffer cmdBuffer) const;
165     void drawCommands(VkCommandBuffer cmdBuffer) const;
166 
167 #ifndef CTS_USES_VULKANSC
168     void beginSecondaryCmdBuffer(VkCommandBuffer cmdBuffer, VkRenderingFlagsKHR renderingFlags = 0u) const;
169     void beginDynamicRender(VkCommandBuffer cmdBuffer, VkRenderingFlagsKHR renderingFlags = 0u) const;
170 #endif // CTS_USES_VULKANSC
171 
172     SharedPtr<Image> m_colorTargetImage;
173     SharedPtr<Image> m_depthTargetImage;
174     Move<VkImageView> m_colorTargetView;
175     Move<VkImageView> m_depthTargetView;
176     SharedPtr<Buffer> m_vertexBuffer;
177     Move<VkRenderPass> m_renderPass;
178     Move<VkFramebuffer> m_framebuffer;
179     Move<VkPipelineLayout> m_pipelineLayout;
180     Move<VkPipeline> m_pipeline;
181 
182     const TestParams m_params;
183     Vec4 m_vertices[TOPOLOGY_MAX_VERTICES_COUNT * TEST_MAX_STEPS_COUNT];
184 };
185 
MultipleClearsTest(Context & context,const TestParams & params)186 MultipleClearsTest::MultipleClearsTest(Context &context, const TestParams &params)
187     : TestInstance(context)
188     , m_params(params)
189 {
190     const DeviceInterface &vk       = m_context.getDeviceInterface();
191     const VkDevice device           = m_context.getDevice();
192     const uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
193     const bool hasColor             = m_params.colorFormat != VK_FORMAT_UNDEFINED;
194     const bool hasDepth             = m_params.depthFormat != VK_FORMAT_UNDEFINED;
195 
196     DescriptorSetLayoutBuilder descriptorSetLayoutBuilder;
197     // Vertex data
198     const auto &vertexData = verticesByTopology[(size_t)m_params.topology];
199     {
200         DE_ASSERT(vertexData.verticesCount <= TOPOLOGY_MAX_VERTICES_COUNT);
201         const size_t verticesCount       = vertexData.verticesCount;
202         const VkDeviceSize dataSize      = verticesCount * sizeof(Vec4);
203         const VkDeviceSize totalDataSize = m_params.steps.size() * dataSize;
204         DE_ASSERT(totalDataSize <= sizeof(m_vertices));
205 
206         for (size_t i = 0; i < m_params.steps.size(); ++i)
207         {
208             const size_t start = i * verticesCount;
209             deMemcpy(&m_vertices[start], vertexData.vertices, static_cast<size_t>(dataSize));
210             for (size_t j = 0; j < verticesCount; ++j)
211                 m_vertices[start + j][2] = m_params.steps[i].depth;
212         }
213         m_vertexBuffer =
214             Buffer::createAndAlloc(vk, device, BufferCreateInfo(totalDataSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT),
215                                    m_context.getDefaultAllocator(), MemoryRequirement::HostVisible);
216         deMemcpy(m_vertexBuffer->getBoundMemory().getHostPtr(), m_vertices, static_cast<std::size_t>(totalDataSize));
217         flushMappedMemoryRange(vk, device, m_vertexBuffer->getBoundMemory().getMemory(),
218                                m_vertexBuffer->getBoundMemory().getOffset(), VK_WHOLE_SIZE);
219     }
220 
221     if (hasColor)
222     {
223         const VkImageUsageFlags targetImageUsageFlags =
224             VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
225         const ImageCreateInfo targetImageCreateInfo(VK_IMAGE_TYPE_2D, m_params.colorFormat, {WIDTH, HEIGHT, 1u}, 1u, 1u,
226                                                     VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_TILING_OPTIMAL,
227                                                     targetImageUsageFlags);
228         m_colorTargetImage =
229             Image::createAndAlloc(vk, device, targetImageCreateInfo, m_context.getDefaultAllocator(), queueFamilyIndex);
230         const ImageViewCreateInfo colorTargetViewInfo(m_colorTargetImage->object(), VK_IMAGE_VIEW_TYPE_2D,
231                                                       m_params.colorFormat);
232         m_colorTargetView = createImageView(vk, device, &colorTargetViewInfo);
233     }
234 
235     if (hasDepth)
236     {
237         const VkImageUsageFlags depthImageUsageFlags = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT |
238                                                        VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
239                                                        VK_IMAGE_USAGE_TRANSFER_DST_BIT;
240         const ImageCreateInfo depthImageCreateInfo(VK_IMAGE_TYPE_2D, m_params.depthFormat, {WIDTH, HEIGHT, 1u}, 1u, 1u,
241                                                    VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_TILING_OPTIMAL,
242                                                    depthImageUsageFlags);
243         m_depthTargetImage =
244             Image::createAndAlloc(vk, device, depthImageCreateInfo, m_context.getDefaultAllocator(), queueFamilyIndex);
245         const ImageViewCreateInfo depthTargetViewInfo(m_depthTargetImage->object(), VK_IMAGE_VIEW_TYPE_2D,
246                                                       m_params.depthFormat);
247         m_depthTargetView = createImageView(vk, device, &depthTargetViewInfo);
248     }
249 
250     // Render pass
251     if (!m_params.groupParams->useDynamicRendering)
252     {
253         RenderPassCreateInfo renderPassCreateInfo;
254         if (hasColor)
255         {
256             renderPassCreateInfo.addAttachment(
257                 AttachmentDescription(m_params.colorFormat,                       // format
258                                       VK_SAMPLE_COUNT_1_BIT,                      // samples
259                                       VK_ATTACHMENT_LOAD_OP_LOAD,                 // loadOp
260                                       VK_ATTACHMENT_STORE_OP_STORE,               // storeOp
261                                       VK_ATTACHMENT_LOAD_OP_DONT_CARE,            // stencilLoadOp
262                                       VK_ATTACHMENT_STORE_OP_DONT_CARE,           // stencilStoreOp
263                                       VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,   // initialLayout
264                                       VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)); // finalLayout
265         }
266         if (hasDepth)
267         {
268             renderPassCreateInfo.addAttachment(
269                 AttachmentDescription(m_params.depthFormat,                               // format
270                                       VK_SAMPLE_COUNT_1_BIT,                              // samples
271                                       VK_ATTACHMENT_LOAD_OP_LOAD,                         // loadOp
272                                       VK_ATTACHMENT_STORE_OP_STORE,                       // storeOp
273                                       VK_ATTACHMENT_LOAD_OP_DONT_CARE,                    // stencilLoadOp
274                                       VK_ATTACHMENT_STORE_OP_DONT_CARE,                   // stencilStoreOp
275                                       VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,   // initialLayout
276                                       VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL)); // finalLayout
277         }
278         const VkAttachmentReference colorAttachmentReference =
279             hasColor ? makeAttachmentReference(0u, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL) : AttachmentReference();
280         const VkAttachmentReference depthAttachmentReference =
281             hasDepth ? makeAttachmentReference(hasColor ? 1u : 0u, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL) :
282                        AttachmentReference();
283         renderPassCreateInfo.addSubpass(
284             SubpassDescription(VK_PIPELINE_BIND_POINT_GRAPHICS,                // pipelineBindPoint
285                                (VkSubpassDescriptionFlags)0,                   // flags
286                                0u,                                             // inputAttachmentCount
287                                DE_NULL,                                        // inputAttachments
288                                hasColor ? 1 : 0,                               // colorAttachmentCount
289                                hasColor ? &colorAttachmentReference : DE_NULL, // colorAttachments
290                                DE_NULL,                                        // resolveAttachments
291                                depthAttachmentReference,                       // depthStencilAttachment
292                                0u,                                             // preserveAttachmentCount
293                                DE_NULL));                                      // preserveAttachments
294         m_renderPass = createRenderPass(vk, device, &renderPassCreateInfo);
295 
296         std::vector<VkImageView> attachments;
297         if (hasColor)
298             attachments.push_back(*m_colorTargetView);
299         if (hasDepth)
300             attachments.push_back(*m_depthTargetView);
301         const FramebufferCreateInfo framebufferCreateInfo(*m_renderPass, attachments, WIDTH, HEIGHT, 1);
302         m_framebuffer = createFramebuffer(vk, device, &framebufferCreateInfo);
303     }
304 
305     // Vertex input
306     const VkVertexInputBindingDescription vertexInputBindingDescription = {
307         0u,                          // uint32_t binding;
308         sizeof(Vec4),                // uint32_t stride;
309         VK_VERTEX_INPUT_RATE_VERTEX, // VkVertexInputRate inputRate;
310     };
311 
312     const VkVertexInputAttributeDescription vertexInputAttributeDescription = {
313         0u,                            // uint32_t location;
314         0u,                            // uint32_t binding;
315         VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
316         0u                             // uint32_t offset;
317     };
318 
319     const PipelineCreateInfo::VertexInputState vertexInputState =
320         PipelineCreateInfo::VertexInputState(1, &vertexInputBindingDescription, 1, &vertexInputAttributeDescription);
321 
322     // Graphics pipeline
323     const Unique<VkShaderModule> vertexModule(
324         createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0));
325     const Unique<VkShaderModule> fragmentModule(
326         createShaderModule(vk, device, m_context.getBinaryCollection().get(hasColor ? "frag" : "frag_depthonly"), 0));
327 
328     const VkPushConstantRange pcRange =
329         vk::VkPushConstantRange{VkShaderStageFlagBits::VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(ClearStep::color)};
330     const PipelineLayoutCreateInfo pipelineLayoutCreateInfo(0u, DE_NULL, 1u, &pcRange);
331     m_pipelineLayout = createPipelineLayout(vk, device, &pipelineLayoutCreateInfo);
332 
333     const VkRect2D scissor    = makeRect2D(WIDTH, HEIGHT);
334     const VkViewport viewport = makeViewport(WIDTH, HEIGHT);
335 
336     const auto vkCbAttachmentState = makePipelineColorBlendAttachmentState(
337         m_params.enableBlend ? VK_TRUE : VK_FALSE, // VkBool32                    blendEnable
338         VK_BLEND_FACTOR_SRC_ALPHA,                 // VkBlendFactor            srcColorBlendFactor
339         VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,       // VkBlendFactor            dstColorBlendFactor
340         VK_BLEND_OP_ADD,                           // VkBlendOp                colorBlendOp
341         VK_BLEND_FACTOR_ZERO,                      // VkBlendFactor            srcAlphaBlendFactor
342         VK_BLEND_FACTOR_ONE,                       // VkBlendFactor            dstAlphaBlendFactor
343         VK_BLEND_OP_ADD,                           // VkBlendOp                alphaBlendOp
344         VK_COLOR_COMPONENT_R_BIT |                 // VkColorComponentFlags    colorWriteMask
345             VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT);
346     PipelineCreateInfo pipelineCreateInfo(*m_pipelineLayout, *m_renderPass, 0, (VkPipelineCreateFlags)0);
347     pipelineCreateInfo.addShader(
348         PipelineCreateInfo::PipelineShaderStage(*vertexModule, "main", VK_SHADER_STAGE_VERTEX_BIT));
349     pipelineCreateInfo.addShader(
350         PipelineCreateInfo::PipelineShaderStage(*fragmentModule, "main", VK_SHADER_STAGE_FRAGMENT_BIT));
351     pipelineCreateInfo.addState(PipelineCreateInfo::VertexInputState(vertexInputState));
352     pipelineCreateInfo.addState(PipelineCreateInfo::InputAssemblerState(vertexData.topology));
353     pipelineCreateInfo.addState(PipelineCreateInfo::ColorBlendState(1, &vkCbAttachmentState));
354     pipelineCreateInfo.addState(
355         PipelineCreateInfo::ViewportState(1, std::vector<VkViewport>(1, viewport), std::vector<VkRect2D>(1, scissor)));
356     pipelineCreateInfo.addState(
357         PipelineCreateInfo::DepthStencilState(hasDepth, hasDepth, VK_COMPARE_OP_ALWAYS, VK_FALSE, VK_FALSE));
358     pipelineCreateInfo.addState(PipelineCreateInfo::RasterizerState());
359     pipelineCreateInfo.addState(PipelineCreateInfo::MultiSampleState());
360 
361 #ifndef CTS_USES_VULKANSC
362     vk::VkPipelineRenderingCreateInfoKHR renderingCreateInfo{VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR,
363                                                              DE_NULL,
364                                                              0u,
365                                                              hasColor,
366                                                              (hasColor ? &m_params.colorFormat : DE_NULL),
367                                                              m_params.depthFormat,
368                                                              VK_FORMAT_UNDEFINED};
369 
370     if (m_params.groupParams->useDynamicRendering)
371         pipelineCreateInfo.pNext = &renderingCreateInfo;
372 #endif // CTS_USES_VULKANSC
373 
374     m_pipeline = createGraphicsPipeline(vk, device, DE_NULL, &pipelineCreateInfo);
375 }
376 
preRenderCommands(VkCommandBuffer cmdBuffer) const377 void MultipleClearsTest::preRenderCommands(VkCommandBuffer cmdBuffer) const
378 {
379     const DeviceInterface &vk = m_context.getDeviceInterface();
380     if (m_params.colorFormat)
381         initialTransitionColor2DImage(vk, cmdBuffer, m_colorTargetImage->object(),
382                                       VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
383                                       VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
384     if (m_params.depthFormat)
385         initialTransitionDepth2DImage(
386             vk, cmdBuffer, m_depthTargetImage->object(), VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
387             VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT);
388 }
389 
beginLegacyRender(VkCommandBuffer cmdBuffer) const390 void MultipleClearsTest::beginLegacyRender(VkCommandBuffer cmdBuffer) const
391 {
392     const DeviceInterface &vk = m_context.getDeviceInterface();
393     const VkRect2D renderArea = makeRect2D(0, 0, WIDTH, HEIGHT);
394 
395     if (!m_params.steps.empty() && m_params.steps[0].clearOp == ClearOp::LOAD)
396         beginRenderPass(vk, cmdBuffer, *m_renderPass, *m_framebuffer, renderArea, m_params.steps[0].color,
397                         m_params.steps[0].depth, 0);
398     else
399         beginRenderPass(vk, cmdBuffer, *m_renderPass, *m_framebuffer, renderArea);
400 }
401 
drawCommands(vk::VkCommandBuffer cmdBuffer) const402 void MultipleClearsTest::drawCommands(vk::VkCommandBuffer cmdBuffer) const
403 {
404     const DeviceInterface &vk = m_context.getDeviceInterface();
405 
406     vk.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
407     {
408         const VkDeviceSize offset = 0;
409         const VkBuffer buffer     = m_vertexBuffer->object();
410         vk.cmdBindVertexBuffers(cmdBuffer, 0, 1, &buffer, &offset);
411     }
412 
413     for (uint32_t i = 0; i < m_params.repeatCount; ++i)
414         for (size_t stepIndex = 0; stepIndex < m_params.steps.size(); ++stepIndex)
415         {
416             const auto &step = m_params.steps[stepIndex];
417 
418             // ClearOp::LOAD only supported for first step
419             DE_ASSERT(stepIndex == 0 || step.clearOp != ClearOp::LOAD);
420 
421             const Vec4 &color = step.color;
422             const float depth = step.depth;
423 
424             switch (step.clearOp)
425             {
426             case ClearOp::LOAD:
427                 break;
428             case ClearOp::DRAW:
429             {
430                 const auto &vertexData       = verticesByTopology[(size_t)m_params.topology];
431                 const uint32_t verticesCount = vertexData.verticesCount;
432                 vk.cmdPushConstants(cmdBuffer, *m_pipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(color),
433                                     color.getPtr());
434                 vk.cmdDraw(cmdBuffer, verticesCount, 1, static_cast<uint32_t>(verticesCount * stepIndex), 0);
435             }
436             break;
437             case ClearOp::CLEAR:
438             {
439                 vector<VkClearAttachment> clearAttachments;
440                 if (m_params.colorFormat != VK_FORMAT_UNDEFINED)
441                 {
442                     const VkClearAttachment clearAttachment{
443                         VK_IMAGE_ASPECT_COLOR_BIT,                      // VkImageAspectFlags     aspectMask
444                         static_cast<uint32_t>(clearAttachments.size()), // uint32_t                 colorAttachment
445                         makeClearValueColor(color)                      // VkClearValue             clearValue
446                     };
447                     clearAttachments.push_back(clearAttachment);
448                 }
449                 if (m_params.depthFormat != VK_FORMAT_UNDEFINED)
450                 {
451                     const VkClearAttachment clearAttachment{
452                         VK_IMAGE_ASPECT_DEPTH_BIT,                      // VkImageAspectFlags     aspectMask
453                         static_cast<uint32_t>(clearAttachments.size()), // uint32_t                 colorAttachment
454                         makeClearValueDepthStencil(depth, 0)            // VkClearValue             clearValue
455                     };
456                     clearAttachments.push_back(clearAttachment);
457                 }
458                 const VkClearRect clearRect{
459                     makeRect2D(WIDTH, HEIGHT), // VkRect2D       rect
460                     0,                         // uint32_t       baseArrayLayer
461                     1                          // uint32_t       layerCount
462                 };
463                 vk.cmdClearAttachments(cmdBuffer, static_cast<uint32_t>(clearAttachments.size()),
464                                        clearAttachments.data(), 1, &clearRect);
465             }
466             break;
467             default:
468                 break;
469             }
470         }
471 }
472 
473 #ifndef CTS_USES_VULKANSC
beginSecondaryCmdBuffer(VkCommandBuffer cmdBuffer,VkRenderingFlagsKHR renderingFlags) const474 void MultipleClearsTest::beginSecondaryCmdBuffer(VkCommandBuffer cmdBuffer, VkRenderingFlagsKHR renderingFlags) const
475 {
476     VkCommandBufferInheritanceRenderingInfoKHR inheritanceRenderingInfo{
477         VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_RENDERING_INFO_KHR, // VkStructureType sType;
478         DE_NULL,                                                         // const void* pNext;
479         renderingFlags,                                                  // VkRenderingFlagsKHR flags;
480         0u,                                                              // uint32_t viewMask;
481         (m_params.colorFormat != VK_FORMAT_UNDEFINED),                   // uint32_t colorAttachmentCount;
482         &m_params.colorFormat,                                           // const VkFormat* pColorAttachmentFormats;
483         m_params.depthFormat,                                            // VkFormat depthAttachmentFormat;
484         VK_FORMAT_UNDEFINED,                                             // VkFormat stencilAttachmentFormat;
485         VK_SAMPLE_COUNT_1_BIT,                                           // VkSampleCountFlagBits rasterizationSamples;
486     };
487 
488     const VkCommandBufferInheritanceInfo bufferInheritanceInfo = initVulkanStructure(&inheritanceRenderingInfo);
489 
490     VkCommandBufferUsageFlags usageFlags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
491     if (!m_params.groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
492         usageFlags |= VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT;
493 
494     const VkCommandBufferBeginInfo commandBufBeginParams{
495         VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType;
496         DE_NULL,                                     // const void* pNext;
497         usageFlags,                                  // VkCommandBufferUsageFlags flags;
498         &bufferInheritanceInfo};
499 
500     const DeviceInterface &vk = m_context.getDeviceInterface();
501     VK_CHECK(vk.beginCommandBuffer(cmdBuffer, &commandBufBeginParams));
502 }
503 
beginDynamicRender(VkCommandBuffer cmdBuffer,VkRenderingFlagsKHR renderingFlags) const504 void MultipleClearsTest::beginDynamicRender(VkCommandBuffer cmdBuffer, VkRenderingFlagsKHR renderingFlags) const
505 {
506     const DeviceInterface &vk = m_context.getDeviceInterface();
507     const VkRect2D renderArea = makeRect2D(0, 0, WIDTH, HEIGHT);
508 
509     VkClearValue clearColorValue = makeClearValueColor(tcu::Vec4(0.0f));
510     VkClearValue clearDepthValue = makeClearValueDepthStencil(0.0f, 0u);
511     if (!m_params.steps.empty() && m_params.steps[0].clearOp == ClearOp::LOAD)
512     {
513         clearColorValue = makeClearValueColor(m_params.steps[0].color);
514         clearDepthValue = makeClearValueDepthStencil(m_params.steps[0].depth, 0u);
515     }
516 
517     vk::VkRenderingAttachmentInfoKHR colorAttachment{
518         vk::VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR, // VkStructureType sType;
519         DE_NULL,                                             // const void* pNext;
520         *m_colorTargetView,                                  // VkImageView imageView;
521         vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,        // VkImageLayout imageLayout;
522         vk::VK_RESOLVE_MODE_NONE,                            // VkResolveModeFlagBits resolveMode;
523         DE_NULL,                                             // VkImageView resolveImageView;
524         vk::VK_IMAGE_LAYOUT_UNDEFINED,                       // VkImageLayout resolveImageLayout;
525         vk::VK_ATTACHMENT_LOAD_OP_LOAD,                      // VkAttachmentLoadOp loadOp;
526         vk::VK_ATTACHMENT_STORE_OP_STORE,                    // VkAttachmentStoreOp storeOp;
527         clearColorValue                                      // VkClearValue clearValue;
528     };
529 
530     vk::VkRenderingAttachmentInfoKHR depthAttachment{
531         vk::VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR,  // VkStructureType sType;
532         DE_NULL,                                              // const void* pNext;
533         *m_depthTargetView,                                   // VkImageView imageView;
534         vk::VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, // VkImageLayout imageLayout;
535         vk::VK_RESOLVE_MODE_NONE,                             // VkResolveModeFlagBits resolveMode;
536         DE_NULL,                                              // VkImageView resolveImageView;
537         vk::VK_IMAGE_LAYOUT_UNDEFINED,                        // VkImageLayout resolveImageLayout;
538         vk::VK_ATTACHMENT_LOAD_OP_LOAD,                       // VkAttachmentLoadOp loadOp;
539         vk::VK_ATTACHMENT_STORE_OP_STORE,                     // VkAttachmentStoreOp storeOp;
540         clearDepthValue                                       // VkClearValue clearValue;
541     };
542 
543     const bool hasColor = m_params.colorFormat != VK_FORMAT_UNDEFINED;
544     const bool hasDepth = m_params.depthFormat != VK_FORMAT_UNDEFINED;
545 
546     vk::VkRenderingInfoKHR renderingInfo{
547         vk::VK_STRUCTURE_TYPE_RENDERING_INFO_KHR,
548         DE_NULL,
549         renderingFlags,                          // VkRenderingFlagsKHR flags;
550         renderArea,                              // VkRect2D renderArea;
551         1u,                                      // uint32_t layerCount;
552         0u,                                      // uint32_t viewMask;
553         hasColor,                                // uint32_t colorAttachmentCount;
554         (hasColor ? &colorAttachment : DE_NULL), // const VkRenderingAttachmentInfoKHR* pColorAttachments;
555         (hasDepth ? &depthAttachment : DE_NULL), // const VkRenderingAttachmentInfoKHR* pDepthAttachment;
556         DE_NULL,                                 // const VkRenderingAttachmentInfoKHR* pStencilAttachment;
557     };
558 
559     vk.cmdBeginRendering(cmdBuffer, &renderingInfo);
560 }
561 #endif // CTS_USES_VULKANSC
562 
iterate(void)563 tcu::TestStatus MultipleClearsTest::iterate(void)
564 {
565     const DeviceInterface &vk       = m_context.getDeviceInterface();
566     const VkDevice device           = m_context.getDevice();
567     const VkQueue queue             = m_context.getUniversalQueue();
568     const uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
569 
570     const CmdPoolCreateInfo cmdPoolCreateInfo(queueFamilyIndex);
571     const Unique<VkCommandPool> cmdPool(createCommandPool(vk, device, &cmdPoolCreateInfo));
572     const Unique<VkCommandBuffer> cmdBuffer(
573         allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
574     Move<VkCommandBuffer> secCmdBuffer;
575 
576     const bool hasColor = m_params.colorFormat != VK_FORMAT_UNDEFINED;
577     const bool hasDepth = m_params.depthFormat != VK_FORMAT_UNDEFINED;
578 
579 #ifndef CTS_USES_VULKANSC
580     if (m_params.groupParams->useSecondaryCmdBuffer)
581     {
582         secCmdBuffer = allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_SECONDARY);
583 
584         // record secondary command buffer
585         if (m_params.groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
586         {
587             beginSecondaryCmdBuffer(*secCmdBuffer, VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT);
588             beginDynamicRender(*secCmdBuffer);
589         }
590         else
591             beginSecondaryCmdBuffer(*secCmdBuffer);
592 
593         drawCommands(*secCmdBuffer);
594 
595         if (m_params.groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
596             endRendering(vk, *secCmdBuffer);
597 
598         endCommandBuffer(vk, *secCmdBuffer);
599 
600         // record primary command buffer
601         beginCommandBuffer(vk, *cmdBuffer, 0u);
602         preRenderCommands(*cmdBuffer);
603 
604         if (!m_params.groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
605             beginDynamicRender(*cmdBuffer, VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS);
606 
607         vk.cmdExecuteCommands(*cmdBuffer, 1u, &*secCmdBuffer);
608 
609         if (!m_params.groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
610             endRendering(vk, *cmdBuffer);
611     }
612     else if (m_params.groupParams->useDynamicRendering)
613     {
614         beginCommandBuffer(vk, *cmdBuffer);
615         preRenderCommands(*cmdBuffer);
616         beginDynamicRender(*cmdBuffer);
617         drawCommands(*cmdBuffer);
618         endRendering(vk, *cmdBuffer);
619     }
620 #endif // CTS_USES_VULKANSC
621 
622     if (!m_params.groupParams->useDynamicRendering)
623     {
624         beginCommandBuffer(vk, *cmdBuffer);
625         preRenderCommands(*cmdBuffer);
626         beginLegacyRender(*cmdBuffer);
627         drawCommands(*cmdBuffer);
628         endRenderPass(vk, *cmdBuffer);
629     }
630 
631     if (hasDepth)
632     {
633         const VkMemoryBarrier memBarrier = {VK_STRUCTURE_TYPE_MEMORY_BARRIER, DE_NULL, VK_ACCESS_TRANSFER_WRITE_BIT,
634                                             VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
635                                                 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT};
636         vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, 0,
637                               1, &memBarrier, 0, DE_NULL, 0, DE_NULL);
638     }
639     if (hasColor)
640     {
641         const VkMemoryBarrier memBarrier = {VK_STRUCTURE_TYPE_MEMORY_BARRIER, DE_NULL, VK_ACCESS_TRANSFER_WRITE_BIT,
642                                             VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT};
643         vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
644                               0, 1, &memBarrier, 0, DE_NULL, 0, DE_NULL);
645     }
646 
647     if (hasColor)
648         transition2DImage(vk, *cmdBuffer, m_colorTargetImage->object(), VK_IMAGE_ASPECT_COLOR_BIT,
649                           VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
650                           VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_MEMORY_READ_BIT,
651                           VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_HOST_BIT);
652     if (hasDepth)
653         transition2DImage(vk, *cmdBuffer, m_depthTargetImage->object(), VK_IMAGE_ASPECT_DEPTH_BIT,
654                           VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
655                           VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, VK_ACCESS_MEMORY_READ_BIT,
656                           VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, VK_PIPELINE_STAGE_HOST_BIT);
657 
658     endCommandBuffer(vk, *cmdBuffer);
659     submitCommandsAndWait(vk, device, queue, *cmdBuffer);
660 
661     VK_CHECK(vk.queueWaitIdle(queue));
662 
663     if (hasColor)
664     {
665         const auto resultImage = m_colorTargetImage->readSurface(queue, m_context.getDefaultAllocator(),
666                                                                  VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, {0, 0, 0}, WIDTH,
667                                                                  HEIGHT, VK_IMAGE_ASPECT_COLOR_BIT);
668 
669 #ifdef CTS_USES_VULKANSC
670         if (m_context.getTestContext().getCommandLine().isSubProcess())
671 #endif // CTS_USES_VULKANSC
672         {
673             for (int z = 0; z < resultImage.getDepth(); ++z)
674                 for (int y = 0; y < resultImage.getHeight(); ++y)
675                     for (int x = 0; x < resultImage.getWidth(); ++x)
676                     {
677                         const Vec4 difference = m_params.expectedColor - resultImage.getPixel(x, y, z);
678                         if (abs(difference.x()) >= m_params.colorEpsilon ||
679                             abs(difference.y()) >= m_params.colorEpsilon ||
680                             abs(difference.z()) >= m_params.colorEpsilon)
681                         {
682                             ostringstream msg;
683                             msg << "Color value mismatch, expected: " << m_params.expectedColor
684                                 << ", got: " << resultImage.getPixel(x, y, z) << " at "
685                                 << "(" << x << ", " << y << ", " << z << ")";
686                             return tcu::TestStatus::fail(msg.str());
687                         }
688                     }
689         }
690     }
691     if (hasDepth)
692     {
693         const auto resultImage = m_depthTargetImage->readSurface(queue, m_context.getDefaultAllocator(),
694                                                                  VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, {0, 0, 0}, WIDTH,
695                                                                  HEIGHT, VK_IMAGE_ASPECT_DEPTH_BIT);
696 
697 #ifdef CTS_USES_VULKANSC
698         if (m_context.getTestContext().getCommandLine().isSubProcess())
699 #endif // CTS_USES_VULKANSC
700         {
701             for (int z = 0; z < resultImage.getDepth(); ++z)
702                 for (int y = 0; y < resultImage.getHeight(); ++y)
703                     for (int x = 0; x < resultImage.getWidth(); ++x)
704                     {
705                         const float difference = m_params.expectedDepth - resultImage.getPixDepth(x, y, z);
706                         if (abs(difference) >= m_params.depthEpsilon)
707                         {
708                             ostringstream msg;
709                             msg << "Depth value mismatch, expected: " << m_params.expectedDepth
710                                 << ", got: " << resultImage.getPixDepth(x, y, z) << " at "
711                                 << "(" << x << ", " << y << ", " << z << ")";
712                             return tcu::TestStatus::fail(msg.str());
713                         }
714                     }
715         }
716     }
717     return tcu::TestStatus::pass("Pass");
718 }
719 
720 class MultipleClearsWithinRenderPassTest : public TestCase
721 {
722 public:
MultipleClearsWithinRenderPassTest(tcu::TestContext & testCtx,const string & name,const TestParams & params)723     MultipleClearsWithinRenderPassTest(tcu::TestContext &testCtx, const string &name, const TestParams &params)
724         : TestCase(testCtx, name)
725         , m_params(params)
726     {
727         DE_ASSERT(m_params.steps.size() <= static_cast<size_t>(TEST_MAX_STEPS_COUNT));
728     }
729 
initPrograms(SourceCollections & programCollection) const730     virtual void initPrograms(SourceCollections &programCollection) const
731     {
732         {
733             ostringstream src;
734             src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
735                 << "\n"
736                 << "layout(location = 0) in vec4 in_position;\n"
737                 << "\n"
738                 << "out gl_PerVertex {\n"
739                 << "    vec4  gl_Position;\n"
740                 << "};\n"
741                 << "\n"
742                 << "void main(void)\n"
743                 << "{\n"
744                 << "    gl_Position = in_position;\n"
745                 << "}\n";
746             programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
747         }
748         {
749             ostringstream src;
750             src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
751                 << "\n"
752                 << "layout(push_constant) uniform Color { vec4 color; } u_color;\n"
753                 << "layout(location = 0) out vec4 out_color;\n"
754                 << "\n"
755                 << "void main(void)\n"
756                 << "{\n"
757                 << "    out_color = u_color.color;\n"
758                 << "}\n";
759             programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
760         }
761         {
762             ostringstream src;
763             src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
764                 << "\n"
765                 << "layout(push_constant) uniform Color { vec4 color; } u_color;\n"
766                 << "\n"
767                 << "void main(void)\n"
768                 << "{\n"
769                 << "}\n";
770             programCollection.glslSources.add("frag_depthonly") << glu::FragmentSource(src.str());
771         }
772     }
773 
checkSupport(Context & context) const774     virtual void checkSupport(Context &context) const
775     {
776         VkImageFormatProperties imageFormatProperties;
777         const auto &vki = context.getInstanceInterface();
778         const auto &vkd = context.getPhysicalDevice();
779         if (m_params.colorFormat != VK_FORMAT_UNDEFINED)
780         {
781             const auto colorUsage =
782                 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
783             if (vki.getPhysicalDeviceImageFormatProperties(vkd, m_params.colorFormat, VK_IMAGE_TYPE_2D,
784                                                            VK_IMAGE_TILING_OPTIMAL, colorUsage, 0u,
785                                                            &imageFormatProperties) != VK_SUCCESS)
786                 TCU_THROW(NotSupportedError, "Color format not supported");
787 
788             vk::VkFormatProperties formatProperties;
789             vki.getPhysicalDeviceFormatProperties(vkd, m_params.colorFormat, &formatProperties);
790             if ((formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT) == 0)
791                 TCU_THROW(NotSupportedError, "Color format not supported");
792         }
793         if (m_params.depthFormat != VK_FORMAT_UNDEFINED)
794         {
795             const auto depthUsage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
796                                     VK_IMAGE_USAGE_TRANSFER_DST_BIT;
797             if (vki.getPhysicalDeviceImageFormatProperties(vkd, m_params.depthFormat, VK_IMAGE_TYPE_2D,
798                                                            VK_IMAGE_TILING_OPTIMAL, depthUsage, 0u,
799                                                            &imageFormatProperties) != VK_SUCCESS)
800                 TCU_THROW(NotSupportedError, "Depth format not supported");
801         }
802 
803         if (m_params.groupParams->useDynamicRendering)
804             context.requireDeviceFunctionality("VK_KHR_dynamic_rendering");
805     }
806 
createInstance(Context & context) const807     virtual TestInstance *createInstance(Context &context) const
808     {
809         return new MultipleClearsTest(context, m_params);
810     }
811 
812 private:
813     const TestParams m_params;
814 };
815 
816 } // namespace
817 
MultipleClearsWithinRenderPassTests(tcu::TestContext & testCtx,const SharedGroupParams groupParams)818 MultipleClearsWithinRenderPassTests::MultipleClearsWithinRenderPassTests(tcu::TestContext &testCtx,
819                                                                          const SharedGroupParams groupParams)
820     : TestCaseGroup(testCtx, "multiple_clears_within_render_pass")
821     , m_groupParams(groupParams)
822 {
823 }
824 
~MultipleClearsWithinRenderPassTests()825 MultipleClearsWithinRenderPassTests::~MultipleClearsWithinRenderPassTests()
826 {
827 }
828 
init()829 void MultipleClearsWithinRenderPassTests::init()
830 {
831     for (const auto &formatPair : formatsToTest)
832     {
833         ostringstream formatSuffix;
834         if (formatPair.colorFormat != VK_FORMAT_UNDEFINED)
835             formatSuffix << "_c" << de::toLower(string(getFormatName(formatPair.colorFormat)).substr(9));
836         if (formatPair.depthFormat != VK_FORMAT_UNDEFINED)
837             formatSuffix << "_d" << de::toLower(string(getFormatName(formatPair.depthFormat)).substr(9));
838         for (const auto &topology : topologiesToTest)
839         {
840             // reduce number of tests for dynamic rendering cases where secondary command buffer is used
841             if (m_groupParams->useSecondaryCmdBuffer && (topology != Topology::TRIANGLE_STRIP))
842                 continue;
843 
844             const string testNameSuffix = formatSuffix.str() + verticesByTopology[(uint32_t)topology].testNameSuffix;
845             {
846                 const TestParams params{formatPair.colorFormat,       // VkFormat colorFormat;
847                                         formatPair.depthFormat,       // VkFormat depthFormat;
848                                         topology,                     // Topology topology;
849                                         Vec4(0.0f, 0.5f, 0.5f, 1.0f), // Vec4 expectedColor;
850                                         0.01f,                        // float colorEpsilon;
851                                         0.9f,                         // float expectedDepth;
852                                         0.01f,                        // float depthEpsilon;
853                                         1u,                           // uint32_t repeatCount;
854                                         true,                         // bool enableBlend;
855                                         m_groupParams,                // SharedGroupParams groupParams;
856                                         {                             // vector<ClearStep> steps;
857                                          {ClearOp::LOAD, Vec4(1.0f, 0.0f, 0.0f, 1.0f), 0.7f},
858                                          {ClearOp::CLEAR, Vec4(0.0f, 1.0f, 0.0f, 1.0f), 0.3f},
859                                          {ClearOp::DRAW, Vec4(0.0f, 0.0f, 1.0f, 0.5f), 0.9f}}};
860                 // Multiple clears within same render pass, methods: load, clear, draw
861                 addChild(new MultipleClearsWithinRenderPassTest(m_testCtx, "load_clear_draw" + testNameSuffix, params));
862             }
863             {
864                 const TestParams params{formatPair.colorFormat,       // VkFormat format;
865                                         formatPair.depthFormat,       // VkFormat depthFormat;
866                                         topology,                     // Topology topology;
867                                         Vec4(0.0f, 0.5f, 0.5f, 1.0f), // Vec4 expectedColor;
868                                         0.01f,                        // float colorEpsilon;
869                                         0.9f,                         // float expectedDepth;
870                                         0.01f,                        // float depthEpsilon;
871                                         1u,                           // uint32_t repeatCount;
872                                         true,                         // bool enableBlend;
873                                         m_groupParams,                // SharedGroupParams groupParams;
874                                         {                             // vector<ClearStep> steps;
875                                          {ClearOp::DRAW, Vec4(1.0f, 0.0f, 0.0f, 1.0f), 0.7f},
876                                          {ClearOp::CLEAR, Vec4(0.0f, 1.0f, 0.0f, 1.0f), 0.3f},
877                                          {ClearOp::DRAW, Vec4(0.0f, 0.0f, 1.0f, 0.5f), 0.9f}}};
878                 // Multiple clears within same render pass, methods: draw, clear, draw
879                 addChild(new MultipleClearsWithinRenderPassTest(m_testCtx, "draw_clear_draw" + testNameSuffix, params));
880             }
881             {
882                 const TestParams params{formatPair.colorFormat,       // VkFormat format;
883                                         formatPair.depthFormat,       // VkFormat depthFormat;
884                                         topology,                     // Topology topology;
885                                         Vec4(0.0f, 0.5f, 0.5f, 1.0f), // Vec4 expectedColor;
886                                         0.01f,                        // float colorEpsilon;
887                                         0.9f,                         // float expectedDepth;
888                                         0.01f,                        // float depthEpsilon;
889                                         1u,                           // uint32_t repeatCount;
890                                         true,                         // bool enableBlend;
891                                         m_groupParams,                // SharedGroupParams groupParams;
892                                         {                             // vector<ClearStep> steps;
893                                          {ClearOp::CLEAR, Vec4(1.0f, 0.0f, 0.0f, 1.0f), 0.7f},
894                                          {ClearOp::CLEAR, Vec4(0.0f, 1.0f, 0.0f, 1.0f), 0.3f},
895                                          {ClearOp::DRAW, Vec4(0.0f, 0.0f, 1.0f, 0.5f), 0.9f}}};
896                 // Multiple clears within same render pass, methods: clear, clear, draw
897                 addChild(
898                     new MultipleClearsWithinRenderPassTest(m_testCtx, "clear_clear_draw" + testNameSuffix, params));
899             }
900             {
901                 const TestParams params{formatPair.colorFormat,       // VkFormat format;
902                                         formatPair.depthFormat,       // VkFormat depthFormat;
903                                         topology,                     // Topology topology;
904                                         Vec4(0.0f, 1.0f, 0.0f, 1.0f), // Vec4 expectedColor;
905                                         0.01f,                        // float colorEpsilon;
906                                         0.9f,                         // float expectedDepth;
907                                         0.01f,                        // float depthEpsilon;
908                                         1u,                           // uint32_t repeatCount;
909                                         false,                        // bool enableBlend;
910                                         m_groupParams,                // SharedGroupParams groupParams;
911                                         {                             // vector<ClearStep> steps;
912                                          {ClearOp::LOAD, Vec4(1.0f, 0.0f, 0.0f, 1.0f), 0.3f},
913                                          {ClearOp::CLEAR, Vec4(0.0f, 1.0f, 0.0f, 1.0f), 0.9f}}};
914                 // Multiple clears within same render pass, methods: load, clear
915                 addChild(new MultipleClearsWithinRenderPassTest(m_testCtx, "load_clear" + testNameSuffix, params));
916             }
917             {
918                 const TestParams params{formatPair.colorFormat,       // VkFormat format;
919                                         formatPair.depthFormat,       // VkFormat depthFormat;
920                                         topology,                     // Topology topology;
921                                         Vec4(0.0f, 1.0f, 0.0f, 1.0f), // Vec4 expectedColor;
922                                         0.01f,                        // float colorEpsilon;
923                                         0.9f,                         // float expectedDepth;
924                                         0.01f,                        // float depthEpsilon;
925                                         1u,                           // uint32_t repeatCount;
926                                         false,                        // bool enableBlend;
927                                         m_groupParams,                // SharedGroupParams groupParams;
928                                         {                             // vector<ClearStep> steps;
929                                          {ClearOp::DRAW, Vec4(1.0f, 0.0f, 0.0f, 1.0f), 0.3f},
930                                          {ClearOp::CLEAR, Vec4(0.0f, 1.0f, 0.0f, 1.0f), 0.9f}}};
931                 // Multiple clears within same render pass, methods: draw, clear
932                 addChild(new MultipleClearsWithinRenderPassTest(m_testCtx, "draw_clear" + testNameSuffix, params));
933             }
934             {
935                 const TestParams params{formatPair.colorFormat,       // VkFormat format;
936                                         formatPair.depthFormat,       // VkFormat depthFormat;
937                                         topology,                     // Topology topology;
938                                         Vec4(0.0f, 1.0f, 0.0f, 1.0f), // Vec4 expectedColor;
939                                         0.01f,                        // float colorEpsilon;
940                                         0.9f,                         // float expectedDepth;
941                                         0.01f,                        // float depthEpsilon;
942                                         1u,                           // uint32_t repeatCount;
943                                         false,                        // bool enableBlend;
944                                         m_groupParams,                // SharedGroupParams groupParams;
945                                         {                             // vector<ClearStep> steps;
946                                          {ClearOp::CLEAR, Vec4(1.0f, 0.0f, 0.0f, 1.0f), 0.3f},
947                                          {ClearOp::CLEAR, Vec4(0.0f, 1.0f, 0.0f, 1.0f), 0.9f}}};
948                 // Multiple clears within same render pass, methods: clear, clear
949                 addChild(new MultipleClearsWithinRenderPassTest(m_testCtx, "clear_clear" + testNameSuffix, params));
950             }
951         }
952     }
953 }
954 } // namespace Draw
955 } // namespace vkt
956