/*------------------------------------------------------------------------
 * 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
		{
			// a dummy 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
