• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "vktRenderPassMultipleSubpassesMultipleCommandBuffersTests.hpp"
26 #include "pipeline/vktPipelineImageUtil.hpp"
27 #include "vkQueryUtil.hpp"
28 #include "vkRefUtil.hpp"
29 #include "vkCmdUtil.hpp"
30 #include "vkObjUtil.hpp"
31 #include "vkImageUtil.hpp"
32 #include "tcuTextureUtil.hpp"
33 #include "tcuImageCompare.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 struct Vertex
49 {
50     tcu::Vec4 position;
51     tcu::Vec4 color;
52 };
53 
54 template <typename T>
sizeInBytes(const std::vector<T> & vec)55 inline VkDeviceSize sizeInBytes(const std::vector<T> &vec)
56 {
57     return vec.size() * sizeof(vec[0]);
58 }
59 
genVertices(void)60 std::vector<Vertex> genVertices(void)
61 {
62     std::vector<Vertex> vectorData;
63     const tcu::Vec4 red    = {1.0f, 0.0f, 0.0f, 1.0f};
64     const tcu::Vec4 green  = {0.0f, 1.0f, 0.0f, 1.0f};
65     const tcu::Vec4 blue   = {0.0f, 0.0f, 1.0f, 1.0f};
66     const tcu::Vec4 yellow = {1.0f, 1.0f, 0.0f, 1.0f};
67 
68     vectorData.push_back({tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f), red});
69     vectorData.push_back({tcu::Vec4(0.0f, -1.0f, 0.0f, 1.0f), red});
70     vectorData.push_back({tcu::Vec4(-1.0f, 1.0f, 0.0f, 1.0f), red});
71     vectorData.push_back({tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f), red});
72 
73     vectorData.push_back({tcu::Vec4(0.0f, -1.0f, 0.0f, 1.0f), green});
74     vectorData.push_back({tcu::Vec4(1.0f, -1.0f, 0.0f, 1.0f), green});
75     vectorData.push_back({tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f), green});
76     vectorData.push_back({tcu::Vec4(1.0f, 1.0f, 0.0f, 1.0f), green});
77 
78     vectorData.push_back({tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f), blue});
79     vectorData.push_back({tcu::Vec4(0.0f, -1.0f, 0.0f, 1.0f), blue});
80     vectorData.push_back({tcu::Vec4(-1.0f, 1.0f, 0.0f, 1.0f), blue});
81     vectorData.push_back({tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f), blue});
82 
83     vectorData.push_back({tcu::Vec4(0.0f, -1.0f, 0.0f, 1.0f), yellow});
84     vectorData.push_back({tcu::Vec4(1.0f, -1.0f, 0.0f, 1.0f), yellow});
85     vectorData.push_back({tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f), yellow});
86     vectorData.push_back({tcu::Vec4(1.0f, 1.0f, 0.0f, 1.0f), yellow});
87 
88     return vectorData;
89 }
90 
91 class MultipleSubpassesMultipleCommandBuffersTestInstance : public TestInstance
92 {
93 public:
94     MultipleSubpassesMultipleCommandBuffersTestInstance(Context &context);
~MultipleSubpassesMultipleCommandBuffersTestInstance(void)95     virtual ~MultipleSubpassesMultipleCommandBuffersTestInstance(void)
96     {
97     }
98     virtual tcu::TestStatus iterate(void);
99     void createCommandBuffer(const DeviceInterface &vk, VkDevice vkDevice);
100 
101 private:
102     static constexpr uint32_t kImageWidth  = 32;
103     static constexpr uint32_t kImageHeight = 32;
104     const tcu::UVec2 m_renderSize          = {kImageWidth, kImageHeight};
105 
106     VkClearValue m_initialColor;
107     VkClearValue m_clearColor;
108 
109     Move<VkImage> m_colorImageA;
110     de::MovePtr<Allocation> m_colorImageAllocA;
111     Move<VkImageView> m_colorAttachmentViewA;
112 
113     Move<VkImage> m_colorImageB;
114     de::MovePtr<Allocation> m_colorImageAllocB;
115     Move<VkImageView> m_colorAttachmentViewB;
116 
117     Move<VkRenderPass> m_renderPass;
118     Move<VkFramebuffer> m_framebufferA;
119     Move<VkFramebuffer> m_framebufferB;
120     Move<VkShaderModule> m_vertexShaderModule;
121     Move<VkShaderModule> m_fragmentShaderModule;
122     Move<VkDescriptorSetLayout> m_descriptorSetLayout;
123     Move<VkPipelineLayout> m_pipelineLayout;
124     Move<VkPipeline> m_graphicsPipeline0;
125     Move<VkPipeline> m_graphicsPipeline1;
126     Move<VkPipeline> m_graphicsPipeline2;
127     Move<VkCommandPool> m_cmdPool;
128     Move<VkCommandBuffer> m_cmdBufferA;
129     Move<VkCommandBuffer> m_cmdBufferB;
130 
131     Move<VkBuffer> m_vertexBuffer;
132     de::MovePtr<Allocation> m_vertexBufferAlloc;
133 };
134 
135 class MultipleSubpassesMultipleCommandBuffersTest : public vkt::TestCase
136 {
137 public:
MultipleSubpassesMultipleCommandBuffersTest(tcu::TestContext & testContext,const std::string & name)138     MultipleSubpassesMultipleCommandBuffersTest(tcu::TestContext &testContext, const std::string &name)
139         : vkt::TestCase(testContext, name)
140     {
141     }
~MultipleSubpassesMultipleCommandBuffersTest(void)142     virtual ~MultipleSubpassesMultipleCommandBuffersTest(void)
143     {
144     }
145     virtual void initPrograms(SourceCollections &sourceCollections) const;
146     virtual TestInstance *createInstance(Context &context) const;
147 };
148 
createInstance(Context & context) const149 TestInstance *MultipleSubpassesMultipleCommandBuffersTest::createInstance(Context &context) const
150 {
151     return new MultipleSubpassesMultipleCommandBuffersTestInstance(context);
152 }
153 
initPrograms(SourceCollections & sourceCollections) const154 void MultipleSubpassesMultipleCommandBuffersTest::initPrograms(SourceCollections &sourceCollections) const
155 {
156     // Vertex shader.
157     sourceCollections.glslSources.add("vert_shader") << glu::VertexSource("#version 450\n"
158                                                                           "layout(location = 0) in vec4 position;\n"
159                                                                           "layout(location = 1) in vec4 color;\n"
160                                                                           "layout(location = 0) out vec4 vtxColor;\n"
161                                                                           "void main (void)\n"
162                                                                           "{\n"
163                                                                           "\tgl_Position = position;\n"
164                                                                           "\tvtxColor = color;\n"
165                                                                           "}\n");
166 
167     // Fragment shader.
168     std::ostringstream fragmentSource;
169 
170     fragmentSource << "#version 450\n"
171                    << "layout(location = 0) in vec4 vtxColor;\n"
172                    << "layout(location = 0) out vec4 fragColor;\n"
173                    << "void main (void)\n"
174                    << "{\n"
175                    << "\tfragColor = vtxColor;\n"
176                    << "}\n";
177 
178     sourceCollections.glslSources.add("frag_shader") << glu::FragmentSource(fragmentSource.str());
179 }
180 
181 // Create a render pass for this use case.
createRenderPass(const DeviceInterface & vk,VkDevice vkDevice)182 Move<VkRenderPass> createRenderPass(const DeviceInterface &vk, VkDevice vkDevice)
183 {
184     // Create attachment descriptions.
185     const VkAttachmentDescription attachmentDescription = {
186         (VkAttachmentDescriptionFlags)0,          // VkAttachmentDescriptionFlags        flags
187         VK_FORMAT_R32G32B32A32_SFLOAT,            // VkFormat                            format
188         VK_SAMPLE_COUNT_1_BIT,                    // VkSampleCountFlagBits            samples
189         VK_ATTACHMENT_LOAD_OP_LOAD,               // VkAttachmentLoadOp                loadOp
190         VK_ATTACHMENT_STORE_OP_STORE,             // VkAttachmentStoreOp                storeOp
191         VK_ATTACHMENT_LOAD_OP_DONT_CARE,          // VkAttachmentLoadOp                stencilLoadOp
192         VK_ATTACHMENT_STORE_OP_DONT_CARE,         // VkAttachmentStoreOp                stencilStoreOp
193         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout                    initialLayout
194         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL  // VkImageLayout                    finalLayout
195     };
196 
197     // Mark attachments as used or not depending on the test parameters.
198     const VkAttachmentReference attachmentReference{
199         0u,                                       // uint32_t                attachment
200         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout        layout
201     };
202 
203     // Create subpass description with the previous color attachment references.
204     std::vector<vk::VkSubpassDescription> subpassDescriptions;
205     {
206         const vk::VkSubpassDescription subpassDescription = {
207             (VkSubpassDescriptionFlags)0,    // VkSubpassDescriptionFlags        flags
208             VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint                pipelineBindPoint
209             0u,                              // uint32_t                            inputAttachmentCount
210             DE_NULL,                         // const VkAttachmentReference*        pInputAttachments
211             1u,                              // uint32_t                            colorAttachmentCount
212             &attachmentReference,            // const VkAttachmentReference*        pColorAttachments
213             DE_NULL,                         // const VkAttachmentReference*        pResolveAttachments
214             DE_NULL,                         // const VkAttachmentReference*        pDepthStencilAttachment
215             0u,                              // uint32_t                            preserveAttachmentCount
216             DE_NULL                          // const uint32_t*                    pPreserveAttachments
217         };
218         subpassDescriptions.emplace_back(subpassDescription);
219         subpassDescriptions.emplace_back(subpassDescription);
220         subpassDescriptions.emplace_back(subpassDescription);
221     }
222 
223     std::vector<vk::VkSubpassDependency> subpassDependencies;
224     {
225         vk::VkSubpassDependency subpassDependency = {
226             0u,                                            // uint32_t                srcSubpass
227             1u,                                            // uint32_t                    dstSubpass
228             VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, // VkPipelineStageFlags        srcStageMask
229             VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, // VkPipelineStageFlags        dstStageMask
230             VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,          // VkAccessFlags            srcAccessMask
231             VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,          // VkAccessFlags            dstAccessMask
232             0u                                             // VkDependencyFlags        dependencyFlags
233         };
234         subpassDependencies.emplace_back(subpassDependency);
235         subpassDependency.srcSubpass = 1u;
236         subpassDependency.dstSubpass = 2u;
237         subpassDependencies.emplace_back(subpassDependency);
238     }
239 
240     const vk::VkRenderPassCreateInfo renderPassInfo = {
241         VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,         // VkStructureType                    sType
242         DE_NULL,                                           // const void*                        pNext
243         (VkRenderPassCreateFlags)0,                        // VkRenderPassCreateFlags            flags
244         1u,                                                // uint32_t                            attachmentCount
245         &attachmentDescription,                            // const VkAttachmentDescription*    pAttachments
246         static_cast<uint32_t>(subpassDescriptions.size()), // uint32_t                            subpassCount
247         subpassDescriptions.data(),                        // const VkSubpassDescription*        pSubpasses
248         static_cast<uint32_t>(subpassDependencies.size()), // uint32_t                            dependencyCount
249         subpassDependencies.data(),                        // const VkSubpassDependency*        pDependencies
250     };
251 
252     return createRenderPass(vk, vkDevice, &renderPassInfo);
253 }
254 
MultipleSubpassesMultipleCommandBuffersTestInstance(Context & context)255 MultipleSubpassesMultipleCommandBuffersTestInstance::MultipleSubpassesMultipleCommandBuffersTestInstance(
256     Context &context)
257     : vkt::TestInstance(context)
258 {
259     // Initial color for all images.
260     m_initialColor.color.float32[0] = 0.0f;
261     m_initialColor.color.float32[1] = 0.0f;
262     m_initialColor.color.float32[2] = 0.0f;
263     m_initialColor.color.float32[3] = 1.0f;
264 
265     // Clear color for used attachments.
266     m_clearColor.color.float32[0] = 1.0f;
267     m_clearColor.color.float32[1] = 1.0f;
268     m_clearColor.color.float32[2] = 1.0f;
269     m_clearColor.color.float32[3] = 1.0f;
270 
271     const DeviceInterface &vk       = m_context.getDeviceInterface();
272     const VkDevice vkDevice         = m_context.getDevice();
273     const uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
274     SimpleAllocator memAlloc(
275         vk, vkDevice,
276         getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
277     const VkComponentMapping componentMapping = {VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY,
278                                                  VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY};
279 
280     // Create color images.
281     {
282         const VkImageCreateInfo colorImageParams = {
283             VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
284             DE_NULL,                             // const void* pNext;
285             0u,                                  // VkImageCreateFlags flags;
286             VK_IMAGE_TYPE_2D,                    // VkImageType imageType;
287             VK_FORMAT_R32G32B32A32_SFLOAT,       // VkFormat format;
288             {kImageWidth, kImageHeight, 1u},     // VkExtent3D extent;
289             1u,                                  // uint32_t mipLevels;
290             1u,                                  // uint32_t arrayLayers;
291             VK_SAMPLE_COUNT_1_BIT,               // VkSampleCountFlagBits samples;
292             VK_IMAGE_TILING_OPTIMAL,             // VkImageTiling tiling;
293             VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
294                 VK_IMAGE_USAGE_TRANSFER_DST_BIT, // VkImageUsageFlags usage;
295             VK_SHARING_MODE_EXCLUSIVE,           // VkSharingMode sharingMode;
296             1u,                                  // uint32_t queueFamilyIndexCount;
297             &queueFamilyIndex,                   // const uint32_t* pQueueFamilyIndices;
298             VK_IMAGE_LAYOUT_UNDEFINED            // VkImageLayout initialLayout;
299         };
300         // Create, allocate and bind image memory.
301         m_colorImageA = createImage(vk, vkDevice, &colorImageParams);
302         m_colorImageAllocA =
303             memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *m_colorImageA), MemoryRequirement::Any);
304         VK_CHECK(vk.bindImageMemory(vkDevice, *m_colorImageA, m_colorImageAllocA->getMemory(),
305                                     m_colorImageAllocA->getOffset()));
306 
307         m_colorImageB = createImage(vk, vkDevice, &colorImageParams);
308         m_colorImageAllocB =
309             memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *m_colorImageB), MemoryRequirement::Any);
310         VK_CHECK(vk.bindImageMemory(vkDevice, *m_colorImageB, m_colorImageAllocB->getMemory(),
311                                     m_colorImageAllocB->getOffset()));
312 
313         // Create image view.
314         {
315             const VkImageViewCreateInfo colorAttachmentViewParamsA = {
316                 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,   // VkStructureType sType;
317                 DE_NULL,                                    // const void* pNext;
318                 0u,                                         // VkImageViewCreateFlags flags;
319                 *m_colorImageA,                             // VkImage image;
320                 VK_IMAGE_VIEW_TYPE_2D,                      // VkImageViewType viewType;
321                 VK_FORMAT_R32G32B32A32_SFLOAT,              // VkFormat format;
322                 componentMapping,                           // VkChannelMapping channels;
323                 {VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u} // VkImageSubresourceRange subresourceRange;
324             };
325             m_colorAttachmentViewA = createImageView(vk, vkDevice, &colorAttachmentViewParamsA);
326 
327             const VkImageViewCreateInfo colorAttachmentViewParamsB = {
328                 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,   // VkStructureType sType;
329                 DE_NULL,                                    // const void* pNext;
330                 0u,                                         // VkImageViewCreateFlags flags;
331                 *m_colorImageB,                             // VkImage image;
332                 VK_IMAGE_VIEW_TYPE_2D,                      // VkImageViewType viewType;
333                 VK_FORMAT_R32G32B32A32_SFLOAT,              // VkFormat format;
334                 componentMapping,                           // VkChannelMapping channels;
335                 {VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u} // VkImageSubresourceRange subresourceRange;
336             };
337             m_colorAttachmentViewB = createImageView(vk, vkDevice, &colorAttachmentViewParamsB);
338         }
339 
340         // Clear image and leave it prepared to be used as a color attachment.
341         {
342             const VkImageAspectFlags aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
343             Move<VkCommandPool> cmdPool;
344             Move<VkCommandBuffer> cmdBuffer;
345             std::vector<VkImageMemoryBarrier> preImageBarriers;
346             std::vector<VkImageMemoryBarrier> postImageBarriers;
347 
348             // Create command pool and buffer
349             cmdPool   = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
350             cmdBuffer = allocateCommandBuffer(vk, vkDevice, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
351 
352             // From undefined layout to VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL.
353             const VkImageMemoryBarrier preImageBarrierA = {
354                 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
355                 DE_NULL,                                // const void* pNext;
356                 0u,                                     // VkAccessFlags srcAccessMask;
357                 VK_ACCESS_TRANSFER_WRITE_BIT,           // VkAccessFlags dstAccessMask;
358                 VK_IMAGE_LAYOUT_UNDEFINED,              // VkImageLayout oldLayout;
359                 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,   // VkImageLayout newLayout;
360                 VK_QUEUE_FAMILY_IGNORED,                // uint32_t srcQueueFamilyIndex;
361                 VK_QUEUE_FAMILY_IGNORED,                // uint32_t dstQueueFamilyIndex;
362                 *m_colorImageA,                         // VkImage image;
363                 {
364                     // VkImageSubresourceRange subresourceRange;
365                     aspectMask, // VkImageAspect aspect;
366                     0u,         // uint32_t baseMipLevel;
367                     1u,         // uint32_t mipLevels;
368                     0u,         // uint32_t baseArraySlice;
369                     1u          // uint32_t arraySize;
370                 }};
371 
372             preImageBarriers.emplace_back(preImageBarrierA);
373 
374             // From VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL to VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL.
375             const VkImageMemoryBarrier postImageBarrierA = {
376                 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,   // VkStructureType sType;
377                 DE_NULL,                                  // const void* pNext;
378                 VK_ACCESS_TRANSFER_WRITE_BIT,             // VkAccessFlags srcAccessMask;
379                 VK_ACCESS_SHADER_READ_BIT,                // VkAccessFlags dstAccessMask;
380                 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,     // VkImageLayout oldLayout;
381                 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout newLayout;
382                 VK_QUEUE_FAMILY_IGNORED,                  // uint32_t srcQueueFamilyIndex;
383                 VK_QUEUE_FAMILY_IGNORED,                  // uint32_t dstQueueFamilyIndex;
384                 *m_colorImageA,                           // VkImage image;
385                 {
386                     // VkImageSubresourceRange subresourceRange;
387                     aspectMask, // VkImageAspect aspect;
388                     0u,         // uint32_t baseMipLevel;
389                     1u,         // uint32_t mipLevels;
390                     0u,         // uint32_t baseArraySlice;
391                     1u          // uint32_t arraySize;
392                 }};
393 
394             postImageBarriers.emplace_back(postImageBarrierA);
395 
396             // From undefined layout to VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL.
397             const VkImageMemoryBarrier preImageBarrierB = {
398                 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
399                 DE_NULL,                                // const void* pNext;
400                 0u,                                     // VkAccessFlags srcAccessMask;
401                 VK_ACCESS_TRANSFER_WRITE_BIT,           // VkAccessFlags dstAccessMask;
402                 VK_IMAGE_LAYOUT_UNDEFINED,              // VkImageLayout oldLayout;
403                 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,   // VkImageLayout newLayout;
404                 VK_QUEUE_FAMILY_IGNORED,                // uint32_t srcQueueFamilyIndex;
405                 VK_QUEUE_FAMILY_IGNORED,                // uint32_t dstQueueFamilyIndex;
406                 *m_colorImageB,                         // VkImage image;
407                 {
408                     // VkImageSubresourceRange subresourceRange;
409                     aspectMask, // VkImageAspect aspect;
410                     0u,         // uint32_t baseMipLevel;
411                     1u,         // uint32_t mipLevels;
412                     0u,         // uint32_t baseArraySlice;
413                     1u          // uint32_t arraySize;
414                 }};
415 
416             preImageBarriers.emplace_back(preImageBarrierB);
417 
418             // From VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL to VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL.
419             const VkImageMemoryBarrier postImageBarrierB = {
420                 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,   // VkStructureType sType;
421                 DE_NULL,                                  // const void* pNext;
422                 VK_ACCESS_TRANSFER_WRITE_BIT,             // VkAccessFlags srcAccessMask;
423                 VK_ACCESS_SHADER_READ_BIT,                // VkAccessFlags dstAccessMask;
424                 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,     // VkImageLayout oldLayout;
425                 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout newLayout;
426                 VK_QUEUE_FAMILY_IGNORED,                  // uint32_t srcQueueFamilyIndex;
427                 VK_QUEUE_FAMILY_IGNORED,                  // uint32_t dstQueueFamilyIndex;
428                 *m_colorImageB,                           // VkImage image;
429                 {
430                     // VkImageSubresourceRange subresourceRange;
431                     aspectMask, // VkImageAspect aspect;
432                     0u,         // uint32_t baseMipLevel;
433                     1u,         // uint32_t mipLevels;
434                     0u,         // uint32_t baseArraySlice;
435                     1u          // uint32_t arraySize;
436                 }};
437 
438             postImageBarriers.emplace_back(postImageBarrierB);
439 
440             const VkImageSubresourceRange clearRange = {
441                 aspectMask, // VkImageAspectFlags aspectMask;
442                 0u,         // uint32_t baseMipLevel;
443                 1u,         // uint32_t levelCount;
444                 0u,         // uint32_t baseArrayLayer;
445                 1u          // uint32_t layerCount;
446             };
447 
448             // Clear image and transfer layout.
449             beginCommandBuffer(vk, *cmdBuffer);
450             vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
451                                   (VkDependencyFlags)0, 0, (const VkMemoryBarrier *)DE_NULL, 0,
452                                   (const VkBufferMemoryBarrier *)DE_NULL,
453                                   static_cast<uint32_t>(preImageBarriers.size()), preImageBarriers.data());
454             vk.cmdClearColorImage(*cmdBuffer, *m_colorImageA, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
455                                   &m_initialColor.color, 1, &clearRange);
456             vk.cmdClearColorImage(*cmdBuffer, *m_colorImageB, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
457                                   &m_initialColor.color, 1, &clearRange);
458             vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT,
459                                   (VkDependencyFlags)0, 0, (const VkMemoryBarrier *)DE_NULL, 0,
460                                   (const VkBufferMemoryBarrier *)DE_NULL,
461                                   static_cast<uint32_t>(postImageBarriers.size()), postImageBarriers.data());
462             endCommandBuffer(vk, *cmdBuffer);
463 
464             submitCommandsAndWait(vk, vkDevice, m_context.getUniversalQueue(), cmdBuffer.get());
465         }
466     }
467 
468     // Create render pass.
469     m_renderPass = createRenderPass(vk, vkDevice);
470 
471     // Create framebuffer
472     {
473         const VkImageView attachmentBindInfosA[1] = {
474             *m_colorAttachmentViewA,
475         };
476         const VkFramebufferCreateInfo framebufferParamsA = {
477             VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType;
478             DE_NULL,                                   // const void* pNext;
479             0u,                                        // VkFramebufferCreateFlags flags;
480             *m_renderPass,                             // VkRenderPass renderPass;
481             1u,                                        // uint32_t attachmentCount;
482             attachmentBindInfosA,                      // const VkImageView* pAttachments;
483             kImageWidth,                               // uint32_t width;
484             kImageHeight,                              // uint32_t height;
485             1u                                         // uint32_t layers;
486         };
487 
488         m_framebufferA = createFramebuffer(vk, vkDevice, &framebufferParamsA);
489 
490         const VkImageView attachmentBindInfosB[1] = {
491             *m_colorAttachmentViewB,
492         };
493         const VkFramebufferCreateInfo framebufferParamsB = {
494             VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType;
495             DE_NULL,                                   // const void* pNext;
496             0u,                                        // VkFramebufferCreateFlags flags;
497             *m_renderPass,                             // VkRenderPass renderPass;
498             1u,                                        // uint32_t attachmentCount;
499             attachmentBindInfosB,                      // const VkImageView* pAttachments;
500             kImageWidth,                               // uint32_t width;
501             kImageHeight,                              // uint32_t height;
502             1u                                         // uint32_t layers;
503         };
504 
505         m_framebufferB = createFramebuffer(vk, vkDevice, &framebufferParamsB);
506     }
507 
508     // Create pipeline layout.
509     {
510         const VkDescriptorSetLayoutCreateInfo descriptorSetLayoutParams = {
511             VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, // VkStructureType                        sType
512             DE_NULL,                                             // const void*                            pNext
513             0u,                                                  // VkDescriptorSetLayoutCreateFlags        flags
514             0u,                                                  // uint32_t                                bindingCount
515             DE_NULL                                              // const VkDescriptorSetLayoutBinding*    pBindings
516         };
517         m_descriptorSetLayout = createDescriptorSetLayout(vk, vkDevice, &descriptorSetLayoutParams);
518 
519         const VkPipelineLayoutCreateInfo pipelineLayoutParams = {
520             VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType;
521             DE_NULL,                                       // const void* pNext;
522             0u,                                            // VkPipelineLayoutCreateFlags flags;
523             1u,                                            // uint32_t setLayoutCount;
524             &m_descriptorSetLayout.get(),                  // const VkDescriptorSetLayout* pSetLayouts;
525             0u,                                            // uint32_t pushConstantRangeCount;
526             DE_NULL                                        // const VkPushConstantRange* pPushConstantRanges;
527         };
528 
529         m_pipelineLayout = createPipelineLayout(vk, vkDevice, &pipelineLayoutParams);
530     }
531 
532     // Create Vertex buffer
533     {
534         const std::vector<Vertex> vertexValues = genVertices();
535         const VkDeviceSize vertexBufferSize    = sizeInBytes(vertexValues);
536 
537         const vk::VkBufferCreateInfo bufferCreateInfo = {
538             VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,                                 // VkStructureType        sType
539             DE_NULL,                                                              // const void*            pNext
540             0u,                                                                   // VkBufferCreateFlags    flags
541             vertexBufferSize,                                                     // VkDeviceSize            size
542             VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, // VkBufferUsageFlags    usage
543             VK_SHARING_MODE_EXCLUSIVE,                                            // VkSharingMode        sharingMode
544             1u,               // uint32_t                queueFamilyIndexCount
545             &queueFamilyIndex // const uint32_t*        pQueueFamilyIndices
546         };
547 
548         m_vertexBuffer      = createBuffer(vk, vkDevice, &bufferCreateInfo);
549         m_vertexBufferAlloc = memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_vertexBuffer),
550                                                 MemoryRequirement::HostVisible);
551         VK_CHECK(vk.bindBufferMemory(vkDevice, *m_vertexBuffer, m_vertexBufferAlloc->getMemory(),
552                                      m_vertexBufferAlloc->getOffset()));
553         // Load vertices into vertex buffer
554         deMemcpy(m_vertexBufferAlloc->getHostPtr(), vertexValues.data(), static_cast<size_t>(vertexBufferSize));
555         flushAlloc(vk, vkDevice, *m_vertexBufferAlloc);
556     }
557 
558     // Vertex buffer description
559     const vk::VkVertexInputBindingDescription bindingDescription = {
560         0u,                         // uint32_t                binding
561         sizeof(Vertex),             // uint32_t                stride
562         VK_VERTEX_INPUT_RATE_VERTEX // VkVertexInputRate    inputRate
563     };
564 
565     std::vector<vk::VkVertexInputAttributeDescription> attributeDescriptions;
566     {
567         vk::VkVertexInputAttributeDescription attributeDescriptionVertex = {
568             0u,                            // uint32_t        location
569             0u,                            // uint32_t        binding
570             VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat        format
571             offsetof(Vertex, position)     // uint32_t        offset
572         };
573 
574         vk::VkVertexInputAttributeDescription attributeDescriptionColor = {
575             1u,                            // uint32_t        location
576             0u,                            // uint32_t        binding
577             VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat        format
578             offsetof(Vertex, color)        // uint32_t        offset
579         };
580         attributeDescriptions.emplace_back(attributeDescriptionVertex);
581         attributeDescriptions.emplace_back(attributeDescriptionColor);
582     }
583 
584     const vk::VkPipelineVertexInputStateCreateInfo vertexInputState = {
585         VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType                            sType
586         DE_NULL,                                                   // const void*                                pNext
587         0u,                                                        // VkPipelineVertexInputStateCreateFlags    flags
588         1u,                  // uint32_t                                    vertexBindingDescriptionCount
589         &bindingDescription, // const VkVertexInputBindingDescription*    pVertexBindingDescriptions
590         static_cast<uint32_t>(
591             attributeDescriptions
592                 .size()),             // uint32_t                                    vertexAttributeDescriptionCount
593         attributeDescriptions.data(), // const VkVertexInputAttributeDescription*    pVertexAttributeDescriptions
594     };
595 
596     m_vertexShaderModule   = createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("vert_shader"), 0);
597     m_fragmentShaderModule = createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("frag_shader"), 0);
598 
599     // Create pipeline.
600     {
601         const std::vector<VkViewport> viewports(1, makeViewport(m_renderSize));
602         const std::vector<VkRect2D> scissors(1, makeRect2D(m_renderSize));
603 
604         const VkPipelineColorBlendAttachmentState colorBlendAttachmentState = {
605             VK_FALSE,                // VkBool32                    blendEnable
606             VK_BLEND_FACTOR_ZERO,    // VkBlendFactor            srcColorBlendFactor
607             VK_BLEND_FACTOR_ZERO,    // VkBlendFactor            dstColorBlendFactor
608             VK_BLEND_OP_ADD,         // VkBlendOp                colorBlendOp
609             VK_BLEND_FACTOR_ZERO,    // VkBlendFactor            srcAlphaBlendFactor
610             VK_BLEND_FACTOR_ZERO,    // VkBlendFactor            dstAlphaBlendFactor
611             VK_BLEND_OP_ADD,         // VkBlendOp                alphaBlendOp
612             VK_COLOR_COMPONENT_R_BIT // VkColorComponentFlags    colorWriteMask
613                 | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT};
614 
615         const VkPipelineColorBlendStateCreateInfo colorBlendStateCreateInfo = {
616             VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType                                sType
617             DE_NULL,                    // const void*                                    pNext
618             0u,                         // VkPipelineColorBlendStateCreateFlags            flags
619             VK_FALSE,                   // VkBool32                                        logicOpEnable
620             VK_LOGIC_OP_CLEAR,          // VkLogicOp                                    logicOp
621             1u,                         // uint32_t                                        attachmentCount
622             &colorBlendAttachmentState, // const VkPipelineColorBlendAttachmentState*    pAttachments
623             {0.0f, 0.0f, 0.0f, 0.0f}    // float                                        blendConstants[4]
624         };
625 
626         m_graphicsPipeline0 = makeGraphicsPipeline(
627             vk,                      // const DeviceInterface&                            vk
628             vkDevice,                // const VkDevice                                    device
629             *m_pipelineLayout,       // const VkPipelineLayout                            pipelineLayout
630             *m_vertexShaderModule,   // const VkShaderModule                                vertexShaderModule
631             DE_NULL,                 // const VkShaderModule                                tessellationControlModule
632             DE_NULL,                 // const VkShaderModule                                tessellationEvalModule
633             DE_NULL,                 // const VkShaderModule                                geometryShaderModule
634             *m_fragmentShaderModule, // const VkShaderModule                                fragmentShaderModule
635             *m_renderPass,           // const VkRenderPass                                renderPass
636             viewports,               // const std::vector<VkViewport>&                    viewports
637             scissors,                // const std::vector<VkRect2D>&                        scissors
638             VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, // const VkPrimitiveTopology                        topology
639             0u,                                   // const uint32_t                                    subpass
640             0u,                // const uint32_t                                    patchControlPoints
641             &vertexInputState, // const VkPipelineVertexInputStateCreateInfo*        vertexInputStateCreateInfo
642             DE_NULL,           // const VkPipelineRasterizationStateCreateInfo*    rasterizationStateCreateInfo
643             DE_NULL,           // const VkPipelineMultisampleStateCreateInfo*        multisampleStateCreateInfo
644             DE_NULL,           // const VkPipelineDepthStencilStateCreateInfo*        depthStencilStateCreateInfo
645             &colorBlendStateCreateInfo); // const VkPipelineColorBlendStateCreateInfo*        colorBlendStateCreateInfo
646 
647         m_graphicsPipeline1 = makeGraphicsPipeline(
648             vk,                      // const DeviceInterface&                            vk
649             vkDevice,                // const VkDevice                                    device
650             *m_pipelineLayout,       // const VkPipelineLayout                            pipelineLayout
651             *m_vertexShaderModule,   // const VkShaderModule                                vertexShaderModule
652             DE_NULL,                 // const VkShaderModule                                tessellationControlModule
653             DE_NULL,                 // const VkShaderModule                                tessellationEvalModule
654             DE_NULL,                 // const VkShaderModule                                geometryShaderModule
655             *m_fragmentShaderModule, // const VkShaderModule                                fragmentShaderModule
656             *m_renderPass,           // const VkRenderPass                                renderPass
657             viewports,               // const std::vector<VkViewport>&                    viewports
658             scissors,                // const std::vector<VkRect2D>&                        scissors
659             VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, // const VkPrimitiveTopology                        topology
660             1u,                                   // const uint32_t                                    subpass
661             0u,                // const uint32_t                                    patchControlPoints
662             &vertexInputState, // const VkPipelineVertexInputStateCreateInfo*        vertexInputStateCreateInfo
663             DE_NULL,           // const VkPipelineRasterizationStateCreateInfo*    rasterizationStateCreateInfo
664             DE_NULL,           // const VkPipelineMultisampleStateCreateInfo*        multisampleStateCreateInfo
665             DE_NULL,           // const VkPipelineDepthStencilStateCreateInfo*        depthStencilStateCreateInfo
666             &colorBlendStateCreateInfo); // const VkPipelineColorBlendStateCreateInfo*        colorBlendStateCreateInfo
667 
668         m_graphicsPipeline2 = makeGraphicsPipeline(
669             vk,                      // const DeviceInterface&                            vk
670             vkDevice,                // const VkDevice                                    device
671             *m_pipelineLayout,       // const VkPipelineLayout                            pipelineLayout
672             *m_vertexShaderModule,   // const VkShaderModule                                vertexShaderModule
673             DE_NULL,                 // const VkShaderModule                                tessellationControlModule
674             DE_NULL,                 // const VkShaderModule                                tessellationEvalModule
675             DE_NULL,                 // const VkShaderModule                                geometryShaderModule
676             *m_fragmentShaderModule, // const VkShaderModule                                fragmentShaderModule
677             *m_renderPass,           // const VkRenderPass                                renderPass
678             viewports,               // const std::vector<VkViewport>&                    viewports
679             scissors,                // const std::vector<VkRect2D>&                        scissors
680             VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, // const VkPrimitiveTopology                        topology
681             2u,                                   // const uint32_t                                    subpass
682             0u,                // const uint32_t                                    patchControlPoints
683             &vertexInputState, // const VkPipelineVertexInputStateCreateInfo*        vertexInputStateCreateInfo
684             DE_NULL,           // const VkPipelineRasterizationStateCreateInfo*    rasterizationStateCreateInfo
685             DE_NULL,           // const VkPipelineMultisampleStateCreateInfo*        multisampleStateCreateInfo
686             DE_NULL,           // const VkPipelineDepthStencilStateCreateInfo*        depthStencilStateCreateInfo
687             &colorBlendStateCreateInfo); // const VkPipelineColorBlendStateCreateInfo*        colorBlendStateCreateInfo
688     }
689 
690     // Create command pool
691     m_cmdPool = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
692 
693     // Create command buffer
694     createCommandBuffer(vk, vkDevice);
695 }
696 
createCommandBuffer(const DeviceInterface & vk,VkDevice vkDevice)697 void MultipleSubpassesMultipleCommandBuffersTestInstance::createCommandBuffer(const DeviceInterface &vk,
698                                                                               VkDevice vkDevice)
699 {
700     const VkRenderPassBeginInfo renderPassBeginInfoA = {
701         VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType;
702         DE_NULL,                                  // const void* pNext;
703         *m_renderPass,                            // VkRenderPass renderPass;
704         *m_framebufferA,                          // VkFramebuffer framebuffer;
705         makeRect2D(m_renderSize),                 // VkRect2D renderArea;
706         0u,                                       // uint32_t clearValueCount;
707         DE_NULL                                   // const VkClearValue* pClearValues;
708     };
709     const VkRenderPassBeginInfo renderPassBeginInfoB = {
710         VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType;
711         DE_NULL,                                  // const void* pNext;
712         *m_renderPass,                            // VkRenderPass renderPass;
713         *m_framebufferB,                          // VkFramebuffer framebuffer;
714         makeRect2D(m_renderSize),                 // VkRect2D renderArea;
715         0u,                                       // uint32_t clearValueCount;
716         DE_NULL                                   // const VkClearValue* pClearValues;
717     };
718 
719     m_cmdBufferA = allocateCommandBuffer(vk, vkDevice, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
720     m_cmdBufferB = allocateCommandBuffer(vk, vkDevice, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
721 
722     const VkClearRect clearRect = {
723         {
724             // VkRect2D rect;
725             {
726                 0,
727                 0,
728             },                          // VkOffset2D offset;
729             {kImageWidth, kImageHeight} // VkExtent2D extent;
730         },
731         0u, // uint32_t baseArrayLayer;
732         1u  // uint32_t layerCount;
733     };
734 
735     const VkClearAttachment clearAttachment = {
736         VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask;
737         0u,                        // uint32_t colorAttachment;
738         m_clearColor               // VkClearValue clearValue;
739     };
740 
741     VkDeviceSize vertexBufferOffset = 0u;
742 
743     // Command Buffer A will set its own event but wait for the B's event before continuing to the next subpass.
744     beginCommandBuffer(vk, *m_cmdBufferA, 0u);
745     beginCommandBuffer(vk, *m_cmdBufferB, 0u);
746     vk.cmdBeginRenderPass(*m_cmdBufferA, &renderPassBeginInfoA, VK_SUBPASS_CONTENTS_INLINE);
747     vk.cmdBindPipeline(*m_cmdBufferA, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_graphicsPipeline0);
748     vk.cmdBindVertexBuffers(*m_cmdBufferA, 0u, 1u, &m_vertexBuffer.get(), &vertexBufferOffset);
749     vk.cmdClearAttachments(*m_cmdBufferA, 1u, &clearAttachment, 1u, &clearRect);
750 
751     vk.cmdBeginRenderPass(*m_cmdBufferB, &renderPassBeginInfoB, VK_SUBPASS_CONTENTS_INLINE);
752     vk.cmdBindPipeline(*m_cmdBufferB, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_graphicsPipeline0);
753     vk.cmdClearAttachments(*m_cmdBufferB, 1u, &clearAttachment, 1u, &clearRect);
754     vk.cmdNextSubpass(*m_cmdBufferB, VK_SUBPASS_CONTENTS_INLINE);
755 
756     vk.cmdNextSubpass(*m_cmdBufferA, VK_SUBPASS_CONTENTS_INLINE);
757     vk.cmdBindPipeline(*m_cmdBufferA, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_graphicsPipeline1);
758     vk.cmdBindVertexBuffers(*m_cmdBufferA, 0u, 1u, &m_vertexBuffer.get(), &vertexBufferOffset);
759     vk.cmdDraw(*m_cmdBufferA, 4u, 1u, 0u, 0u);
760 
761     vertexBufferOffset = 8 * sizeof(Vertex);
762     vk.cmdBindPipeline(*m_cmdBufferB, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_graphicsPipeline1);
763     vk.cmdBindVertexBuffers(*m_cmdBufferB, 0u, 1u, &m_vertexBuffer.get(), &vertexBufferOffset);
764     vk.cmdDraw(*m_cmdBufferB, 4u, 1u, 0u, 0u);
765     vk.cmdNextSubpass(*m_cmdBufferB, VK_SUBPASS_CONTENTS_INLINE);
766 
767     vertexBufferOffset = 0u;
768     vk.cmdNextSubpass(*m_cmdBufferA, VK_SUBPASS_CONTENTS_INLINE);
769     vk.cmdBindPipeline(*m_cmdBufferA, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_graphicsPipeline2);
770     vk.cmdBindVertexBuffers(*m_cmdBufferA, 0u, 1u, &m_vertexBuffer.get(), &vertexBufferOffset);
771     vk.cmdDraw(*m_cmdBufferA, 4u, 1u, 4u, 0u);
772 
773     vertexBufferOffset = 8 * sizeof(Vertex);
774     vk.cmdBindPipeline(*m_cmdBufferB, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_graphicsPipeline2);
775     vk.cmdDraw(*m_cmdBufferB, 4u, 1u, 4u, 0u);
776     vk.cmdEndRenderPass(*m_cmdBufferB);
777     vk.cmdEndRenderPass(*m_cmdBufferA);
778     endCommandBuffer(vk, *m_cmdBufferA);
779     endCommandBuffer(vk, *m_cmdBufferB);
780 }
781 
iterate(void)782 tcu::TestStatus MultipleSubpassesMultipleCommandBuffersTestInstance::iterate(void)
783 {
784     const DeviceInterface &vk       = m_context.getDeviceInterface();
785     const VkDevice vkDevice         = m_context.getDevice();
786     const VkQueue queue             = m_context.getUniversalQueue();
787     const uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
788     SimpleAllocator allocator(
789         vk, vkDevice,
790         getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
791 
792     {
793         const Unique<VkFence> fence(createFence(vk, vkDevice));
794         std::vector<VkCommandBuffer> commandBuffers;
795         commandBuffers.emplace_back(m_cmdBufferA.get());
796         commandBuffers.emplace_back(m_cmdBufferB.get());
797 
798         const VkSubmitInfo submitInfo = {
799             VK_STRUCTURE_TYPE_SUBMIT_INFO,                // VkStructureType sType;
800             DE_NULL,                                      // const void* pNext;
801             0u,                                           // uint32_t waitSemaphoreCount;
802             DE_NULL,                                      // const VkSemaphore* pWaitSemaphores;
803             (const VkPipelineStageFlags *)DE_NULL,        // const VkPipelineStageFlags* pWaitDstStageMask;
804             static_cast<uint32_t>(commandBuffers.size()), // uint32_t commandBufferCount;
805             commandBuffers.data(),                        // const VkCommandBuffer* pCommandBuffers;
806             0u,                                           // uint32_t signalSemaphoreCount;
807             DE_NULL,                                      // const VkSemaphore* pSignalSemaphores;
808         };
809 
810         VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo, *fence));
811         VK_CHECK(vk.waitForFences(vkDevice, 1u, &fence.get(), true, ~0ull));
812     }
813 
814     {
815         // Colors to compare to.
816         const tcu::Vec4 red    = {1.0f, 0.0f, 0.0f, 1.0f};
817         const tcu::Vec4 green  = {0.0f, 1.0f, 0.0f, 1.0f};
818         const tcu::Vec4 blue   = {0.0f, 0.0f, 1.0f, 1.0f};
819         const tcu::Vec4 yellow = {1.0f, 1.0f, 0.0f, 1.0f};
820 
821         // Read result images.
822         de::MovePtr<tcu::TextureLevel> imagePixelsA =
823             pipeline::readColorAttachment(vk, vkDevice, queue, queueFamilyIndex, allocator, *m_colorImageA,
824                                           VK_FORMAT_R32G32B32A32_SFLOAT, m_renderSize);
825         de::MovePtr<tcu::TextureLevel> imagePixelsB =
826             pipeline::readColorAttachment(vk, vkDevice, queue, queueFamilyIndex, allocator, *m_colorImageB,
827                                           VK_FORMAT_R32G32B32A32_SFLOAT, m_renderSize);
828 
829         // Verify pixel colors match.
830         const tcu::ConstPixelBufferAccess &imageAccessA = imagePixelsA->getAccess();
831         const tcu::ConstPixelBufferAccess &imageAccessB = imagePixelsB->getAccess();
832 
833         tcu::TextureLevel referenceImageA(mapVkFormat(VK_FORMAT_R32G32B32A32_SFLOAT), m_renderSize.x(),
834                                           m_renderSize.y());
835         tcu::TextureLevel referenceImageB(mapVkFormat(VK_FORMAT_R32G32B32A32_SFLOAT), m_renderSize.x(),
836                                           m_renderSize.y());
837 
838         tcu::clear(tcu::getSubregion(referenceImageA.getAccess(), 0u, 0u, imageAccessA.getWidth() / 2,
839                                      imageAccessA.getHeight()),
840                    red);
841         tcu::clear(tcu::getSubregion(referenceImageA.getAccess(), imageAccessA.getWidth() / 2, 0u,
842                                      imageAccessA.getWidth() / 2, imageAccessA.getHeight()),
843                    green);
844 
845         if (!tcu::floatThresholdCompare(m_context.getTestContext().getLog(), "Compare", "Result comparison",
846                                         referenceImageA.getAccess(), imageAccessA, tcu::Vec4(0.02f),
847                                         tcu::COMPARE_LOG_RESULT))
848             TCU_FAIL("[A] Rendered image is not correct");
849 
850         tcu::clear(tcu::getSubregion(referenceImageB.getAccess(), 0u, 0u, imageAccessB.getWidth() / 2,
851                                      imageAccessB.getHeight()),
852                    blue);
853         tcu::clear(tcu::getSubregion(referenceImageB.getAccess(), imageAccessB.getWidth() / 2, 0u,
854                                      imageAccessA.getWidth() / 2, imageAccessB.getHeight()),
855                    yellow);
856 
857         if (!tcu::floatThresholdCompare(m_context.getTestContext().getLog(), "Compare", "Result comparison",
858                                         referenceImageB.getAccess(), imageAccessB, tcu::Vec4(0.02f),
859                                         tcu::COMPARE_LOG_RESULT))
860             TCU_FAIL("[B] Rendered image is not correct");
861     }
862 
863     return tcu::TestStatus::pass("Pass");
864 }
865 } // namespace
866 
createRenderPassMultipleSubpassesMultipleCommandBuffersTests(tcu::TestContext & testCtx)867 tcu::TestCaseGroup *createRenderPassMultipleSubpassesMultipleCommandBuffersTests(tcu::TestContext &testCtx)
868 {
869     de::MovePtr<tcu::TestCaseGroup> testGroup(
870         new tcu::TestCaseGroup(testCtx, "multiple_subpasses_multiple_command_buffers"));
871 
872     testGroup->addChild(new MultipleSubpassesMultipleCommandBuffersTest(testCtx, "test"));
873 
874     return testGroup.release();
875 }
876 
877 } // namespace renderpass
878 } // namespace vkt
879