/*------------------------------------------------------------------------
 * 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 Queue bind sparse tests
 *//*--------------------------------------------------------------------*/

#include "vktSparseResourcesQueueBindSparseTests.hpp"
#include "vktSparseResourcesTestsUtil.hpp"
#include "vktSparseResourcesBase.hpp"
#include "vktTestGroupUtil.hpp"

#include "vkDefs.hpp"
#include "vkRefUtil.hpp"
#include "vkMemUtil.hpp"
#include "vkTypeUtil.hpp"
#include "vkQueryUtil.hpp"

#include "deUniquePtr.hpp"
#include "deSharedPtr.hpp"

#include <string>
#include <vector>

using namespace vk;
using de::MovePtr;

namespace vkt
{
namespace sparse
{
namespace
{

typedef de::SharedPtr<Unique<VkSemaphore> >	SemaphoreSp;
typedef de::SharedPtr<Unique<VkFence> >		FenceSp;

struct TestParams
{
	deUint32	numQueues;					//! use 2 or more to sync between different queues
	deUint32	numWaitSemaphores;
	deUint32	numSignalSemaphores;
	bool		emptySubmission;			//! will make an empty bind sparse submission
	bool		bindSparseUseFence;
};

struct QueueSubmission
{
	union InfoUnion
	{
		VkSubmitInfo		regular;
		VkBindSparseInfo	sparse;
	};

	const Queue*			queue;
	bool					isSparseBinding;
	InfoUnion				info;
};

QueueSubmission makeSubmissionRegular	(const Queue*					queue,
										 const deUint32					numWaitSemaphores,
										 const VkSemaphore*				pWaitSemaphore,
										 const VkPipelineStageFlags*	pWaitDstStageMask,
										 const deUint32					numSignalSemaphores,
										 const VkSemaphore*				pSignalSemaphore)
{
	const VkSubmitInfo submitInfo =
	{
		VK_STRUCTURE_TYPE_SUBMIT_INFO,	// VkStructureType				sType;
		DE_NULL,						// const void*					pNext;
		numWaitSemaphores,				// uint32_t						waitSemaphoreCount;
		pWaitSemaphore,					// const VkSemaphore*			pWaitSemaphores;
		pWaitDstStageMask,				// const VkPipelineStageFlags*	pWaitDstStageMask;
		0u,								// uint32_t						commandBufferCount;
		DE_NULL,						// const VkCommandBuffer*		pCommandBuffers;
		numSignalSemaphores,			// uint32_t						signalSemaphoreCount;
		pSignalSemaphore,				// const VkSemaphore*			pSignalSemaphores;
	};

	QueueSubmission submission;
	submission.isSparseBinding	= false;
	submission.queue			= queue;
	submission.info.regular		= submitInfo;

	return submission;
}

QueueSubmission makeSubmissionSparse	(const Queue*		queue,
										 const deUint32		numWaitSemaphores,
										 const VkSemaphore*	pWaitSemaphore,
										 const deUint32		numSignalSemaphores,
										 const VkSemaphore*	pSignalSemaphore)
{
	const VkBindSparseInfo bindInfo =
	{
		VK_STRUCTURE_TYPE_BIND_SPARSE_INFO,			// VkStructureType							sType;
		DE_NULL,									// const void*								pNext;
		numWaitSemaphores,							// uint32_t									waitSemaphoreCount;
		pWaitSemaphore,								// const VkSemaphore*						pWaitSemaphores;
		0u,											// uint32_t									bufferBindCount;
		DE_NULL,									// const VkSparseBufferMemoryBindInfo*		pBufferBinds;
		0u,											// uint32_t									imageOpaqueBindCount;
		DE_NULL,									// const VkSparseImageOpaqueMemoryBindInfo*	pImageOpaqueBinds;
		0u,											// uint32_t									imageBindCount;
		DE_NULL,									// const VkSparseImageMemoryBindInfo*		pImageBinds;
		numSignalSemaphores,						// uint32_t									signalSemaphoreCount;
		pSignalSemaphore,							// const VkSemaphore*						pSignalSemaphores;
	};

	QueueSubmission submission;
	submission.isSparseBinding	= true;
	submission.queue			= queue;
	submission.info.sparse		= bindInfo;

	return submission;
}

bool waitForFences (const DeviceInterface& vk, const VkDevice device, const std::vector<FenceSp>& fences)
{
	for (std::vector<FenceSp>::const_iterator fenceSpIter = fences.begin(); fenceSpIter != fences.end(); ++fenceSpIter)
	{
		if (vk.waitForFences(device, 1u, &(***fenceSpIter), VK_TRUE, ~0ull) != VK_SUCCESS)
			return false;
	}
	return true;
}

class SparseQueueBindTestInstance : public SparseResourcesBaseInstance
{
public:
	SparseQueueBindTestInstance (Context &context, const TestParams& params)
		: SparseResourcesBaseInstance	(context)
		, m_params						(params)
	{
		DE_ASSERT(m_params.numQueues > 0u);		// must use at least one queue
		DE_ASSERT(!m_params.emptySubmission || (m_params.numWaitSemaphores == 0u && m_params.numSignalSemaphores == 0u));	// can't use semaphores if we don't submit
	}

	tcu::TestStatus iterate (void)
	{
		const Queue*				sparseQueue	= DE_NULL;
		std::vector<const Queue*>	otherQueues;

		// Determine required queues and create a device that supports them
		{
			QueueRequirementsVec requirements;
			requirements.push_back(QueueRequirements(VK_QUEUE_SPARSE_BINDING_BIT, 1u));
			requirements.push_back(QueueRequirements((VkQueueFlags)0, m_params.numQueues));		// any queue flags

			createDeviceSupportingQueues(requirements);

			sparseQueue = &getQueue(VK_QUEUE_SPARSE_BINDING_BIT, 0u);

			// We probably have picked the sparse queue again, so filter it out
			for (deUint32 queueNdx = 0u; queueNdx < m_params.numQueues; ++queueNdx)
			{
				const Queue* queue = &getQueue((VkQueueFlags)0, queueNdx);
				if (queue->queueHandle != sparseQueue->queueHandle)
					otherQueues.push_back(queue);
			}
		}

		const DeviceInterface&				vk = getDeviceInterface();

		std::vector<SemaphoreSp>			allSemaphores;
		std::vector<VkSemaphore>			waitSemaphores;
		std::vector<VkSemaphore>			signalSemaphores;
		std::vector<VkPipelineStageFlags>	signalSemaphoresWaitDstStageMask;
		std::vector<QueueSubmission>		queueSubmissions;

		for (deUint32 i = 0; i < m_params.numWaitSemaphores; ++i)
		{
			allSemaphores.push_back(makeVkSharedPtr(createSemaphore(vk, getDevice())));
			waitSemaphores.push_back(**allSemaphores.back());
		}

		for (deUint32 i = 0; i < m_params.numSignalSemaphores; ++i)
		{
			allSemaphores.push_back(makeVkSharedPtr(createSemaphore(vk, getDevice())));
			signalSemaphores.push_back(**allSemaphores.back());
			signalSemaphoresWaitDstStageMask.push_back(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT);
		}

		// Prepare submissions: signal semaphores for the sparse bind operation
		{
			deUint32 numQueues		= 1u + static_cast<deUint32>(otherQueues.size());
			deUint32 numSemaphores	= m_params.numWaitSemaphores;

			while (numSemaphores > 0u && numQueues > 0u)
			{
				if (numQueues == 1u)	// sparse queue is assigned last
				{
					// sparse queue can handle regular submissions as well
					queueSubmissions.push_back(makeSubmissionRegular(
						sparseQueue, 0u, DE_NULL, DE_NULL, numSemaphores, getDataOrNullptr(waitSemaphores)));
					numSemaphores	= 0u;
					numQueues		= 0u;
				}
				else
				{
					queueSubmissions.push_back(makeSubmissionRegular(
						otherQueues[numQueues - 2], 0u, DE_NULL, DE_NULL, 1u, getDataOrNullptr(waitSemaphores, numSemaphores - 1)));
					--numQueues;
					--numSemaphores;
				}
			}
		}

		// Prepare submission: bind sparse
		if (!m_params.emptySubmission)
		{
			queueSubmissions.push_back(makeSubmissionSparse(
				sparseQueue, m_params.numWaitSemaphores, getDataOrNullptr(waitSemaphores), m_params.numSignalSemaphores, getDataOrNullptr(signalSemaphores)));
		}
		else
		{
			// an unused submission, won't be used in a call to vkQueueBindSparse
			queueSubmissions.push_back(makeSubmissionSparse(sparseQueue, 0u, DE_NULL, 0u, DE_NULL));
		}

		// Prepare submissions: wait on semaphores signaled by the sparse bind operation
		if (!m_params.emptySubmission)
		{
			deUint32 numQueues		= 1u + static_cast<deUint32>(otherQueues.size());
			deUint32 numSemaphores	= m_params.numSignalSemaphores;

			while (numSemaphores > 0u && numQueues > 0u)
			{
				if (numQueues == 1u)
				{
					queueSubmissions.push_back(makeSubmissionRegular(
						sparseQueue, numSemaphores, getDataOrNullptr(signalSemaphores), getDataOrNullptr(signalSemaphoresWaitDstStageMask), 0u, DE_NULL));
					numSemaphores	= 0u;
					numQueues		= 0u;
				}
				else
				{
					queueSubmissions.push_back(makeSubmissionRegular(
						otherQueues[numQueues - 2], 1u, getDataOrNullptr(signalSemaphores, numSemaphores - 1), getDataOrNullptr(signalSemaphoresWaitDstStageMask, numSemaphores - 1), 0u, DE_NULL));
					--numQueues;
					--numSemaphores;
				}
			}
		}

		// Submit to queues
		{
			std::vector<FenceSp>	regularFences;
			std::vector<FenceSp>	bindSparseFences;

			for (std::vector<QueueSubmission>::const_iterator submissionIter = queueSubmissions.begin(); submissionIter != queueSubmissions.end(); ++submissionIter)
			{
				if (submissionIter->isSparseBinding)
				{
					VkFence fence = DE_NULL;

					if (m_params.bindSparseUseFence)
					{
						bindSparseFences.push_back(makeVkSharedPtr(createFence(vk, getDevice())));
						fence = **bindSparseFences.back();
					}

					if (m_params.emptySubmission)
						VK_CHECK(vk.queueBindSparse(submissionIter->queue->queueHandle, 0u, DE_NULL, fence));
					else
						VK_CHECK(vk.queueBindSparse(submissionIter->queue->queueHandle, 1u, &submissionIter->info.sparse, fence));
				}
				else
				{
					regularFences.push_back(makeVkSharedPtr(createFence(vk, getDevice())));
					VK_CHECK(vk.queueSubmit(submissionIter->queue->queueHandle, 1u, &submissionIter->info.regular, **regularFences.back()));
				}
			}

			if (!waitForFences(vk, getDevice(), bindSparseFences))
				return tcu::TestStatus::fail("vkQueueBindSparse didn't signal the fence");

			if (!waitForFences(vk, getDevice(), regularFences))
				return tcu::TestStatus::fail("Some fences weren't signaled (vkQueueBindSparse didn't signal semaphores?)");
		}

		// May return an error if some waitSemaphores didn't get signaled
		VK_CHECK(vk.deviceWaitIdle(getDevice()));

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

private:
	const TestParams	m_params;
};

class SparseQueueBindTest : public TestCase
{
public:
					SparseQueueBindTest	(tcu::TestContext& testCtx, const std::string& name, const std::string& description, const TestParams& params)
		: TestCase	(testCtx, name, description)
		, m_params	(params)
	{
		DE_ASSERT(params.numQueues > 0u);
		DE_ASSERT(params.numQueues == 1u || m_params.numWaitSemaphores > 0u || m_params.numSignalSemaphores > 0u);	// without any semaphores, only sparse queue will be used
	}

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

	virtual void	checkSupport		(Context& context) const
	{
		context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_SPARSE_BINDING);
	}

private:
	const TestParams	m_params;
};

void populateTestGroup(tcu::TestCaseGroup* group)
{
	const struct
	{
		std::string		name;
		TestParams		params;
		std::string		description;
	} cases[] =
	{
		// case name									// numQueues, numWaitSems, numSignalSems, emptySubmission, checkFence
		{ "no_dependency",								{	1u,	0u,	0u,	false,	false,	}, "submit without any semaphores", },
		{ "no_dependency_fence",						{	1u,	0u,	0u,	false,	true,	}, "submit without any semaphores, signal a fence", },

		{ "single_queue_wait_one",						{	1u,	1u,	0u,	false,	true,	}, "only sparse queue, wait for semaphore(s)", },
		{ "single_queue_wait_many",						{	1u,	3u,	0u,	false,	true,	}, "only sparse queue, wait for semaphore(s)", },
		{ "single_queue_signal_one",					{	1u,	0u,	1u,	false,	true,	}, "only sparse queue, signal semaphore(s)", },
		{ "single_queue_signal_many",					{	1u,	0u,	3u,	false,	true,	}, "only sparse queue, signal semaphore(s)", },
		{ "single_queue_wait_one_signal_one",			{	1u,	1u,	1u,	false,	true,	}, "only sparse queue, wait for and signal semaphore(s)", },
		{ "single_queue_wait_many_signal_many",			{	1u,	2u,	3u,	false,	true,	}, "only sparse queue, wait for and signal semaphore(s)", },

		{ "multi_queue_wait_one",						{	2u,	1u,	0u,	false,	true,	}, "sparse and other queues, wait for semaphore(s)", },
		{ "multi_queue_wait_many",						{	2u,	2u,	0u,	false,	true,	}, "sparse and other queues, wait for semaphore(s)", },
		{ "multi_queue_signal_one",						{	2u,	0u,	1u,	false,	true,	}, "sparse and other queues, signal semaphore(s)", },
		{ "multi_queue_signal_many",					{	2u,	0u,	2u,	false,	true,	}, "sparse and other queues, signal semaphore(s)", },
		{ "multi_queue_wait_one_signal_one",			{	2u,	1u,	1u,	false,	true,	}, "sparse and other queues, wait for and signal semaphore(s)", },
		{ "multi_queue_wait_many_signal_many",			{	2u,	2u,	2u,	false,	true,	}, "sparse and other queues, wait for and signal semaphore(s)", },
		{ "multi_queue_wait_one_signal_one_other",		{	2u,	1u,	1u,	false,	true,	}, "sparse and other queues, wait for and signal semaphore(s) on other queues", },
		{ "multi_queue_wait_many_signal_many_other",	{	3u,	2u,	2u,	false,	true,	}, "sparse and other queues, wait for and signal semaphore(s) on other queues", },

		{ "empty",										{	1u,	0u,	0u,	true,	false,	}, "call vkQueueBindSparse with zero bindInfos", },
		{ "empty_fence",								{	1u,	0u,	0u,	true,	true,	}, "call vkQueueBindSparse with zero bindInfos, signal a fence", },
	};

	for (int caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(cases); ++caseNdx)
		group->addChild(new SparseQueueBindTest(group->getTestContext(), cases[caseNdx].name, cases[caseNdx].description, cases[caseNdx].params));
}

} // anonymous ns

//! Sparse queue binding edge cases and synchronization with semaphores/fences.
//! Actual binding and usage is tested by other test groups.
tcu::TestCaseGroup* createQueueBindSparseTests (tcu::TestContext& testCtx)
{
	return createTestGroup(testCtx, "queue_bind", "Queue bind sparse tests", populateTestGroup);
}

} // sparse
} // vkt
