/*------------------------------------------------------------------------
 * Vulkan Conformance Tests
 * ------------------------
 *
 * Copyright (c) 2016 The Khronos Group 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.
 *
 *//*!
 * \file
 * \brief Synchronization semaphore basic tests
 *//*--------------------------------------------------------------------*/

#include "vktSynchronizationBasicSemaphoreTests.hpp"
#include "vktTestCaseUtil.hpp"
#include "vktSynchronizationUtil.hpp"

#include "vkDefs.hpp"
#include "vkPlatform.hpp"
#include "vkQueryUtil.hpp"
#include "vkCmdUtil.hpp"


#include "vkRef.hpp"

namespace vkt
{
namespace synchronization
{
namespace
{

using namespace vk;

struct TestConfig
{
	bool				useTypeCreate;
	VkSemaphoreTypeKHR	semaphoreType;
};

static const int basicChainLength	= 32768;

Move<VkSemaphore> createTestSemaphore(Context& context, const DeviceInterface& vk, const VkDevice device, const TestConfig& config)
{
	Move<VkSemaphore> semaphore;

	if (config.semaphoreType == VK_SEMAPHORE_TYPE_TIMELINE_KHR && !context.getTimelineSemaphoreFeatures().timelineSemaphore)
		TCU_THROW(NotSupportedError, "Timeline semaphore not supported");

	return Move<VkSemaphore>(config.useTypeCreate ? createSemaphoreType(vk, device, config.semaphoreType) : createSemaphore(vk, device));
}

#define FENCE_WAIT	~0ull

tcu::TestStatus basicOneQueueCase (Context& context, const TestConfig config)
{
	const DeviceInterface&					vk					= context.getDeviceInterface();
	const VkDevice							device				= context.getDevice();
	const VkQueue							queue				= context.getUniversalQueue();
	const deUint32							queueFamilyIndex	= context.getUniversalQueueFamilyIndex();
	const Unique<VkSemaphore>				semaphore			(createTestSemaphore(context, vk, device, config));
	const Unique<VkCommandPool>				cmdPool				(createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
	const Unique<VkCommandBuffer>			cmdBuffer			(makeCommandBuffer(vk, device, *cmdPool));
	const VkCommandBufferBeginInfo			info				=
																{
																	VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,	// VkStructureType                          sType;
																	DE_NULL,										// const void*                              pNext;
																	VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT,	// VkCommandBufferUsageFlags                flags;
																	DE_NULL,										// const VkCommandBufferInheritanceInfo*    pInheritanceInfo;
																};
	const VkPipelineStageFlags				stageBits[]			= { VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT };
	const deUint64							timelineValue		= 1u;
	const VkTimelineSemaphoreSubmitInfoKHR	timelineWaitInfo	=
																{
																	VK_STRUCTURE_TYPE_TIMELINE_SEMAPHORE_SUBMIT_INFO_KHR,	// VkStructureType	sType;
																	DE_NULL,												// const void*		pNext;
																	1u,														// deUint32			waitSemaphoreValueCount
																	&timelineValue,											// const deUint64*	pWaitSemaphoreValues
																	0u,														// deUint32			signalSemaphoreValueCount
																	DE_NULL,												// const deUint64*	pSignalSemaphoreValues
																};
	const VkTimelineSemaphoreSubmitInfoKHR	timelineSignalInfo	=
																{
																	VK_STRUCTURE_TYPE_TIMELINE_SEMAPHORE_SUBMIT_INFO_KHR,	// VkStructureType	sType;
																	DE_NULL,												// const void*		pNext;
																	0u,														// deUint32			waitSemaphoreValueCount
																	DE_NULL,												// const deUint64*	pWaitSemaphoreValues
																	1u,														// deUint32			signalSemaphoreValueCount
																	&timelineValue,											// const deUint64*	pSignalSemaphoreValues
																};
	const VkSubmitInfo						submitInfo[2]		=
																{
																	{
																		VK_STRUCTURE_TYPE_SUBMIT_INFO,															// VkStructureType			sType;
																		config.semaphoreType == VK_SEMAPHORE_TYPE_TIMELINE_KHR ? &timelineSignalInfo : DE_NULL,	// const void*				pNext;
																		0u,																						// deUint32					waitSemaphoreCount;
																		DE_NULL,																				// const VkSemaphore*		pWaitSemaphores;
																		(const VkPipelineStageFlags*)DE_NULL,
																		1u,																						// deUint32					commandBufferCount;
																		&cmdBuffer.get(),																		// const VkCommandBuffer*	pCommandBuffers;
																		1u,																						// deUint32					signalSemaphoreCount;
																		&semaphore.get(),																		// const VkSemaphore*		pSignalSemaphores;
																	},
																	{
																		VK_STRUCTURE_TYPE_SUBMIT_INFO,															// VkStructureType				sType;
																		config.semaphoreType == VK_SEMAPHORE_TYPE_TIMELINE_KHR ? &timelineWaitInfo : DE_NULL,	// const void*					pNext;
																		1u,																						// deUint32						waitSemaphoreCount;
																		&semaphore.get(),																		// const VkSemaphore*			pWaitSemaphores;
																		stageBits,																				// const VkPipelineStageFlags*	pWaitDstStageMask;
																		1u,																						// deUint32						commandBufferCount;
																		&cmdBuffer.get(),																		// const VkCommandBuffer*		pCommandBuffers;
																		0u,																						// deUint32						signalSemaphoreCount;
																		DE_NULL,																				// const VkSemaphore*			pSignalSemaphores;
																	}
																};
	const Unique<VkFence>					fence				(createFence(vk, device));

	VK_CHECK(vk.beginCommandBuffer(*cmdBuffer, &info));
	endCommandBuffer(vk, *cmdBuffer);
	VK_CHECK(vk.queueSubmit(queue, 2u, submitInfo, *fence));

	if (VK_SUCCESS != vk.waitForFences(device, 1u, &fence.get(), DE_TRUE, FENCE_WAIT))
		return tcu::TestStatus::fail("Basic semaphore tests with one queue failed");

	return tcu::TestStatus::pass("Basic semaphore tests with one queue passed");
}

tcu::TestStatus basicChainCase (Context& context)
{
	VkResult					err			= VK_SUCCESS;
	const DeviceInterface&		vk			= context.getDeviceInterface();
	const VkDevice&				device		= context.getDevice();
	const VkQueue				queue		= context.getUniversalQueue();
	VkPipelineStageFlags		flags		= VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
	VkSemaphoreCreateInfo		sci			= { VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO, DE_NULL, 0 };
	VkFenceCreateInfo			fci			= { VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, DE_NULL, 0 };
	std::vector<VkSemaphore>	semaphores;
	VkFence						fence;

	for (int i = 0; err == VK_SUCCESS && i < basicChainLength; i++)
	{
		VkSemaphore				semaphore;
		err = vk.createSemaphore(device, &sci, DE_NULL, &semaphore);
		if (err == VK_SUCCESS)
		{
			semaphores.push_back(semaphore);

			VkSubmitInfo si = { VK_STRUCTURE_TYPE_SUBMIT_INFO,
				DE_NULL,
				semaphores.size() > 1 ? 1u : 0u,
				semaphores.size() > 1 ? &semaphores[semaphores.size() - 2] : DE_NULL,
				&flags,
				0,
				DE_NULL,
				1,
				&semaphores[semaphores.size() - 1] };
			err = vk.queueSubmit(queue, 1, &si, 0);
		}
	}

	VK_CHECK(vk.createFence(device, &fci, DE_NULL, &fence));

	VkSubmitInfo si = { VK_STRUCTURE_TYPE_SUBMIT_INFO, DE_NULL, 1, &semaphores.back(), &flags, 0, DE_NULL, 0, DE_NULL };
	VK_CHECK(vk.queueSubmit(queue, 1, &si, fence));

	vk.waitForFences(device, 1, &fence, VK_TRUE, ~(0ull));

	vk.destroyFence(device, fence, DE_NULL);

	for (unsigned int i = 0; i < semaphores.size(); i++)
		vk.destroySemaphore(device, semaphores[i], DE_NULL);

	if (err == VK_SUCCESS)
		return tcu::TestStatus::pass("Basic semaphore chain test passed");

	return tcu::TestStatus::fail("Basic semaphore chain test failed");
}

tcu::TestStatus basicChainTimelineCase (Context& context)
{
	VkResult						err			= VK_SUCCESS;
	const DeviceInterface&			vk			= context.getDeviceInterface();
	const VkDevice&					device		= context.getDevice();
	const VkQueue					queue		= context.getUniversalQueue();
	VkPipelineStageFlags			flags		= VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
	VkSemaphoreTypeCreateInfoKHR	scti		= { VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO_KHR, DE_NULL, VK_SEMAPHORE_TYPE_TIMELINE_KHR, 0 };
	VkSemaphoreCreateInfo			sci			= { VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO, &scti, 0 };
	VkFenceCreateInfo				fci			= { VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, DE_NULL, 0 };
	VkSemaphore						semaphore;
	VkFence							fence;

	if (!context.getTimelineSemaphoreFeatures().timelineSemaphore)
		TCU_THROW(NotSupportedError, "Timeline semaphore not supported");

	VK_CHECK(vk.createSemaphore(device, &sci, DE_NULL, &semaphore));

	for (int i = 0; err == VK_SUCCESS && i < basicChainLength; i++)
	{
		deUint64							waitValue = i;
		deUint64							signalValue = i + 1;
		VkTimelineSemaphoreSubmitInfoKHR	tsi =
		{
			VK_STRUCTURE_TYPE_TIMELINE_SEMAPHORE_SUBMIT_INFO_KHR,	// VkStructureType	sType;
			DE_NULL,												// const void*		pNext;
			i == 0 ? 0u : 1u,										// deUint32			waitSemaphoreValueCount
			&waitValue,												// const deUint64*	pWaitSemaphoreValues
			1u,														// deUint32			signalSemaphoreValueCount
			&signalValue,											// const deUint64*	pSignalSemaphoreValues
		};
		VkSubmitInfo					si =
		{
			VK_STRUCTURE_TYPE_SUBMIT_INFO,	// VkStructureType				sType;
			&tsi,							// const void*					pNext;
			i == 0 ? 0u : 1u,				// deUint32						waitSemaphoreCount;
			&semaphore,						// const VkSemaphore*			pWaitSemaphores;
			&flags,							// const VkPipelineStageFlags*	pWaitDstStageMask;
			0,								// deUint32						commandBufferCount;
			DE_NULL,						// const VkCommandBuffer*		pCommandBuffers;
			1,								// deUint32						signalSemaphoreCount;
			&semaphore,						// const VkSemaphore*			pSignalSemaphores;
		};
		err = vk.queueSubmit(queue, 1, &si, 0);
	}

	VK_CHECK(vk.createFence(device, &fci, DE_NULL, &fence));

	deUint64							waitValue = basicChainLength;
	VkTimelineSemaphoreSubmitInfoKHR	tsi =
	{
		VK_STRUCTURE_TYPE_TIMELINE_SEMAPHORE_SUBMIT_INFO_KHR,	// VkStructureType	sType;
		DE_NULL,												// const void*		pNext;
		1u,														// deUint32			waitSemaphoreValueCount
		&waitValue,												// const deUint64*	pWaitSemaphoreValues
		0u,														// deUint32			signalSemaphoreValueCount
		DE_NULL,												// const deUint64*	pSignalSemaphoreValues
	};
	VkSubmitInfo					si =
	{
		VK_STRUCTURE_TYPE_SUBMIT_INFO,	// VkStructureType				sType;
		&tsi,							// const void*					pNext;
		1,								// deUint32						waitSemaphoreCount;
		&semaphore,						// const VkSemaphore*			pWaitSemaphores;
		&flags,							// const VkPipelineStageFlags*	pWaitDstStageMask;
		0,								// deUint32						commandBufferCount;
		DE_NULL,						// const VkCommandBuffer*		pCommandBuffers;
		0,								// deUint32						signalSemaphoreCount;
		DE_NULL,						// const VkSemaphore*			pSignalSemaphores;
	};
	VK_CHECK(vk.queueSubmit(queue, 1, &si, fence));

	vk.waitForFences(device, 1, &fence, VK_TRUE, ~(0ull));

	vk.destroyFence(device, fence, DE_NULL);
	vk.destroySemaphore(device, semaphore, DE_NULL);

	if (err == VK_SUCCESS)
		return tcu::TestStatus::pass("Basic semaphore chain test passed");

	return tcu::TestStatus::fail("Basic semaphore chain test failed");
}

tcu::TestStatus basicMultiQueueCase (Context& context, TestConfig config)
{
	enum {NO_MATCH_FOUND = ~((deUint32)0)};
	enum QueuesIndexes {FIRST = 0, SECOND, COUNT};

	struct Queues
	{
		VkQueue		queue;
		deUint32	queueFamilyIndex;
	};


	const DeviceInterface&					vk							= context.getDeviceInterface();
	const InstanceInterface&				instance					= context.getInstanceInterface();
	const VkPhysicalDevice					physicalDevice				= context.getPhysicalDevice();
	vk::Move<vk::VkDevice>					logicalDevice;
	std::vector<VkQueueFamilyProperties>	queueFamilyProperties;
	VkDeviceCreateInfo						deviceInfo;
	VkPhysicalDeviceFeatures				deviceFeatures;
	const float								queuePriorities[COUNT]		= {1.0f, 1.0f};
	VkDeviceQueueCreateInfo					queueInfos[COUNT];
	Queues									queues[COUNT]				=
																		{
																			{DE_NULL, (deUint32)NO_MATCH_FOUND},
																			{DE_NULL, (deUint32)NO_MATCH_FOUND}
																		};
	const VkCommandBufferBeginInfo			info						=
																		{
																			VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,	// VkStructureType                          sType;
																			DE_NULL,										// const void*                              pNext;
																			VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT,	// VkCommandBufferUsageFlags                flags;
																			DE_NULL,										// const VkCommandBufferInheritanceInfo*    pInheritanceInfo;
																		};
	Move<VkSemaphore>						semaphore;
	Move<VkCommandPool>						cmdPool[COUNT];
	Move<VkCommandBuffer>					cmdBuffer[COUNT];
	const VkPipelineStageFlags				stageBits[]					= { VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT };
	VkSubmitInfo							submitInfo[COUNT];
	VkTimelineSemaphoreSubmitInfoKHR		timelineSubmitInfo[COUNT];
	deUint64								timelineValues[COUNT];
	Move<VkFence>							fence[COUNT];

	queueFamilyProperties = getPhysicalDeviceQueueFamilyProperties(instance, physicalDevice);

	for (deUint32 queueNdx = 0; queueNdx < queueFamilyProperties.size(); ++queueNdx)
	{
		if (NO_MATCH_FOUND == queues[FIRST].queueFamilyIndex)
			queues[FIRST].queueFamilyIndex = queueNdx;

		if (queues[FIRST].queueFamilyIndex != queueNdx || queueFamilyProperties[queueNdx].queueCount > 1u)
		{
			queues[SECOND].queueFamilyIndex = queueNdx;
			break;
		}
	}

	if (queues[FIRST].queueFamilyIndex == NO_MATCH_FOUND || queues[SECOND].queueFamilyIndex == NO_MATCH_FOUND)
		TCU_THROW(NotSupportedError, "Queues couldn't be created");

	for (int queueNdx = 0; queueNdx < COUNT; ++queueNdx)
	{
		VkDeviceQueueCreateInfo queueInfo;
		deMemset(&queueInfo, 0, sizeof(queueInfo));

		queueInfo.sType				= VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
		queueInfo.pNext				= DE_NULL;
		queueInfo.flags				= (VkDeviceQueueCreateFlags)0u;
		queueInfo.queueFamilyIndex	= queues[queueNdx].queueFamilyIndex;
		queueInfo.queueCount		= (queues[FIRST].queueFamilyIndex == queues[SECOND].queueFamilyIndex) ? 2 : 1;
		queueInfo.pQueuePriorities	= queuePriorities;

		queueInfos[queueNdx]		= queueInfo;

		if (queues[FIRST].queueFamilyIndex == queues[SECOND].queueFamilyIndex)
			break;
	}

	deMemset(&deviceInfo, 0, sizeof(deviceInfo));
	instance.getPhysicalDeviceFeatures(physicalDevice, &deviceFeatures);

	deviceInfo.sType					= VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
	deviceInfo.pNext					= DE_NULL;
	deviceInfo.enabledExtensionCount	= 0u;
	deviceInfo.ppEnabledExtensionNames	= DE_NULL;
	deviceInfo.enabledLayerCount		= 0u;
	deviceInfo.ppEnabledLayerNames		= DE_NULL;
	deviceInfo.pEnabledFeatures			= &deviceFeatures;
	deviceInfo.queueCreateInfoCount		= (queues[FIRST].queueFamilyIndex == queues[SECOND].queueFamilyIndex) ? 1 : COUNT;
	deviceInfo.pQueueCreateInfos		= queueInfos;

	logicalDevice = vk::createDevice(context.getPlatformInterface(), context.getInstance(), instance, physicalDevice, &deviceInfo);

	for (deUint32 queueReqNdx = 0; queueReqNdx < COUNT; ++queueReqNdx)
	{
		if (queues[FIRST].queueFamilyIndex == queues[SECOND].queueFamilyIndex)
			vk.getDeviceQueue(*logicalDevice, queues[queueReqNdx].queueFamilyIndex, queueReqNdx, &queues[queueReqNdx].queue);
		else
			vk.getDeviceQueue(*logicalDevice, queues[queueReqNdx].queueFamilyIndex, 0u, &queues[queueReqNdx].queue);
	}

	semaphore			= (createTestSemaphore(context, vk, *logicalDevice, config));
	cmdPool[FIRST]		= (createCommandPool(vk, *logicalDevice, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queues[FIRST].queueFamilyIndex));
	cmdPool[SECOND]		= (createCommandPool(vk, *logicalDevice, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queues[SECOND].queueFamilyIndex));
	cmdBuffer[FIRST]	= (makeCommandBuffer(vk, *logicalDevice, *cmdPool[FIRST]));
	cmdBuffer[SECOND]	= (makeCommandBuffer(vk, *logicalDevice, *cmdPool[SECOND]));

	timelineValues[FIRST]									= 1ull;

	timelineSubmitInfo[FIRST].sType							= VK_STRUCTURE_TYPE_TIMELINE_SEMAPHORE_SUBMIT_INFO_KHR;
	timelineSubmitInfo[FIRST].pNext							= DE_NULL;
	timelineSubmitInfo[FIRST].waitSemaphoreValueCount		= 0;
	timelineSubmitInfo[FIRST].pWaitSemaphoreValues			= DE_NULL;
	timelineSubmitInfo[FIRST].signalSemaphoreValueCount		= 1;
	timelineSubmitInfo[FIRST].pSignalSemaphoreValues		= &timelineValues[FIRST];

	submitInfo[FIRST].sType									= VK_STRUCTURE_TYPE_SUBMIT_INFO;
	submitInfo[FIRST].pNext									= config.semaphoreType == VK_SEMAPHORE_TYPE_TIMELINE_KHR ? &timelineSubmitInfo[FIRST] : DE_NULL;
	submitInfo[FIRST].waitSemaphoreCount					= 0u;
	submitInfo[FIRST].pWaitSemaphores						= DE_NULL;
	submitInfo[FIRST].pWaitDstStageMask						= (const VkPipelineStageFlags*)DE_NULL;
	submitInfo[FIRST].commandBufferCount					= 1u;
	submitInfo[FIRST].pCommandBuffers						= &cmdBuffer[FIRST].get();
	submitInfo[FIRST].signalSemaphoreCount					= 1u;
	submitInfo[FIRST].pSignalSemaphores						= &semaphore.get();

	timelineValues[SECOND]									= 2ull;

	timelineSubmitInfo[SECOND].sType						= VK_STRUCTURE_TYPE_TIMELINE_SEMAPHORE_SUBMIT_INFO_KHR;
	timelineSubmitInfo[SECOND].pNext						= DE_NULL;
	timelineSubmitInfo[SECOND].waitSemaphoreValueCount		= 1;
	timelineSubmitInfo[SECOND].pWaitSemaphoreValues			= &timelineValues[FIRST];
	timelineSubmitInfo[SECOND].signalSemaphoreValueCount	= 1;
	timelineSubmitInfo[SECOND].pSignalSemaphoreValues		= &timelineValues[SECOND];

	submitInfo[SECOND].sType								= VK_STRUCTURE_TYPE_SUBMIT_INFO;
	submitInfo[SECOND].pNext								= config.semaphoreType == VK_SEMAPHORE_TYPE_TIMELINE_KHR ? &timelineSubmitInfo[SECOND] : DE_NULL;
	submitInfo[SECOND].waitSemaphoreCount					= 1u;
	submitInfo[SECOND].pWaitSemaphores						= &semaphore.get();
	submitInfo[SECOND].pWaitDstStageMask					= stageBits;
	submitInfo[SECOND].commandBufferCount					= 1u;
	submitInfo[SECOND].pCommandBuffers						= &cmdBuffer[SECOND].get();
	submitInfo[SECOND].signalSemaphoreCount					= 0u;
	submitInfo[SECOND].pSignalSemaphores					= DE_NULL;

	VK_CHECK(vk.beginCommandBuffer(*cmdBuffer[FIRST], &info));
	endCommandBuffer(vk, *cmdBuffer[FIRST]);
	VK_CHECK(vk.beginCommandBuffer(*cmdBuffer[SECOND], &info));
	endCommandBuffer(vk, *cmdBuffer[SECOND]);

	fence[FIRST]  = (createFence(vk, *logicalDevice));
	fence[SECOND] = (createFence(vk, *logicalDevice));

	VK_CHECK(vk.queueSubmit(queues[FIRST].queue, 1u, &submitInfo[FIRST], *fence[FIRST]));
	VK_CHECK(vk.queueSubmit(queues[SECOND].queue, 1u, &submitInfo[SECOND], *fence[SECOND]));

	if (VK_SUCCESS != vk.waitForFences(*logicalDevice, 1u, &fence[FIRST].get(), DE_TRUE, FENCE_WAIT))
		return tcu::TestStatus::fail("Basic semaphore tests with multi queue failed");

	if (VK_SUCCESS != vk.waitForFences(*logicalDevice, 1u, &fence[SECOND].get(), DE_TRUE, FENCE_WAIT))
		return tcu::TestStatus::fail("Basic semaphore tests with multi queue failed");

	{
		VkSubmitInfo swapInfo				= submitInfo[SECOND];
		submitInfo[SECOND]					= submitInfo[FIRST];
		submitInfo[FIRST]					= swapInfo;
		submitInfo[SECOND].pCommandBuffers	= &cmdBuffer[SECOND].get();
		submitInfo[FIRST].pCommandBuffers	= &cmdBuffer[FIRST].get();
	}

	VK_CHECK(vk.resetFences(*logicalDevice, 1u, &fence[FIRST].get()));
	VK_CHECK(vk.resetFences(*logicalDevice, 1u, &fence[SECOND].get()));

	if (config.semaphoreType == VK_SEMAPHORE_TYPE_TIMELINE_KHR)
	{
		timelineValues[FIRST]	= 3ull;
		timelineValues[SECOND]	= 4ull;
	}

	VK_CHECK(vk.queueSubmit(queues[SECOND].queue, 1u, &submitInfo[SECOND], *fence[SECOND]));
	VK_CHECK(vk.queueSubmit(queues[FIRST].queue, 1u, &submitInfo[FIRST], *fence[FIRST]));

	if (VK_SUCCESS != vk.waitForFences(*logicalDevice, 1u, &fence[FIRST].get(), DE_TRUE, FENCE_WAIT))
		return tcu::TestStatus::fail("Basic semaphore tests with multi queue failed");

	if (VK_SUCCESS != vk.waitForFences(*logicalDevice, 1u, &fence[SECOND].get(), DE_TRUE, FENCE_WAIT))
		return tcu::TestStatus::fail("Basic semaphore tests with multi queue failed");

	return tcu::TestStatus::pass("Basic semaphore tests with multi queue passed");
}

} // anonymous

tcu::TestCaseGroup* createBasicBinarySemaphoreTests (tcu::TestContext& testCtx)
{
	de::MovePtr<tcu::TestCaseGroup> basicTests(new tcu::TestCaseGroup(testCtx, "binary_semaphore", "Basic semaphore tests"));

	for (deUint32 typedCreate = 0; typedCreate < 2; typedCreate++)
	{
		const TestConfig config =
		{
			typedCreate != 0,
			VK_SEMAPHORE_TYPE_BINARY_KHR,
		};
		const std::string createName = config.useTypeCreate ? "_typed" : "";

			addFunctionCase(basicTests.get(), "one_queue" + createName,   "Basic binary semaphore tests with one queue",   basicOneQueueCase, config);
			addFunctionCase(basicTests.get(), "multi_queue" + createName, "Basic binary semaphore tests with multi queue", basicMultiQueueCase, config);
	}

	addFunctionCase(basicTests.get(), "chain", "Binary semaphore chain test", basicChainCase);

	return basicTests.release();
}

tcu::TestCaseGroup* createBasicTimelineSemaphoreTests (tcu::TestContext& testCtx)
{
	de::MovePtr<tcu::TestCaseGroup> basicTests(new tcu::TestCaseGroup(testCtx, "timeline_semaphore", "Basic timeline semaphore tests"));
	const TestConfig				config =
	{
		true,
		VK_SEMAPHORE_TYPE_TIMELINE_KHR,
	};

	addFunctionCase(basicTests.get(), "one_queue",   "Basic timeline semaphore tests with one queue",   basicOneQueueCase, config);
	addFunctionCase(basicTests.get(), "multi_queue", "Basic timeline semaphore tests with multi queue", basicMultiQueueCase, config);
	addFunctionCase(basicTests.get(), "chain", "Timeline semaphore chain test", basicChainTimelineCase);

	return basicTests.release();
}

} // synchronization
} // vkt
