/*-------------------------------------------------------------------------
 * Vulkan Conformance Tests
 * ------------------------
 *
 * Copyright (c) 2015 The Khronos Group Inc.
 * Copyright (c) 2015 Samsung Electronics Co., Ltd.
 * Copyright (c) 2015 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 *//*--------------------------------------------------------------------*/

#include "vkDefs.hpp"
#include "vktTestCaseUtil.hpp"
#include "vkBuilderUtil.hpp"
#include "vkPlatform.hpp"
#include "vkRefUtil.hpp"
#include "vkQueryUtil.hpp"
#include "vkMemUtil.hpp"
#include "vkDeviceUtil.hpp"
#include "vkCmdUtil.hpp"
#include "vkObjUtil.hpp"
#include "tcuTextureUtil.hpp"
#include "vkImageUtil.hpp"
#include "vkPrograms.hpp"
#include "vkTypeUtil.hpp"
#include "vkAllocationCallbackUtil.hpp"
#include "vkCmdUtil.hpp"
#include "vkBarrierUtil.hpp"
#include "vkBufferWithMemory.hpp"
#include "vkImageWithMemory.hpp"
#include "vktApiCommandBuffersTests.hpp"
#include "vktApiBufferComputeInstance.hpp"
#include "vktApiComputeInstanceResultBuffer.hpp"
#include "deSharedPtr.hpp"
#include "deRandom.hpp"
#include <sstream>
#include <limits>

namespace vkt
{
namespace api
{
namespace
{

using namespace vk;

typedef de::SharedPtr<vk::Unique<vk::VkEvent> >	VkEventSp;

// Global variables
const deUint64								INFINITE_TIMEOUT		= ~(deUint64)0u;


template <deUint32 NumBuffers>
class CommandBufferBareTestEnvironment
{
public:
											CommandBufferBareTestEnvironment	(Context&						context,
																				 VkCommandPoolCreateFlags		commandPoolCreateFlags);

	VkCommandPool							getCommandPool						(void) const					{ return *m_commandPool; }
	VkCommandBuffer							getCommandBuffer					(deUint32 bufferIndex) const;

protected:
	Context&								m_context;
	const VkDevice							m_device;
	const DeviceInterface&					m_vkd;
	const VkQueue							m_queue;
	const deUint32							m_queueFamilyIndex;
	Allocator&								m_allocator;

	// \note All VkCommandBuffers are allocated from m_commandPool so there is no need
	//       to free them separately as the auto-generated dtor will do that through
	//       destroying the pool.
	Move<VkCommandPool>						m_commandPool;
	VkCommandBuffer							m_primaryCommandBuffers[NumBuffers];
};

template <deUint32 NumBuffers>
CommandBufferBareTestEnvironment<NumBuffers>::CommandBufferBareTestEnvironment(Context& context, VkCommandPoolCreateFlags commandPoolCreateFlags)
	: m_context								(context)
	, m_device								(context.getDevice())
	, m_vkd									(context.getDeviceInterface())
	, m_queue								(context.getUniversalQueue())
	, m_queueFamilyIndex					(context.getUniversalQueueFamilyIndex())
	, m_allocator							(context.getDefaultAllocator())
{
	m_commandPool = createCommandPool(m_vkd, m_device, commandPoolCreateFlags, m_queueFamilyIndex);

	const VkCommandBufferAllocateInfo		cmdBufferAllocateInfo	=
	{
		VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,				// VkStructureType             sType;
		DE_NULL,													// const void*                 pNext;
		*m_commandPool,												// VkCommandPool               commandPool;
		VK_COMMAND_BUFFER_LEVEL_PRIMARY,							// VkCommandBufferLevel        level;
		NumBuffers												// deUint32                    commandBufferCount;
	};

	VK_CHECK(m_vkd.allocateCommandBuffers(m_device, &cmdBufferAllocateInfo, m_primaryCommandBuffers));
}

template <deUint32 NumBuffers>
VkCommandBuffer CommandBufferBareTestEnvironment<NumBuffers>::getCommandBuffer(deUint32 bufferIndex) const
{
	DE_ASSERT(bufferIndex < NumBuffers);
	return m_primaryCommandBuffers[bufferIndex];
}

class CommandBufferRenderPassTestEnvironment : public CommandBufferBareTestEnvironment<1>
{
public:
											CommandBufferRenderPassTestEnvironment	(Context&						context,
																					 VkCommandPoolCreateFlags		commandPoolCreateFlags);

	VkRenderPass							getRenderPass							(void) const { return *m_renderPass; }
	VkFramebuffer							getFrameBuffer							(void) const { return *m_frameBuffer; }
	VkCommandBuffer							getPrimaryCommandBuffer					(void) const { return getCommandBuffer(0); }
	VkCommandBuffer							getSecondaryCommandBuffer				(void) const { return *m_secondaryCommandBuffer; }

	void									beginPrimaryCommandBuffer				(VkCommandBufferUsageFlags usageFlags);
	void									beginSecondaryCommandBuffer				(VkCommandBufferUsageFlags usageFlags, bool framebufferHint);
	void									beginRenderPass							(VkSubpassContents content);
	void									submitPrimaryCommandBuffer				(void);
	de::MovePtr<tcu::TextureLevel>			readColorAttachment						(void);

	static const VkImageType				DEFAULT_IMAGE_TYPE;
	static const VkFormat					DEFAULT_IMAGE_FORMAT;
	static const VkExtent3D					DEFAULT_IMAGE_SIZE;
	static const VkRect2D					DEFAULT_IMAGE_AREA;

protected:

	Move<VkImage>							m_colorImage;
	Move<VkImageView>						m_colorImageView;
	Move<VkRenderPass>						m_renderPass;
	Move<VkFramebuffer>						m_frameBuffer;
	de::MovePtr<Allocation>					m_colorImageMemory;
	Move<VkCommandBuffer>					m_secondaryCommandBuffer;

};

const VkImageType		CommandBufferRenderPassTestEnvironment::DEFAULT_IMAGE_TYPE		= VK_IMAGE_TYPE_2D;
const VkFormat			CommandBufferRenderPassTestEnvironment::DEFAULT_IMAGE_FORMAT	= VK_FORMAT_R8G8B8A8_UINT;
const VkExtent3D		CommandBufferRenderPassTestEnvironment::DEFAULT_IMAGE_SIZE		= {255, 255, 1};
const VkRect2D			CommandBufferRenderPassTestEnvironment::DEFAULT_IMAGE_AREA		=
{
	{ 0u, 0u, },												//	VkOffset2D	offset;
	{ DEFAULT_IMAGE_SIZE.width,	DEFAULT_IMAGE_SIZE.height },	//	VkExtent2D	extent;
};

CommandBufferRenderPassTestEnvironment::CommandBufferRenderPassTestEnvironment(Context& context, VkCommandPoolCreateFlags commandPoolCreateFlags)
	: CommandBufferBareTestEnvironment<1>		(context, commandPoolCreateFlags)
{
	m_renderPass = makeRenderPass(m_vkd, m_device, DEFAULT_IMAGE_FORMAT);

	{
		const VkImageCreateInfo					imageCreateInfo			=
		{
			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,		// VkStructureType			sType;
			DE_NULL,									// const void*				pNext;
			0u,											// VkImageCreateFlags		flags;
			DEFAULT_IMAGE_TYPE,							// VkImageType				imageType;
			DEFAULT_IMAGE_FORMAT,						// VkFormat					format;
			DEFAULT_IMAGE_SIZE,							// VkExtent3D				extent;
			1,											// deUint32					mipLevels;
			1,											// deUint32					arrayLayers;
			VK_SAMPLE_COUNT_1_BIT,						// VkSampleCountFlagBits	samples;
			VK_IMAGE_TILING_OPTIMAL,					// VkImageTiling			tiling;
			VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
			VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
			VK_IMAGE_USAGE_TRANSFER_DST_BIT,			// VkImageUsageFlags		usage;
			VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode			sharingMode;
			1,											// deUint32					queueFamilyIndexCount;
			&m_queueFamilyIndex,						// const deUint32*			pQueueFamilyIndices;
			VK_IMAGE_LAYOUT_UNDEFINED					// VkImageLayout			initialLayout;
		};

		m_colorImage = createImage(m_vkd, m_device, &imageCreateInfo, DE_NULL);
	}

	m_colorImageMemory = m_allocator.allocate(getImageMemoryRequirements(m_vkd, m_device, *m_colorImage), MemoryRequirement::Any);
	VK_CHECK(m_vkd.bindImageMemory(m_device, *m_colorImage, m_colorImageMemory->getMemory(), m_colorImageMemory->getOffset()));

	{
		const VkImageViewCreateInfo				imageViewCreateInfo		=
		{
			VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,	// VkStructureType				sType;
			DE_NULL,									// const void*					pNext;
			0u,											// VkImageViewCreateFlags		flags;
			*m_colorImage,								// VkImage						image;
			VK_IMAGE_VIEW_TYPE_2D,						// VkImageViewType				viewType;
			DEFAULT_IMAGE_FORMAT,						// VkFormat						format;
			{
				VK_COMPONENT_SWIZZLE_R,
				VK_COMPONENT_SWIZZLE_G,
				VK_COMPONENT_SWIZZLE_B,
				VK_COMPONENT_SWIZZLE_A
			},											// VkComponentMapping			components;
			{
				VK_IMAGE_ASPECT_COLOR_BIT,					// VkImageAspectFlags			aspectMask;
				0u,											// deUint32						baseMipLevel;
				1u,											// deUint32						mipLevels;
				0u,											// deUint32						baseArrayLayer;
				1u,											// deUint32						arraySize;
			},											// VkImageSubresourceRange		subresourceRange;
		};

		m_colorImageView = createImageView(m_vkd, m_device, &imageViewCreateInfo, DE_NULL);
	}

	{
		const VkImageView						attachmentViews[1]		=
		{
			*m_colorImageView
		};

		const VkFramebufferCreateInfo			framebufferCreateInfo	=
		{
			VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,	// VkStructureType			sType;
			DE_NULL,									// const void*				pNext;
			0u,											// VkFramebufferCreateFlags	flags;
			*m_renderPass,								// VkRenderPass				renderPass;
			1,											// deUint32					attachmentCount;
			attachmentViews,							// const VkImageView*		pAttachments;
			DEFAULT_IMAGE_SIZE.width,					// deUint32					width;
			DEFAULT_IMAGE_SIZE.height,					// deUint32					height;
			1u,											// deUint32					layers;
		};

		m_frameBuffer = createFramebuffer(m_vkd, m_device, &framebufferCreateInfo, DE_NULL);
	}

	{
		const VkCommandBufferAllocateInfo		cmdBufferAllocateInfo	=
		{
			VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,				// VkStructureType             sType;
			DE_NULL,													// const void*                 pNext;
			*m_commandPool,												// VkCommandPool               commandPool;
			VK_COMMAND_BUFFER_LEVEL_SECONDARY,							// VkCommandBufferLevel        level;
			1u															// deUint32                    commandBufferCount;
		};

		m_secondaryCommandBuffer = allocateCommandBuffer(m_vkd, m_device, &cmdBufferAllocateInfo);

	}
}

void CommandBufferRenderPassTestEnvironment::beginRenderPass(VkSubpassContents content)
{
	vk::beginRenderPass(m_vkd, m_primaryCommandBuffers[0], *m_renderPass, *m_frameBuffer, DEFAULT_IMAGE_AREA, tcu::UVec4(17, 59, 163, 251), content);
}

void CommandBufferRenderPassTestEnvironment::beginPrimaryCommandBuffer(VkCommandBufferUsageFlags usageFlags)
{
	beginCommandBuffer(m_vkd, m_primaryCommandBuffers[0], usageFlags);
}

void CommandBufferRenderPassTestEnvironment::beginSecondaryCommandBuffer(VkCommandBufferUsageFlags usageFlags, bool framebufferHint)
{
	const VkCommandBufferInheritanceInfo	commandBufferInheritanceInfo =
	{
		VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO,		// VkStructureType                  sType;
		DE_NULL,												// const void*                      pNext;
		*m_renderPass,											// VkRenderPass                     renderPass;
		0u,														// deUint32                         subpass;
		(framebufferHint ? *m_frameBuffer : DE_NULL),			// VkFramebuffer                    framebuffer;
		VK_FALSE,												// VkBool32                         occlusionQueryEnable;
		0u,														// VkQueryControlFlags              queryFlags;
		0u														// VkQueryPipelineStatisticFlags    pipelineStatistics;
	};

	const VkCommandBufferBeginInfo			commandBufferBeginInfo	=
	{
		VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,			// VkStructureType                          sType;
		DE_NULL,												// const void*                              pNext;
		usageFlags,												// VkCommandBufferUsageFlags                flags;
		&commandBufferInheritanceInfo							// const VkCommandBufferInheritanceInfo*    pInheritanceInfo;
	};

	VK_CHECK(m_vkd.beginCommandBuffer(*m_secondaryCommandBuffer, &commandBufferBeginInfo));

}

void CommandBufferRenderPassTestEnvironment::submitPrimaryCommandBuffer(void)
{
	submitCommandsAndWait(m_vkd, m_device, m_queue, *m_primaryCommandBuffers);
}

de::MovePtr<tcu::TextureLevel> CommandBufferRenderPassTestEnvironment::readColorAttachment ()
{
	Move<VkBuffer>					buffer;
	de::MovePtr<Allocation>			bufferAlloc;
	const tcu::TextureFormat		tcuFormat		= mapVkFormat(DEFAULT_IMAGE_FORMAT);
	const VkDeviceSize				pixelDataSize	= DEFAULT_IMAGE_SIZE.height * DEFAULT_IMAGE_SIZE.height * tcuFormat.getPixelSize();
	de::MovePtr<tcu::TextureLevel>	resultLevel		(new tcu::TextureLevel(tcuFormat, DEFAULT_IMAGE_SIZE.width, DEFAULT_IMAGE_SIZE.height));

	// Create destination buffer
	{
		const VkBufferCreateInfo bufferParams =
		{
			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		// VkStructureType		sType;
			DE_NULL,									// const void*			pNext;
			0u,											// VkBufferCreateFlags	flags;
			pixelDataSize,								// VkDeviceSize			size;
			VK_BUFFER_USAGE_TRANSFER_DST_BIT,			// VkBufferUsageFlags	usage;
			VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode		sharingMode;
			0u,											// deUint32				queueFamilyIndexCount;
			DE_NULL										// const deUint32*		pQueueFamilyIndices;
		};

		buffer		= createBuffer(m_vkd, m_device, &bufferParams);
		bufferAlloc = m_allocator.allocate(getBufferMemoryRequirements(m_vkd, m_device, *buffer), MemoryRequirement::HostVisible);
		VK_CHECK(m_vkd.bindBufferMemory(m_device, *buffer, bufferAlloc->getMemory(), bufferAlloc->getOffset()));
	}

	// Copy image to buffer
	beginPrimaryCommandBuffer(0);
	copyImageToBuffer(m_vkd, m_primaryCommandBuffers[0], *m_colorImage, *buffer, tcu::IVec2(DEFAULT_IMAGE_SIZE.width, DEFAULT_IMAGE_SIZE.height));
	endCommandBuffer(m_vkd, m_primaryCommandBuffers[0]);

	submitPrimaryCommandBuffer();

	// Read buffer data
	invalidateAlloc(m_vkd, m_device, *bufferAlloc);
	tcu::copy(*resultLevel, tcu::ConstPixelBufferAccess(resultLevel->getFormat(), resultLevel->getSize(), bufferAlloc->getHostPtr()));

	return resultLevel;
}


// Testcases
/********* 19.1. Command Pools (5.1 in VK 1.0 Spec) ***************************/
tcu::TestStatus createPoolNullParamsTest(Context& context)
{
	const VkDevice							vkDevice				= context.getDevice();
	const DeviceInterface&					vk						= context.getDeviceInterface();
	const deUint32							queueFamilyIndex		= context.getUniversalQueueFamilyIndex();

	createCommandPool(vk, vkDevice, 0u, queueFamilyIndex);

	return tcu::TestStatus::pass("Command Pool allocated correctly.");
}

tcu::TestStatus createPoolNonNullAllocatorTest(Context& context)
{
	const VkDevice							vkDevice				= context.getDevice();
	const DeviceInterface&					vk						= context.getDeviceInterface();
	const deUint32							queueFamilyIndex		= context.getUniversalQueueFamilyIndex();
	const VkAllocationCallbacks*			allocationCallbacks		= getSystemAllocator();

	const VkCommandPoolCreateInfo			cmdPoolParams			=
	{
		VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,					// sType;
		DE_NULL,													// pNext;
		0u,															// flags;
		queueFamilyIndex,											// queueFamilyIndex;
	};

	createCommandPool(vk, vkDevice, &cmdPoolParams, allocationCallbacks);

	return tcu::TestStatus::pass("Command Pool allocated correctly.");
}

tcu::TestStatus createPoolTransientBitTest(Context& context)
{
	const VkDevice							vkDevice				= context.getDevice();
	const DeviceInterface&					vk						= context.getDeviceInterface();
	const deUint32							queueFamilyIndex		= context.getUniversalQueueFamilyIndex();

	const VkCommandPoolCreateInfo			cmdPoolParams			=
	{
		VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,					// sType;
		DE_NULL,													// pNext;
		VK_COMMAND_POOL_CREATE_TRANSIENT_BIT,						// flags;
		queueFamilyIndex,											// queueFamilyIndex;
	};

	createCommandPool(vk, vkDevice, &cmdPoolParams, DE_NULL);

	return tcu::TestStatus::pass("Command Pool allocated correctly.");
}

tcu::TestStatus createPoolResetBitTest(Context& context)
{
	const VkDevice							vkDevice				= context.getDevice();
	const DeviceInterface&					vk						= context.getDeviceInterface();
	const deUint32							queueFamilyIndex		= context.getUniversalQueueFamilyIndex();

	const VkCommandPoolCreateInfo			cmdPoolParams			=
	{
		VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,					// sType;
		DE_NULL,													// pNext;
		VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,			// flags;
		queueFamilyIndex,											// queueFamilyIndex;
	};

	createCommandPool(vk, vkDevice, &cmdPoolParams, DE_NULL);

	return tcu::TestStatus::pass("Command Pool allocated correctly.");
}

tcu::TestStatus resetPoolReleaseResourcesBitTest(Context& context)
{
	const VkDevice							vkDevice				= context.getDevice();
	const DeviceInterface&					vk						= context.getDeviceInterface();
	const deUint32							queueFamilyIndex		= context.getUniversalQueueFamilyIndex();

	const VkCommandPoolCreateInfo			cmdPoolParams			=
	{
		VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,					// sType;
		DE_NULL,													// pNext;
		0u,															// flags;
		queueFamilyIndex,											// queueFamilyIndex;
	};

	const Unique<VkCommandPool>				cmdPool					(createCommandPool(vk, vkDevice, &cmdPoolParams, DE_NULL));

	VK_CHECK(vk.resetCommandPool(vkDevice, *cmdPool, VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT));

	return tcu::TestStatus::pass("Command Pool allocated correctly.");
}

tcu::TestStatus resetPoolNoFlagsTest(Context& context)
{
	const VkDevice							vkDevice				= context.getDevice();
	const DeviceInterface&					vk						= context.getDeviceInterface();
	const deUint32							queueFamilyIndex		= context.getUniversalQueueFamilyIndex();

	const VkCommandPoolCreateInfo			cmdPoolParams			=
	{
		VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,					// sType;
		DE_NULL,													// pNext;
		0u,															// flags;
		queueFamilyIndex,											// queueFamilyIndex;
	};

	const Unique<VkCommandPool>				cmdPool					(createCommandPool(vk, vkDevice, &cmdPoolParams, DE_NULL));

	VK_CHECK(vk.resetCommandPool(vkDevice, *cmdPool, 0u));

	return tcu::TestStatus::pass("Command Pool allocated correctly.");
}

bool executeCommandBuffer (const VkDevice			device,
						   const DeviceInterface&	vk,
						   const VkQueue			queue,
						   const VkCommandBuffer	commandBuffer,
						   const bool				exitBeforeEndCommandBuffer = false)
{
	const Unique<VkEvent>			event					(createEvent(vk, device));
	beginCommandBuffer(vk, commandBuffer, 0u);
	{
		const VkPipelineStageFlags stageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
		vk.cmdSetEvent(commandBuffer, *event, stageMask);
		if (exitBeforeEndCommandBuffer)
			return exitBeforeEndCommandBuffer;
	}
	endCommandBuffer(vk, commandBuffer);

	submitCommandsAndWait(vk, device, queue, commandBuffer);

	// check if buffer has been executed
	const VkResult result = vk.getEventStatus(device, *event);
	return result == VK_EVENT_SET;
}

tcu::TestStatus resetPoolReuseTest (Context& context)
{
	const VkDevice						vkDevice			= context.getDevice();
	const DeviceInterface&				vk					= context.getDeviceInterface();
	const deUint32						queueFamilyIndex	= context.getUniversalQueueFamilyIndex();
	const VkQueue						queue				= context.getUniversalQueue();

	const VkCommandPoolCreateInfo		cmdPoolParams		=
	{
		VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,	// sType;
		DE_NULL,									// pNext;
		0u,											// flags;
		queueFamilyIndex							// queueFamilyIndex;
	};
	const Unique<VkCommandPool>			cmdPool				(createCommandPool(vk, vkDevice, &cmdPoolParams, DE_NULL));
	const VkCommandBufferAllocateInfo	cmdBufParams		=
	{
		VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,	// sType;
		DE_NULL,										// pNext;
		*cmdPool,										// commandPool;
		VK_COMMAND_BUFFER_LEVEL_PRIMARY,				// level;
		1u												// bufferCount;
	};
	const Move<VkCommandBuffer>			commandBuffers[]	=
	{
		allocateCommandBuffer(vk, vkDevice, &cmdBufParams),
		allocateCommandBuffer(vk, vkDevice, &cmdBufParams)
	};

	if (!executeCommandBuffer(vkDevice, vk, queue, *(commandBuffers[0])))
		return tcu::TestStatus::fail("Failed");
	if (!executeCommandBuffer(vkDevice, vk, queue, *(commandBuffers[1]), true))
		return tcu::TestStatus::fail("Failed");

	VK_CHECK(vk.resetCommandPool(vkDevice, *cmdPool, VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT));

	if (!executeCommandBuffer(vkDevice, vk, queue, *(commandBuffers[0])))
		return tcu::TestStatus::fail("Failed");
	if (!executeCommandBuffer(vkDevice, vk, queue, *(commandBuffers[1])))
		return tcu::TestStatus::fail("Failed");

	{
		const Unique<VkCommandBuffer> afterResetCommandBuffers(allocateCommandBuffer(vk, vkDevice, &cmdBufParams));
		if (!executeCommandBuffer(vkDevice, vk, queue, *afterResetCommandBuffers))
			return tcu::TestStatus::fail("Failed");
	}

	return tcu::TestStatus::pass("Passed");
}

/******** 19.2. Command Buffer Lifetime (5.2 in VK 1.0 Spec) ******************/
tcu::TestStatus allocatePrimaryBufferTest(Context& context)
{
	const VkDevice							vkDevice				= context.getDevice();
	const DeviceInterface&					vk						= context.getDeviceInterface();
	const deUint32							queueFamilyIndex		= context.getUniversalQueueFamilyIndex();

	const VkCommandPoolCreateInfo			cmdPoolParams			=
	{
		VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,					// sType;
		DE_NULL,													// pNext;
		VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,			// flags;
		queueFamilyIndex,											// queueFamilyIndex;
	};
	const Unique<VkCommandPool>				cmdPool					(createCommandPool(vk, vkDevice, &cmdPoolParams));

	// Command buffer
	const VkCommandBufferAllocateInfo		cmdBufParams			=
	{
		VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,				// sType;
		DE_NULL,													// pNext;
		*cmdPool,													// commandPool;
		VK_COMMAND_BUFFER_LEVEL_PRIMARY,							// level;
		1u,															// bufferCount;
	};
	const Unique<VkCommandBuffer>			cmdBuf					(allocateCommandBuffer(vk, vkDevice, &cmdBufParams));

	return tcu::TestStatus::pass("Buffer was created correctly.");
}

tcu::TestStatus allocateManyPrimaryBuffersTest(Context& context)
{

	const VkDevice							vkDevice				= context.getDevice();
	const DeviceInterface&					vk						= context.getDeviceInterface();
	const deUint32							queueFamilyIndex		= context.getUniversalQueueFamilyIndex();

	const VkCommandPoolCreateInfo			cmdPoolParams			=
	{
		VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,					//	VkStructureType				sType;
		DE_NULL,													//	const void*					pNext;
		VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,			//	VkCommandPoolCreateFlags	flags;
		queueFamilyIndex,											//	deUint32					queueFamilyIndex;
	};
	const Unique<VkCommandPool>				cmdPool					(createCommandPool(vk, vkDevice, &cmdPoolParams));

	// \todo Determining the minimum number of command buffers should be a function of available system memory and driver capabilities.
#if (DE_PTR_SIZE == 4)
	const unsigned minCommandBuffer = 1024;
#else
	const unsigned minCommandBuffer = 10000;
#endif

	// Command buffer
	const VkCommandBufferAllocateInfo		cmdBufParams			=
	{
		VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,				//	VkStructureType				sType;
		DE_NULL,													//	const void*					pNext;
		*cmdPool,													//	VkCommandPool				pool;
		VK_COMMAND_BUFFER_LEVEL_PRIMARY,							//	VkCommandBufferLevel		level;
		minCommandBuffer,											//	uint32_t					bufferCount;
	};

	// do not keep the handles to buffers, as they will be freed with command pool

	// allocate the minimum required amount of buffers
	VkCommandBuffer cmdBuffers[minCommandBuffer];
	VK_CHECK(vk.allocateCommandBuffers(vkDevice, &cmdBufParams, cmdBuffers));

	std::ostringstream out;
	out << "allocateManyPrimaryBuffersTest succeded: created " << minCommandBuffer << " command buffers";

	return tcu::TestStatus::pass(out.str());
}

tcu::TestStatus allocateSecondaryBufferTest(Context& context)
{
	const VkDevice							vkDevice				= context.getDevice();
	const DeviceInterface&					vk						= context.getDeviceInterface();
	const deUint32							queueFamilyIndex		= context.getUniversalQueueFamilyIndex();

	const VkCommandPoolCreateInfo			cmdPoolParams			=
	{
		VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,					// sType;
		DE_NULL,													// pNext;
		VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,			// flags;
		queueFamilyIndex,											// queueFamilyIndex;
	};
	const Unique<VkCommandPool>				cmdPool					(createCommandPool(vk, vkDevice, &cmdPoolParams));

	// Command buffer
	const VkCommandBufferAllocateInfo		cmdBufParams			=
	{
		VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,				// sType;
		DE_NULL,													// pNext;
		*cmdPool,													// commandPool;
		VK_COMMAND_BUFFER_LEVEL_SECONDARY,							// level;
		1u,															// bufferCount;
	};
	const Unique<VkCommandBuffer>			cmdBuf					(allocateCommandBuffer(vk, vkDevice, &cmdBufParams));

	return tcu::TestStatus::pass("Buffer was created correctly.");
}

tcu::TestStatus allocateManySecondaryBuffersTest(Context& context)
{

	const VkDevice							vkDevice				= context.getDevice();
	const DeviceInterface&					vk						= context.getDeviceInterface();
	const deUint32							queueFamilyIndex		= context.getUniversalQueueFamilyIndex();

	const VkCommandPoolCreateInfo			cmdPoolParams			=
	{
		VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,					//	VkStructureType				sType;
		DE_NULL,													//	const void*					pNext;
		VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,			//	VkCommandPoolCreateFlags	flags;
		queueFamilyIndex,											//	deUint32					queueFamilyIndex;
	};
	const Unique<VkCommandPool>				cmdPool					(createCommandPool(vk, vkDevice, &cmdPoolParams));

	// \todo Determining the minimum number of command buffers should be a function of available system memory and driver capabilities.
#if (DE_PTR_SIZE == 4)
	const unsigned minCommandBuffer = 1024;
#else
	const unsigned minCommandBuffer = 10000;
#endif

	// Command buffer
	const VkCommandBufferAllocateInfo		cmdBufParams			=
	{
		VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,				//	VkStructureType				sType;
		DE_NULL,													//	const void*					pNext;
		*cmdPool,													//	VkCommandPool				pool;
		VK_COMMAND_BUFFER_LEVEL_SECONDARY,							//	VkCommandBufferLevel		level;
		minCommandBuffer,											//	uint32_t					bufferCount;
	};

	// do not keep the handles to buffers, as they will be freed with command pool

	// allocate the minimum required amount of buffers
	VkCommandBuffer cmdBuffers[minCommandBuffer];
	VK_CHECK(vk.allocateCommandBuffers(vkDevice, &cmdBufParams, cmdBuffers));

	std::ostringstream out;
	out << "allocateManySecondaryBuffersTest succeded: created " << minCommandBuffer << " command buffers";

	return tcu::TestStatus::pass(out.str());
}

tcu::TestStatus executePrimaryBufferTest(Context& context)
{
	const VkDevice							vkDevice				= context.getDevice();
	const DeviceInterface&					vk						= context.getDeviceInterface();
	const VkQueue							queue					= context.getUniversalQueue();
	const deUint32							queueFamilyIndex		= context.getUniversalQueueFamilyIndex();

	const VkCommandPoolCreateInfo			cmdPoolParams			=
	{
		VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,					//	VkStructureType				sType;
		DE_NULL,													//	const void*					pNext;
		VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,			//	VkCommandPoolCreateFlags	flags;
		queueFamilyIndex,											//	deUint32					queueFamilyIndex;
	};
	const Unique<VkCommandPool>				cmdPool					(createCommandPool(vk, vkDevice, &cmdPoolParams));

	// Command buffer
	const VkCommandBufferAllocateInfo		cmdBufParams			=
	{
		VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,				//	VkStructureType				sType;
		DE_NULL,													//	const void*					pNext;
		*cmdPool,													//	VkCommandPool				pool;
		VK_COMMAND_BUFFER_LEVEL_PRIMARY,							//	VkCommandBufferLevel		level;
		1u,															//	uint32_t					bufferCount;
	};
	const Unique<VkCommandBuffer>			primCmdBuf				(allocateCommandBuffer(vk, vkDevice, &cmdBufParams));

	// create event that will be used to check if secondary command buffer has been executed
	const Unique<VkEvent>					event					(createEvent(vk, vkDevice));

	// reset event
	VK_CHECK(vk.resetEvent(vkDevice, *event));

	// record primary command buffer
	beginCommandBuffer(vk, *primCmdBuf, 0u);
	{
		// allow execution of event during every stage of pipeline
		VkPipelineStageFlags stageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;

		// record setting event
		vk.cmdSetEvent(*primCmdBuf, *event,stageMask);
	}
	endCommandBuffer(vk, *primCmdBuf);

	submitCommandsAndWait(vk, vkDevice, queue, primCmdBuf.get());

	// check if buffer has been executed
	VkResult result = vk.getEventStatus(vkDevice,*event);
	if (result == VK_EVENT_SET)
		return tcu::TestStatus::pass("Execute Primary Command Buffer succeeded");

	return tcu::TestStatus::fail("Execute Primary Command Buffer FAILED");
}

tcu::TestStatus executeLargePrimaryBufferTest(Context& context)
{
	const VkDevice							vkDevice				= context.getDevice();
	const DeviceInterface&					vk						= context.getDeviceInterface();
	const VkQueue							queue					= context.getUniversalQueue();
	const deUint32							queueFamilyIndex		= context.getUniversalQueueFamilyIndex();
	const deUint32							LARGE_BUFFER_SIZE		= 10000;

	const VkCommandPoolCreateInfo			cmdPoolParams			=
	{
		VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,					//	VkStructureType				sType;
		DE_NULL,													//	const void*					pNext;
		VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,			//	VkCommandPoolCreateFlags	flags;
		queueFamilyIndex,											//	deUint32					queueFamilyIndex;
	};
	const Unique<VkCommandPool>				cmdPool					(createCommandPool(vk, vkDevice, &cmdPoolParams));

	// Command buffer
	const VkCommandBufferAllocateInfo		cmdBufParams			=
	{
		VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,				//	VkStructureType				sType;
		DE_NULL,													//	const void*					pNext;
		*cmdPool,													//	VkCommandPool				pool;
		VK_COMMAND_BUFFER_LEVEL_PRIMARY,							//	VkCommandBufferLevel		level;
		1u,															//	uint32_t					bufferCount;
	};
	const Unique<VkCommandBuffer>			primCmdBuf				(allocateCommandBuffer(vk, vkDevice, &cmdBufParams));

	std::vector<VkEventSp>					events;
	for (deUint32 ndx = 0; ndx < LARGE_BUFFER_SIZE; ++ndx)
		events.push_back(VkEventSp(new vk::Unique<VkEvent>(createEvent(vk, vkDevice))));

	// record primary command buffer
	beginCommandBuffer(vk, *primCmdBuf, 0u);
	{
		// set all the events
		for (deUint32 ndx = 0; ndx < LARGE_BUFFER_SIZE; ++ndx)
		{
			vk.cmdSetEvent(*primCmdBuf, events[ndx]->get(), VK_PIPELINE_STAGE_ALL_COMMANDS_BIT);
		}
	}
	endCommandBuffer(vk, *primCmdBuf);

	submitCommandsAndWait(vk, vkDevice, queue, primCmdBuf.get());

	// check if the buffer was executed correctly - all events had their status
	// changed
	tcu::TestStatus testResult = tcu::TestStatus::incomplete();

	for (deUint32 ndx = 0; ndx < LARGE_BUFFER_SIZE; ++ndx)
	{
		if (vk.getEventStatus(vkDevice, events[ndx]->get()) != VK_EVENT_SET)
		{
			testResult = tcu::TestStatus::fail("An event was not set.");
			break;
		}
	}

	if (!testResult.isComplete())
		testResult = tcu::TestStatus::pass("All events set correctly.");

	return testResult;
}

tcu::TestStatus resetBufferImplicitlyTest(Context& context)
{
	const VkDevice							vkDevice				= context.getDevice();
	const DeviceInterface&					vk						= context.getDeviceInterface();
	const VkQueue							queue					= context.getUniversalQueue();
	const deUint32							queueFamilyIndex		= context.getUniversalQueueFamilyIndex();

	const VkCommandPoolCreateInfo			cmdPoolParams			=
	{
		VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,					// sType;
		DE_NULL,													// pNext;
		VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,			// flags;
		queueFamilyIndex,											// queueFamilyIndex;
	};
	const Unique<VkCommandPool>				cmdPool					(createCommandPool(vk, vkDevice, &cmdPoolParams));

	// Command buffer
	const VkCommandBufferAllocateInfo		cmdBufParams			=
	{
		VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,				// sType;
		DE_NULL,													// pNext;
		*cmdPool,													// pool;
		VK_COMMAND_BUFFER_LEVEL_PRIMARY,							// level;
		1u,															// bufferCount;
	};
	const Unique<VkCommandBuffer>			cmdBuf						(allocateCommandBuffer(vk, vkDevice, &cmdBufParams));

	const Unique<VkEvent>					event					(createEvent(vk, vkDevice));

	// Put the command buffer in recording state.
	beginCommandBuffer(vk, *cmdBuf, 0u);
	{
		// Set the event
		vk.cmdSetEvent(*cmdBuf, *event, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT);
	}
	endCommandBuffer(vk, *cmdBuf);

	submitCommandsAndWait(vk, vkDevice, queue, cmdBuf.get());

	// Check if the buffer was executed
	if (vk.getEventStatus(vkDevice, *event) != VK_EVENT_SET)
		return tcu::TestStatus::fail("Failed to set the event.");

	// Reset the event
	vk.resetEvent(vkDevice, *event);
	if(vk.getEventStatus(vkDevice, *event) != VK_EVENT_RESET)
		return tcu::TestStatus::fail("Failed to reset the event.");

	// Reset the command buffer by putting it in recording state again. This
	// should empty the command buffer.
	beginCommandBuffer(vk, *cmdBuf, 0u);
	endCommandBuffer(vk, *cmdBuf);

	// Submit the command buffer after resetting. It should have no commands
	// recorded, so the event should remain unsignaled.
	submitCommandsAndWait(vk, vkDevice, queue, cmdBuf.get());

	// Check if the event remained unset.
	if(vk.getEventStatus(vkDevice, *event) == VK_EVENT_RESET)
		return tcu::TestStatus::pass("Buffer was reset correctly.");
	else
		return tcu::TestStatus::fail("Buffer was not reset correctly.");
}

using  de::SharedPtr;
typedef SharedPtr<Unique<VkEvent> >			VkEventShared;

template<typename T>
inline SharedPtr<Unique<T> > makeSharedPtr (Move<T> move)
{
	return SharedPtr<Unique<T> >(new Unique<T>(move));
}

bool submitAndCheck (Context& context, std::vector<VkCommandBuffer>& cmdBuffers, std::vector <VkEventShared>& events)
{
	const VkDevice						vkDevice	= context.getDevice();
	const DeviceInterface&				vk			= context.getDeviceInterface();
	const VkQueue						queue		= context.getUniversalQueue();
	const Unique<VkFence>				fence		(createFence(vk, vkDevice));

	const VkSubmitInfo					submitInfo	=
	{
		VK_STRUCTURE_TYPE_SUBMIT_INFO,				// sType
		DE_NULL,									// pNext
		0u,											// waitSemaphoreCount
		DE_NULL,									// pWaitSemaphores
		(const VkPipelineStageFlags*)DE_NULL,		// pWaitDstStageMask
		static_cast<deUint32>(cmdBuffers.size()),	// commandBufferCount
		&cmdBuffers[0],								// pCommandBuffers
		0u,											// signalSemaphoreCount
		DE_NULL,									// pSignalSemaphores
	};

	VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo, fence.get()));
	VK_CHECK(vk.waitForFences(vkDevice, 1u, &fence.get(), 0u, INFINITE_TIMEOUT));

	for(int eventNdx = 0; eventNdx < static_cast<int>(events.size()); ++eventNdx)
	{
		if (vk.getEventStatus(vkDevice, **events[eventNdx]) != VK_EVENT_SET)
			return false;
		vk.resetEvent(vkDevice, **events[eventNdx]);
	}

	return true;
}

void createCommadBuffers (const DeviceInterface&		vk,
						  const VkDevice				vkDevice,
						  deUint32						bufferCount,
						  VkCommandPool					pool,
						  const VkCommandBufferLevel	cmdBufferLevel,
						  VkCommandBuffer*				pCommandBuffers)
{
	const VkCommandBufferAllocateInfo		cmdBufParams	=
	{
		VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,	//	VkStructureType				sType;
		DE_NULL,										//	const void*					pNext;
		pool,											//	VkCommandPool				pool;
		cmdBufferLevel,									//	VkCommandBufferLevel		level;
		bufferCount,									//	uint32_t					bufferCount;
	};
	VK_CHECK(vk.allocateCommandBuffers(vkDevice, &cmdBufParams, pCommandBuffers));
}

void addCommandsToBuffer (const DeviceInterface& vk, std::vector<VkCommandBuffer>& cmdBuffers, std::vector <VkEventShared>& events)
{
	const VkCommandBufferInheritanceInfo	secCmdBufInheritInfo	=
	{
		VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO,
		DE_NULL,
		(VkRenderPass)0u,								// renderPass
		0u,												// subpass
		(VkFramebuffer)0u,								// framebuffer
		VK_FALSE,										// occlusionQueryEnable
		(VkQueryControlFlags)0u,						// queryFlags
		(VkQueryPipelineStatisticFlags)0u,				// pipelineStatistics
	};

	const VkCommandBufferBeginInfo		cmdBufBeginInfo	=
	{
		VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,	// sType
		DE_NULL,										// pNext
		0u,												// flags
		&secCmdBufInheritInfo,							// pInheritanceInfo;
	};

	for(int bufferNdx = 0; bufferNdx < static_cast<int>(cmdBuffers.size()); ++bufferNdx)
	{
		VK_CHECK(vk.beginCommandBuffer(cmdBuffers[bufferNdx], &cmdBufBeginInfo));
		vk.cmdSetEvent(cmdBuffers[bufferNdx], **events[bufferNdx % events.size()], VK_PIPELINE_STAGE_ALL_COMMANDS_BIT);
		endCommandBuffer(vk, cmdBuffers[bufferNdx]);
	}
}

bool executeSecondaryCmdBuffer (Context&						context,
								VkCommandPool					pool,
								std::vector<VkCommandBuffer>&	cmdBuffersSecondary,
								std::vector <VkEventShared>&	events)
{
	const VkDevice					vkDevice		= context.getDevice();
	const DeviceInterface&			vk				= context.getDeviceInterface();
	std::vector<VkCommandBuffer>	cmdBuffer		(1);

	createCommadBuffers(vk, vkDevice, 1u, pool, VK_COMMAND_BUFFER_LEVEL_PRIMARY, &cmdBuffer[0]);
	beginCommandBuffer(vk, cmdBuffer[0], 0u);
	vk.cmdExecuteCommands(cmdBuffer[0], static_cast<deUint32>(cmdBuffersSecondary.size()), &cmdBuffersSecondary[0]);
	endCommandBuffer(vk, cmdBuffer[0]);

	bool returnValue = submitAndCheck(context, cmdBuffer, events);
	vk.freeCommandBuffers(vkDevice, pool, 1u, &cmdBuffer[0]);
	return returnValue;
}

tcu::TestStatus trimCommandPoolTest (Context& context, const VkCommandBufferLevel cmdBufferLevel)
{
	if (!context.isDeviceFunctionalitySupported("VK_KHR_maintenance1"))
		TCU_THROW(NotSupportedError, "Extension VK_KHR_maintenance1 not supported");

	const VkDevice							vkDevice				= context.getDevice();
	const DeviceInterface&					vk						= context.getDeviceInterface();
	const deUint32							queueFamilyIndex		= context.getUniversalQueueFamilyIndex();

	//test parameters
	const deUint32							cmdBufferIterationCount	= 300u;
	const deUint32							cmdBufferCount			= 10u;

	const VkCommandPoolCreateInfo			cmdPoolParams			=
	{
		VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,					// sType;
		DE_NULL,													// pNext;
		VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,			// flags;
		queueFamilyIndex,											// queueFamilyIndex;
	};
	const Unique<VkCommandPool>				cmdPool					(createCommandPool(vk, vkDevice, &cmdPoolParams));

	std::vector <VkEventShared>				events;
	for (deUint32 ndx = 0u; ndx < cmdBufferCount; ++ndx)
		events.push_back(makeSharedPtr(createEvent(vk, vkDevice)));

	{
		std::vector<VkCommandBuffer> cmdBuffers(cmdBufferCount);
		createCommadBuffers(vk, vkDevice, cmdBufferCount, *cmdPool, cmdBufferLevel, &cmdBuffers[0]);

		for (deUint32 cmdBufferIterationrNdx = 0; cmdBufferIterationrNdx < cmdBufferIterationCount; ++cmdBufferIterationrNdx)
		{
			addCommandsToBuffer(vk, cmdBuffers, events);

			//Peak, situation when we use a lot more command buffers
			if (cmdBufferIterationrNdx % 10u == 0)
			{
				std::vector<VkCommandBuffer> cmdBuffersPeak(cmdBufferCount * 10u);
				createCommadBuffers(vk, vkDevice, static_cast<deUint32>(cmdBuffersPeak.size()), *cmdPool, cmdBufferLevel, &cmdBuffersPeak[0]);
				addCommandsToBuffer(vk, cmdBuffersPeak, events);

				switch(cmdBufferLevel)
				{
					case VK_COMMAND_BUFFER_LEVEL_PRIMARY:
						if (!submitAndCheck(context, cmdBuffersPeak, events))
							return tcu::TestStatus::fail("Fail");
						break;
					case VK_COMMAND_BUFFER_LEVEL_SECONDARY:
						if (!executeSecondaryCmdBuffer(context, *cmdPool, cmdBuffersPeak, events))
							return tcu::TestStatus::fail("Fail");
						break;
					default:
						DE_ASSERT(0);
				}
				vk.freeCommandBuffers(vkDevice, *cmdPool, static_cast<deUint32>(cmdBuffersPeak.size()), &cmdBuffersPeak[0]);
			}

			vk.trimCommandPool(vkDevice, *cmdPool, (VkCommandPoolTrimFlags)0);

			switch(cmdBufferLevel)
			{
				case VK_COMMAND_BUFFER_LEVEL_PRIMARY:
					if (!submitAndCheck(context, cmdBuffers, events))
						return tcu::TestStatus::fail("Fail");
					break;
				case VK_COMMAND_BUFFER_LEVEL_SECONDARY:
					if (!executeSecondaryCmdBuffer(context, *cmdPool, cmdBuffers, events))
						return tcu::TestStatus::fail("Fail");
					break;
				default:
					DE_ASSERT(0);
			}

			for (deUint32 bufferNdx = cmdBufferIterationrNdx % 3u; bufferNdx < cmdBufferCount; bufferNdx+=2u)
			{
				vk.freeCommandBuffers(vkDevice, *cmdPool, 1u, &cmdBuffers[bufferNdx]);
				createCommadBuffers(vk, vkDevice, 1u, *cmdPool, cmdBufferLevel, &cmdBuffers[bufferNdx]);
			}
		}
	}

	return tcu::TestStatus::pass("Pass");
}

/******** 19.3. Command Buffer Recording (5.3 in VK 1.0 Spec) *****************/
tcu::TestStatus recordSinglePrimaryBufferTest(Context& context)
{
	const VkDevice							vkDevice				= context.getDevice();
	const DeviceInterface&					vk						= context.getDeviceInterface();
	const deUint32							queueFamilyIndex		= context.getUniversalQueueFamilyIndex();

	const VkCommandPoolCreateInfo			cmdPoolParams			=
	{
		VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,					//	VkStructureType				sType;
		DE_NULL,													//	const void*					pNext;
		VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,			//	VkCommandPoolCreateFlags	flags;
		queueFamilyIndex,											//	deUint32					queueFamilyIndex;
	};
	const Unique<VkCommandPool>				cmdPool					(createCommandPool(vk, vkDevice, &cmdPoolParams));

	// Command buffer
	const VkCommandBufferAllocateInfo		cmdBufParams			=
	{
		VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,				//	VkStructureType				sType;
		DE_NULL,													//	const void*					pNext;
		*cmdPool,													//	VkCommandPool				pool;
		VK_COMMAND_BUFFER_LEVEL_PRIMARY,							//	VkCommandBufferLevel		level;
		1u,															//	uint32_t					bufferCount;
	};
	const Unique<VkCommandBuffer>			primCmdBuf				(allocateCommandBuffer(vk, vkDevice, &cmdBufParams));

	// create event that will be used to check if secondary command buffer has been executed
	const Unique<VkEvent>					event					(createEvent(vk, vkDevice));

	// record primary command buffer
	beginCommandBuffer(vk, *primCmdBuf, 0u);
	{
		// record setting event
		vk.cmdSetEvent(*primCmdBuf, *event, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT);
	}
	endCommandBuffer(vk, *primCmdBuf);

	return tcu::TestStatus::pass("Primary buffer recorded successfully.");
}

tcu::TestStatus recordLargePrimaryBufferTest(Context &context)
{
	const VkDevice							vkDevice				= context.getDevice();
	const DeviceInterface&					vk						= context.getDeviceInterface();
	const VkQueue							queue					= context.getUniversalQueue();
	const deUint32							queueFamilyIndex		= context.getUniversalQueueFamilyIndex();

	const VkCommandPoolCreateInfo			cmdPoolParams			=
	{
		VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,					//	VkStructureType				sType;
		DE_NULL,													//	const void*					pNext;
		VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,			//	VkCommandPoolCreateFlags	flags;
		queueFamilyIndex,											//	deUint32					queueFamilyIndex;
	};
	const Unique<VkCommandPool>				cmdPool					(createCommandPool(vk, vkDevice, &cmdPoolParams));

	// Command buffer
	const VkCommandBufferAllocateInfo		cmdBufParams			=
	{
		VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,				//	VkStructureType				sType;
		DE_NULL,													//	const void*					pNext;
		*cmdPool,													//	VkCommandPool				pool;
		VK_COMMAND_BUFFER_LEVEL_PRIMARY,							//	VkCommandBufferLevel		level;
		1u,															//	uint32_t					bufferCount;
	};
	const Unique<VkCommandBuffer>			primCmdBuf				(allocateCommandBuffer(vk, vkDevice, &cmdBufParams));

	// create event that will be used to check if secondary command buffer has been executed
	const Unique<VkEvent>					event					(createEvent(vk, vkDevice));

	// reset event
	VK_CHECK(vk.resetEvent(vkDevice, *event));

	// record primary command buffer
	beginCommandBuffer(vk, *primCmdBuf, 0u);
	{
		// allow execution of event during every stage of pipeline
		VkPipelineStageFlags stageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;

		// define minimal amount of commands to accept
		const long long unsigned minNumCommands = 10000llu;

		for ( long long unsigned currentCommands = 0; currentCommands < minNumCommands / 2; ++currentCommands )
		{
			// record setting event
			vk.cmdSetEvent(*primCmdBuf, *event,stageMask);

			// record resetting event
			vk.cmdResetEvent(*primCmdBuf, *event,stageMask);
		}

	}
	endCommandBuffer(vk, *primCmdBuf);

	submitCommandsAndWait(vk, vkDevice, queue, primCmdBuf.get());

	return tcu::TestStatus::pass("hugeTest succeeded");
}

tcu::TestStatus recordSingleSecondaryBufferTest(Context& context)
{
	const VkDevice							vkDevice				= context.getDevice();
	const DeviceInterface&					vk						= context.getDeviceInterface();
	const deUint32							queueFamilyIndex		= context.getUniversalQueueFamilyIndex();

	const VkCommandPoolCreateInfo			cmdPoolParams			=
	{
		VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,					//	VkStructureType				sType;
		DE_NULL,													//	const void*					pNext;
		VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,			//	VkCommandPoolCreateFlags	flags;
		queueFamilyIndex,											//	deUint32					queueFamilyIndex;
	};
	const Unique<VkCommandPool>				cmdPool					(createCommandPool(vk, vkDevice, &cmdPoolParams));

	// Command buffer
	const VkCommandBufferAllocateInfo		cmdBufParams			=
	{
		VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,				//	VkStructureType				sType;
		DE_NULL,													//	const void*					pNext;
		*cmdPool,													//	VkCommandPool				pool;
		VK_COMMAND_BUFFER_LEVEL_SECONDARY,							//	VkCommandBufferLevel		level;
		1u,															//	uint32_t					bufferCount;
	};
	const Unique<VkCommandBuffer>			secCmdBuf				(allocateCommandBuffer(vk, vkDevice, &cmdBufParams));

	const VkCommandBufferInheritanceInfo	secCmdBufInheritInfo	=
	{
		VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO,
		DE_NULL,
		(VkRenderPass)0u,											// renderPass
		0u,															// subpass
		(VkFramebuffer)0u,											// framebuffer
		VK_FALSE,													// occlusionQueryEnable
		(VkQueryControlFlags)0u,									// queryFlags
		(VkQueryPipelineStatisticFlags)0u,							// pipelineStatistics
	};
	const VkCommandBufferBeginInfo			secCmdBufBeginInfo		=
	{
		VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
		DE_NULL,
		0,															// flags
		&secCmdBufInheritInfo,
	};

	// create event that will be used to check if secondary command buffer has been executed
	const Unique<VkEvent>					event					(createEvent(vk, vkDevice));

	// record primary command buffer
	VK_CHECK(vk.beginCommandBuffer(*secCmdBuf, &secCmdBufBeginInfo));
	{
		// record setting event
		vk.cmdSetEvent(*secCmdBuf, *event, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT);
	}
	endCommandBuffer(vk, *secCmdBuf);

	return tcu::TestStatus::pass("Secondary buffer recorded successfully.");
}

tcu::TestStatus recordLargeSecondaryBufferTest(Context &context)
{
	const VkDevice							vkDevice				= context.getDevice();
	const DeviceInterface&					vk						= context.getDeviceInterface();
	const VkQueue							queue					= context.getUniversalQueue();
	const deUint32							queueFamilyIndex		= context.getUniversalQueueFamilyIndex();

	const VkCommandPoolCreateInfo			cmdPoolParams			=
	{
		VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,					//	VkStructureType				sType;
		DE_NULL,													//	const void*					pNext;
		VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,			//	VkCommandPoolCreateFlags	flags;
		queueFamilyIndex,											//	deUint32					queueFamilyIndex;
	};
	const Unique<VkCommandPool>				cmdPool					(createCommandPool(vk, vkDevice, &cmdPoolParams));

	// Command buffer
	const VkCommandBufferAllocateInfo		cmdBufParams			=
	{
		VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,				//	VkStructureType				sType;
		DE_NULL,													//	const void*					pNext;
		*cmdPool,													//	VkCommandPool				pool;
		VK_COMMAND_BUFFER_LEVEL_PRIMARY,							//	VkCommandBufferLevel		level;
		1u,															//	uint32_t					bufferCount;
	};
	const Unique<VkCommandBuffer>			primCmdBuf				(allocateCommandBuffer(vk, vkDevice, &cmdBufParams));

	const VkCommandBufferAllocateInfo		secCmdBufParams			=
	{
		VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,				//	VkStructureType				sType;
		DE_NULL,													//	const void*					pNext;
		*cmdPool,													//	VkCommandPool				pool;
		VK_COMMAND_BUFFER_LEVEL_SECONDARY,							//	VkCommandBufferLevel		level;
		1u,															//	uint32_t					bufferCount;
	};
	const Unique<VkCommandBuffer>			secCmdBuf				(allocateCommandBuffer(vk, vkDevice, &secCmdBufParams));

	const VkCommandBufferInheritanceInfo	secCmdBufInheritInfo	=
	{
		VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO,
		DE_NULL,
		(VkRenderPass)0u,											// renderPass
		0u,															// subpass
		(VkFramebuffer)0u,											// framebuffer
		VK_FALSE,													// occlusionQueryEnable
		(VkQueryControlFlags)0u,									// queryFlags
		(VkQueryPipelineStatisticFlags)0u,							// pipelineStatistics
	};
	const VkCommandBufferBeginInfo			secCmdBufBeginInfo		=
	{
		VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
		DE_NULL,
		0,															// flags
		&secCmdBufInheritInfo,
	};

	// create event that will be used to check if secondary command buffer has been executed
	const Unique<VkEvent>					event					(createEvent(vk, vkDevice));

	// reset event
	VK_CHECK(vk.resetEvent(vkDevice, *event));

	// record primary command buffer
	beginCommandBuffer(vk, *primCmdBuf, 0u);
	{
		// record secondary command buffer
		VK_CHECK(vk.beginCommandBuffer(*secCmdBuf, &secCmdBufBeginInfo));
		{
			// allow execution of event during every stage of pipeline
			VkPipelineStageFlags stageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;

			// define minimal amount of commands to accept
			const long long unsigned minNumCommands = 10000llu;

			for ( long long unsigned currentCommands = 0; currentCommands < minNumCommands / 2; ++currentCommands )
			{
				// record setting event
				vk.cmdSetEvent(*primCmdBuf, *event,stageMask);

				// record resetting event
				vk.cmdResetEvent(*primCmdBuf, *event,stageMask);
			}
		}

		// end recording of secondary buffers
		endCommandBuffer(vk, *secCmdBuf);

		// execute secondary buffer
		vk.cmdExecuteCommands(*primCmdBuf, 1, &secCmdBuf.get());
	}
	endCommandBuffer(vk, *primCmdBuf);

	submitCommandsAndWait(vk, vkDevice, queue, primCmdBuf.get());

	return tcu::TestStatus::pass("hugeTest succeeded");
}

tcu::TestStatus submitPrimaryBufferTwiceTest(Context& context)
{
	const VkDevice							vkDevice				= context.getDevice();
	const DeviceInterface&					vk						= context.getDeviceInterface();
	const VkQueue							queue					= context.getUniversalQueue();
	const deUint32							queueFamilyIndex		= context.getUniversalQueueFamilyIndex();

	const VkCommandPoolCreateInfo			cmdPoolParams			=
	{
		VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,					//	VkStructureType				sType;
		DE_NULL,													//	const void*					pNext;
		VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,			//	VkCommandPoolCreateFlags	flags;
		queueFamilyIndex,											//	deUint32					queueFamilyIndex;
	};
	const Unique<VkCommandPool>				cmdPool					(createCommandPool(vk, vkDevice, &cmdPoolParams));

	// Command buffer
	const VkCommandBufferAllocateInfo		cmdBufParams			=
	{
		VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,				//	VkStructureType			sType;
		DE_NULL,													//	const void*				pNext;
		*cmdPool,													//	VkCommandPool				pool;
		VK_COMMAND_BUFFER_LEVEL_PRIMARY,							//	VkCommandBufferLevel		level;
		1u,															//	uint32_t					bufferCount;
	};
	const Unique<VkCommandBuffer>			primCmdBuf				(allocateCommandBuffer(vk, vkDevice, &cmdBufParams));

	// create event that will be used to check if secondary command buffer has been executed
	const Unique<VkEvent>					event					(createEvent(vk, vkDevice));

	// reset event
	VK_CHECK(vk.resetEvent(vkDevice, *event));

	// record primary command buffer
	beginCommandBuffer(vk, *primCmdBuf, 0u);
	{
		// allow execution of event during every stage of pipeline
		VkPipelineStageFlags stageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;

		// record setting event
		vk.cmdSetEvent(*primCmdBuf, *event,stageMask);
	}
	endCommandBuffer(vk, *primCmdBuf);

	submitCommandsAndWait(vk, vkDevice, queue, primCmdBuf.get());

	// check if buffer has been executed
	VkResult result = vk.getEventStatus(vkDevice,*event);
	if (result != VK_EVENT_SET)
		return tcu::TestStatus::fail("Submit Twice Test FAILED");

	// reset event
	VK_CHECK(vk.resetEvent(vkDevice, *event));

	submitCommandsAndWait(vk, vkDevice, queue, primCmdBuf.get());

	// check if buffer has been executed
	result = vk.getEventStatus(vkDevice,*event);
	if (result != VK_EVENT_SET)
		return tcu::TestStatus::fail("Submit Twice Test FAILED");
	else
		return tcu::TestStatus::pass("Submit Twice Test succeeded");
}

tcu::TestStatus submitSecondaryBufferTwiceTest(Context& context)
{
	const VkDevice							vkDevice				= context.getDevice();
	const DeviceInterface&					vk						= context.getDeviceInterface();
	const VkQueue							queue					= context.getUniversalQueue();
	const deUint32							queueFamilyIndex		= context.getUniversalQueueFamilyIndex();

	const VkCommandPoolCreateInfo			cmdPoolParams			=
	{
		VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,					//	VkStructureType				sType;
		DE_NULL,													//	const void*					pNext;
		VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,			//	VkCommandPoolCreateFlags	flags;
		queueFamilyIndex,											//	deUint32					queueFamilyIndex;
	};

	const Unique<VkCommandPool>				cmdPool					(createCommandPool(vk, vkDevice, &cmdPoolParams));

	// Command buffer
	const VkCommandBufferAllocateInfo		cmdBufParams			=
	{
		VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,				//	VkStructureType			sType;
		DE_NULL,													//	const void*				pNext;
		*cmdPool,													//	VkCommandPool				pool;
		VK_COMMAND_BUFFER_LEVEL_PRIMARY,							//	VkCommandBufferLevel		level;
		1u,															//	uint32_t					bufferCount;
	};

	const Unique<VkCommandBuffer>			primCmdBuf1				(allocateCommandBuffer(vk, vkDevice, &cmdBufParams));
	const Unique<VkCommandBuffer>			primCmdBuf2				(allocateCommandBuffer(vk, vkDevice, &cmdBufParams));

	// Secondary Command buffer
	const VkCommandBufferAllocateInfo		secCmdBufParams			=
	{
		VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,				//	VkStructureType			sType;
		DE_NULL,													//	const void*				pNext;
		*cmdPool,													//	VkCommandPool				pool;
		VK_COMMAND_BUFFER_LEVEL_SECONDARY,							//	VkCommandBufferLevel		level;
		1u,															//	uint32_t					bufferCount;
	};
	const Unique<VkCommandBuffer>			secCmdBuf				(allocateCommandBuffer(vk, vkDevice, &secCmdBufParams));

	const VkCommandBufferInheritanceInfo	secCmdBufInheritInfo	=
	{
		VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO,
		DE_NULL,
		(VkRenderPass)0u,											// renderPass
		0u,															// subpass
		(VkFramebuffer)0u,											// framebuffer
		VK_FALSE,													// occlusionQueryEnable
		(VkQueryControlFlags)0u,									// queryFlags
		(VkQueryPipelineStatisticFlags)0u,							// pipelineStatistics
	};
	const VkCommandBufferBeginInfo			secCmdBufBeginInfo		=
	{
		VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
		DE_NULL,
		0u,															// flags
		&secCmdBufInheritInfo,
	};

	// create event that will be used to check if secondary command buffer has been executed
	const Unique<VkEvent>					event					(createEvent(vk, vkDevice));

	// reset event
	VK_CHECK(vk.resetEvent(vkDevice, *event));

	// record first primary command buffer
	beginCommandBuffer(vk, *primCmdBuf1, 0u);
	{
		// record secondary command buffer
		VK_CHECK(vk.beginCommandBuffer(*secCmdBuf, &secCmdBufBeginInfo));
		{
			// allow execution of event during every stage of pipeline
			VkPipelineStageFlags stageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;

			// record setting event
			vk.cmdSetEvent(*secCmdBuf, *event,stageMask);
		}

		// end recording of secondary buffers
		endCommandBuffer(vk, *secCmdBuf);

		// execute secondary buffer
		vk.cmdExecuteCommands(*primCmdBuf1, 1, &secCmdBuf.get());
	}
	endCommandBuffer(vk, *primCmdBuf1);

	submitCommandsAndWait(vk, vkDevice, queue, primCmdBuf1.get());

	// check if secondary buffer has been executed
	VkResult result = vk.getEventStatus(vkDevice,*event);
	if (result != VK_EVENT_SET)
		return tcu::TestStatus::fail("Submit Twice Secondary Command Buffer FAILED");

	// reset first primary buffer
	vk.resetCommandBuffer( *primCmdBuf1, 0u);

	// reset event to allow receiving it again
	VK_CHECK(vk.resetEvent(vkDevice, *event));

	// record second primary command buffer
	beginCommandBuffer(vk, *primCmdBuf2, 0u);
	{
		// execute secondary buffer
		vk.cmdExecuteCommands(*primCmdBuf2, 1, &secCmdBuf.get());
	}
	// end recording
	endCommandBuffer(vk, *primCmdBuf2);

	submitCommandsAndWait(vk, vkDevice, queue, primCmdBuf2.get());

	// check if secondary buffer has been executed
	result = vk.getEventStatus(vkDevice,*event);
	if (result != VK_EVENT_SET)
		return tcu::TestStatus::fail("Submit Twice Secondary Command Buffer FAILED");
	else
		return tcu::TestStatus::pass("Submit Twice Secondary Command Buffer succeeded");
}

tcu::TestStatus oneTimeSubmitFlagPrimaryBufferTest(Context& context)
{
	const VkDevice							vkDevice				= context.getDevice();
	const DeviceInterface&					vk						= context.getDeviceInterface();
	const VkQueue							queue					= context.getUniversalQueue();
	const deUint32							queueFamilyIndex		= context.getUniversalQueueFamilyIndex();

	const VkCommandPoolCreateInfo			cmdPoolParams			=
	{
		VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,					//	VkStructureType				sType;
		DE_NULL,													//	const void*					pNext;
		VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,			//	VkCommandPoolCreateFlags	flags;
		queueFamilyIndex,											//	deUint32					queueFamilyIndex;
	};
	const Unique<VkCommandPool>				cmdPool					(createCommandPool(vk, vkDevice, &cmdPoolParams));

	// Command buffer
	const VkCommandBufferAllocateInfo		cmdBufParams			=
	{
		VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,				//	VkStructureType				sType;
		DE_NULL,													//	const void*					pNext;
		*cmdPool,													//	VkCommandPool				pool;
		VK_COMMAND_BUFFER_LEVEL_PRIMARY,							//	VkCommandBufferLevel		level;
		1u,															//	uint32_t					bufferCount;
	};
	const Unique<VkCommandBuffer>			primCmdBuf				(allocateCommandBuffer(vk, vkDevice, &cmdBufParams));

	// create event that will be used to check if secondary command buffer has been executed
	const Unique<VkEvent>					event					(createEvent(vk, vkDevice));

	// reset event
	VK_CHECK(vk.resetEvent(vkDevice, *event));

	// record primary command buffer
	beginCommandBuffer(vk, *primCmdBuf);
	{
		// allow execution of event during every stage of pipeline
		VkPipelineStageFlags stageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;

		// record setting event
		vk.cmdSetEvent(*primCmdBuf, *event,stageMask);
	}
	endCommandBuffer(vk, *primCmdBuf);

	submitCommandsAndWait(vk, vkDevice, queue, primCmdBuf.get());

	// check if buffer has been executed
	VkResult result = vk.getEventStatus(vkDevice,*event);
	if (result != VK_EVENT_SET)
		return tcu::TestStatus::fail("oneTimeSubmitFlagPrimaryBufferTest FAILED");

	// record primary command buffer again - implicit reset because of VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT
	beginCommandBuffer(vk, *primCmdBuf);
	{
		// allow execution of event during every stage of pipeline
		VkPipelineStageFlags stageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;

		// record setting event
		vk.cmdSetEvent(*primCmdBuf, *event,stageMask);
	}
	endCommandBuffer(vk, *primCmdBuf);

	submitCommandsAndWait(vk, vkDevice, queue, primCmdBuf.get());

	// check if buffer has been executed
	result = vk.getEventStatus(vkDevice,*event);
	if (result != VK_EVENT_SET)
		return tcu::TestStatus::fail("oneTimeSubmitFlagPrimaryBufferTest FAILED");
	else
		return tcu::TestStatus::pass("oneTimeSubmitFlagPrimaryBufferTest succeeded");
}

tcu::TestStatus oneTimeSubmitFlagSecondaryBufferTest(Context& context)
{
	const VkDevice							vkDevice				= context.getDevice();
	const DeviceInterface&					vk						= context.getDeviceInterface();
	const VkQueue							queue					= context.getUniversalQueue();
	const deUint32							queueFamilyIndex		= context.getUniversalQueueFamilyIndex();

	const VkCommandPoolCreateInfo			cmdPoolParams			=
	{
		VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,					//	VkStructureType				sType;
		DE_NULL,													//	const void*					pNext;
		VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,			//	VkCommandPoolCreateFlags	flags;
		queueFamilyIndex,											//	deUint32					queueFamilyIndex;
	};

	const Unique<VkCommandPool>				cmdPool					(createCommandPool(vk, vkDevice, &cmdPoolParams));

	// Command buffer
	const VkCommandBufferAllocateInfo		cmdBufParams			=
	{
		VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,				//	VkStructureType			sType;
		DE_NULL,													//	const void*				pNext;
		*cmdPool,													//	VkCommandPool				pool;
		VK_COMMAND_BUFFER_LEVEL_PRIMARY,							//	VkCommandBufferLevel		level;
		1u,															//	uint32_t					bufferCount;
	};

	const Unique<VkCommandBuffer>			primCmdBuf1				(allocateCommandBuffer(vk, vkDevice, &cmdBufParams));
	const Unique<VkCommandBuffer>			primCmdBuf2				(allocateCommandBuffer(vk, vkDevice, &cmdBufParams));

	// Secondary Command buffer
	const VkCommandBufferAllocateInfo		secCmdBufParams			=
	{
		VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,				//	VkStructureType			sType;
		DE_NULL,													//	const void*				pNext;
		*cmdPool,													//	VkCommandPool				pool;
		VK_COMMAND_BUFFER_LEVEL_SECONDARY,							//	VkCommandBufferLevel		level;
		1u,															//	uint32_t					bufferCount;
	};
	const Unique<VkCommandBuffer>			secCmdBuf				(allocateCommandBuffer(vk, vkDevice, &secCmdBufParams));

	const VkCommandBufferInheritanceInfo	secCmdBufInheritInfo	=
	{
		VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO,
		DE_NULL,
		(VkRenderPass)0u,											// renderPass
		0u,															// subpass
		(VkFramebuffer)0u,											// framebuffer
		VK_FALSE,													// occlusionQueryEnable
		(VkQueryControlFlags)0u,									// queryFlags
		(VkQueryPipelineStatisticFlags)0u,							// pipelineStatistics
	};
	const VkCommandBufferBeginInfo			secCmdBufBeginInfo		=
	{
		VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
		DE_NULL,
		VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,				// flags
		&secCmdBufInheritInfo,
	};

	// create event that will be used to check if secondary command buffer has been executed
	const Unique<VkEvent>					event					(createEvent(vk, vkDevice));

	// reset event
	VK_CHECK(vk.resetEvent(vkDevice, *event));

	// record first primary command buffer
	beginCommandBuffer(vk, *primCmdBuf1, 0u);
	{
		// record secondary command buffer
		VK_CHECK(vk.beginCommandBuffer(*secCmdBuf, &secCmdBufBeginInfo));
		{
			// allow execution of event during every stage of pipeline
			VkPipelineStageFlags stageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;

			// record setting event
			vk.cmdSetEvent(*secCmdBuf, *event,stageMask);
		}

		// end recording of secondary buffers
		endCommandBuffer(vk, *secCmdBuf);

		// execute secondary buffer
		vk.cmdExecuteCommands(*primCmdBuf1, 1, &secCmdBuf.get());
	}
	endCommandBuffer(vk, *primCmdBuf1);

	submitCommandsAndWait(vk, vkDevice, queue, primCmdBuf1.get());

	// check if secondary buffer has been executed
	VkResult result = vk.getEventStatus(vkDevice,*event);
	if (result != VK_EVENT_SET)
		return tcu::TestStatus::fail("Submit Twice Secondary Command Buffer FAILED");

	// reset first primary buffer
	vk.resetCommandBuffer( *primCmdBuf1, 0u);

	// reset event to allow receiving it again
	VK_CHECK(vk.resetEvent(vkDevice, *event));

	// record secondary command buffer again
	VK_CHECK(vk.beginCommandBuffer(*secCmdBuf, &secCmdBufBeginInfo));
	{
		// allow execution of event during every stage of pipeline
		VkPipelineStageFlags stageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;

		// record setting event
		vk.cmdSetEvent(*secCmdBuf, *event,stageMask);
	}
	// end recording of secondary buffers
	endCommandBuffer(vk, *secCmdBuf);

	// record second primary command buffer
	beginCommandBuffer(vk, *primCmdBuf2, 0u);
	{
		// execute secondary buffer
		vk.cmdExecuteCommands(*primCmdBuf2, 1, &secCmdBuf.get());
	}
	// end recording
	endCommandBuffer(vk, *primCmdBuf2);

	submitCommandsAndWait(vk, vkDevice, queue, primCmdBuf2.get());

	// check if secondary buffer has been executed
	result = vk.getEventStatus(vkDevice,*event);
	if (result != VK_EVENT_SET)
		return tcu::TestStatus::fail("oneTimeSubmitFlagSecondaryBufferTest FAILED");
	else
		return tcu::TestStatus::pass("oneTimeSubmitFlagSecondaryBufferTest succeeded");
}

tcu::TestStatus renderPassContinueTest(Context& context, bool framebufferHint)
{
	const DeviceInterface&					vkd						= context.getDeviceInterface();
	CommandBufferRenderPassTestEnvironment	env						(context, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT);

	VkCommandBuffer							primaryCommandBuffer	= env.getPrimaryCommandBuffer();
	VkCommandBuffer							secondaryCommandBuffer	= env.getSecondaryCommandBuffer();
	const deUint32							clearColor[4]			= { 2, 47, 131, 211 };

	const VkClearAttachment					clearAttachment			=
	{
		VK_IMAGE_ASPECT_COLOR_BIT,									// VkImageAspectFlags	aspectMask;
		0,															// deUint32				colorAttachment;
		makeClearValueColorU32(clearColor[0],
							   clearColor[1],
							   clearColor[2],
							   clearColor[3])						// VkClearValue			clearValue;
	};

	const VkClearRect						clearRect				=
	{
		CommandBufferRenderPassTestEnvironment::DEFAULT_IMAGE_AREA,	// VkRect2D	rect;
		0u,															// deUint32	baseArrayLayer;
		1u															// deUint32	layerCount;
	};

	env.beginSecondaryCommandBuffer(VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT, framebufferHint);
	vkd.cmdClearAttachments(secondaryCommandBuffer, 1, &clearAttachment, 1, &clearRect);
	endCommandBuffer(vkd, secondaryCommandBuffer);


	env.beginPrimaryCommandBuffer(0);
	env.beginRenderPass(VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS);
	vkd.cmdExecuteCommands(primaryCommandBuffer, 1, &secondaryCommandBuffer);
	endRenderPass(vkd, primaryCommandBuffer);

	endCommandBuffer(vkd, primaryCommandBuffer);

	env.submitPrimaryCommandBuffer();

	de::MovePtr<tcu::TextureLevel>			result					= env.readColorAttachment();
	tcu::PixelBufferAccess					pixelBufferAccess		= result->getAccess();

	for (deUint32 i = 0; i < (CommandBufferRenderPassTestEnvironment::DEFAULT_IMAGE_SIZE.width * CommandBufferRenderPassTestEnvironment::DEFAULT_IMAGE_SIZE.height); ++i)
	{
		deUint8* colorData = reinterpret_cast<deUint8*>(pixelBufferAccess.getDataPtr());
		for (int colorComponent = 0; colorComponent < 4; ++colorComponent)
			if (colorData[i * 4 + colorComponent] != clearColor[colorComponent])
				return tcu::TestStatus::fail("clear value mismatch");
	}

	return tcu::TestStatus::pass("render pass continue test passed");
}

tcu::TestStatus simultaneousUsePrimaryBufferTest(Context& context)
{
	const VkDevice							vkDevice				= context.getDevice();
	const DeviceInterface&					vk						= context.getDeviceInterface();
	const VkQueue							queue					= context.getUniversalQueue();
	const deUint32							queueFamilyIndex		= context.getUniversalQueueFamilyIndex();

	const VkCommandPoolCreateInfo			cmdPoolParams			=
	{
		VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,					//	VkStructureType				sType;
		DE_NULL,													//	const void*					pNext;
		VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,			//	VkCommandPoolCreateFlags	flags;
		queueFamilyIndex,											//	deUint32					queueFamilyIndex;
	};
	const Unique<VkCommandPool>				cmdPool					(createCommandPool(vk, vkDevice, &cmdPoolParams));

	// Command buffer
	const VkCommandBufferAllocateInfo		cmdBufParams			=
	{
		VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,				//	VkStructureType				sType;
		DE_NULL,													//	const void*					pNext;
		*cmdPool,													//	VkCommandPool				pool;
		VK_COMMAND_BUFFER_LEVEL_PRIMARY,							//	VkCommandBufferLevel		level;
		1u,															//	uint32_t					bufferCount;
	};
	const Unique<VkCommandBuffer>			primCmdBuf				(allocateCommandBuffer(vk, vkDevice, &cmdBufParams));

	// create event that will be used to check if secondary command buffer has been executed
	const Unique<VkEvent>					eventOne				(createEvent(vk, vkDevice));
	const Unique<VkEvent>					eventTwo				(createEvent(vk, vkDevice));

	// reset event
	VK_CHECK(vk.resetEvent(vkDevice, *eventOne));

	// record primary command buffer
	beginCommandBuffer(vk, *primCmdBuf, VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT);
	{
		// wait for event
		vk.cmdWaitEvents(*primCmdBuf, 1u, &eventOne.get(), VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0u, DE_NULL, 0u, DE_NULL, 0u, DE_NULL);

		// Set the second event
		vk.cmdSetEvent(*primCmdBuf, eventTwo.get(), VK_PIPELINE_STAGE_ALL_COMMANDS_BIT);
	}
	endCommandBuffer(vk, *primCmdBuf);

	// create fence to wait for execution of queue
	const Unique<VkFence>					fence1					(createFence(vk, vkDevice));
	const Unique<VkFence>					fence2					(createFence(vk, vkDevice));

	const VkSubmitInfo						submitInfo				=
	{
		VK_STRUCTURE_TYPE_SUBMIT_INFO,								// sType
		DE_NULL,													// pNext
		0u,															// waitSemaphoreCount
		DE_NULL,													// pWaitSemaphores
		(const VkPipelineStageFlags*)DE_NULL,						// pWaitDstStageMask
		1,															// commandBufferCount
		&primCmdBuf.get(),											// pCommandBuffers
		0u,															// signalSemaphoreCount
		DE_NULL,													// pSignalSemaphores
	};

	// submit first buffer
	VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo, *fence1));

	// submit second buffer
	VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo, *fence2));

	// wait for both buffer to stop at event for 100 microseconds
	vk.waitForFences(vkDevice, 1, &fence1.get(), 0u, 100000);
	vk.waitForFences(vkDevice, 1, &fence2.get(), 0u, 100000);

	// set event
	VK_CHECK(vk.setEvent(vkDevice, *eventOne));

	// wait for end of execution of the first buffer
	VK_CHECK(vk.waitForFences(vkDevice, 1, &fence1.get(), 0u, INFINITE_TIMEOUT));
	// wait for end of execution of the second buffer
	VK_CHECK(vk.waitForFences(vkDevice, 1, &fence2.get(), 0u, INFINITE_TIMEOUT));

	// TODO: this will be true if the command buffer was executed only once
	// TODO: add some test that will say if it was executed twice

	// check if buffer has been executed
	VkResult result = vk.getEventStatus(vkDevice, *eventTwo);
	if (result == VK_EVENT_SET)
		return tcu::TestStatus::pass("simultaneous use - primary buffers test succeeded");
	else
		return tcu::TestStatus::fail("simultaneous use - primary buffers test FAILED");
}

tcu::TestStatus simultaneousUseSecondaryBufferTest(Context& context)
{
	const VkDevice							vkDevice				= context.getDevice();
	const DeviceInterface&					vk						= context.getDeviceInterface();
	const VkQueue							queue					= context.getUniversalQueue();
	const deUint32							queueFamilyIndex		= context.getUniversalQueueFamilyIndex();

	const VkCommandPoolCreateInfo			cmdPoolParams			=
	{
		VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,					//	VkStructureType				sType;
		DE_NULL,													//	const void*					pNext;
		VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,			//	VkCommandPoolCreateFlags	flags;
		queueFamilyIndex,											//	deUint32					queueFamilyIndex;
	};
	const Unique<VkCommandPool>				cmdPool					(createCommandPool(vk, vkDevice, &cmdPoolParams));

	// Command buffer
	const VkCommandBufferAllocateInfo		cmdBufParams			=
	{
		VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,				//	VkStructureType			sType;
		DE_NULL,													//	const void*				pNext;
		*cmdPool,													//	VkCommandPool				pool;
		VK_COMMAND_BUFFER_LEVEL_PRIMARY,							//	VkCommandBufferLevel		level;
		1u,															//	uint32_t					bufferCount;
	};
	const Unique<VkCommandBuffer>			primCmdBuf				(allocateCommandBuffer(vk, vkDevice, &cmdBufParams));

	// Secondary Command buffer params
	const VkCommandBufferAllocateInfo		secCmdBufParams			=
	{
		VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,				//	VkStructureType			sType;
		DE_NULL,													//	const void*				pNext;
		*cmdPool,													//	VkCommandPool				pool;
		VK_COMMAND_BUFFER_LEVEL_SECONDARY,							//	VkCommandBufferLevel		level;
		1u,															//	uint32_t					bufferCount;
	};
	const Unique<VkCommandBuffer>			secCmdBuf				(allocateCommandBuffer(vk, vkDevice, &secCmdBufParams));

	const VkCommandBufferInheritanceInfo	secCmdBufInheritInfo	=
	{
		VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO,
		DE_NULL,
		(VkRenderPass)0u,											// renderPass
		0u,															// subpass
		(VkFramebuffer)0u,											// framebuffer
		VK_FALSE,													// occlusionQueryEnable
		(VkQueryControlFlags)0u,									// queryFlags
		(VkQueryPipelineStatisticFlags)0u,							// pipelineStatistics
	};
	const VkCommandBufferBeginInfo			secCmdBufBeginInfo		=
	{
		VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
		DE_NULL,
		VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT,				// flags
		&secCmdBufInheritInfo,
	};

	// create event that will be used to check if secondary command buffer has been executed
	const Unique<VkEvent>					eventOne				(createEvent(vk, vkDevice));
	const Unique<VkEvent>					eventTwo				(createEvent(vk, vkDevice));

	// reset event
	VK_CHECK(vk.resetEvent(vkDevice, *eventOne));
	VK_CHECK(vk.resetEvent(vkDevice, *eventTwo));

	// record secondary command buffer
	VK_CHECK(vk.beginCommandBuffer(*secCmdBuf, &secCmdBufBeginInfo));
	{
		// allow execution of event during every stage of pipeline
		VkPipelineStageFlags stageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;

		// wait for event
		vk.cmdWaitEvents(*secCmdBuf, 1, &eventOne.get(), stageMask, stageMask, 0, DE_NULL, 0u, DE_NULL, 0u, DE_NULL);

		// reset event
		vk.cmdSetEvent(*secCmdBuf, *eventTwo, stageMask);
	}
	// end recording of secondary buffers
	endCommandBuffer(vk, *secCmdBuf);

	// record primary command buffer
	beginCommandBuffer(vk, *primCmdBuf, 0u);
	{
		// execute secondary buffer
		vk.cmdExecuteCommands(*primCmdBuf, 1, &secCmdBuf.get());
	}
	endCommandBuffer(vk, *primCmdBuf);

	// create fence to wait for execution of queue
	const Unique<VkFence>					fence					(createFence(vk, vkDevice));

	const VkSubmitInfo						submitInfo				=
	{
		VK_STRUCTURE_TYPE_SUBMIT_INFO,								// sType
		DE_NULL,													// pNext
		0u,															// waitSemaphoreCount
		DE_NULL,													// pWaitSemaphores
		(const VkPipelineStageFlags*)DE_NULL,						// pWaitDstStageMask
		1,															// commandBufferCount
		&primCmdBuf.get(),											// pCommandBuffers
		0u,															// signalSemaphoreCount
		DE_NULL,													// pSignalSemaphores
	};

	// submit primary buffer, the secondary should be executed too
	VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo, *fence));

	// wait for both buffers to stop at event for 100 microseconds
	vk.waitForFences(vkDevice, 1, &fence.get(), 0u, 100000);

	// set event
	VK_CHECK(vk.setEvent(vkDevice, *eventOne));

	// wait for end of execution of queue
	VK_CHECK(vk.waitForFences(vkDevice, 1, &fence.get(), 0u, INFINITE_TIMEOUT));

	// TODO: this will be true if the command buffer was executed only once
	// TODO: add some test that will say if it was executed twice

	// check if secondary buffer has been executed
	VkResult result = vk.getEventStatus(vkDevice,*eventTwo);
	if (result == VK_EVENT_SET)
		return tcu::TestStatus::pass("Simultaneous Secondary Command Buffer Execution succeeded");
	else
		return tcu::TestStatus::fail("Simultaneous Secondary Command Buffer Execution FAILED");
}

tcu::TestStatus simultaneousUseSecondaryBufferOnePrimaryBufferTest(Context& context)
{
	const VkDevice							vkDevice = context.getDevice();
	const DeviceInterface&					vk = context.getDeviceInterface();
	const VkQueue							queue = context.getUniversalQueue();
	const deUint32							queueFamilyIndex = context.getUniversalQueueFamilyIndex();
	Allocator&								allocator = context.getDefaultAllocator();
	const ComputeInstanceResultBuffer		result(vk, vkDevice, allocator, 0.0f);

	const VkCommandPoolCreateInfo			cmdPoolParams =
	{
		VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,					//	VkStructureType				sType;
		DE_NULL,													//	const void*					pNext;
		VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,			//	VkCommandPoolCreateFlags	flags;
		queueFamilyIndex,											//	deUint32					queueFamilyIndex;
	};
	const Unique<VkCommandPool>				cmdPool(createCommandPool(vk, vkDevice, &cmdPoolParams));

	// Command buffer
	const VkCommandBufferAllocateInfo		cmdBufParams =
	{
		VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,				//	VkStructureType			sType;
		DE_NULL,													//	const void*				pNext;
		*cmdPool,													//	VkCommandPool				pool;
		VK_COMMAND_BUFFER_LEVEL_PRIMARY,							//	VkCommandBufferLevel		level;
		1u,															//	uint32_t					bufferCount;
	};
	const Unique<VkCommandBuffer>			primCmdBuf(allocateCommandBuffer(vk, vkDevice, &cmdBufParams));

	// Secondary Command buffer params
	const VkCommandBufferAllocateInfo		secCmdBufParams =
	{
		VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,				//	VkStructureType			sType;
		DE_NULL,													//	const void*				pNext;
		*cmdPool,													//	VkCommandPool				pool;
		VK_COMMAND_BUFFER_LEVEL_SECONDARY,							//	VkCommandBufferLevel		level;
		1u,															//	uint32_t					bufferCount;
	};
	const Unique<VkCommandBuffer>			secCmdBuf(allocateCommandBuffer(vk, vkDevice, &secCmdBufParams));

	const VkCommandBufferInheritanceInfo	secCmdBufInheritInfo =
	{
		VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO,
		DE_NULL,
		(VkRenderPass)0u,
		0u,															// subpass
		(VkFramebuffer)0u,
		VK_FALSE,													// occlusionQueryEnable
		(VkQueryControlFlags)0u,
		(VkQueryPipelineStatisticFlags)0u,
	};
	const VkCommandBufferBeginInfo			secCmdBufBeginInfo =
	{
		VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
		DE_NULL,
		VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT,				// flags
		&secCmdBufInheritInfo,
	};

	const deUint32							offset = (0u);
	const deUint32							addressableSize = 256;
	const deUint32							dataSize = 8;
	de::MovePtr<Allocation>					bufferMem;
	const Unique<VkBuffer>					buffer(createDataBuffer(context, offset, addressableSize, 0x00, dataSize, 0x5A, &bufferMem));
	// Secondary command buffer will have a compute shader that does an atomic increment to make sure that all instances of secondary buffers execute
	const Unique<VkDescriptorSetLayout>		descriptorSetLayout(createDescriptorSetLayout(context));
	const Unique<VkDescriptorPool>			descriptorPool(createDescriptorPool(context));
	const Unique<VkDescriptorSet>			descriptorSet(createDescriptorSet(context, *descriptorPool, *descriptorSetLayout, *buffer, offset, result.getBuffer()));
	const VkDescriptorSet					descriptorSets[] = { *descriptorSet };
	const int								numDescriptorSets = DE_LENGTH_OF_ARRAY(descriptorSets);

	const VkPipelineLayoutCreateInfo layoutCreateInfo =
	{
		VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,				// sType
		DE_NULL,													// pNext
		(VkPipelineLayoutCreateFlags)0,
		numDescriptorSets,											// setLayoutCount
		&descriptorSetLayout.get(),									// pSetLayouts
		0u,															// pushConstantRangeCount
		DE_NULL,													// pPushConstantRanges
	};
	Unique<VkPipelineLayout>				pipelineLayout(createPipelineLayout(vk, vkDevice, &layoutCreateInfo));

	const Unique<VkShaderModule>			computeModule(createShaderModule(vk, vkDevice, context.getBinaryCollection().get("compute_increment"), (VkShaderModuleCreateFlags)0u));

	const VkPipelineShaderStageCreateInfo	shaderCreateInfo =
	{
		VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
		DE_NULL,
		(VkPipelineShaderStageCreateFlags)0,
		VK_SHADER_STAGE_COMPUTE_BIT,								// stage
		*computeModule,												// shader
		"main",
		DE_NULL,													// pSpecializationInfo
	};

	const VkComputePipelineCreateInfo		pipelineCreateInfo =
	{
		VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
		DE_NULL,
		0u,															// flags
		shaderCreateInfo,											// cs
		*pipelineLayout,											// layout
		(vk::VkPipeline)0,											// basePipelineHandle
		0u,															// basePipelineIndex
	};

	const VkBufferMemoryBarrier				bufferBarrier =
	{
		VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,					// sType
		DE_NULL,													// pNext
		VK_ACCESS_SHADER_WRITE_BIT,									// srcAccessMask
		VK_ACCESS_HOST_READ_BIT,									// dstAccessMask
		VK_QUEUE_FAMILY_IGNORED,									// srcQueueFamilyIndex
		VK_QUEUE_FAMILY_IGNORED,									// destQueueFamilyIndex
		*buffer,													// buffer
		(VkDeviceSize)0u,											// offset
		(VkDeviceSize)VK_WHOLE_SIZE,								// size
	};

	const Unique<VkPipeline>				pipeline(createComputePipeline(vk, vkDevice, (VkPipelineCache)0u, &pipelineCreateInfo));

	// record secondary command buffer
	VK_CHECK(vk.beginCommandBuffer(*secCmdBuf, &secCmdBufBeginInfo));
	{
		vk.cmdBindPipeline(*secCmdBuf, VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline);
		vk.cmdBindDescriptorSets(*secCmdBuf, VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0, numDescriptorSets, descriptorSets, 0, 0);
		vk.cmdDispatch(*secCmdBuf, 1u, 1u, 1u);
		vk.cmdPipelineBarrier(*secCmdBuf, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0,
						  0, (const VkMemoryBarrier*)DE_NULL,
						  1, &bufferBarrier,
						  0, (const VkImageMemoryBarrier*)DE_NULL);
	}
	// end recording of secondary buffer
	endCommandBuffer(vk, *secCmdBuf);

	// record primary command buffer
	beginCommandBuffer(vk, *primCmdBuf, 0u);
	{
		// execute secondary buffer twice in same primary
		vk.cmdExecuteCommands(*primCmdBuf, 1, &secCmdBuf.get());
		vk.cmdExecuteCommands(*primCmdBuf, 1, &secCmdBuf.get());
	}
	endCommandBuffer(vk, *primCmdBuf);

	submitCommandsAndWait(vk, vkDevice, queue, primCmdBuf.get());

	deUint32 resultCount;
	result.readResultContentsTo(&resultCount);
	// check if secondary buffer has been executed
	if (resultCount == 2)
		return tcu::TestStatus::pass("Simultaneous Secondary Command Buffer Execution succeeded");
	else
		return tcu::TestStatus::fail("Simultaneous Secondary Command Buffer Execution FAILED");
}

enum class BadInheritanceInfoCase
{
	RANDOM_PTR = 0,
	RANDOM_PTR_CONTINUATION,
	RANDOM_DATA_PTR,
	INVALID_STRUCTURE_TYPE,
	VALID_NONSENSE_TYPE,
};

tcu::TestStatus badInheritanceInfoTest (Context& context, BadInheritanceInfoCase testCase)
{
	const auto&							vkd					= context.getDeviceInterface();
	const auto							device				= context.getDevice();
	const auto							queue				= context.getUniversalQueue();
	const auto							queueFamilyIndex	= context.getUniversalQueueFamilyIndex();
	auto&								allocator			= context.getDefaultAllocator();
	const ComputeInstanceResultBuffer	result				(vkd, device, allocator, 0.0f);

	// Command pool and command buffer.
	const auto							cmdPool			= makeCommandPool(vkd, device, queueFamilyIndex);
	const auto							cmdBufferPtr	= allocateCommandBuffer(vkd, device, cmdPool.get(), VK_COMMAND_BUFFER_LEVEL_PRIMARY);
	const auto							cmdBuffer		= cmdBufferPtr.get();

	// Buffers, descriptor set layouts and descriptor sets.
	const deUint32							offset			= 0u;
	const deUint32							addressableSize	= 256u;
	const deUint32							dataSize		= 8u;

	// The uniform buffer will not be used by the shader but is needed by auxiliar functions here.
	de::MovePtr<Allocation>					bufferMem;
	const Unique<VkBuffer>					buffer(createDataBuffer(context, offset, addressableSize, 0x00, dataSize, 0x5A, &bufferMem));

	const Unique<VkDescriptorSetLayout>		descriptorSetLayout	(createDescriptorSetLayout(context));
	const Unique<VkDescriptorPool>			descriptorPool		(createDescriptorPool(context));
	const Unique<VkDescriptorSet>			descriptorSet		(createDescriptorSet(context, *descriptorPool, *descriptorSetLayout, *buffer, offset, result.getBuffer()));
	const VkDescriptorSet					descriptorSets[]	= { *descriptorSet };
	const int								numDescriptorSets	= DE_LENGTH_OF_ARRAY(descriptorSets);

	// Pipeline layout.
	const auto								pipelineLayout		= makePipelineLayout(vkd, device, descriptorSetLayout.get());

	// Compute shader module.
	const Unique<VkShaderModule>			computeModule		(createShaderModule(vkd, device, context.getBinaryCollection().get("compute_increment"), (VkShaderModuleCreateFlags)0u));

	const VkPipelineShaderStageCreateInfo	shaderCreateInfo	=
	{
		VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
		DE_NULL,
		(VkPipelineShaderStageCreateFlags)0,
		VK_SHADER_STAGE_COMPUTE_BIT,								// stage
		*computeModule,												// shader
		"main",
		DE_NULL,													// pSpecializationInfo
	};

	const VkComputePipelineCreateInfo		pipelineCreateInfo	=
	{
		VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
		DE_NULL,
		0u,															// flags
		shaderCreateInfo,											// cs
		*pipelineLayout,											// layout
		(vk::VkPipeline)0,											// basePipelineHandle
		0u,															// basePipelineIndex
	};

	const Unique<VkPipeline>				pipeline			(createComputePipeline(vkd, device, (VkPipelineCache)0u, &pipelineCreateInfo));

	// Compute to host barrier to read result.
	const VkBufferMemoryBarrier				bufferBarrier		=
	{
		VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,					// sType
		DE_NULL,													// pNext
		VK_ACCESS_SHADER_WRITE_BIT,									// srcAccessMask
		VK_ACCESS_HOST_READ_BIT,									// dstAccessMask
		VK_QUEUE_FAMILY_IGNORED,									// srcQueueFamilyIndex
		VK_QUEUE_FAMILY_IGNORED,									// destQueueFamilyIndex
		*buffer,													// buffer
		(VkDeviceSize)0u,											// offset
		(VkDeviceSize)VK_WHOLE_SIZE,								// size
	};

	// Record command buffer and submit it.
	VkCommandBufferBeginInfo				beginInfo			=
	{
		VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,	//	VkStructureType							sType;
		nullptr,										//	const void*								pNext;
		0u,												//	VkCommandBufferUsageFlags				flags;
		nullptr,										//	const VkCommandBufferInheritanceInfo*	pInheritanceInfo;
	};

	// Structures used in different test types.
	VkCommandBufferInheritanceInfo			inheritanceInfo;
	VkBufferCreateInfo						validNonsenseStructure;
	struct
	{
		VkStructureType	sType;
		void*			pNext;
	} invalidStructure;

	if (testCase == BadInheritanceInfoCase::RANDOM_PTR || testCase == BadInheritanceInfoCase::RANDOM_PTR_CONTINUATION)
	{
		de::Random						rnd		(1602600778u);
		VkCommandBufferInheritanceInfo*	info;
		auto							ptrData	= reinterpret_cast<deUint8*>(&info);

		// Fill pointer value with pseudorandom garbage.
		for (size_t i = 0; i < sizeof(info); ++i)
			*ptrData++ = rnd.getUint8();

		beginInfo.pInheritanceInfo = info;

		// Try to trick the implementation into reading pInheritanceInfo one more way.
		if (testCase == BadInheritanceInfoCase::RANDOM_PTR_CONTINUATION)
			beginInfo.flags |= VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT;

	}
	else if (testCase == BadInheritanceInfoCase::RANDOM_DATA_PTR)
	{
		de::Random		rnd	(1602601141u);
		auto			itr	= reinterpret_cast<deUint8*>(&inheritanceInfo);

		// Fill inheritance info data structure with random data.
		for (size_t i = 0; i < sizeof(inheritanceInfo); ++i)
			*itr++ = rnd.getUint8();

		beginInfo.pInheritanceInfo = &inheritanceInfo;
	}
	else if (testCase == BadInheritanceInfoCase::INVALID_STRUCTURE_TYPE)
	{
		de::Random	rnd			(1602658515u);
		auto		ptrData		= reinterpret_cast<deUint8*>(&(invalidStructure.pNext));
		invalidStructure.sType	= VK_STRUCTURE_TYPE_MAX_ENUM;

		// Fill pNext pointer with random data.
		for (size_t i = 0; i < sizeof(invalidStructure.pNext); ++i)
			*ptrData++ = rnd.getUint8();

		beginInfo.pInheritanceInfo = reinterpret_cast<VkCommandBufferInheritanceInfo*>(&invalidStructure);
	}
	else if (testCase == BadInheritanceInfoCase::VALID_NONSENSE_TYPE)
	{
		validNonsenseStructure.sType					= VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
		validNonsenseStructure.pNext					= nullptr;
		validNonsenseStructure.flags					= 0u;
		validNonsenseStructure.size						= 1024u;
		validNonsenseStructure.usage					= VK_BUFFER_USAGE_TRANSFER_DST_BIT;
		validNonsenseStructure.sharingMode				= VK_SHARING_MODE_EXCLUSIVE;
		validNonsenseStructure.queueFamilyIndexCount	= 0u;
		validNonsenseStructure.pQueueFamilyIndices		= nullptr;

		beginInfo.pInheritanceInfo						= reinterpret_cast<VkCommandBufferInheritanceInfo*>(&validNonsenseStructure);
	}
	else
	{
		DE_ASSERT(false);
	}

	VK_CHECK(vkd.beginCommandBuffer(cmdBuffer, &beginInfo));
	{
		vkd.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline);
		vkd.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0, numDescriptorSets, descriptorSets, 0, 0);
		vkd.cmdDispatch(cmdBuffer, 1u, 1u, 1u);
		vkd.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0,
							   0, (const VkMemoryBarrier*)DE_NULL,
							   1, &bufferBarrier,
							   0, (const VkImageMemoryBarrier*)DE_NULL);
	}
	endCommandBuffer(vkd, cmdBuffer);
	submitCommandsAndWait(vkd, device, queue, cmdBuffer);

	deUint32 resultCount;
	result.readResultContentsTo(&resultCount);

	// Make sure the command buffer was run.
	if (resultCount != 1u)
	{
		std::ostringstream msg;
		msg << "Invalid value found in results buffer (expected value 1u but found " << resultCount << ")";
		return tcu::TestStatus::fail(msg.str());
	}

	return tcu::TestStatus::pass("Pass");
}

tcu::TestStatus simultaneousUseSecondaryBufferTwoPrimaryBuffersTest(Context& context)
{
	const VkDevice							vkDevice = context.getDevice();
	const DeviceInterface&					vk = context.getDeviceInterface();
	const VkQueue							queue = context.getUniversalQueue();
	const deUint32							queueFamilyIndex = context.getUniversalQueueFamilyIndex();
	Allocator&								allocator = context.getDefaultAllocator();
	const ComputeInstanceResultBuffer		result(vk, vkDevice, allocator, 0.0f);

	const VkCommandPoolCreateInfo			cmdPoolParams =
	{
		VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,					//	VkStructureType				sType;
		DE_NULL,													//	const void*					pNext;
		VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,			//	VkCommandPoolCreateFlags	flags;
		queueFamilyIndex,											//	deUint32					queueFamilyIndex;
	};
	const Unique<VkCommandPool>				cmdPool(createCommandPool(vk, vkDevice, &cmdPoolParams));

	// Command buffer
	const VkCommandBufferAllocateInfo		cmdBufParams =
	{
		VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,				//	VkStructureType			sType;
		DE_NULL,													//	const void*				pNext;
		*cmdPool,													//	VkCommandPool				pool;
		VK_COMMAND_BUFFER_LEVEL_PRIMARY,							//	VkCommandBufferLevel		level;
		1u,															//	uint32_t					bufferCount;
	};
	// Two separate primary cmd buffers that will be executed with the same secondary cmd buffer
	const deUint32 numPrimCmdBufs = 2;
	const Unique<VkCommandBuffer>			primCmdBufOne(allocateCommandBuffer(vk, vkDevice, &cmdBufParams));
	const Unique<VkCommandBuffer>			primCmdBufTwo(allocateCommandBuffer(vk, vkDevice, &cmdBufParams));
	VkCommandBuffer primCmdBufs[numPrimCmdBufs];
	primCmdBufs[0] = primCmdBufOne.get();
	primCmdBufs[1] = primCmdBufTwo.get();

	// Secondary Command buffer params
	const VkCommandBufferAllocateInfo		secCmdBufParams =
	{
		VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,				//	VkStructureType			sType;
		DE_NULL,													//	const void*				pNext;
		*cmdPool,													//	VkCommandPool				pool;
		VK_COMMAND_BUFFER_LEVEL_SECONDARY,							//	VkCommandBufferLevel		level;
		1u,															//	uint32_t					bufferCount;
	};
	const Unique<VkCommandBuffer>			secCmdBuf(allocateCommandBuffer(vk, vkDevice, &secCmdBufParams));

	const VkCommandBufferBeginInfo			primCmdBufBeginInfo =
	{
		VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
		DE_NULL,
		0,															// flags
		(const VkCommandBufferInheritanceInfo*)DE_NULL,
	};

	const VkCommandBufferInheritanceInfo	secCmdBufInheritInfo =
	{
		VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO,
		DE_NULL,
		(VkRenderPass)0u,											// renderPass
		0u,															// subpass
		(VkFramebuffer)0u,											// framebuffer
		VK_FALSE,													// occlusionQueryEnable
		(VkQueryControlFlags)0u,									// queryFlags
		(VkQueryPipelineStatisticFlags)0u,							// pipelineStatistics
	};
	const VkCommandBufferBeginInfo			secCmdBufBeginInfo =
	{
		VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
		DE_NULL,
		VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT,				// flags
		&secCmdBufInheritInfo,
	};

	const deUint32							offset = (0u);
	const deUint32							addressableSize = 256;
	const deUint32							dataSize = 8;
	de::MovePtr<Allocation>					bufferMem;
	const Unique<VkBuffer>					buffer(createDataBuffer(context, offset, addressableSize, 0x00, dataSize, 0x5A, &bufferMem));
	// Secondary command buffer will have a compute shader that does an atomic increment to make sure that all instances of secondary buffers execute
	const Unique<VkDescriptorSetLayout>		descriptorSetLayout(createDescriptorSetLayout(context));
	const Unique<VkDescriptorPool>			descriptorPool(createDescriptorPool(context));
	const Unique<VkDescriptorSet>			descriptorSet(createDescriptorSet(context, *descriptorPool, *descriptorSetLayout, *buffer, offset, result.getBuffer()));
	const VkDescriptorSet					descriptorSets[] = { *descriptorSet };
	const int								numDescriptorSets = DE_LENGTH_OF_ARRAY(descriptorSets);

	const VkPipelineLayoutCreateInfo layoutCreateInfo =
	{
		VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,				// sType
		DE_NULL,													// pNext
		(VkPipelineLayoutCreateFlags)0,
		numDescriptorSets,											// setLayoutCount
		&descriptorSetLayout.get(),									// pSetLayouts
		0u,															// pushConstantRangeCount
		DE_NULL,													// pPushConstantRanges
	};
	Unique<VkPipelineLayout>				pipelineLayout(createPipelineLayout(vk, vkDevice, &layoutCreateInfo));

	const Unique<VkShaderModule>			computeModule(createShaderModule(vk, vkDevice, context.getBinaryCollection().get("compute_increment"), (VkShaderModuleCreateFlags)0u));

	const VkPipelineShaderStageCreateInfo	shaderCreateInfo =
	{
		VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
		DE_NULL,
		(VkPipelineShaderStageCreateFlags)0,
		VK_SHADER_STAGE_COMPUTE_BIT,								// stage
		*computeModule,												// shader
		"main",
		DE_NULL,													// pSpecializationInfo
	};

	const VkComputePipelineCreateInfo		pipelineCreateInfo =
	{
		VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
		DE_NULL,
		0u,															// flags
		shaderCreateInfo,											// cs
		*pipelineLayout,											// layout
		(vk::VkPipeline)0,											// basePipelineHandle
		0u,															// basePipelineIndex
	};

	const Unique<VkPipeline>				pipeline(createComputePipeline(vk, vkDevice, (VkPipelineCache)0u, &pipelineCreateInfo));

	// record secondary command buffer
	VK_CHECK(vk.beginCommandBuffer(*secCmdBuf, &secCmdBufBeginInfo));
	{
		vk.cmdBindPipeline(*secCmdBuf, VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline);
		vk.cmdBindDescriptorSets(*secCmdBuf, VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0, numDescriptorSets, descriptorSets, 0, 0);
		vk.cmdDispatch(*secCmdBuf, 1u, 1u, 1u);
	}
	// end recording of secondary buffer
	endCommandBuffer(vk, *secCmdBuf);

	// record primary command buffers
	// Insert one instance of same secondary command buffer into two separate primary command buffers
	VK_CHECK(vk.beginCommandBuffer(*primCmdBufOne, &primCmdBufBeginInfo));
	{
		vk.cmdExecuteCommands(*primCmdBufOne, 1, &secCmdBuf.get());
	}
	endCommandBuffer(vk, *primCmdBufOne);

	VK_CHECK(vk.beginCommandBuffer(*primCmdBufTwo, &primCmdBufBeginInfo));
	{
		vk.cmdExecuteCommands(*primCmdBufTwo, 1, &secCmdBuf.get());
	}
	endCommandBuffer(vk, *primCmdBufTwo);

	// create fence to wait for execution of queue
	const Unique<VkFence>					fence(createFence(vk, vkDevice));

	const VkSubmitInfo						submitInfo =
	{
		VK_STRUCTURE_TYPE_SUBMIT_INFO,								// sType
		DE_NULL,													// pNext
		0u,															// waitSemaphoreCount
		DE_NULL,													// pWaitSemaphores
		(const VkPipelineStageFlags*)DE_NULL,						// pWaitDstStageMask
		numPrimCmdBufs,												// commandBufferCount
		primCmdBufs,												// pCommandBuffers
		0u,															// signalSemaphoreCount
		DE_NULL,													// pSignalSemaphores
	};

	// submit primary buffers, the secondary should be executed too
	VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo, *fence));

	// wait for end of execution of queue
	VK_CHECK(vk.waitForFences(vkDevice, 1, &fence.get(), 0u, INFINITE_TIMEOUT));

	deUint32 resultCount;
	result.readResultContentsTo(&resultCount);
	// check if secondary buffer has been executed
	if (resultCount == 2)
		return tcu::TestStatus::pass("Simultaneous Secondary Command Buffer Execution succeeded");
	else
		return tcu::TestStatus::fail("Simultaneous Secondary Command Buffer Execution FAILED");
}

tcu::TestStatus recordBufferQueryPreciseWithFlagTest(Context& context)
{
	const VkDevice							vkDevice				= context.getDevice();
	const DeviceInterface&					vk						= context.getDeviceInterface();
	const deUint32							queueFamilyIndex		= context.getUniversalQueueFamilyIndex();

	if (!context.getDeviceFeatures().inheritedQueries)
		TCU_THROW(NotSupportedError, "Inherited queries feature is not supported");

	const VkCommandPoolCreateInfo			cmdPoolParams			=
	{
		VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,					// sType;
		DE_NULL,													// pNext;
		VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,			// flags;
		queueFamilyIndex,											// queueFamilyIndex;
	};
	const Unique<VkCommandPool>				cmdPool					(createCommandPool(vk, vkDevice, &cmdPoolParams));

	// Command buffer
	const VkCommandBufferAllocateInfo		primCmdBufParams		=
	{
		VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,				// sType;
		DE_NULL,													// pNext;
		*cmdPool,													// pool;
		VK_COMMAND_BUFFER_LEVEL_PRIMARY,							// level;
		1u,															// flags;
	};
	const Unique<VkCommandBuffer>			primCmdBuf				(allocateCommandBuffer(vk, vkDevice, &primCmdBufParams));

	// Secondary Command buffer params
	const VkCommandBufferAllocateInfo		secCmdBufParams			=
	{
		VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,				// sType;
		DE_NULL,													// pNext;
		*cmdPool,													// pool;
		VK_COMMAND_BUFFER_LEVEL_SECONDARY,							// level;
		1u,															// flags;
	};
	const Unique<VkCommandBuffer>			secCmdBuf				(allocateCommandBuffer(vk, vkDevice, &secCmdBufParams));

	const VkCommandBufferBeginInfo			primBufferBeginInfo		=
	{
		VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,				// sType
		DE_NULL,													// pNext
		0u,															// flags
		(const VkCommandBufferInheritanceInfo*)DE_NULL,
	};

	const VkCommandBufferInheritanceInfo	secBufferInheritInfo	=
	{
		VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO,
		DE_NULL,
		0u,															// renderPass
		0u,															// subpass
		0u,															// framebuffer
		VK_TRUE,													// occlusionQueryEnable
		VK_QUERY_CONTROL_PRECISE_BIT,								// queryFlags
		(VkQueryPipelineStatisticFlags)0u,							// pipelineStatistics
	};
	const VkCommandBufferBeginInfo			secBufferBeginInfo		=
	{
		VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,				// sType
		DE_NULL,													// pNext
		0u,															// flags
		&secBufferInheritInfo,
	};

	const VkQueryPoolCreateInfo				queryPoolCreateInfo		=
	{
		VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO,					// sType
		DE_NULL,													// pNext
		(VkQueryPoolCreateFlags)0,									// flags
		VK_QUERY_TYPE_OCCLUSION,									// queryType
		1u,															// entryCount
		0u,															// pipelineStatistics
	};
	Unique<VkQueryPool>						queryPool				(createQueryPool(vk, vkDevice, &queryPoolCreateInfo));

	VK_CHECK(vk.beginCommandBuffer(secCmdBuf.get(), &secBufferBeginInfo));
	endCommandBuffer(vk, secCmdBuf.get());

	VK_CHECK(vk.beginCommandBuffer(primCmdBuf.get(), &primBufferBeginInfo));
	{
		vk.cmdResetQueryPool(primCmdBuf.get(), queryPool.get(), 0u, 1u);
		vk.cmdBeginQuery(primCmdBuf.get(), queryPool.get(), 0u, VK_QUERY_CONTROL_PRECISE_BIT);
		{
			vk.cmdExecuteCommands(primCmdBuf.get(), 1u, &secCmdBuf.get());
		}
		vk.cmdEndQuery(primCmdBuf.get(), queryPool.get(), 0u);
	}
	endCommandBuffer(vk, primCmdBuf.get());

	return tcu::TestStatus::pass("Successfully recorded a secondary command buffer allowing a precise occlusion query.");
}

tcu::TestStatus recordBufferQueryImpreciseWithFlagTest(Context& context)
{
	const VkDevice							vkDevice				= context.getDevice();
	const DeviceInterface&					vk						= context.getDeviceInterface();
	const deUint32							queueFamilyIndex		= context.getUniversalQueueFamilyIndex();

	if (!context.getDeviceFeatures().inheritedQueries)
		TCU_THROW(NotSupportedError, "Inherited queries feature is not supported");

	const VkCommandPoolCreateInfo			cmdPoolParams			=
	{
		VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,					// sType;
		DE_NULL,													// pNext;
		VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,			// flags;
		queueFamilyIndex,											// queueFamilyIndex;
	};
	const Unique<VkCommandPool>				cmdPool					(createCommandPool(vk, vkDevice, &cmdPoolParams));

	// Command buffer
	const VkCommandBufferAllocateInfo		primCmdBufParams		=
	{
		VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,				// sType;
		DE_NULL,													// pNext;
		*cmdPool,													// pool;
		VK_COMMAND_BUFFER_LEVEL_PRIMARY,							// level;
		1u,															// flags;
	};
	const Unique<VkCommandBuffer>			primCmdBuf				(allocateCommandBuffer(vk, vkDevice, &primCmdBufParams));

	// Secondary Command buffer params
	const VkCommandBufferAllocateInfo		secCmdBufParams			=
	{
		VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,				// sType;
		DE_NULL,													// pNext;
		*cmdPool,													// pool;
		VK_COMMAND_BUFFER_LEVEL_SECONDARY,							// level;
		1u,															// flags;
	};
	const Unique<VkCommandBuffer>			secCmdBuf				(allocateCommandBuffer(vk, vkDevice, &secCmdBufParams));

	const VkCommandBufferBeginInfo			primBufferBeginInfo		=
	{
		VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,				// sType
		DE_NULL,													// pNext
		0u,															// flags
		(const VkCommandBufferInheritanceInfo*)DE_NULL,
	};

	const VkCommandBufferInheritanceInfo	secBufferInheritInfo	=
	{
		VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO,
		DE_NULL,
		0u,															// renderPass
		0u,															// subpass
		0u,															// framebuffer
		VK_TRUE,													// occlusionQueryEnable
		VK_QUERY_CONTROL_PRECISE_BIT,								// queryFlags
		(VkQueryPipelineStatisticFlags)0u,							// pipelineStatistics
	};
	const VkCommandBufferBeginInfo			secBufferBeginInfo		=
	{
		VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,				// sType
		DE_NULL,													// pNext
		0u,															// flags
		&secBufferInheritInfo,
	};

	const VkQueryPoolCreateInfo				queryPoolCreateInfo		=
	{
		VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO,					// sType
		DE_NULL,													// pNext
		0u,															// flags
		VK_QUERY_TYPE_OCCLUSION,									// queryType
		1u,															// entryCount
		0u,															// pipelineStatistics
	};
	Unique<VkQueryPool>						queryPool				(createQueryPool(vk, vkDevice, &queryPoolCreateInfo));

	VK_CHECK(vk.beginCommandBuffer(secCmdBuf.get(), &secBufferBeginInfo));
	endCommandBuffer(vk, secCmdBuf.get());

	VK_CHECK(vk.beginCommandBuffer(primCmdBuf.get(), &primBufferBeginInfo));
	{
		vk.cmdResetQueryPool(primCmdBuf.get(), queryPool.get(), 0u, 1u);
		vk.cmdBeginQuery(primCmdBuf.get(), queryPool.get(), 0u, 0u);
		{
			vk.cmdExecuteCommands(primCmdBuf.get(), 1u, &secCmdBuf.get());
		}
		vk.cmdEndQuery(primCmdBuf.get(), queryPool.get(), 0u);
	}
	endCommandBuffer(vk, primCmdBuf.get());

	return tcu::TestStatus::pass("Successfully recorded an imprecise query with a secondary command buffer allowing a precise occlusion query.");
}

tcu::TestStatus recordBufferQueryImpreciseWithoutFlagTest(Context& context)
{
	const VkDevice							vkDevice				= context.getDevice();
	const DeviceInterface&					vk						= context.getDeviceInterface();
	const deUint32							queueFamilyIndex		= context.getUniversalQueueFamilyIndex();

	if (!context.getDeviceFeatures().inheritedQueries)
		TCU_THROW(NotSupportedError, "Inherited queries feature is not supported");

	const VkCommandPoolCreateInfo			cmdPoolParams			=
	{
		VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,					// sType;
		DE_NULL,													// pNext;
		VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,			// flags;
		queueFamilyIndex,											// queueFamilyIndex;
	};
	const Unique<VkCommandPool>				cmdPool					(createCommandPool(vk, vkDevice, &cmdPoolParams));

	// Command buffer
	const VkCommandBufferAllocateInfo		primCmdBufParams		=
	{
		VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,				// sType;
		DE_NULL,													// pNext;
		*cmdPool,													// pool;
		VK_COMMAND_BUFFER_LEVEL_PRIMARY,							// level;
		1u,															// flags;
	};
	const Unique<VkCommandBuffer>			primCmdBuf				(allocateCommandBuffer(vk, vkDevice, &primCmdBufParams));

	// Secondary Command buffer params
	const VkCommandBufferAllocateInfo		secCmdBufParams			=
	{
		VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,				// sType;
		DE_NULL,													// pNext;
		*cmdPool,													// pool;
		VK_COMMAND_BUFFER_LEVEL_SECONDARY,							// level;
		1u,															// flags;
	};
	const Unique<VkCommandBuffer>			secCmdBuf				(allocateCommandBuffer(vk, vkDevice, &secCmdBufParams));

	const VkCommandBufferBeginInfo			primBufferBeginInfo		=
	{
		VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,				// sType
		DE_NULL,													// pNext
		0u,															// flags
		(const VkCommandBufferInheritanceInfo*)DE_NULL,
	};

	const VkCommandBufferInheritanceInfo	secBufferInheritInfo	=
	{
		VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO,
		DE_NULL,
		0u,															// renderPass
		0u,															// subpass
		0u,															// framebuffer
		VK_TRUE,													// occlusionQueryEnable
		0u,															// queryFlags
		(VkQueryPipelineStatisticFlags)0u,							// pipelineStatistics
	};
	const VkCommandBufferBeginInfo			secBufferBeginInfo		=
	{
		VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,				// sType
		DE_NULL,													// pNext
		0u,															// flags
		&secBufferInheritInfo,
	};

	const VkQueryPoolCreateInfo				queryPoolCreateInfo		=
	{
		VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO,					// sType
		DE_NULL,													// pNext
		(VkQueryPoolCreateFlags)0,
		VK_QUERY_TYPE_OCCLUSION,
		1u,
		0u,
	};
	Unique<VkQueryPool>						queryPool				(createQueryPool(vk, vkDevice, &queryPoolCreateInfo));

	VK_CHECK(vk.beginCommandBuffer(secCmdBuf.get(), &secBufferBeginInfo));
	endCommandBuffer(vk, secCmdBuf.get());

	VK_CHECK(vk.beginCommandBuffer(primCmdBuf.get(), &primBufferBeginInfo));
	{
		vk.cmdResetQueryPool(primCmdBuf.get(), queryPool.get(), 0u, 1u);
		vk.cmdBeginQuery(primCmdBuf.get(), queryPool.get(), 0u, 0u);
		{
			vk.cmdExecuteCommands(primCmdBuf.get(), 1u, &secCmdBuf.get());
		}
		vk.cmdEndQuery(primCmdBuf.get(), queryPool.get(), 0u);
	}
	endCommandBuffer(vk, primCmdBuf.get());

	return tcu::TestStatus::pass("Successfully recorded an imprecise query with a secondary command buffer not allowing a precise occlusion query.");
}

/******** 19.4. Command Buffer Submission (5.4 in VK 1.0 Spec) ****************/
tcu::TestStatus submitBufferCountNonZero(Context& context)
{
	const VkDevice							vkDevice				= context.getDevice();
	const DeviceInterface&					vk						= context.getDeviceInterface();
	const VkQueue							queue					= context.getUniversalQueue();
	const deUint32							queueFamilyIndex		= context.getUniversalQueueFamilyIndex();

	const deUint32							BUFFER_COUNT			= 5u;

	const VkCommandPoolCreateInfo			cmdPoolParams			=
	{
		VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,					// sType;
		DE_NULL,													// pNext;
		0u,															// flags;
		queueFamilyIndex,											// queueFamilyIndex;
	};
	const Unique<VkCommandPool>				cmdPool					(createCommandPool(vk, vkDevice, &cmdPoolParams));

	// Command buffer
	const VkCommandBufferAllocateInfo		cmdBufParams			=
	{
		VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,				// sType;
		DE_NULL,													// pNext;
		*cmdPool,													// pool;
		VK_COMMAND_BUFFER_LEVEL_PRIMARY,							// level;
		BUFFER_COUNT,												// bufferCount;
	};
	VkCommandBuffer cmdBuffers[BUFFER_COUNT];
	VK_CHECK(vk.allocateCommandBuffers(vkDevice, &cmdBufParams, cmdBuffers));

	const VkCommandBufferBeginInfo			cmdBufBeginInfo			=
	{
		VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,				// sType
		DE_NULL,													// pNext
		0u,															// flags
		(const VkCommandBufferInheritanceInfo*)DE_NULL,
	};

	std::vector<VkEventSp>					events;
	for (deUint32 ndx = 0; ndx < BUFFER_COUNT; ++ndx)
	{
		events.push_back(VkEventSp(new vk::Unique<VkEvent>(createEvent(vk, vkDevice))));
	}

	// Record the command buffers
	for (deUint32 ndx = 0; ndx < BUFFER_COUNT; ++ndx)
	{
		VK_CHECK(vk.beginCommandBuffer(cmdBuffers[ndx], &cmdBufBeginInfo));
		{
			vk.cmdSetEvent(cmdBuffers[ndx], events[ndx]->get(), VK_PIPELINE_STAGE_ALL_COMMANDS_BIT);
		}
		endCommandBuffer(vk, cmdBuffers[ndx]);
	}

	// We'll use a fence to wait for the execution of the queue
	const Unique<VkFence>					fence					(createFence(vk, vkDevice));

	const VkSubmitInfo						submitInfo				=
	{
		VK_STRUCTURE_TYPE_SUBMIT_INFO,								// sType
		DE_NULL,													// pNext
		0u,															// waitSemaphoreCount
		DE_NULL,													// pWaitSemaphores
		(const VkPipelineStageFlags*)DE_NULL,						// pWaitDstStageMask
		BUFFER_COUNT,												// commandBufferCount
		cmdBuffers,													// pCommandBuffers
		0u,															// signalSemaphoreCount
		DE_NULL,													// pSignalSemaphores
	};

	// Submit the alpha command buffer to the queue
	VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo, fence.get()));
	// Wait for the queue
	VK_CHECK(vk.waitForFences(vkDevice, 1u, &fence.get(), VK_TRUE, INFINITE_TIMEOUT));

	// Check if the buffers were executed
	tcu::TestStatus testResult = tcu::TestStatus::incomplete();

	for (deUint32 ndx = 0; ndx < BUFFER_COUNT; ++ndx)
	{
		if (vk.getEventStatus(vkDevice, events[ndx]->get()) != VK_EVENT_SET)
		{
			testResult = tcu::TestStatus::fail("Failed to set the event.");
			break;
		}
	}

	if (!testResult.isComplete())
		testResult = tcu::TestStatus::pass("All buffers were submitted and executed correctly.");

	return testResult;
}

tcu::TestStatus submitBufferCountEqualZero(Context& context)
{
	const VkDevice							vkDevice				= context.getDevice();
	const DeviceInterface&					vk						= context.getDeviceInterface();
	const VkQueue							queue					= context.getUniversalQueue();
	const deUint32							queueFamilyIndex		= context.getUniversalQueueFamilyIndex();

	const deUint32							BUFFER_COUNT			= 2u;

	const VkCommandPoolCreateInfo			cmdPoolParams			=
	{
		VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,					// sType;
		DE_NULL,													// pNext;
		0u,															// flags;
		queueFamilyIndex,											// queueFamilyIndex;
	};
	const Unique<VkCommandPool>				cmdPool					(createCommandPool(vk, vkDevice, &cmdPoolParams));

	// Command buffer
	const VkCommandBufferAllocateInfo		cmdBufParams			=
	{
		VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,				// sType;
		DE_NULL,													// pNext;
		*cmdPool,													// pool;
		VK_COMMAND_BUFFER_LEVEL_PRIMARY,							// level;
		BUFFER_COUNT,												// bufferCount;
	};
	VkCommandBuffer cmdBuffers[BUFFER_COUNT];
	VK_CHECK(vk.allocateCommandBuffers(vkDevice, &cmdBufParams, cmdBuffers));

	const VkCommandBufferBeginInfo			cmdBufBeginInfo			=
	{
		VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,				// sType
		DE_NULL,													// pNext
		0u,															// flags
		(const VkCommandBufferInheritanceInfo*)DE_NULL,
	};

	std::vector<VkEventSp>					events;
	for (deUint32 ndx = 0; ndx < BUFFER_COUNT; ++ndx)
		events.push_back(VkEventSp(new vk::Unique<VkEvent>(createEvent(vk, vkDevice))));

	// Record the command buffers
	for (deUint32 ndx = 0; ndx < BUFFER_COUNT; ++ndx)
	{
		VK_CHECK(vk.beginCommandBuffer(cmdBuffers[ndx], &cmdBufBeginInfo));
		{
			vk.cmdSetEvent(cmdBuffers[ndx], events[ndx]->get(), VK_PIPELINE_STAGE_ALL_COMMANDS_BIT);
		}
		endCommandBuffer(vk, cmdBuffers[ndx]);
	}

	// We'll use a fence to wait for the execution of the queue
	const Unique<VkFence>					fenceZero				(createFence(vk, vkDevice));
	const Unique<VkFence>					fenceOne				(createFence(vk, vkDevice));

	const VkSubmitInfo						submitInfoCountZero		=
	{
		VK_STRUCTURE_TYPE_SUBMIT_INFO,								// sType
		DE_NULL,													// pNext
		0u,															// waitSemaphoreCount
		DE_NULL,													// pWaitSemaphores
		(const VkPipelineStageFlags*)DE_NULL,						// pWaitDstStageMask
		1u,															// commandBufferCount
		&cmdBuffers[0],												// pCommandBuffers
		0u,															// signalSemaphoreCount
		DE_NULL,													// pSignalSemaphores
	};

	const VkSubmitInfo						submitInfoCountOne		=
	{
		VK_STRUCTURE_TYPE_SUBMIT_INFO,								// sType
		DE_NULL,													// pNext
		0u,															// waitSemaphoreCount
		DE_NULL,													// pWaitSemaphores
		(const VkPipelineStageFlags*)DE_NULL,						// pWaitDstStageMask
		1u,															// commandBufferCount
		&cmdBuffers[1],												// pCommandBuffers
		0u,															// signalSemaphoreCount
		DE_NULL,													// pSignalSemaphores
	};

	// Submit the command buffers to the queue
	// We're performing two submits to make sure that the first one has
	// a chance to be processed before we check the event's status
	VK_CHECK(vk.queueSubmit(queue, 0, &submitInfoCountZero, fenceZero.get()));
	VK_CHECK(vk.queueSubmit(queue, 1, &submitInfoCountOne, fenceOne.get()));

	const VkFence							fences[]				=
	{
		fenceZero.get(),
		fenceOne.get(),
	};

	// Wait for the queue
	VK_CHECK(vk.waitForFences(vkDevice, (deUint32)DE_LENGTH_OF_ARRAY(fences), fences, VK_TRUE, INFINITE_TIMEOUT));

	// Check if the first buffer was executed
	tcu::TestStatus testResult = tcu::TestStatus::incomplete();

	if (vk.getEventStatus(vkDevice, events[0]->get()) == VK_EVENT_SET)
		testResult = tcu::TestStatus::fail("The first event was signaled.");
	else
		testResult = tcu::TestStatus::pass("The first submission was ignored.");

	return testResult;
}

tcu::TestStatus submitBufferWaitSingleSemaphore(Context& context)
{
	const VkDevice							vkDevice				= context.getDevice();
	const DeviceInterface&					vk						= context.getDeviceInterface();
	const VkQueue							queue					= context.getUniversalQueue();
	const deUint32							queueFamilyIndex		= context.getUniversalQueueFamilyIndex();

	const VkCommandPoolCreateInfo			cmdPoolParams			=
	{
		VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,					// VkStructureType				sType;
		DE_NULL,													// const void*					pNext;
		VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,			// VkCommandPoolCreateFlags		flags;
		queueFamilyIndex,											// deUint32						queueFamilyIndex;
	};
	const Unique<VkCommandPool>				cmdPool					(createCommandPool(vk, vkDevice, &cmdPoolParams));

	// Command buffer
	const VkCommandBufferAllocateInfo		cmdBufParams			=
	{
		VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,				// VkStructureType				sType;
		DE_NULL,													// const void*					pNext;
		*cmdPool,													// VkCommandPool				pool;
		VK_COMMAND_BUFFER_LEVEL_PRIMARY,							// VkCommandBufferLevel			level;
		1u,															// uint32_t						bufferCount;
	};

	// Create two command buffers
	const Unique<VkCommandBuffer>			primCmdBuf1				(allocateCommandBuffer(vk, vkDevice, &cmdBufParams));
	const Unique<VkCommandBuffer>			primCmdBuf2				(allocateCommandBuffer(vk, vkDevice, &cmdBufParams));

	const VkCommandBufferBeginInfo			primCmdBufBeginInfo		=
	{
		VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,				// sType
		DE_NULL,													// pNext
		0,															// flags
		DE_NULL														// const VkCommandBufferInheritanceInfo*	pInheritanceInfo;
	};

	// create two events that will be used to check if command buffers has been executed
	const Unique<VkEvent>					event1					(createEvent(vk, vkDevice));
	const Unique<VkEvent>					event2					(createEvent(vk, vkDevice));

	// reset events
	VK_CHECK(vk.resetEvent(vkDevice, *event1));
	VK_CHECK(vk.resetEvent(vkDevice, *event2));

	// record first command buffer
	VK_CHECK(vk.beginCommandBuffer(*primCmdBuf1, &primCmdBufBeginInfo));
	{
		// allow execution of event during every stage of pipeline
		VkPipelineStageFlags stageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;

		// record setting event
		vk.cmdSetEvent(*primCmdBuf1, *event1,stageMask);
	}
	endCommandBuffer(vk, *primCmdBuf1);

	// record second command buffer
	VK_CHECK(vk.beginCommandBuffer(*primCmdBuf2, &primCmdBufBeginInfo));
	{
		// allow execution of event during every stage of pipeline
		VkPipelineStageFlags stageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;

		// record setting event
		vk.cmdSetEvent(*primCmdBuf2, *event2,stageMask);
	}
	endCommandBuffer(vk, *primCmdBuf2);

	// create fence to wait for execution of queue
	const Unique<VkFence>					fence					(createFence(vk, vkDevice));

	// create semaphore for use in this test
	const Unique <VkSemaphore>				semaphore				(createSemaphore(vk, vkDevice));

	// create submit info for first buffer - signalling semaphore
	const VkSubmitInfo						submitInfo1				=
	{
		VK_STRUCTURE_TYPE_SUBMIT_INFO,								// sType
		DE_NULL,													// pNext
		0u,															// waitSemaphoreCount
		DE_NULL,													// pWaitSemaphores
		DE_NULL,													// pWaitDstStageMask
		1,															// commandBufferCount
		&primCmdBuf1.get(),											// pCommandBuffers
		1u,															// signalSemaphoreCount
		&semaphore.get(),											// pSignalSemaphores
	};

	// Submit the command buffer to the queue
	VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo1, *fence));

	// wait for end of execution of queue
	VK_CHECK(vk.waitForFences(vkDevice, 1, &fence.get(), 0u, INFINITE_TIMEOUT));

	// check if buffer has been executed
	VkResult result = vk.getEventStatus(vkDevice,*event1);
	if (result != VK_EVENT_SET)
		return tcu::TestStatus::fail("Submit Buffer and Wait for Single Semaphore Test FAILED");

	const VkPipelineStageFlags				waitDstStageFlags		= VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;

	// create submit info for second buffer - waiting for semaphore
	const VkSubmitInfo						submitInfo2				=
	{
		VK_STRUCTURE_TYPE_SUBMIT_INFO,								// sType
		DE_NULL,													// pNext
		1u,															// waitSemaphoreCount
		&semaphore.get(),											// pWaitSemaphores
		&waitDstStageFlags,											// pWaitDstStageMask
		1,															// commandBufferCount
		&primCmdBuf2.get(),											// pCommandBuffers
		0u,															// signalSemaphoreCount
		DE_NULL,													// pSignalSemaphores
	};

	// reset fence, so it can be used again
	VK_CHECK(vk.resetFences(vkDevice, 1u, &fence.get()));

	// Submit the second command buffer to the queue
	VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo2, *fence));

	// wait for end of execution of queue
	VK_CHECK(vk.waitForFences(vkDevice, 1, &fence.get(), 0u, INFINITE_TIMEOUT));

	// check if second buffer has been executed
	// if it has been executed, it means that the semaphore was signalled - so test if passed
	result = vk.getEventStatus(vkDevice,*event1);
	if (result != VK_EVENT_SET)
		return tcu::TestStatus::fail("Submit Buffer and Wait for Single Semaphore Test FAILED");

	return tcu::TestStatus::pass("Submit Buffer and Wait for Single Semaphore Test succeeded");
}

tcu::TestStatus submitBufferWaitManySemaphores(Context& context)
{
	// This test will create numSemaphores semaphores, and signal them in NUM_SEMAPHORES submits to queue
	// After that the numSubmissions queue submissions will wait for each semaphore

	const deUint32							numSemaphores			= 10u;  // it must be multiply of numSubmission
	const deUint32							numSubmissions			= 2u;
	const VkDevice							vkDevice				= context.getDevice();
	const DeviceInterface&					vk						= context.getDeviceInterface();
	const VkQueue							queue					= context.getUniversalQueue();
	const deUint32							queueFamilyIndex		= context.getUniversalQueueFamilyIndex();

	const VkCommandPoolCreateInfo			cmdPoolParams			=
	{
		VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,					// VkStructureType				sType;
		DE_NULL,													// const void*					pNext;
		VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,			// VkCommandPoolCreateFlags		flags;
		queueFamilyIndex,											// deUint32						queueFamilyIndex;
	};
	const Unique<VkCommandPool>				cmdPool					(createCommandPool(vk, vkDevice, &cmdPoolParams));

	// Command buffer
	const VkCommandBufferAllocateInfo		cmdBufParams			=
	{
		VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,				// VkStructureType				sType;
		DE_NULL,													// const void*					pNext;
		*cmdPool,													// VkCommandPool				pool;
		VK_COMMAND_BUFFER_LEVEL_PRIMARY,							// VkCommandBufferLevel			level;
		1u,															// uint32_t						bufferCount;
	};

	// Create command buffer
	const Unique<VkCommandBuffer>			primCmdBuf				(allocateCommandBuffer(vk, vkDevice, &cmdBufParams));

	const VkCommandBufferBeginInfo			primCmdBufBeginInfo		=
	{
		VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,				// sType
		DE_NULL,													// pNext
		0,															// flags
		DE_NULL														// const VkCommandBufferInheritanceInfo*	pInheritanceInfo;
	};

	// create event that will be used to check if command buffers has been executed
	const Unique<VkEvent>					event					(createEvent(vk, vkDevice));

	// reset event - at creation state is undefined
	VK_CHECK(vk.resetEvent(vkDevice, *event));

	// record command buffer
	VK_CHECK(vk.beginCommandBuffer(*primCmdBuf, &primCmdBufBeginInfo));
	{
		// allow execution of event during every stage of pipeline
		VkPipelineStageFlags stageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;

		// record setting event
		vk.cmdSetEvent(*primCmdBuf, *event,stageMask);
	}
	endCommandBuffer(vk, *primCmdBuf);

	// create fence to wait for execution of queue
	const Unique<VkFence>					fence					(createFence(vk, vkDevice));

	// numSemaphores is declared const, so this array can be static
	// the semaphores will be destroyed automatically at end of scope
	Move <VkSemaphore>						semaphoreArray[numSemaphores];
	VkSemaphore								semaphores[numSemaphores];

	for (deUint32 idx = 0; idx < numSemaphores; ++idx) {
		// create semaphores for use in this test
		semaphoreArray[idx] = createSemaphore(vk, vkDevice);
		semaphores[idx] = semaphoreArray[idx].get();
	}

	{
		// create submit info for buffer - signal semaphores
		const VkSubmitInfo submitInfo1 =
		{
			VK_STRUCTURE_TYPE_SUBMIT_INFO,							// sType
			DE_NULL,												// pNext
			0u,														// waitSemaphoreCount
			DE_NULL,												// pWaitSemaphores
			DE_NULL,												// pWaitDstStageMask
			1,														// commandBufferCount
			&primCmdBuf.get(),										// pCommandBuffers
			numSemaphores,											// signalSemaphoreCount
			semaphores												// pSignalSemaphores
		};
		// Submit the command buffer to the queue
		VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo1, *fence));

		// wait for end of execution of queue
		VK_CHECK(vk.waitForFences(vkDevice, 1, &fence.get(), 0u, INFINITE_TIMEOUT));

		// check if buffer has been executed
		VkResult result = vk.getEventStatus(vkDevice,*event);
		if (result != VK_EVENT_SET)
			return tcu::TestStatus::fail("Submit Buffer and Wait for Many Semaphores Test FAILED");

		// reset event, so next buffers can set it again
		VK_CHECK(vk.resetEvent(vkDevice, *event));

		// reset fence, so it can be used again
		VK_CHECK(vk.resetFences(vkDevice, 1u, &fence.get()));
	}

	const deUint32							numberOfSemaphoresToBeWaitedByOneSubmission	= numSemaphores / numSubmissions;
	const std::vector<VkPipelineStageFlags>	waitDstStageFlags							(numberOfSemaphoresToBeWaitedByOneSubmission, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT);

	// the following code waits for the semaphores set above - numSubmissions queues will wait for each semaphore from above
	for (deUint32 idxSubmission = 0; idxSubmission < numSubmissions; ++idxSubmission) {

		// create submit info for buffer - waiting for semaphore
		const VkSubmitInfo				submitInfo2				=
		{
			VK_STRUCTURE_TYPE_SUBMIT_INFO,												// sType
			DE_NULL,																	// pNext
			numberOfSemaphoresToBeWaitedByOneSubmission,								// waitSemaphoreCount
			semaphores + (numberOfSemaphoresToBeWaitedByOneSubmission * idxSubmission),	// pWaitSemaphores
			waitDstStageFlags.data(),													// pWaitDstStageMask
			1,																			// commandBufferCount
			&primCmdBuf.get(),															// pCommandBuffers
			0u,																			// signalSemaphoreCount
			DE_NULL,																	// pSignalSemaphores
		};

		// Submit the second command buffer to the queue
		VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo2, *fence));

		// wait for 1 second.
		VK_CHECK(vk.waitForFences(vkDevice, 1, &fence.get(), 0u, 1000 * 1000 * 1000));

		// check if second buffer has been executed
		// if it has been executed, it means that the semaphore was signalled - so test if passed
		VkResult result = vk.getEventStatus(vkDevice,*event);
		if (result != VK_EVENT_SET)
			return tcu::TestStatus::fail("Submit Buffer and Wait for Many Semaphores Test FAILED");

		// reset fence, so it can be used again
		VK_CHECK(vk.resetFences(vkDevice, 1u, &fence.get()));

		// reset event, so next buffers can set it again
		VK_CHECK(vk.resetEvent(vkDevice, *event));
	}

	return tcu::TestStatus::pass("Submit Buffer and Wait for Many Semaphores Test succeeded");
}

tcu::TestStatus submitBufferNullFence(Context& context)
{
	const VkDevice							vkDevice				= context.getDevice();
	const DeviceInterface&					vk						= context.getDeviceInterface();
	const VkQueue							queue					= context.getUniversalQueue();
	const deUint32							queueFamilyIndex		= context.getUniversalQueueFamilyIndex();

	const short								BUFFER_COUNT			= 2;

	const VkCommandPoolCreateInfo			cmdPoolParams			=
	{
		VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,					// sType;
		DE_NULL,													// pNext;
		0u,															// flags;
		queueFamilyIndex,											// queueFamilyIndex;
	};
	const Unique<VkCommandPool>				cmdPool					(createCommandPool(vk, vkDevice, &cmdPoolParams));

	// Command buffer
	const VkCommandBufferAllocateInfo		cmdBufParams			=
	{
		VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,				// sType;
		DE_NULL,													// pNext;
		*cmdPool,													// pool;
		VK_COMMAND_BUFFER_LEVEL_PRIMARY,							// level;
		1u,															// bufferCount;
	};
	VkCommandBuffer cmdBuffers[BUFFER_COUNT];
	for (deUint32 ndx = 0; ndx < BUFFER_COUNT; ++ndx)
		VK_CHECK(vk.allocateCommandBuffers(vkDevice, &cmdBufParams, &cmdBuffers[ndx]));

	const VkCommandBufferBeginInfo			cmdBufBeginInfo			=
	{
		VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,				// sType
		DE_NULL,													// pNext
		0u,															// flags
		(const VkCommandBufferInheritanceInfo*)DE_NULL,
	};

	std::vector<VkEventSp>					events;
	for (deUint32 ndx = 0; ndx < BUFFER_COUNT; ++ndx)
		events.push_back(VkEventSp(new vk::Unique<VkEvent>(createEvent(vk, vkDevice))));

	// Record the command buffers
	for (deUint32 ndx = 0; ndx < BUFFER_COUNT; ++ndx)
	{
		VK_CHECK(vk.beginCommandBuffer(cmdBuffers[ndx], &cmdBufBeginInfo));
		{
			vk.cmdSetEvent(cmdBuffers[ndx], events[ndx]->get(), VK_PIPELINE_STAGE_ALL_COMMANDS_BIT);
		}
		endCommandBuffer(vk, cmdBuffers[ndx]);
	}

	// We'll use a fence to wait for the execution of the queue
	const Unique<VkFence>					fence					(createFence(vk, vkDevice));

	const VkSubmitInfo						submitInfoNullFence		=
	{
		VK_STRUCTURE_TYPE_SUBMIT_INFO,								// sType
		DE_NULL,													// pNext
		0u,															// waitSemaphoreCount
		DE_NULL,													// pWaitSemaphores
		(const VkPipelineStageFlags*)DE_NULL,						// pWaitDstStageMask
		1u,															// commandBufferCount
		&cmdBuffers[0],												// pCommandBuffers
		0u,															// signalSemaphoreCount
		DE_NULL,													// pSignalSemaphores
	};

	const VkSubmitInfo						submitInfoNonNullFence	=
	{
		VK_STRUCTURE_TYPE_SUBMIT_INFO,								// sType
		DE_NULL,													// pNext
		0u,															// waitSemaphoreCount
		DE_NULL,													// pWaitSemaphores
		(const VkPipelineStageFlags*)DE_NULL,						// pWaitDstStageMask
		1u,															// commandBufferCount
		&cmdBuffers[1],												// pCommandBuffers
		0u,															// signalSemaphoreCount
		DE_NULL,													// pSignalSemaphores
	};

	// Perform two submissions - one with no fence, the other one with a valid
	// fence Hoping submitting the other buffer will give the first one time to
	// execute
	VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfoNullFence, DE_NULL));
	VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfoNonNullFence, fence.get()));

	// Wait for the queue
	VK_CHECK(vk.waitForFences(vkDevice, 1u, &fence.get(), VK_TRUE, INFINITE_TIMEOUT));


	tcu::TestStatus testResult = tcu::TestStatus::incomplete();

	//Fence guaranteed that all buffers submited before fence were executed
	if (vk.getEventStatus(vkDevice, events[0]->get()) != VK_EVENT_SET || vk.getEventStatus(vkDevice, events[1]->get()) != VK_EVENT_SET)
	{
		testResult = tcu::TestStatus::fail("One of the buffers was not executed.");
	}
	else
	{
		testResult = tcu::TestStatus::pass("Buffers have been submitted and executed correctly.");
	}

	vk.queueWaitIdle(queue);
	return testResult;
}

tcu::TestStatus submitTwoBuffersOneBufferNullWithFence(Context& context)
{
	const VkDevice							vkDevice				= context.getDevice();
	const DeviceInterface&					vk						= context.getDeviceInterface();
	const VkQueue							queue					= context.getUniversalQueue();
	const deUint32							queueFamilyIndex		= context.getUniversalQueueFamilyIndex();
	const deUint32							BUFFER_COUNT			= 2u;

	const VkCommandPoolCreateInfo			cmdPoolParams			=
	{
		VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,			// sType;
		DE_NULL,											// pNext;
		VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,	// flags;
		queueFamilyIndex,									// queueFamilyIndex;
	};
	const Unique<VkCommandPool>				cmdPool					(createCommandPool(vk, vkDevice, &cmdPoolParams));

	const VkCommandBufferAllocateInfo		cmdBufParams			=
	{
		VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,	// sType;
		DE_NULL,										// pNext;
		*cmdPool,										// pool;
		VK_COMMAND_BUFFER_LEVEL_PRIMARY,				// level;
		BUFFER_COUNT,									// bufferCount;
	};

	VkCommandBuffer							cmdBuffers[BUFFER_COUNT];
	VK_CHECK(vk.allocateCommandBuffers(vkDevice, &cmdBufParams, cmdBuffers));

	const VkCommandBufferBeginInfo			cmdBufBeginInfo			=
	{
		VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,	// sType
		DE_NULL,										// pNext
		0u,												// flags
		(const VkCommandBufferInheritanceInfo*)DE_NULL,	// pInheritanceInfo
	};

	std::vector<VkEventSp>					events;
	for (deUint32 ndx = 0; ndx < BUFFER_COUNT; ++ndx)
		events.push_back(VkEventSp(new vk::Unique<VkEvent>(createEvent(vk, vkDevice))));

	// Record the command buffers
	for (deUint32 ndx = 0; ndx < BUFFER_COUNT; ++ndx)
	{
		VK_CHECK(vk.beginCommandBuffer(cmdBuffers[ndx], &cmdBufBeginInfo));
		{
			vk.cmdSetEvent(cmdBuffers[ndx], events[ndx]->get(), VK_PIPELINE_STAGE_ALL_COMMANDS_BIT);
		}
		VK_CHECK(vk.endCommandBuffer(cmdBuffers[ndx]));
	}

	// First command buffer
	const VkSubmitInfo						submitInfoNonNullFirst	=
	{
		VK_STRUCTURE_TYPE_SUBMIT_INFO,				// sType
		DE_NULL,									// pNext
		0u,											// waitSemaphoreCount
		DE_NULL,									// pWaitSemaphores
		(const VkPipelineStageFlags*)DE_NULL,		// pWaitDstStageMask
		1u,											// commandBufferCount
		&cmdBuffers[0],								// pCommandBuffers
		0u,											// signalSemaphoreCount
		DE_NULL,									// pSignalSemaphores
	};

	// Second command buffer
	const VkSubmitInfo						submitInfoNonNullSecond	=
	{
		VK_STRUCTURE_TYPE_SUBMIT_INFO,				// sType
		DE_NULL,									// pNext
		0u,											// waitSemaphoreCount
		DE_NULL,									// pWaitSemaphores
		(const VkPipelineStageFlags*)DE_NULL,		// pWaitDstStageMask
		1u,											// commandBufferCount
		&cmdBuffers[1],								// pCommandBuffers
		0u,											// signalSemaphoreCount
		DE_NULL,									// pSignalSemaphores
	};

	// Fence will be submitted with the null queue
	const Unique<VkFence>					fence					(createFence(vk, vkDevice));

	// Perform two separate queueSubmit calls on the same queue followed
	// by a third call with no submitInfos and with a valid fence
	VK_CHECK(vk.queueSubmit(queue,	1u,	&submitInfoNonNullFirst,	DE_NULL));
	VK_CHECK(vk.queueSubmit(queue,	1u,	&submitInfoNonNullSecond,	DE_NULL));
	VK_CHECK(vk.queueSubmit(queue,	0u,	DE_NULL,					fence.get()));

	// Wait for the queue
	VK_CHECK(vk.waitForFences(vkDevice, 1u, &fence.get(), VK_TRUE, INFINITE_TIMEOUT));

	return tcu::TestStatus::pass("Buffers have been submitted correctly");
}

/******** 19.5. Secondary Command Buffer Execution (5.6 in VK 1.0 Spec) *******/
tcu::TestStatus executeSecondaryBufferTest(Context& context)
{
	const VkDevice							vkDevice				= context.getDevice();
	const DeviceInterface&					vk						= context.getDeviceInterface();
	const VkQueue							queue					= context.getUniversalQueue();
	const deUint32							queueFamilyIndex		= context.getUniversalQueueFamilyIndex();

	const VkCommandPoolCreateInfo			cmdPoolParams			=
	{
		VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,					// sType;
		DE_NULL,													// pNext;
		VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,			// flags;
		queueFamilyIndex,											// queueFamilyIndex;
	};
	const Unique<VkCommandPool>				cmdPool					(createCommandPool(vk, vkDevice, &cmdPoolParams));

	// Command buffer
	const VkCommandBufferAllocateInfo		cmdBufParams			=
	{
		VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,				// sType;
		DE_NULL,													// pNext;
		*cmdPool,													// commandPool;
		VK_COMMAND_BUFFER_LEVEL_PRIMARY,							// level;
		1u,															// bufferCount;
	};
	const Unique<VkCommandBuffer>			primCmdBuf				(allocateCommandBuffer(vk, vkDevice, &cmdBufParams));

	// Secondary Command buffer
	const VkCommandBufferAllocateInfo		secCmdBufParams			=
	{
		VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,				// sType;
		DE_NULL,													// pNext;
		*cmdPool,													// commandPool;
		VK_COMMAND_BUFFER_LEVEL_SECONDARY,							// level;
		1u,															// bufferCount;
	};
	const Unique<VkCommandBuffer>			secCmdBuf				(allocateCommandBuffer(vk, vkDevice, &secCmdBufParams));

	const VkCommandBufferBeginInfo			primCmdBufBeginInfo		=
	{
		VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,				// sType
		DE_NULL,													// pNext
		0u,															// flags
		(const VkCommandBufferInheritanceInfo*)DE_NULL,
	};

	const VkCommandBufferInheritanceInfo	secCmdBufInheritInfo	=
	{
		VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO,
		DE_NULL,
		DE_NULL,													// renderPass
		0u,															// subpass
		DE_NULL,													// framebuffer
		VK_FALSE,													// occlusionQueryEnable
		(VkQueryControlFlags)0u,									// queryFlags
		(VkQueryPipelineStatisticFlags)0u,							// pipelineStatistics
	};
	const VkCommandBufferBeginInfo			secCmdBufBeginInfo		=
	{
		VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,				// sType
		DE_NULL,													// pNext
		0u,															// flags
		&secCmdBufInheritInfo,
	};

	// create event that will be used to check if secondary command buffer has been executed
	const Unique<VkEvent>					event					(createEvent(vk, vkDevice));

	// reset event
	VK_CHECK(vk.resetEvent(vkDevice, *event));

	// record secondary command buffer
	VK_CHECK(vk.beginCommandBuffer(*secCmdBuf, &secCmdBufBeginInfo));
	{
		// allow execution of event during every stage of pipeline
		VkPipelineStageFlags stageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
		// record setting event
		vk.cmdSetEvent(*secCmdBuf, *event, stageMask);
	}
	// end recording of the secondary buffer
	endCommandBuffer(vk, *secCmdBuf);

	// record primary command buffer
	VK_CHECK(vk.beginCommandBuffer(*primCmdBuf, &primCmdBufBeginInfo));
	{
		// execute secondary buffer
		vk.cmdExecuteCommands(*primCmdBuf, 1u, &secCmdBuf.get());
	}
	endCommandBuffer(vk, *primCmdBuf);

	submitCommandsAndWait(vk, vkDevice, queue, primCmdBuf.get());

	// check if secondary buffer has been executed
	VkResult result = vk.getEventStatus(vkDevice, *event);
	if (result == VK_EVENT_SET)
		return tcu::TestStatus::pass("executeSecondaryBufferTest succeeded");

	return tcu::TestStatus::fail("executeSecondaryBufferTest FAILED");
}

tcu::TestStatus executeSecondaryBufferTwiceTest(Context& context)
{
	const deUint32							BUFFER_COUNT			= 10u;
	const VkDevice							vkDevice				= context.getDevice();
	const DeviceInterface&					vk						= context.getDeviceInterface();
	const VkQueue							queue					= context.getUniversalQueue();
	const deUint32							queueFamilyIndex		= context.getUniversalQueueFamilyIndex();

	const VkCommandPoolCreateInfo			cmdPoolParams			=
	{
		VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,					//	VkStructureType				sType;
		DE_NULL,													//	const void*					pNext;
		VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,			//	VkCommandPoolCreateFlags	flags;
		queueFamilyIndex,											//	deUint32					queueFamilyIndex;
	};
	const Unique<VkCommandPool>				cmdPool					(createCommandPool(vk, vkDevice, &cmdPoolParams));

	// Command buffer
	const VkCommandBufferAllocateInfo		cmdBufParams			=
	{
		VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,				//	VkStructureType			sType;
		DE_NULL,													//	const void*				pNext;
		*cmdPool,													//	VkCommandPool				pool;
		VK_COMMAND_BUFFER_LEVEL_PRIMARY,							//	VkCommandBufferLevel		level;
		1u,															//	uint32_t					bufferCount;
	};
	const Unique<VkCommandBuffer>			primCmdBufOne			(allocateCommandBuffer(vk, vkDevice, &cmdBufParams));
	const Unique<VkCommandBuffer>			primCmdBufTwo			(allocateCommandBuffer(vk, vkDevice, &cmdBufParams));

	// Secondary Command buffers params
	const VkCommandBufferAllocateInfo		secCmdBufParams			=
	{
		VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,				//	VkStructureType			sType;
		DE_NULL,													//	const void*				pNext;
		*cmdPool,													//	VkCommandPool				pool;
		VK_COMMAND_BUFFER_LEVEL_SECONDARY,							//	VkCommandBufferLevel		level;
		BUFFER_COUNT,												//	uint32_t					bufferCount;
	};
	VkCommandBuffer cmdBuffers[BUFFER_COUNT];
	VK_CHECK(vk.allocateCommandBuffers(vkDevice, &secCmdBufParams, cmdBuffers));

	const VkCommandBufferBeginInfo			primCmdBufBeginInfo		=
	{
		VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
		DE_NULL,
		0,															// flags
		(const VkCommandBufferInheritanceInfo*)DE_NULL,
	};

	const VkCommandBufferInheritanceInfo	secCmdBufInheritInfo	=
	{
		VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO,
		DE_NULL,
		(VkRenderPass)0u,											// renderPass
		0u,															// subpass
		(VkFramebuffer)0u,											// framebuffer
		VK_FALSE,													// occlusionQueryEnable
		(VkQueryControlFlags)0u,									// queryFlags
		(VkQueryPipelineStatisticFlags)0u,							// pipelineStatistics
	};
	const VkCommandBufferBeginInfo			secCmdBufBeginInfo		=
	{
		VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
		DE_NULL,
		VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT,				// flags
		&secCmdBufInheritInfo,
	};

	// create event that will be used to check if secondary command buffer has been executed
	const Unique<VkEvent>					eventOne				(createEvent(vk, vkDevice));

	// reset event
	VK_CHECK(vk.resetEvent(vkDevice, *eventOne));

	for (deUint32 ndx = 0; ndx < BUFFER_COUNT; ++ndx)
	{
		// record secondary command buffer
		VK_CHECK(vk.beginCommandBuffer(cmdBuffers[ndx], &secCmdBufBeginInfo));
		{
			// allow execution of event during every stage of pipeline
			VkPipelineStageFlags stageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;

			// wait for event
			vk.cmdWaitEvents(cmdBuffers[ndx], 1, &eventOne.get(), stageMask, stageMask, 0, DE_NULL, 0u, DE_NULL, 0u, DE_NULL);
		}
		// end recording of secondary buffers
		endCommandBuffer(vk, cmdBuffers[ndx]);
	}

	// record primary command buffer one
	VK_CHECK(vk.beginCommandBuffer(*primCmdBufOne, &primCmdBufBeginInfo));
	{
		// execute one secondary buffer
		vk.cmdExecuteCommands(*primCmdBufOne, 1, cmdBuffers );
	}
	endCommandBuffer(vk, *primCmdBufOne);

	// record primary command buffer two
	VK_CHECK(vk.beginCommandBuffer(*primCmdBufTwo, &primCmdBufBeginInfo));
	{
		// execute one secondary buffer with all buffers
		vk.cmdExecuteCommands(*primCmdBufTwo, BUFFER_COUNT, cmdBuffers );
	}
	endCommandBuffer(vk, *primCmdBufTwo);

	// create fence to wait for execution of queue
	const Unique<VkFence>					fenceOne				(createFence(vk, vkDevice));
	const Unique<VkFence>					fenceTwo				(createFence(vk, vkDevice));

	const VkSubmitInfo						submitInfoOne			=
	{
		VK_STRUCTURE_TYPE_SUBMIT_INFO,								// sType
		DE_NULL,													// pNext
		0u,															// waitSemaphoreCount
		DE_NULL,													// pWaitSemaphores
		(const VkPipelineStageFlags*)DE_NULL,						// pWaitDstStageMask
		1,															// commandBufferCount
		&primCmdBufOne.get(),										// pCommandBuffers
		0u,															// signalSemaphoreCount
		DE_NULL,													// pSignalSemaphores
	};

	// submit primary buffer, the secondary should be executed too
	VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfoOne, *fenceOne));

	// wait for buffer to stop at event for 100 microseconds
	vk.waitForFences(vkDevice, 1, &fenceOne.get(), 0u, 100000);

	const VkSubmitInfo						submitInfoTwo			=
	{
		VK_STRUCTURE_TYPE_SUBMIT_INFO,								// sType
		DE_NULL,													// pNext
		0u,															// waitSemaphoreCount
		DE_NULL,													// pWaitSemaphores
		(const VkPipelineStageFlags*)DE_NULL,						// pWaitDstStageMask
		1,															// commandBufferCount
		&primCmdBufTwo.get(),										// pCommandBuffers
		0u,															// signalSemaphoreCount
		DE_NULL,													// pSignalSemaphores
	};

	// submit second primary buffer, the secondary should be executed too
	VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfoTwo, *fenceTwo));

	// wait for all buffers to stop at event for 100 microseconds
	vk.waitForFences(vkDevice, 1, &fenceOne.get(), 0u, 100000);

	// now all buffers are waiting at eventOne
	// set event eventOne
	VK_CHECK(vk.setEvent(vkDevice, *eventOne));

	// wait for end of execution of fenceOne
	VK_CHECK(vk.waitForFences(vkDevice, 1, &fenceOne.get(), 0u, INFINITE_TIMEOUT));

	// wait for end of execution of second queue
	VK_CHECK(vk.waitForFences(vkDevice, 1, &fenceTwo.get(), 0u, INFINITE_TIMEOUT));

	return tcu::TestStatus::pass("executeSecondaryBufferTwiceTest succeeded");
}

/******** 19.6. Commands Allowed Inside Command Buffers (? in VK 1.0 Spec) **/
tcu::TestStatus orderBindPipelineTest(Context& context)
{
	const DeviceInterface&					vk						= context.getDeviceInterface();
	const VkDevice							device					= context.getDevice();
	const VkQueue							queue					= context.getUniversalQueue();
	const deUint32							queueFamilyIndex		= context.getUniversalQueueFamilyIndex();
	Allocator&								allocator				= context.getDefaultAllocator();
	const ComputeInstanceResultBuffer		result					(vk, device, allocator);

	enum
	{
		ADDRESSABLE_SIZE = 256, // allocate a lot more than required
	};

	const tcu::Vec4							colorA1					= tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f);
	const tcu::Vec4							colorA2					= tcu::Vec4(1.0f, 1.0f, 0.0f, 1.0f);
	const tcu::Vec4							colorB1					= tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f);
	const tcu::Vec4							colorB2					= tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f);

	const deUint32							dataOffsetA				= (0u);
	const deUint32							dataOffsetB				= (0u);
	const deUint32							viewOffsetA				= (0u);
	const deUint32							viewOffsetB				= (0u);
	const deUint32							bufferSizeA				= dataOffsetA + ADDRESSABLE_SIZE;
	const deUint32							bufferSizeB				= dataOffsetB + ADDRESSABLE_SIZE;

	de::MovePtr<Allocation>					bufferMemA;
	const Unique<VkBuffer>					bufferA					(createColorDataBuffer(dataOffsetA, bufferSizeA, colorA1, colorA2, &bufferMemA, context));

	de::MovePtr<Allocation>					bufferMemB;
	const Unique<VkBuffer>					bufferB					(createColorDataBuffer(dataOffsetB, bufferSizeB, colorB1, colorB2, &bufferMemB, context));

	const Unique<VkDescriptorSetLayout>		descriptorSetLayout		(createDescriptorSetLayout(context));
	const Unique<VkDescriptorPool>			descriptorPool			(createDescriptorPool(context));
	const Unique<VkDescriptorSet>			descriptorSet			(createDescriptorSet(*descriptorPool, *descriptorSetLayout, *bufferA, viewOffsetA, *bufferB, viewOffsetB, result.getBuffer(), context));
	const VkDescriptorSet					descriptorSets[]		= { *descriptorSet };
	const int								numDescriptorSets		= DE_LENGTH_OF_ARRAY(descriptorSets);

	const VkPipelineLayoutCreateInfo layoutCreateInfo =
	{
		VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,				// sType
		DE_NULL,													// pNext
		(VkPipelineLayoutCreateFlags)0,
		numDescriptorSets,											// setLayoutCount
		&descriptorSetLayout.get(),									// pSetLayouts
		0u,															// pushConstantRangeCount
		DE_NULL,													// pPushConstantRanges
	};
	Unique<VkPipelineLayout>				pipelineLayout			(createPipelineLayout(vk, device, &layoutCreateInfo));

	const Unique<VkShaderModule>			computeModuleGood		(createShaderModule(vk, device, context.getBinaryCollection().get("compute_good"), (VkShaderModuleCreateFlags)0u));
	const Unique<VkShaderModule>			computeModuleBad		(createShaderModule(vk, device, context.getBinaryCollection().get("compute_bad"),  (VkShaderModuleCreateFlags)0u));

	const VkPipelineShaderStageCreateInfo	shaderCreateInfoGood	=
	{
		VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
		DE_NULL,
		(VkPipelineShaderStageCreateFlags)0,
		VK_SHADER_STAGE_COMPUTE_BIT,								// stage
		*computeModuleGood,											// shader
		"main",
		DE_NULL,													// pSpecializationInfo
	};

	const VkPipelineShaderStageCreateInfo	shaderCreateInfoBad	=
	{
		VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
		DE_NULL,
		(vk::VkPipelineShaderStageCreateFlags)0,
		vk::VK_SHADER_STAGE_COMPUTE_BIT,							// stage
		*computeModuleBad,											// shader
		"main",
		DE_NULL,													// pSpecializationInfo
	};

	const VkComputePipelineCreateInfo		createInfoGood			=
	{
		VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
		DE_NULL,
		0u,															// flags
		shaderCreateInfoGood,										// cs
		*pipelineLayout,											// layout
		(vk::VkPipeline)0,											// basePipelineHandle
		0u,															// basePipelineIndex
	};

	const VkComputePipelineCreateInfo		createInfoBad			=
	{
		VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
		DE_NULL,
		0u,															// flags
		shaderCreateInfoBad,										// cs
		*pipelineLayout,											// descriptorSetLayout.get()
		(VkPipeline)0,												// basePipelineHandle
		0u,															// basePipelineIndex
	};

	const Unique<VkPipeline>				pipelineGood			(createComputePipeline(vk, device, (VkPipelineCache)0u, &createInfoGood));
	const Unique<VkPipeline>				pipelineBad				(createComputePipeline(vk, device, (VkPipelineCache)0u, &createInfoBad));

	const VkAccessFlags						inputBit				= (VK_ACCESS_UNIFORM_READ_BIT);
	const VkBufferMemoryBarrier				bufferBarriers[]		=
	{
		{
			VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
			DE_NULL,
			VK_ACCESS_HOST_WRITE_BIT,									// srcAccessMask
			inputBit,													// dstAccessMask
			VK_QUEUE_FAMILY_IGNORED,									// srcQueueFamilyIndex
			VK_QUEUE_FAMILY_IGNORED,									// destQueueFamilyIndex
			*bufferA,													// buffer
			(VkDeviceSize)0u,											// offset
			(VkDeviceSize)bufferSizeA,									// size
		},
		{
			VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
			DE_NULL,
			VK_ACCESS_HOST_WRITE_BIT,									// srcAccessMask
			inputBit,													// dstAccessMask
			VK_QUEUE_FAMILY_IGNORED,									// srcQueueFamilyIndex
			VK_QUEUE_FAMILY_IGNORED,									// destQueueFamilyIndex
			*bufferB,													// buffer
			(VkDeviceSize)0u,											// offset
			(VkDeviceSize)bufferSizeB,									// size
		}
	};

	const deUint32							numSrcBuffers			= 1u;

	const deUint32* const					dynamicOffsets			= (DE_NULL);
	const deUint32							numDynamicOffsets		= (0);
	const int								numPreBarriers			= numSrcBuffers;
	const vk::VkBufferMemoryBarrier* const	postBarriers			= result.getResultReadBarrier();
	const int								numPostBarriers			= 1;
	const tcu::Vec4							refQuadrantValue14		= (colorA2);
	const tcu::Vec4							refQuadrantValue23		= (colorA1);
	const tcu::Vec4							references[4]			=
	{
		refQuadrantValue14,
		refQuadrantValue23,
		refQuadrantValue23,
		refQuadrantValue14,
	};
	tcu::Vec4								results[4];

	// submit and wait begin

	const tcu::UVec3 numWorkGroups = tcu::UVec3(4, 1u, 1);

	const VkCommandPoolCreateInfo			cmdPoolCreateInfo		=
	{
		VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,					// sType;
		DE_NULL,													// pNext
		VK_COMMAND_POOL_CREATE_TRANSIENT_BIT,						// flags
		queueFamilyIndex,											// queueFamilyIndex
	};
	const Unique<VkCommandPool>				cmdPool					(createCommandPool(vk, device, &cmdPoolCreateInfo));
	const VkCommandBufferAllocateInfo		cmdBufCreateInfo		=
	{
		VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,				// sType
		DE_NULL,													// pNext
		*cmdPool,													// commandPool
		VK_COMMAND_BUFFER_LEVEL_PRIMARY,							// level
		1u,															// bufferCount;
	};

	const VkCommandBufferBeginInfo			cmdBufBeginInfo			=
	{
		VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,				// sType
		DE_NULL,													// pNext
		0u,															// flags
		(const VkCommandBufferInheritanceInfo*)DE_NULL,
	};

	const Unique<VkCommandBuffer>			cmd						(allocateCommandBuffer(vk, device, &cmdBufCreateInfo));

	VK_CHECK(vk.beginCommandBuffer(*cmd, &cmdBufBeginInfo));

	vk.cmdBindPipeline(*cmd, VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineBad);
	vk.cmdBindPipeline(*cmd, VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineGood);
	vk.cmdBindDescriptorSets(*cmd, VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0, numDescriptorSets, descriptorSets, numDynamicOffsets, dynamicOffsets);

	if (numPreBarriers)
		vk.cmdPipelineBarrier(*cmd, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, (VkDependencyFlags)0,
							  0, (const VkMemoryBarrier*)DE_NULL,
							  numPreBarriers, bufferBarriers,
							  0, (const VkImageMemoryBarrier*)DE_NULL);

	vk.cmdDispatch(*cmd, numWorkGroups.x(), numWorkGroups.y(), numWorkGroups.z());
	vk.cmdPipelineBarrier(*cmd, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0,
						  0, (const VkMemoryBarrier*)DE_NULL,
						  numPostBarriers, postBarriers,
						  0, (const VkImageMemoryBarrier*)DE_NULL);
	endCommandBuffer(vk, *cmd);

	// run
	// submit second primary buffer, the secondary should be executed too
	submitCommandsAndWait(vk, device, queue, cmd.get());

	// submit and wait end
	result.readResultContentsTo(&results);

	// verify
	if (results[0] == references[0] &&
		results[1] == references[1] &&
		results[2] == references[2] &&
		results[3] == references[3])
	{
		return tcu::TestStatus::pass("Pass");
	}
	else if (results[0] == tcu::Vec4(-1.0f) &&
			 results[1] == tcu::Vec4(-1.0f) &&
			 results[2] == tcu::Vec4(-1.0f) &&
			 results[3] == tcu::Vec4(-1.0f))
	{
		context.getTestContext().getLog()
		<< tcu::TestLog::Message
		<< "Result buffer was not written to."
		<< tcu::TestLog::EndMessage;
		return tcu::TestStatus::fail("Result buffer was not written to");
	}
	else
	{
		context.getTestContext().getLog()
		<< tcu::TestLog::Message
		<< "Error expected ["
		<< references[0] << ", "
		<< references[1] << ", "
		<< references[2] << ", "
		<< references[3] << "], got ["
		<< results[0] << ", "
		<< results[1] << ", "
		<< results[2] << ", "
		<< results[3] << "]"
		<< tcu::TestLog::EndMessage;
		return tcu::TestStatus::fail("Invalid result values");
	}
}

enum StateTransitionTest
{
	STT_RECORDING_TO_INITIAL	= 0,
	STT_EXECUTABLE_TO_INITIAL,
	STT_RECORDING_TO_INVALID,
	STT_EXECUTABLE_TO_INVALID,
};

tcu::TestStatus executeStateTransitionTest(Context& context, StateTransitionTest type)
{
	const VkDevice					vkDevice			= context.getDevice();
	const DeviceInterface&			vk					= context.getDeviceInterface();
	const VkQueue					queue				= context.getUniversalQueue();
	const deUint32					queueFamilyIndex	= context.getUniversalQueueFamilyIndex();
	const Unique<VkCommandPool>		cmdPool				(createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
	const Unique<VkCommandBuffer>	cmdBuffer			(allocateCommandBuffer(vk, vkDevice, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
	const Unique<VkEvent>			globalEvent			(createEvent(vk, vkDevice));

	VK_CHECK(vk.resetEvent(vkDevice, *globalEvent));

	switch (type)
	{
		case STT_RECORDING_TO_INITIAL:
		{
			beginCommandBuffer(vk, *cmdBuffer, 0u);
			vk.cmdSetEvent(*cmdBuffer, *globalEvent, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT);
			break;
			// command buffer is still in recording state
		}
		case STT_EXECUTABLE_TO_INITIAL:
		{
			beginCommandBuffer(vk, *cmdBuffer, 0u);
			vk.cmdSetEvent(*cmdBuffer, *globalEvent, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT);
			endCommandBuffer(vk, *cmdBuffer);
			break;
			// command buffer is still in executable state
		}
		case STT_RECORDING_TO_INVALID:
		{
			VkSubpassDescription subpassDescription;
			deMemset(&subpassDescription, 0, sizeof(VkSubpassDescription));
			subpassDescription.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;

			VkRenderPassCreateInfo renderPassCreateInfo
			{
				VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
				DE_NULL, 0, 0, DE_NULL,
				1, &subpassDescription, 0, DE_NULL
			};

			// Error here - renderpass and framebuffer were created localy
			Move <VkRenderPass> renderPass = createRenderPass(vk, vkDevice, &renderPassCreateInfo);

			VkFramebufferCreateInfo framebufferCreateInfo
			{
				VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, DE_NULL,
				0, *renderPass, 0, DE_NULL, 16, 16, 1
			};
			Move <VkFramebuffer> framebuffer = createFramebuffer(vk, vkDevice, &framebufferCreateInfo);

			VkRenderPassBeginInfo renderPassBeginInfo =
			{
				VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
				DE_NULL, *renderPass, *framebuffer, { { 0, 0 }, { 16, 16 } },
				0, DE_NULL
			};

			beginCommandBuffer(vk, *cmdBuffer, 0u);
			vk.cmdBeginRenderPass(*cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
			vk.cmdEndRenderPass(*cmdBuffer);

			// not executing endCommandBuffer(vk, *cmdBuffer);
			// command buffer is still in recording state
			break;
			// renderpass and framebuffer are destroyed; command buffer should be now in invalid state
		}
		case STT_EXECUTABLE_TO_INVALID:
		{
			// create event that will be used to check if command buffer has been executed
			const Unique<VkEvent> localEvent(createEvent(vk, vkDevice));
			VK_CHECK(vk.resetEvent(vkDevice, *localEvent));

			beginCommandBuffer(vk, *cmdBuffer, 0u);
			vk.cmdSetEvent(*cmdBuffer, *localEvent, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT);
			endCommandBuffer(vk, *cmdBuffer);
			// command buffer is in executable state
			break;
			// localEvent is destroyed; command buffer should be now in invalid state
		}
	}

	VK_CHECK(vk.resetEvent(vkDevice, *globalEvent));

	vk.resetCommandBuffer(*cmdBuffer, 0u);
	// command buffer should now be back in initial state

	// verify commandBuffer
	beginCommandBuffer(vk, *cmdBuffer, 0u);
	vk.cmdSetEvent(*cmdBuffer, *globalEvent, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT);
	endCommandBuffer(vk, *cmdBuffer);
	submitCommandsAndWait(vk, vkDevice, queue, *cmdBuffer);

	// check if buffer has been executed
	VkResult result = vk.getEventStatus(vkDevice, *globalEvent);
	if (result != VK_EVENT_SET)
		return tcu::TestStatus::fail("Submit failed");

	return tcu::TestStatus::pass("Pass");
}

// Shaders
void genComputeSource (SourceCollections& programCollection)
{
	const char* const						versionDecl				= glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES);
	std::ostringstream						bufGood;

	bufGood << versionDecl << "\n"
	<< ""
	<< "layout(local_size_x = 1u, local_size_y = 1u, local_size_z = 1u) in;\n"
	<< "layout(set = 0, binding = 1u, std140) uniform BufferName\n"
	<< "{\n"
	<< "	highp vec4 colorA;\n"
	<< "	highp vec4 colorB;\n"
	<< "} b_instance;\n"
	<< "layout(set = 0, binding = 0, std140) writeonly buffer OutBuf\n"
	<< "{\n"
	<< "	highp vec4 read_colors[4];\n"
	<< "} b_out;\n"
	<< "void main(void)\n"
	<< "{\n"
	<< "	highp int quadrant_id = int(gl_WorkGroupID.x);\n"
	<< "	highp vec4 result_color;\n"
	<< "	if (quadrant_id == 1 || quadrant_id == 2)\n"
	<< "		result_color = b_instance.colorA;\n"
	<< "	else\n"
	<< "		result_color = b_instance.colorB;\n"
	<< "	b_out.read_colors[gl_WorkGroupID.x] = result_color;\n"
	<< "}\n";

	programCollection.glslSources.add("compute_good") << glu::ComputeSource(bufGood.str());

	std::ostringstream	bufBad;

	bufBad	<< versionDecl << "\n"
	<< ""
	<< "layout(local_size_x = 1u, local_size_y = 1u, local_size_z = 1u) in;\n"
	<< "layout(set = 0, binding = 1u, std140) uniform BufferName\n"
	<< "{\n"
	<< "	highp vec4 colorA;\n"
	<< "	highp vec4 colorB;\n"
	<< "} b_instance;\n"
	<< "layout(set = 0, binding = 0, std140) writeonly buffer OutBuf\n"
	<< "{\n"
	<< "	highp vec4 read_colors[4];\n"
	<< "} b_out;\n"
	<< "void main(void)\n"
	<< "{\n"
	<< "	highp int quadrant_id = int(gl_WorkGroupID.x);\n"
	<< "	highp vec4 result_color;\n"
	<< "	if (quadrant_id == 1 || quadrant_id == 2)\n"
	<< "		result_color = b_instance.colorA;\n"
	<< "	else\n"
	<< "		result_color = b_instance.colorB;\n"
	<< "	b_out.read_colors[gl_WorkGroupID.x] = vec4(0.0, 0.0, 0.0, 0.0);\n"
	<< "}\n";

	programCollection.glslSources.add("compute_bad") << glu::ComputeSource(bufBad.str());
}

void genComputeIncrementSource (SourceCollections& programCollection)
{
	const char* const						versionDecl = glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES);
	std::ostringstream						bufIncrement;

	bufIncrement << versionDecl << "\n"
		<< ""
		<< "layout(local_size_x = 1u, local_size_y = 1u, local_size_z = 1u) in;\n"
		<< "layout(set = 0, binding = 0, std140) buffer InOutBuf\n"
		<< "{\n"
		<< "    coherent uint count;\n"
		<< "} b_in_out;\n"
		<< "void main(void)\n"
		<< "{\n"
		<< "	atomicAdd(b_in_out.count, 1u);\n"
		<< "}\n";

	programCollection.glslSources.add("compute_increment") << glu::ComputeSource(bufIncrement.str());
}

void genComputeIncrementSourceBadInheritance(SourceCollections& programCollection, BadInheritanceInfoCase testCase)
{
	DE_UNREF(testCase);
	return genComputeIncrementSource(programCollection);
}

void checkEventSupport (Context& context)
{
	if (context.isDeviceFunctionalitySupported("VK_KHR_portability_subset") && !context.getPortabilitySubsetFeatures().events)
		TCU_THROW(NotSupportedError, "VK_KHR_portability_subset: Events are not supported by this implementation");
}

void checkEventSupport (Context& context, const VkCommandBufferLevel)
{
	checkEventSupport(context);
}

struct ManyDrawsParams
{
	VkCommandBufferLevel	level;
	VkExtent3D				imageExtent;
	deUint32				seed;

	ManyDrawsParams(VkCommandBufferLevel level_, const VkExtent3D& extent_, deUint32 seed_)
		: level			(level_)
		, imageExtent	(extent_)
		, seed			(seed_)
	{}
};

struct ManyDrawsVertex
{
	using Color = tcu::Vector<deUint8, 4>;

	tcu::Vec2	coords;
	Color		color;

	ManyDrawsVertex (const tcu::Vec2& coords_, const Color& color_) : coords(coords_), color(color_) {}
};

VkFormat getSupportedDepthStencilFormat (const InstanceInterface& vki, VkPhysicalDevice physDev)
{
	const VkFormat				formatList[]	= { VK_FORMAT_D24_UNORM_S8_UINT, VK_FORMAT_D32_SFLOAT_S8_UINT };
	const VkFormatFeatureFlags	requirements	= (VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT);

	for (int i = 0; i < DE_LENGTH_OF_ARRAY(formatList); ++i)
	{
		const auto properties = getPhysicalDeviceFormatProperties(vki, physDev, formatList[i]);
		if ((properties.optimalTilingFeatures & requirements) == requirements)
			return formatList[i];
	}

	TCU_THROW(NotSupportedError, "No suitable depth/stencil format support");
	return VK_FORMAT_UNDEFINED;
}

class ManyDrawsCase : public TestCase
{
public:
							ManyDrawsCase			(tcu::TestContext& testCtx, const std::string& name, const std::string& description, const ManyDrawsParams& params);
	virtual					~ManyDrawsCase			(void) {}

	virtual void			checkSupport			(Context& context) const;
	virtual void			initPrograms			(vk::SourceCollections& programCollection) const;
	virtual TestInstance*	createInstance			(Context& context) const;

	static VkFormat			getColorFormat			(void) { return VK_FORMAT_R8G8B8A8_UINT; }

protected:
	ManyDrawsParams			m_params;
};

class ManyDrawsInstance : public TestInstance
{
public:
								ManyDrawsInstance	(Context& context, const ManyDrawsParams& params);
	virtual						~ManyDrawsInstance	(void) {}

	virtual tcu::TestStatus		iterate				(void);

protected:
	ManyDrawsParams				m_params;
};

using BufferPtr = de::MovePtr<BufferWithMemory>;
using ImagePtr = de::MovePtr<ImageWithMemory>;

struct ManyDrawsVertexBuffers
{
	BufferPtr stagingBuffer;
	BufferPtr vertexBuffer;
};

struct ManyDrawsAllocatedData
{
	ManyDrawsVertexBuffers	frontBuffers;
	ManyDrawsVertexBuffers	backBuffers;
	ImagePtr				colorAttachment;
	ImagePtr				dsAttachment;
	BufferPtr				colorCheckBuffer;
	BufferPtr				stencilCheckBuffer;

	static deUint32 calcNumPixels (const VkExtent3D& extent)
	{
		DE_ASSERT(extent.depth == 1u);
		return (extent.width * extent.height);
	}
	static deUint32 calcNumVertices (const VkExtent3D& extent)
	{
		// One triangle (3 vertices) per output image pixel.
		return (calcNumPixels(extent) * 3u);
	}

	static VkDeviceSize calcVertexBufferSize (const VkExtent3D& extent)
	{
		return calcNumVertices(extent) * sizeof(ManyDrawsVertex);
	}

	static void makeVertexBuffers (const DeviceInterface& vkd, VkDevice device, Allocator& alloc, VkDeviceSize size, ManyDrawsVertexBuffers& buffers)
	{
		const auto stagingBufferInfo	= makeBufferCreateInfo(size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
		const auto vertexBufferInfo		= makeBufferCreateInfo(size, (VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT));

		buffers.stagingBuffer	= BufferPtr(new BufferWithMemory(vkd, device, alloc, stagingBufferInfo, MemoryRequirement::HostVisible));
		buffers.vertexBuffer	= BufferPtr(new BufferWithMemory(vkd, device, alloc, vertexBufferInfo, MemoryRequirement::Any));
	}

	ManyDrawsAllocatedData (const DeviceInterface &vkd, VkDevice device, Allocator &alloc, const VkExtent3D& imageExtent, VkFormat colorFormat, VkFormat dsFormat)
	{
		const auto numPixels		= calcNumPixels(imageExtent);
		const auto vertexBufferSize	= calcVertexBufferSize(imageExtent);

		makeVertexBuffers(vkd, device, alloc, vertexBufferSize, frontBuffers);
		makeVertexBuffers(vkd, device, alloc, vertexBufferSize, backBuffers);

		const auto colorUsage	= (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
		const auto dsUsage		= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;

		const VkImageCreateInfo colorAttachmentInfo =
		{
			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,	//	VkStructureType			sType;
			nullptr,								//	const void*				pNext;
			0u,										//	VkImageCreateFlags		flags;
			VK_IMAGE_TYPE_2D,						//	VkImageType				imageType;
			colorFormat,							//	VkFormat				format;
			imageExtent,							//	VkExtent3D				extent;
			1u,										//	deUint32				mipLevels;
			1u,										//	deUint32				arrayLayers;
			VK_SAMPLE_COUNT_1_BIT,					//	VkSampleCountFlagBits	samples;
			VK_IMAGE_TILING_OPTIMAL,				//	VkImageTiling			tiling;
			colorUsage,								//	VkImageUsageFlags		usage;
			VK_SHARING_MODE_EXCLUSIVE,				//	VkSharingMode			sharingMode;
			0u,										//	deUint32				queueFamilyIndexCount;
			nullptr,								//	const deUint32*			pQueueFamilyIndices;
			VK_IMAGE_LAYOUT_UNDEFINED,				//	VkImageLayout			initialLayout;
		};
		colorAttachment = ImagePtr(new ImageWithMemory(vkd, device, alloc, colorAttachmentInfo, MemoryRequirement::Any));

		const VkImageCreateInfo dsAttachmentInfo =
		{
			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,	//	VkStructureType			sType;
			nullptr,								//	const void*				pNext;
			0u,										//	VkImageCreateFlags		flags;
			VK_IMAGE_TYPE_2D,						//	VkImageType				imageType;
			dsFormat,								//	VkFormat				format;
			imageExtent,							//	VkExtent3D				extent;
			1u,										//	deUint32				mipLevels;
			1u,										//	deUint32				arrayLayers;
			VK_SAMPLE_COUNT_1_BIT,					//	VkSampleCountFlagBits	samples;
			VK_IMAGE_TILING_OPTIMAL,				//	VkImageTiling			tiling;
			dsUsage,								//	VkImageUsageFlags		usage;
			VK_SHARING_MODE_EXCLUSIVE,				//	VkSharingMode			sharingMode;
			0u,										//	deUint32				queueFamilyIndexCount;
			nullptr,								//	const deUint32*			pQueueFamilyIndices;
			VK_IMAGE_LAYOUT_UNDEFINED,				//	VkImageLayout			initialLayout;
		};
		dsAttachment = ImagePtr(new ImageWithMemory(vkd, device, alloc, dsAttachmentInfo, MemoryRequirement::Any));

		const auto colorCheckBufferSize		= static_cast<VkDeviceSize>(numPixels * tcu::getPixelSize(mapVkFormat(colorFormat)));
		const auto colorCheckBufferInfo		= makeBufferCreateInfo(colorCheckBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT);

		colorCheckBuffer = BufferPtr(new BufferWithMemory(vkd, device, alloc, colorCheckBufferInfo, MemoryRequirement::HostVisible));

		const auto stencilFormat			= tcu::TextureFormat(tcu::TextureFormat::S, tcu::TextureFormat::UNSIGNED_INT8);
		const auto stencilCheckBufferSize	= static_cast<VkDeviceSize>(numPixels * tcu::getPixelSize(stencilFormat));
		const auto stencilCheckBufferInfo	= makeBufferCreateInfo(stencilCheckBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT);

		stencilCheckBuffer = BufferPtr(new BufferWithMemory(vkd, device, alloc, stencilCheckBufferInfo, MemoryRequirement::HostVisible));
	}
};

ManyDrawsCase::ManyDrawsCase (tcu::TestContext& testCtx, const std::string& name, const std::string& description, const ManyDrawsParams& params)
	: TestCase	(testCtx, name, description)
	, m_params	(params)
{}

void ManyDrawsCase::checkSupport (Context& context) const
{
	const auto& vki			= context.getInstanceInterface();
	const auto	physDev		= context.getPhysicalDevice();
	const auto&	vkd			= context.getDeviceInterface();
	const auto	device		= context.getDevice();
	auto&		alloc		= context.getDefaultAllocator();
	const auto	dsFormat	= getSupportedDepthStencilFormat(vki, physDev);

	try
	{
		ManyDrawsAllocatedData allocatedData(vkd, device, alloc, m_params.imageExtent, getColorFormat(), dsFormat);
	}
	catch (const vk::Error& err)
	{
		const auto result = err.getError();
		if (result == VK_ERROR_OUT_OF_HOST_MEMORY || result == VK_ERROR_OUT_OF_DEVICE_MEMORY)
			TCU_THROW(NotSupportedError, "Not enough memory to run this test");
		throw;
	}
}

void ManyDrawsCase::initPrograms (vk::SourceCollections& programCollection) const
{
	std::ostringstream vert;
	vert
		<< "#version 450\n"
		<< "\n"
		<< "layout(location=0) in vec2 inCoords;\n"
		<< "layout(location=1) in uvec4 inColor;\n"
		<< "\n"
		<< "layout(location=0) out flat uvec4 outColor;\n"
		<< "\n"
		<< "void main()\n"
		<< "{\n"
		<< "    gl_Position = vec4(inCoords, 0.0, 1.0);\n"
		<< "    outColor = inColor;\n"
		<< "}\n"
		;

	std::ostringstream frag;
	frag
		<< "#version 450\n"
		<< "\n"
		<< "layout(location=0) in flat uvec4 inColor;\n"
		<< "layout(location=0) out uvec4 outColor;\n"
		<< "\n"
		<< "void main()\n"
		<< "{\n"
		<< "	outColor = inColor;\n"
		<< "}\n"
		;

	programCollection.glslSources.add("vert") << glu::VertexSource(vert.str());
	programCollection.glslSources.add("frag") << glu::FragmentSource(frag.str());
}

TestInstance* ManyDrawsCase::createInstance (Context& context) const
{
	return new ManyDrawsInstance(context, m_params);
}

ManyDrawsInstance::ManyDrawsInstance (Context& context, const ManyDrawsParams& params)
	: TestInstance	(context)
	, m_params		(params)
{}

void copyAndFlush (const DeviceInterface& vkd, VkDevice device, BufferWithMemory& buffer, const std::vector<ManyDrawsVertex>& vertices)
{
	auto& alloc		= buffer.getAllocation();
	void* hostPtr	= alloc.getHostPtr();

	deMemcpy(hostPtr, vertices.data(), de::dataSize(vertices));
	flushAlloc(vkd, device, alloc);
}

tcu::TestStatus ManyDrawsInstance::iterate (void)
{
	const auto&	vki					= m_context.getInstanceInterface();
	const auto	physDev				= m_context.getPhysicalDevice();
	const auto&	vkd					= m_context.getDeviceInterface();
	const auto	device				= m_context.getDevice();
	auto&		alloc				= m_context.getDefaultAllocator();
	const auto	qIndex				= m_context.getUniversalQueueFamilyIndex();
	const auto	queue				= m_context.getUniversalQueue();

	const auto	colorFormat			= ManyDrawsCase::getColorFormat();
	const auto	dsFormat			= getSupportedDepthStencilFormat(vki, physDev);
	const auto	vertexBufferSize	= ManyDrawsAllocatedData::calcVertexBufferSize(m_params.imageExtent);
	const auto	vertexBufferOffset	= static_cast<VkDeviceSize>(0);
	const auto	numPixels			= ManyDrawsAllocatedData::calcNumPixels(m_params.imageExtent);
	const auto	numVertices			= ManyDrawsAllocatedData::calcNumVertices(m_params.imageExtent);
	const auto	alphaValue			= std::numeric_limits<deUint8>::max();
	const auto	pixelWidth			= 2.0f / static_cast<float>(m_params.imageExtent.width);	// Normalized size.
	const auto	pixelWidthHalf		= pixelWidth / 2.0f;										// Normalized size.
	const auto	pixelHeight			= 2.0f / static_cast<float>(m_params.imageExtent.height);	// Normalized size.
	const auto	useSecondary		= (m_params.level == VK_COMMAND_BUFFER_LEVEL_SECONDARY);

	// Allocate all needed data up front.
	ManyDrawsAllocatedData testData(vkd, device, alloc, m_params.imageExtent, colorFormat, dsFormat);

	// Generate random colors.
	de::Random							rnd(m_params.seed);
	std::vector<ManyDrawsVertex::Color>	colors;

	colors.reserve(numPixels);
	for (deUint32 i = 0; i < numPixels; ++i)
	{
#if 0
		const deUint8 red	= ((i      ) & 0xFFu);
		const deUint8 green	= ((i >>  8) & 0xFFu);
		const deUint8 blue	= ((i >> 16) & 0xFFu);
		colors.push_back(ManyDrawsVertex::Color(red, green, blue, alphaValue));
#else
		colors.push_back(ManyDrawsVertex::Color(rnd.getUint8(), rnd.getUint8(), rnd.getUint8(), alphaValue));
#endif
	}

	// Fill vertex data. One triangle per pixel, front and back.
	std::vector<ManyDrawsVertex> frontVector;
	std::vector<ManyDrawsVertex> backVector;
	frontVector.reserve(numVertices);
	backVector.reserve(numVertices);

	for (deUint32 y = 0; y < m_params.imageExtent.height; ++y)
	for (deUint32 x = 0; x < m_params.imageExtent.width; ++x)
	{
		float x_left	= static_cast<float>(x) * pixelWidth - 1.0f;
		float x_mid		= x_left + pixelWidthHalf;
		float x_right	= x_left + pixelWidth;
		float y_top		= static_cast<float>(y) * pixelHeight - 1.0f;
		float y_bottom	= y_top + pixelHeight;

		// Triangles in the "back" mesh will have different colors.
		const auto		colorIdx		= y * m_params.imageExtent.width + x;
		const auto&		frontColor		= colors[colorIdx];
		const auto&		backColor		= colors[colors.size() - 1u - colorIdx];

		const tcu::Vec2	triangle[3u]	=
		{
			tcu::Vec2(x_left, y_top),
			tcu::Vec2(x_right, y_top),
			tcu::Vec2(x_mid, y_bottom),
		};

		frontVector.emplace_back(triangle[0], frontColor);
		frontVector.emplace_back(triangle[1], frontColor);
		frontVector.emplace_back(triangle[2], frontColor);

		backVector.emplace_back(triangle[0], backColor);
		backVector.emplace_back(triangle[1], backColor);
		backVector.emplace_back(triangle[2], backColor);
	}

	// Copy vertex data to staging buffers.
	copyAndFlush(vkd, device, *testData.frontBuffers.stagingBuffer, frontVector);
	copyAndFlush(vkd, device, *testData.backBuffers.stagingBuffer, backVector);

	// Color attachment view.
	const auto		colorResourceRange	= makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
	const auto		colorAttachmentView	= makeImageView(vkd, device, testData.colorAttachment->get(), VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorResourceRange);

	// Depth/stencil attachment view.
	const auto		dsResourceRange		= makeImageSubresourceRange((VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT), 0u, 1u, 0u, 1u);
	const auto		dsAttachmentView	= makeImageView(vkd, device, testData.dsAttachment->get(), VK_IMAGE_VIEW_TYPE_2D, dsFormat, dsResourceRange);

	const VkImageView	attachmentArray[]	= { colorAttachmentView.get(), dsAttachmentView.get() };
	const auto			numAttachments		= static_cast<deUint32>(DE_LENGTH_OF_ARRAY(attachmentArray));

	const auto renderPass	= makeRenderPass(vkd, device, colorFormat, dsFormat);
	const auto framebuffer	= makeFramebuffer(vkd, device, renderPass.get(), numAttachments, attachmentArray, m_params.imageExtent.width, m_params.imageExtent.height);

	const auto vertModule	= createShaderModule(vkd, device, m_context.getBinaryCollection().get("vert"), 0u);
	const auto fragModule	= createShaderModule(vkd, device, m_context.getBinaryCollection().get("frag"), 0u);

	const std::vector<VkViewport>	viewports	(1u, makeViewport(m_params.imageExtent));
	const std::vector<VkRect2D>		scissors	(1u, makeRect2D(m_params.imageExtent));

	const auto descriptorSetLayout	= DescriptorSetLayoutBuilder().build(vkd, device);
	const auto pipelineLayout		= makePipelineLayout(vkd, device, descriptorSetLayout.get());

	const VkVertexInputBindingDescription bindings[] =
	{
		makeVertexInputBindingDescription(0u, static_cast<deUint32>(sizeof(ManyDrawsVertex)), VK_VERTEX_INPUT_RATE_VERTEX),
	};

	const VkVertexInputAttributeDescription attributes[] =
	{
		makeVertexInputAttributeDescription(0u, 0u, VK_FORMAT_R32G32_SFLOAT, static_cast<deUint32>(offsetof(ManyDrawsVertex, coords))),
		makeVertexInputAttributeDescription(1u, 0u, VK_FORMAT_R8G8B8A8_UINT, static_cast<deUint32>(offsetof(ManyDrawsVertex, color))),
	};

	const VkPipelineVertexInputStateCreateInfo inputState =
	{
		VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,	//	VkStructureType								sType;
		nullptr,													//	const void*									pNext;
		0u,															//	VkPipelineVertexInputStateCreateFlags		flags;
		static_cast<deUint32>(DE_LENGTH_OF_ARRAY(bindings)),		//	deUint32									vertexBindingDescriptionCount;
		bindings,													//	const VkVertexInputBindingDescription*		pVertexBindingDescriptions;
		static_cast<deUint32>(DE_LENGTH_OF_ARRAY(attributes)),		//	deUint32									vertexAttributeDescriptionCount;
		attributes,													//	const VkVertexInputAttributeDescription*	pVertexAttributeDescriptions;
	};

	// Stencil state: this is key for checking and obtaining the right results. The stencil buffer will be cleared to 0. The first
	// set of draws ("front" set of triangles) will pass the test and increment the stencil value to 1. The second set of draws
	// ("back" set of triangles, not really in the back because all of them have depth 0.0) will not pass the stencil test then, but
	// still increment the stencil value to 2.
	//
	// At the end of the test, if every draw command was executed correctly in the expected order, the color buffer will have the
	// colors of the front set, and the stencil buffer will be full of 2s.
	const auto stencilOpState = makeStencilOpState(VK_STENCIL_OP_INCREMENT_AND_CLAMP, VK_STENCIL_OP_INCREMENT_AND_CLAMP, VK_STENCIL_OP_KEEP,
		VK_COMPARE_OP_EQUAL, 0xFFu, 0xFFu, 0u);

	const VkPipelineDepthStencilStateCreateInfo dsState =
	{
		VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,	// VkStructureType                          sType
		nullptr,													// const void*                              pNext
		0u,															// VkPipelineDepthStencilStateCreateFlags   flags
		VK_FALSE,													// VkBool32                                 depthTestEnable
		VK_FALSE,													// VkBool32                                 depthWriteEnable
		VK_COMPARE_OP_NEVER,										// VkCompareOp                              depthCompareOp
		VK_FALSE,													// VkBool32                                 depthBoundsTestEnable
		VK_TRUE,													// VkBool32                                 stencilTestEnable
		stencilOpState,												// VkStencilOpState                         front
		stencilOpState,												// VkStencilOpState                         back
		0.0f,														// float                                    minDepthBounds
		1.0f,														// float                                    maxDepthBounds
	};

	const auto pipeline = makeGraphicsPipeline(vkd, device, pipelineLayout.get(),
			vertModule.get(), DE_NULL, DE_NULL, DE_NULL, fragModule.get(),
			renderPass.get(), viewports, scissors, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0u, 0u,
			&inputState, nullptr, nullptr, &dsState);

	// Command pool and buffers.
	using CmdBufferPtr = Move<VkCommandBuffer>;
	const auto cmdPool = makeCommandPool(vkd, device, qIndex);

	CmdBufferPtr	primaryCmdBufferPtr;
	CmdBufferPtr	secondaryCmdBufferPtr;
	VkCommandBuffer	primaryCmdBuffer;
	VkCommandBuffer	secondaryCmdBuffer;
	VkCommandBuffer	drawsCmdBuffer;

	primaryCmdBufferPtr		= allocateCommandBuffer(vkd, device, cmdPool.get(), VK_COMMAND_BUFFER_LEVEL_PRIMARY);
	primaryCmdBuffer		= primaryCmdBufferPtr.get();
	drawsCmdBuffer			= primaryCmdBuffer;
	beginCommandBuffer(vkd, primaryCmdBuffer);

	// Clear values.
	std::vector<VkClearValue> clearValues(2u);
	clearValues[0] = makeClearValueColorU32(0u, 0u, 0u, 0u);
	clearValues[1] = makeClearValueDepthStencil(1.0f, 0u);

	// Copy staging buffers to vertex buffers.
	const auto copyRegion = makeBufferCopy(0ull, 0ull, vertexBufferSize);
	vkd.cmdCopyBuffer(primaryCmdBuffer, testData.frontBuffers.stagingBuffer->get(), testData.frontBuffers.vertexBuffer->get(), 1u, &copyRegion);
	vkd.cmdCopyBuffer(primaryCmdBuffer, testData.backBuffers.stagingBuffer->get(), testData.backBuffers.vertexBuffer->get(), 1u, &copyRegion);

	// Use barrier for vertex reads.
	const auto vertexBarier = makeMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT);
	vkd.cmdPipelineBarrier(primaryCmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, 0u, 1u, &vertexBarier, 0u, nullptr, 0u, nullptr);

	// Change depth/stencil attachment layout.
	const auto dsBarrier = makeImageMemoryBarrier(0, (VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT), VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, testData.dsAttachment->get(), dsResourceRange);
	vkd.cmdPipelineBarrier(primaryCmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, (VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT), 0u, 0u, nullptr, 0u, nullptr, 1u, &dsBarrier);

	beginRenderPass(vkd, primaryCmdBuffer, renderPass.get(), framebuffer.get(),
		scissors[0], static_cast<deUint32>(clearValues.size()), clearValues.data(),
		(useSecondary ? VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS : VK_SUBPASS_CONTENTS_INLINE));

	if (useSecondary)
	{
		secondaryCmdBufferPtr	= allocateCommandBuffer(vkd, device, cmdPool.get(), VK_COMMAND_BUFFER_LEVEL_SECONDARY);
		secondaryCmdBuffer		= secondaryCmdBufferPtr.get();
		drawsCmdBuffer			= secondaryCmdBuffer;

		const VkCommandBufferInheritanceInfo inheritanceInfo =
		{
			VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO,	//	VkStructureType					sType;
			nullptr,											//	const void*						pNext;
			renderPass.get(),									//	VkRenderPass					renderPass;
			0u,													//	deUint32						subpass;
			framebuffer.get(),									//	VkFramebuffer					framebuffer;
			0u,													//	VkBool32						occlusionQueryEnable;
			0u,													//	VkQueryControlFlags				queryFlags;
			0u,													//	VkQueryPipelineStatisticFlags	pipelineStatistics;
		};

		const VkCommandBufferUsageFlags	usageFlags	= (VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT | VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT);
		const VkCommandBufferBeginInfo	beginInfo	=
		{
			VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
			nullptr,
			usageFlags,										//	VkCommandBufferUsageFlags				flags;
			&inheritanceInfo,								//	const VkCommandBufferInheritanceInfo*	pInheritanceInfo;
		};

		VK_CHECK(vkd.beginCommandBuffer(secondaryCmdBuffer, &beginInfo));
	}

	// Bind pipeline.
	vkd.cmdBindPipeline(drawsCmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.get());

	// Draw triangles in front.
	vkd.cmdBindVertexBuffers(drawsCmdBuffer, 0u, 1u, &testData.frontBuffers.vertexBuffer->get(), &vertexBufferOffset);
	for (deUint32 i = 0; i < numPixels; ++i)
		vkd.cmdDraw(drawsCmdBuffer, 3u, 1u, i*3u, 0u);

	// Draw triangles in the "back". This should have no effect due to the stencil test.
	vkd.cmdBindVertexBuffers(drawsCmdBuffer, 0u, 1u, &testData.backBuffers.vertexBuffer->get(), &vertexBufferOffset);
	for (deUint32 i = 0; i < numPixels; ++i)
		vkd.cmdDraw(drawsCmdBuffer, 3u, 1u, i*3u, 0u);

	if (useSecondary)
	{
		endCommandBuffer(vkd, secondaryCmdBuffer);
		vkd.cmdExecuteCommands(primaryCmdBuffer, 1u, &secondaryCmdBuffer);
	}

	endRenderPass(vkd, primaryCmdBuffer);

	// Copy color and depth/stencil attachments to verification buffers.
	const auto colorAttachmentBarrier = makeImageMemoryBarrier(VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, testData.colorAttachment->get(), colorResourceRange);
	vkd.cmdPipelineBarrier(primaryCmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, nullptr, 0u, nullptr, 1u, &colorAttachmentBarrier);

	const auto colorResourceLayers	= makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u);
	const auto colorCopyRegion		= makeBufferImageCopy(m_params.imageExtent, colorResourceLayers);
	vkd.cmdCopyImageToBuffer(primaryCmdBuffer, testData.colorAttachment->get(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, testData.colorCheckBuffer->get(), 1u, &colorCopyRegion);

	const auto stencilAttachmentBarrier = makeImageMemoryBarrier(VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, testData.dsAttachment->get(), dsResourceRange);
	vkd.cmdPipelineBarrier(primaryCmdBuffer, (VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT), VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, nullptr, 0u, nullptr, 1u, &stencilAttachmentBarrier);

	const auto stencilResourceLayers	= makeImageSubresourceLayers(VK_IMAGE_ASPECT_STENCIL_BIT, 0u, 0u, 1u);
	const auto stencilCopyRegion		= makeBufferImageCopy(m_params.imageExtent, stencilResourceLayers);
	vkd.cmdCopyImageToBuffer(primaryCmdBuffer, testData.dsAttachment->get(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, testData.stencilCheckBuffer->get(), 1u, &stencilCopyRegion);

	const auto verificationBuffersBarrier = makeMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT);
	vkd.cmdPipelineBarrier(primaryCmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 1u, &verificationBuffersBarrier, 0u, nullptr, 0u, nullptr);

	endCommandBuffer(vkd, primaryCmdBuffer);
	submitCommandsAndWait(vkd, device, queue, primaryCmdBuffer);

	// Check buffer contents.
	auto& colorCheckBufferAlloc	= testData.colorCheckBuffer->getAllocation();
	void* colorCheckBufferData	= colorCheckBufferAlloc.getHostPtr();
	invalidateAlloc(vkd, device, colorCheckBufferAlloc);

	auto& stencilCheckBufferAlloc	= testData.stencilCheckBuffer->getAllocation();
	void* stencilCheckBufferData	= stencilCheckBufferAlloc.getHostPtr();
	invalidateAlloc(vkd, device, stencilCheckBufferAlloc);

	const auto iWidth			= static_cast<int>(m_params.imageExtent.width);
	const auto iHeight			= static_cast<int>(m_params.imageExtent.height);
	const auto colorTcuFormat	= mapVkFormat(colorFormat);
	const auto stencilTcuFormat	= tcu::TextureFormat(tcu::TextureFormat::S, tcu::TextureFormat::UNSIGNED_INT8);

	tcu::TextureLevel			referenceLevel		(colorTcuFormat, iWidth, iHeight);
	tcu::PixelBufferAccess		referenceAccess		= referenceLevel.getAccess();
	tcu::TextureLevel			colorErrorLevel		(mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM), iWidth, iHeight);
	tcu::PixelBufferAccess		colorErrorAccess	= colorErrorLevel.getAccess();
	tcu::TextureLevel			stencilErrorLevel	(mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM), iWidth, iHeight);
	tcu::PixelBufferAccess		stencilErrorAccess	= stencilErrorLevel.getAccess();
	tcu::ConstPixelBufferAccess	colorAccess			(colorTcuFormat, iWidth, iHeight, 1, colorCheckBufferData);
	tcu::ConstPixelBufferAccess	stencilAccess		(stencilTcuFormat, iWidth, iHeight, 1, stencilCheckBufferData);
	const tcu::Vec4				green				(0.0f, 1.0f, 0.0f, 1.0f);
	const tcu::Vec4				red					(1.0f, 0.0f, 0.0f, 1.0f);
	const int					expectedStencil		= 2;
	bool						colorFail			= false;
	bool						stencilFail			= false;

	for (int y = 0; y < iHeight; ++y)
	for (int x = 0; x < iWidth; ++x)
	{
		const tcu::UVec4	colorValue		= colorAccess.getPixelUint(x, y);
		const auto			expectedPixel	= colors[y * iWidth + x];
		const tcu::UVec4	expectedValue	(expectedPixel.x(), expectedPixel.y(), expectedPixel.z(), expectedPixel.w());
		const bool			colorMismatch	= (colorValue != expectedValue);

		const auto			stencilValue	= stencilAccess.getPixStencil(x, y);
		const bool			stencilMismatch	= (stencilValue != expectedStencil);

		referenceAccess.setPixel(expectedValue, x, y);
		colorErrorAccess.setPixel((colorMismatch ? red : green), x, y);
		stencilErrorAccess.setPixel((stencilMismatch ? red : green), x, y);

		if (stencilMismatch)
			stencilFail = true;

		if (colorMismatch)
			colorFail = true;
	}

	if (colorFail || stencilFail)
	{
		auto& log = m_context.getTestContext().getLog();
		log
			<< tcu::TestLog::ImageSet("Result", "")
			<< tcu::TestLog::Image("ColorOutput", "", colorAccess)
			<< tcu::TestLog::Image("ColorReference", "", referenceAccess)
			<< tcu::TestLog::Image("ColorError", "", colorErrorAccess)
			<< tcu::TestLog::Image("StencilError", "", stencilErrorAccess)
			<< tcu::TestLog::EndImageSet
			;
		TCU_FAIL("Mismatched output and reference color or stencil; please check test log --");
	}

	return tcu::TestStatus::pass("Pass");
}

} // anonymous

tcu::TestCaseGroup* createCommandBuffersTests (tcu::TestContext& testCtx)
{
	de::MovePtr<tcu::TestCaseGroup>	commandBuffersTests	(new tcu::TestCaseGroup(testCtx, "command_buffers", "Command Buffers Tests"));

	/* 19.1. Command Pools (5.1 in VK 1.0 Spec) */
	addFunctionCase				(commandBuffersTests.get(), "pool_create_null_params",			"",	createPoolNullParamsTest);
	addFunctionCase				(commandBuffersTests.get(), "pool_create_non_null_allocator",	"",	createPoolNonNullAllocatorTest);
	addFunctionCase				(commandBuffersTests.get(), "pool_create_transient_bit",		"",	createPoolTransientBitTest);
	addFunctionCase				(commandBuffersTests.get(), "pool_create_reset_bit",			"",	createPoolResetBitTest);
	addFunctionCase				(commandBuffersTests.get(), "pool_reset_release_res",			"",	resetPoolReleaseResourcesBitTest);
	addFunctionCase				(commandBuffersTests.get(), "pool_reset_no_flags_res",			"",	resetPoolNoFlagsTest);
	addFunctionCase				(commandBuffersTests.get(), "pool_reset_reuse",					"",	checkEventSupport, resetPoolReuseTest);
	/* 19.2. Command Buffer Lifetime (5.2 in VK 1.0 Spec) */
	addFunctionCase				(commandBuffersTests.get(), "allocate_single_primary",			"", allocatePrimaryBufferTest);
	addFunctionCase				(commandBuffersTests.get(), "allocate_many_primary",			"",	allocateManyPrimaryBuffersTest);
	addFunctionCase				(commandBuffersTests.get(), "allocate_single_secondary",		"", allocateSecondaryBufferTest);
	addFunctionCase				(commandBuffersTests.get(), "allocate_many_secondary",			"", allocateManySecondaryBuffersTest);
	addFunctionCase				(commandBuffersTests.get(), "execute_small_primary",			"",	checkEventSupport, executePrimaryBufferTest);
	addFunctionCase				(commandBuffersTests.get(), "execute_large_primary",			"",	checkEventSupport, executeLargePrimaryBufferTest);
	addFunctionCase				(commandBuffersTests.get(), "reset_implicit",					"", checkEventSupport, resetBufferImplicitlyTest);
	addFunctionCase				(commandBuffersTests.get(), "trim_command_pool",				"", checkEventSupport, trimCommandPoolTest, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
	addFunctionCase				(commandBuffersTests.get(), "trim_command_pool_secondary",		"", checkEventSupport, trimCommandPoolTest, VK_COMMAND_BUFFER_LEVEL_SECONDARY);
	/* 19.3. Command Buffer Recording (5.3 in VK 1.0 Spec) */
	addFunctionCase				(commandBuffersTests.get(), "record_single_primary",			"",	checkEventSupport, recordSinglePrimaryBufferTest);
	addFunctionCase				(commandBuffersTests.get(), "record_many_primary",				"", checkEventSupport, recordLargePrimaryBufferTest);
	addFunctionCase				(commandBuffersTests.get(), "record_single_secondary",			"",	checkEventSupport, recordSingleSecondaryBufferTest);
	addFunctionCase				(commandBuffersTests.get(), "record_many_secondary",			"", checkEventSupport, recordLargeSecondaryBufferTest);
	{
		deUint32	seed		= 1614182419u;
		const auto	smallExtent	= makeExtent3D(128u, 128u, 1u);
		const auto	largeExtent	= makeExtent3D(512u, 512u, 1u);

		commandBuffersTests->addChild(new ManyDrawsCase(testCtx, "record_many_draws_primary_1",		"", ManyDrawsParams(VK_COMMAND_BUFFER_LEVEL_PRIMARY,	smallExtent,	seed++)));
		commandBuffersTests->addChild(new ManyDrawsCase(testCtx, "record_many_draws_primary_2",		"", ManyDrawsParams(VK_COMMAND_BUFFER_LEVEL_PRIMARY,	largeExtent,	seed++)));
		commandBuffersTests->addChild(new ManyDrawsCase(testCtx, "record_many_draws_secondary_1",	"", ManyDrawsParams(VK_COMMAND_BUFFER_LEVEL_SECONDARY,	smallExtent,	seed++)));
		commandBuffersTests->addChild(new ManyDrawsCase(testCtx, "record_many_draws_secondary_2",	"", ManyDrawsParams(VK_COMMAND_BUFFER_LEVEL_SECONDARY,	largeExtent,	seed++)));
	}
	addFunctionCase				(commandBuffersTests.get(), "submit_twice_primary",				"",	checkEventSupport, submitPrimaryBufferTwiceTest);
	addFunctionCase				(commandBuffersTests.get(), "submit_twice_secondary",			"",	checkEventSupport, submitSecondaryBufferTwiceTest);
	addFunctionCase				(commandBuffersTests.get(), "record_one_time_submit_primary",	"",	checkEventSupport, oneTimeSubmitFlagPrimaryBufferTest);
	addFunctionCase				(commandBuffersTests.get(), "record_one_time_submit_secondary",	"",	checkEventSupport, oneTimeSubmitFlagSecondaryBufferTest);
	addFunctionCase				(commandBuffersTests.get(), "render_pass_continue",				"",	renderPassContinueTest, true);
	addFunctionCase				(commandBuffersTests.get(), "render_pass_continue_no_fb",		"",	renderPassContinueTest, false);
	addFunctionCase				(commandBuffersTests.get(), "record_simul_use_primary",			"",	checkEventSupport, simultaneousUsePrimaryBufferTest);
	addFunctionCase				(commandBuffersTests.get(), "record_simul_use_secondary",		"",	checkEventSupport, simultaneousUseSecondaryBufferTest);
	addFunctionCaseWithPrograms (commandBuffersTests.get(), "record_simul_use_secondary_one_primary", "", genComputeIncrementSource, simultaneousUseSecondaryBufferOnePrimaryBufferTest);
	addFunctionCaseWithPrograms (commandBuffersTests.get(), "record_simul_use_secondary_two_primary", "", genComputeIncrementSource, simultaneousUseSecondaryBufferTwoPrimaryBuffersTest);
	addFunctionCase				(commandBuffersTests.get(), "record_query_precise_w_flag",		"",	recordBufferQueryPreciseWithFlagTest);
	addFunctionCase				(commandBuffersTests.get(), "record_query_imprecise_w_flag",	"",	recordBufferQueryImpreciseWithFlagTest);
	addFunctionCase				(commandBuffersTests.get(), "record_query_imprecise_wo_flag",	"",	recordBufferQueryImpreciseWithoutFlagTest);
	addFunctionCaseWithPrograms (commandBuffersTests.get(), "bad_inheritance_info_random",		"", genComputeIncrementSourceBadInheritance, badInheritanceInfoTest, BadInheritanceInfoCase::RANDOM_PTR);
	addFunctionCaseWithPrograms (commandBuffersTests.get(), "bad_inheritance_info_random_cont",	"", genComputeIncrementSourceBadInheritance, badInheritanceInfoTest, BadInheritanceInfoCase::RANDOM_PTR_CONTINUATION);
	addFunctionCaseWithPrograms (commandBuffersTests.get(), "bad_inheritance_info_random_data",	"", genComputeIncrementSourceBadInheritance, badInheritanceInfoTest, BadInheritanceInfoCase::RANDOM_DATA_PTR);
	addFunctionCaseWithPrograms (commandBuffersTests.get(), "bad_inheritance_info_invalid_type", "", genComputeIncrementSourceBadInheritance, badInheritanceInfoTest, BadInheritanceInfoCase::INVALID_STRUCTURE_TYPE);
	addFunctionCaseWithPrograms (commandBuffersTests.get(), "bad_inheritance_info_valid_nonsense_type", "", genComputeIncrementSourceBadInheritance, badInheritanceInfoTest, BadInheritanceInfoCase::VALID_NONSENSE_TYPE);
	/* 19.4. Command Buffer Submission (5.4 in VK 1.0 Spec) */
	addFunctionCase				(commandBuffersTests.get(), "submit_count_non_zero",			"", checkEventSupport, submitBufferCountNonZero);
	addFunctionCase				(commandBuffersTests.get(), "submit_count_equal_zero",			"", checkEventSupport, submitBufferCountEqualZero);
	addFunctionCase				(commandBuffersTests.get(), "submit_wait_single_semaphore",		"", checkEventSupport, submitBufferWaitSingleSemaphore);
	addFunctionCase				(commandBuffersTests.get(), "submit_wait_many_semaphores",		"", checkEventSupport, submitBufferWaitManySemaphores);
	addFunctionCase				(commandBuffersTests.get(), "submit_null_fence",				"", checkEventSupport, submitBufferNullFence);
	addFunctionCase				(commandBuffersTests.get(), "submit_two_buffers_one_buffer_null_with_fence", "", checkEventSupport, submitTwoBuffersOneBufferNullWithFence);
	/* 19.5. Secondary Command Buffer Execution (5.6 in VK 1.0 Spec) */
	addFunctionCase				(commandBuffersTests.get(), "secondary_execute",				"",	checkEventSupport, executeSecondaryBufferTest);
	addFunctionCase				(commandBuffersTests.get(), "secondary_execute_twice",			"",	checkEventSupport, executeSecondaryBufferTwiceTest);
	/* 19.6. Commands Allowed Inside Command Buffers (? in VK 1.0 Spec) */
	addFunctionCaseWithPrograms (commandBuffersTests.get(), "order_bind_pipeline",				"", genComputeSource, orderBindPipelineTest);
	/* Verify untested transitions between command buffer states */
	addFunctionCase				(commandBuffersTests.get(), "recording_to_ininitial",			"", executeStateTransitionTest, STT_RECORDING_TO_INITIAL);
	addFunctionCase				(commandBuffersTests.get(), "executable_to_ininitial",			"", executeStateTransitionTest, STT_EXECUTABLE_TO_INITIAL);
	addFunctionCase				(commandBuffersTests.get(), "recording_to_invalid",				"", executeStateTransitionTest, STT_RECORDING_TO_INVALID);
	addFunctionCase				(commandBuffersTests.get(), "executable_to_invalid",			"", executeStateTransitionTest, STT_EXECUTABLE_TO_INVALID);

	return commandBuffersTests.release();
}

} // api
} // vkt

