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