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