/*------------------------------------------------------------------------
 * 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 fence basic tests
 *//*--------------------------------------------------------------------*/

#include "vktSynchronizationBasicFenceTests.hpp"
#include "vktTestCaseUtil.hpp"
#include "vktSynchronizationUtil.hpp"

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

namespace vkt
{
namespace synchronization
{
namespace
{
using namespace vk;

static const deUint64	SHORT_FENCE_WAIT	= 1000ull;			// 1us
static const deUint64	LONG_FENCE_WAIT		= 1000000000ull;	// 1s

tcu::TestStatus basicOneFenceCase (Context& context)
{
	const DeviceInterface&			vk					= context.getDeviceInterface();
	const VkDevice					device				= context.getDevice();
	const VkQueue					queue				= context.getUniversalQueue();
	const deUint32					queueFamilyIndex	= context.getUniversalQueueFamilyIndex();
	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 VkFenceCreateInfo			fenceInfo			=
	{
		VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,	// VkStructureType      sType;
		DE_NULL,								// const void*          pNext;
		0u,										// VkFenceCreateFlags   flags;
	};

	const Unique<VkFence>			fence				(createFence(vk, device, &fenceInfo));

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

	if (VK_NOT_READY != vk.getFenceStatus(device, *fence))
		return tcu::TestStatus::fail("Created fence should be in unsignaled state");

	if (VK_TIMEOUT != vk.waitForFences(device, 1u, &fence.get(), VK_TRUE, SHORT_FENCE_WAIT))
		return tcu::TestStatus::fail("vkWaitForFences should return VK_TIMEOUT");

	if (VK_NOT_READY != vk.getFenceStatus(device, *fence))
		return tcu::TestStatus::fail("Created fence should be in unsignaled state");

	beginCommandBuffer(vk, *cmdBuffer);
	endCommandBuffer(vk, *cmdBuffer);

	VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo, *fence));

	if (VK_SUCCESS != vk.waitForFences(device, 1u, &fence.get(), DE_TRUE, LONG_FENCE_WAIT))
		return tcu::TestStatus::fail("vkWaitForFences should return VK_SUCCESS");

	if (VK_SUCCESS != vk.getFenceStatus(device, *fence))
		return tcu::TestStatus::fail("Fence should be in signaled state");

	if (VK_SUCCESS != vk.resetFences(device, 1u, &fence.get()))
		return tcu::TestStatus::fail("Couldn't reset the fence");

	if (VK_NOT_READY != vk.getFenceStatus(device, *fence))
		return tcu::TestStatus::fail("Fence after reset should be in unsignaled state");

	return tcu::TestStatus::pass("Basic one fence tests passed");
}

tcu::TestStatus basicMultiFenceCase (Context& context)
{
	enum
	{
		FIRST_FENCE = 0,
		SECOND_FENCE
	};

	const DeviceInterface&			vk					= context.getDeviceInterface();
	const VkDevice					device				= context.getDevice();
	const VkQueue					queue				= context.getUniversalQueue();
	const deUint32					queueFamilyIndex	= context.getUniversalQueueFamilyIndex();
	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 VkFenceCreateInfo			fenceInfo			=
	{
		VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,	// VkStructureType      sType;
		DE_NULL,								// const void*          pNext;
		0u,										// VkFenceCreateFlags   flags;
	};

	const Move<VkFence>				ptrFence[2]			=
	{
		createFence(vk, device, &fenceInfo),
		createFence(vk, device, &fenceInfo)
	};

	const VkFence					fence[2]			=
	{
		*ptrFence[FIRST_FENCE],
		*ptrFence[SECOND_FENCE]
	};

	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 VkSubmitInfo				submitInfo			=
	{
		VK_STRUCTURE_TYPE_SUBMIT_INFO,			// VkStructureType                sType;
		DE_NULL,								// const void*                    pNext;
		0u,										// deUint32                       waitSemaphoreCount;
		DE_NULL,								// const VkSemaphore*             pWaitSemaphores;
		(const VkPipelineStageFlags*)DE_NULL,	// const VkPipelineStageFlags*    pWaitDstStageMask;
		1u,										// deUint32                       commandBufferCount;
		&cmdBuffer.get(),						// const VkCommandBuffer*         pCommandBuffers;
		0u,										// deUint32                       signalSemaphoreCount;
		DE_NULL,								// const VkSemaphore*             pSignalSemaphores;
	};

	VK_CHECK(vk.beginCommandBuffer(*cmdBuffer, &info));
	endCommandBuffer(vk, *cmdBuffer);

	VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo, fence[FIRST_FENCE]));

	if (VK_SUCCESS != vk.waitForFences(device, 1u, &fence[FIRST_FENCE], DE_FALSE, LONG_FENCE_WAIT))
		return tcu::TestStatus::fail("vkWaitForFences should return VK_SUCCESS");

	if (VK_SUCCESS != vk.resetFences(device, 1u, &fence[FIRST_FENCE]))
		return tcu::TestStatus::fail("Couldn't reset the fence");

	VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo, fence[FIRST_FENCE]));

	if (VK_TIMEOUT != vk.waitForFences(device, 2u, &fence[FIRST_FENCE], DE_TRUE, SHORT_FENCE_WAIT))
		return tcu::TestStatus::fail("vkWaitForFences should return VK_TIMEOUT");

	VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo, fence[SECOND_FENCE]));

	if (VK_SUCCESS != vk.waitForFences(device, 2u, &fence[FIRST_FENCE], DE_TRUE, LONG_FENCE_WAIT))
		return tcu::TestStatus::fail("vkWaitForFences should return VK_SUCCESS");

	return tcu::TestStatus::pass("Basic multi fence tests passed");
}

tcu::TestStatus emptySubmitCase (Context& context)
{
	const DeviceInterface&			vk					= context.getDeviceInterface();
	const VkDevice					device				= context.getDevice();
	const VkQueue					queue				= context.getUniversalQueue();

	const VkFenceCreateInfo			fenceCreateInfo		=
	{
		VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,	// VkStructureType       sType;
		DE_NULL,								// const void*           pNext;
		(VkFenceCreateFlags)0,					// VkFenceCreateFlags    flags;
	};

	const Unique<VkFence>			fence				(createFence(vk, device, &fenceCreateInfo));

	VK_CHECK(vk.queueSubmit(queue, 0u, DE_NULL, *fence));

	if (VK_SUCCESS != vk.waitForFences(device, 1u, &fence.get(), DE_TRUE, LONG_FENCE_WAIT))
		return tcu::TestStatus::fail("vkWaitForFences should return VK_SUCCESS");

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

tcu::TestStatus basicMultiFenceWaitAllFalseCase (Context& context)
{
	enum
	{
		FIRST_FENCE = 0,
		SECOND_FENCE
	};

	const DeviceInterface&			vk					= context.getDeviceInterface();
	const VkDevice					device				= context.getDevice();
	const VkQueue					queue				= context.getUniversalQueue();
	const deUint32					queueFamilyIndex	= context.getUniversalQueueFamilyIndex();
	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 VkFenceCreateInfo			fenceInfo			=
	{
		VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,	// VkStructureType     sType;
		DE_NULL,								// const void*         pNext;
		0u,										// VkFenceCreateFlags  flags;
	};

	const Move<VkFence>				ptrFence[2]			=
	{
		createFence(vk, device, &fenceInfo),
		createFence(vk, device, &fenceInfo)
	};

	const VkFence					fence[2]			=
	{
		*ptrFence[FIRST_FENCE],
		*ptrFence[SECOND_FENCE]
	};

	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 VkSubmitInfo				submitInfo			=
	{
		VK_STRUCTURE_TYPE_SUBMIT_INFO,			// VkStructureType                sType;
		DE_NULL,								// const void*                    pNext;
		0u,										// deUint32                       waitSemaphoreCount;
		DE_NULL,								// const VkSemaphore*             pWaitSemaphores;
		(const VkPipelineStageFlags*)DE_NULL,	// const VkPipelineStageFlags*    pWaitDstStageMask;
		1u,										// deUint32                       commandBufferCount;
		&cmdBuffer.get(),						// const VkCommandBuffer*         pCommandBuffers;
		0u,										// deUint32                       signalSemaphoreCount;
		DE_NULL,								// const VkSemaphore*             pSignalSemaphores;
	};

	VK_CHECK(vk.beginCommandBuffer(*cmdBuffer, &info));
	endCommandBuffer(vk, *cmdBuffer);


	if (VK_TIMEOUT != vk.waitForFences(device, 2u, &fence[FIRST_FENCE], DE_FALSE, SHORT_FENCE_WAIT))
		return tcu::TestStatus::fail("vkWaitForFences should return VK_TIMEOUT for case: Wait for any fence (No fence has been signaled)");

	if (VK_TIMEOUT != vk.waitForFences(device, 2u, &fence[FIRST_FENCE], DE_TRUE, SHORT_FENCE_WAIT))
		return tcu::TestStatus::fail("vkWaitForFences should return VK_TIMEOUT for case: Wait for all fences (No fence has been signaled)");

	VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo, fence[SECOND_FENCE]));

	if (VK_SUCCESS != vk.waitForFences(device, 2u, &fence[FIRST_FENCE], DE_FALSE, LONG_FENCE_WAIT))
		return tcu::TestStatus::fail("vkWaitForFences should return VK_SUCCESS for case: Wait for any fence (Only second fence signaled)");

	if (VK_TIMEOUT != vk.waitForFences(device, 2u, &fence[FIRST_FENCE], DE_TRUE, SHORT_FENCE_WAIT))
		return tcu::TestStatus::fail("vkWaitForFences should return VK_TIMEOUT for case: Wait for all fences (Only second fence signaled)");

	VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo, fence[FIRST_FENCE]));

	if (VK_SUCCESS != vk.waitForFences(device, 2u, &fence[FIRST_FENCE], DE_FALSE, LONG_FENCE_WAIT))
		return tcu::TestStatus::fail("vkWaitForFences should return VK_SUCCESS for case: Wait for any fence (All fences signaled)");

	if (VK_SUCCESS != vk.waitForFences(device, 2u, &fence[FIRST_FENCE], DE_TRUE, LONG_FENCE_WAIT))
		return tcu::TestStatus::fail("vkWaitForFences should return VK_SUCCESS for case: Wait for all fences (All fences signaled)");

	return tcu::TestStatus::pass("Basic multi fence test without waitAll passed");
}

} // anonymous

tcu::TestCaseGroup* createBasicFenceTests (tcu::TestContext& testCtx)
{
	de::MovePtr<tcu::TestCaseGroup> basicFenceTests(new tcu::TestCaseGroup(testCtx, "fence", "Basic fence tests"));
	addFunctionCase(basicFenceTests.get(),	"one",					"Basic one fence tests",							basicOneFenceCase);
	addFunctionCase(basicFenceTests.get(),	"multi",				"Basic multi fence tests",							basicMultiFenceCase);
	addFunctionCase(basicFenceTests.get(),	"empty_submit",			"Signal a fence after an empty queue submission",	emptySubmitCase);
	addFunctionCase(basicFenceTests.get(),	"multi_waitall_false",	"Basic multi fence test without waitAll",			basicMultiFenceWaitAllFalseCase);

	return basicFenceTests.release();
}

} // synchronization
} // vkt
