/*------------------------------------------------------------------------
 * Vulkan Conformance Tests
 * ------------------------
 *
 * Copyright (c) 2021 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  Vulkan SC VkCommandPoolMemoryReservationCreateInfo tests
*//*--------------------------------------------------------------------*/

#include "vktCommandPoolMemoryReservationTests.hpp"

#include <set>
#include <vector>
#include <string>

#include "vkRefUtil.hpp"
#include "vktTestCaseUtil.hpp"
#include "vkSafetyCriticalUtil.hpp"
#include "tcuTestLog.hpp"

namespace vkt
{
namespace sc
{

using namespace vk;

namespace
{

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

enum CommandPoolReservedSize
{
	CPS_UNUSED = 0,
	CPS_SMALL,
	CPS_BIG
};

struct TestParams
{
	CommandPoolReservedSize	commandPoolReservedSize;
	deUint32				commandBufferCount;
	deUint32				iterations;
	bool					multipleRecording;
};

void beginCommandBuffer (const DeviceInterface& vk, const VkCommandBuffer commandBuffer, VkCommandBufferUsageFlags flags)
{
	const VkCommandBufferBeginInfo commandBufBeginParams =
	{
		VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,	// VkStructureType                  sType;
		DE_NULL,										// const void*                      pNext;
		flags,											// VkCommandBufferUsageFlags        flags;
		(const VkCommandBufferInheritanceInfo*)DE_NULL,
	};
	VK_CHECK(vk.beginCommandBuffer(commandBuffer, &commandBufBeginParams));
}

void endCommandBuffer (const DeviceInterface& vk, const VkCommandBuffer commandBuffer)
{
	VK_CHECK(vk.endCommandBuffer(commandBuffer));
}


// verify that VkCommandPoolMemoryReservationCreateInfo::commandPoolReservedSize == VkCommandPoolMemoryConsumption::commandPoolReservedSize
tcu::TestStatus verifyCommandPoolReservedSize (Context& context, TestParams testParams)
{
	const VkDevice							device					= context.getDevice();
	const DeviceInterface&					vk						= context.getDeviceInterface();
	const deUint32							queueFamilyIndex		= context.getUniversalQueueFamilyIndex();

	if ( testParams.commandBufferCount >  context.getDeviceVulkanSC10Properties().maxCommandPoolCommandBuffers )
		TCU_THROW(NotSupportedError, "commandBufferCount is greater than maxCommandPoolCommandBuffers");

	VkDeviceSize							commandPoolReservedSize	= 0u;
	switch (testParams.commandPoolReservedSize)
	{
		case CPS_SMALL:
			commandPoolReservedSize = de::max(VkDeviceSize(64u * context.getTestContext().getCommandLine().getCommandDefaultSize()), VkDeviceSize(context.getTestContext().getCommandLine().getCommandPoolMinSize()) );
			break;
		case CPS_BIG:
			commandPoolReservedSize = de::max(VkDeviceSize(8192u * context.getTestContext().getCommandLine().getCommandDefaultSize()), VkDeviceSize(context.getTestContext().getCommandLine().getCommandPoolMinSize()));
			break;
		default:
			TCU_THROW(InternalError, "Unsupported commandPoolReservedSize value");
	}
	commandPoolReservedSize = de::max(commandPoolReservedSize, VkDeviceSize(testParams.commandBufferCount * context.getTestContext().getCommandLine().getCommandBufferMinSize()));

	// Create command pool with declared size
	// By connecting our own VkCommandPoolMemoryReservationCreateInfo we avoid getting unknown data from DeviceDriverSC::createCommandPoolHandlerNorm()
	VkCommandPoolMemoryReservationCreateInfo cpMemReservationCI		=
	{
		VK_STRUCTURE_TYPE_COMMAND_POOL_MEMORY_RESERVATION_CREATE_INFO,	// VkStructureType		sType
		DE_NULL,														// const void*			pNext
		commandPoolReservedSize,										// VkDeviceSize			commandPoolReservedSize
		testParams.commandBufferCount									// uint32_t				commandPoolMaxCommandBuffers
	};

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

	// check if size collected by vkGetCommandPoolMemoryConsumption matches size from VkCommandPoolMemoryReservationCreateInfo

	VkCommandPoolMemoryConsumption			memConsumption			=
	{
		VK_STRUCTURE_TYPE_COMMAND_POOL_MEMORY_CONSUMPTION,	// VkStructureType	sType
		DE_NULL,											// void*			pNext
		0,													// VkDeviceSize		commandPoolAllocated
		0,													// VkDeviceSize		commandPoolReservedSize
		0,													// VkDeviceSize		commandBufferAllocated
	};

	vk.getCommandPoolMemoryConsumption(device, *cmdPool, DE_NULL, &memConsumption);

	if (commandPoolReservedSize != memConsumption.commandPoolReservedSize)
		return tcu::TestStatus::fail("Failed");
	return tcu::TestStatus::pass("Pass");
}

// verify that VkCommandPoolMemoryReservationCreateInfo::commandPoolAllocated == sum of VkCommandPoolMemoryConsumption::commandBufferAllocated
tcu::TestStatus verifyCommandPoolAllocEqualsCommandBufferAlloc (Context& context, TestParams testParams)
{
	const VkDevice							device					= context.getDevice();
	const DeviceInterface&					vk						= context.getDeviceInterface();
	const deUint32							queueFamilyIndex		= context.getUniversalQueueFamilyIndex();

	// fill command buffers
	deUint32								eventCount				= 0u;
	switch (testParams.commandPoolReservedSize)
	{
		case CPS_SMALL:
			eventCount				= 1u;
			break;
		case CPS_BIG:
			eventCount				= 32u;
			break;
		default:
			TCU_THROW(InternalError, "Unsupported commandPoolReservedSize value");
	}
	VkDeviceSize							commandPoolReservedSize	= de::max(VkDeviceSize(eventCount * context.getTestContext().getCommandLine().getCommandDefaultSize()), VkDeviceSize(context.getTestContext().getCommandLine().getCommandPoolMinSize()));
	commandPoolReservedSize											= de::max(commandPoolReservedSize, VkDeviceSize(testParams.commandBufferCount * context.getTestContext().getCommandLine().getCommandBufferMinSize()));

	// Create command pool with declared size
	// By connecting our own VkCommandPoolMemoryReservationCreateInfo we avoid getting unknown data from DeviceDriverSC::createCommandPoolHandlerNorm()
	VkCommandPoolMemoryReservationCreateInfo cpMemReservationCI		=
	{
		VK_STRUCTURE_TYPE_COMMAND_POOL_MEMORY_RESERVATION_CREATE_INFO,	// VkStructureType		sType
		DE_NULL,														// const void*			pNext
		commandPoolReservedSize,										// VkDeviceSize			commandPoolReservedSize
		testParams.commandBufferCount									// uint32_t				commandPoolMaxCommandBuffers
	};

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

	// Allocate command buffers
	std::vector<VkCommandBuffer>			commandBuffers			(testParams.commandBufferCount);
	const VkCommandBufferAllocateInfo		cmdBufferAllocateInfo	=
	{
		VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,				// VkStructureType             sType;
		DE_NULL,													// const void*                 pNext;
		*cmdPool,													// VkCommandPool               commandPool;
		VK_COMMAND_BUFFER_LEVEL_PRIMARY,							// VkCommandBufferLevel        level;
		testParams.commandBufferCount								// deUint32                    commandBufferCount;
	};
	VK_CHECK(vk.allocateCommandBuffers(device, &cmdBufferAllocateInfo, commandBuffers.data()));

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

	bool isOK = true;
	for (deUint32 iter = 0; iter < 2 * testParams.iterations; ++iter)
	{
		// Build command buffers on even iteration
		if (0 == iter % 2)
		{
			if (testParams.multipleRecording)
			{
				for (deUint32 i = 0; i < testParams.commandBufferCount; ++i)
					beginCommandBuffer(vk, commandBuffers[i], 0u);

				for (deUint32 i = 0; i < testParams.commandBufferCount; ++i)
					for (deUint32 j = 0; j < eventCount; ++j)
						vk.cmdSetEvent(commandBuffers[i], events[j]->get(), VK_PIPELINE_STAGE_ALL_COMMANDS_BIT);

				for (deUint32 i = 0; i < testParams.commandBufferCount; ++i)
					endCommandBuffer(vk, commandBuffers[i]);
			}
			else
			{
				for (deUint32 i = 0; i < testParams.commandBufferCount; ++i)
				{
					beginCommandBuffer(vk, commandBuffers[i], 0u);

					for (deUint32 j = 0; j < eventCount; ++j)
						vk.cmdSetEvent(commandBuffers[i], events[j]->get(), VK_PIPELINE_STAGE_ALL_COMMANDS_BIT);

					endCommandBuffer(vk, commandBuffers[i]);
				}
			}
		}
		else // Reset command buffers on odd iteration
		{
			// leave loop when implementation is not able to perform vkResetCommandPool()
			if (context.getDeviceVulkanSC10Properties().commandPoolResetCommandBuffer == VK_FALSE)
				break;
			vk.resetCommandPool(device, *cmdPool, VkCommandPoolResetFlags(0u));
		}

		// check if size collected by sum of command buffer allocs is equal to command pool alloc
		VkDeviceSize							cbAllocSum				= 0u;
		VkDeviceSize							commandPoolAlloc		= 0u;
		for (deUint32 i = 0; i < testParams.commandBufferCount; ++i)
		{
			VkCommandPoolMemoryConsumption			memConsumption =
			{
				VK_STRUCTURE_TYPE_COMMAND_POOL_MEMORY_CONSUMPTION,	// VkStructureType	sType
				DE_NULL,											// void*			pNext
				0,													// VkDeviceSize		commandPoolAllocated
				0,													// VkDeviceSize		commandPoolReservedSize
				0,													// VkDeviceSize		commandBufferAllocated
			};
			vk.getCommandPoolMemoryConsumption(device, *cmdPool, commandBuffers[i], &memConsumption);
			cbAllocSum			+=	memConsumption.commandBufferAllocated;
			commandPoolAlloc	=	memConsumption.commandPoolAllocated;
		}
		if (cbAllocSum != commandPoolAlloc)
			isOK = false;
		// if we just performed a vkResetCommandPool() then allocated commandPool memory should be equal to 0
		if ( (1 == iter % 2 ) && commandPoolAlloc != 0u )
			isOK = false;
	}
	return isOK ? tcu::TestStatus::pass("Pass") : tcu::TestStatus::fail("Failed");
}

void checkSupport (Context& context, TestParams testParams)
{
	if (testParams.iterations > 1 && context.getDeviceVulkanSC10Properties().commandPoolResetCommandBuffer == VK_FALSE)
		TCU_THROW(NotSupportedError, "commandPoolResetCommandBuffer is not supported");
	if (testParams.multipleRecording && context.getDeviceVulkanSC10Properties().commandPoolMultipleCommandBuffersRecording == VK_FALSE)
		TCU_THROW(NotSupportedError, "commandPoolMultipleCommandBuffersRecording is not supported");
	if (testParams.commandBufferCount > context.getDeviceVulkanSC10Properties().maxCommandPoolCommandBuffers)
		TCU_THROW(NotSupportedError, "commandBufferCount is greater than maxCommandPoolCommandBuffers");

}

} // anonymous

tcu::TestCaseGroup*	createCommandPoolMemoryReservationTests (tcu::TestContext& testCtx)
{
	de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "command_pool_memory_reservation", "Tests verifying memory reservation for command pools in Vulkan SC"));

	// add vkGetCommandPoolMemoryConsumption tests
	const struct
	{
		deUint32					commandPoolMaxCommandBuffers;
		const char*					name;
	} maxCommandBuffers[] =
	{
		{ 1,						"cb_single"				},
		{ 4,						"cb_few"				},
		{ 21,						"cb_many"				},
		{ 256,						"cb_min_limit"			},
		{ 1024,						"cb_above_min_limit"	},
	};

	const struct
	{
		CommandPoolReservedSize		commandPoolReservedSize;
		const char*					name;
	} reservedSizes[] =
	{
		{ CPS_SMALL,				"size_small"	},
		{ CPS_BIG,					"size_big"		},
	};

	const struct
	{
		bool						multipleRecording;
		const char*					name;
	} recording[] =
	{
		{ false,					"single_recording"		},
		{ true,						"multiple_recording"	},
	};

	const struct
	{
		deUint32					count;
		const char*					name;
	} iterations[] =
	{
		{ 1u,						"1"				},
		{ 2u,						"2"				},
		{ 4u,						"8"				},
		{ 8u,						"16"			},
	};

	{
		de::MovePtr<tcu::TestCaseGroup>	memConGroup(new tcu::TestCaseGroup(testCtx, "memory_consumption", "Testing vkGetCommandPoolMemoryConsumption"));

		for (int cbIdx = 0; cbIdx < DE_LENGTH_OF_ARRAY(maxCommandBuffers); ++cbIdx)
		{
			de::MovePtr<tcu::TestCaseGroup> cbGroup(new tcu::TestCaseGroup(testCtx, maxCommandBuffers[cbIdx].name, ""));

			for (int sizeIdx = 0; sizeIdx < DE_LENGTH_OF_ARRAY(reservedSizes); ++sizeIdx)
			{
				de::MovePtr<tcu::TestCaseGroup> sizeGroup(new tcu::TestCaseGroup(testCtx, reservedSizes[sizeIdx].name, ""));

				for (int simIdx = 0; simIdx < DE_LENGTH_OF_ARRAY(recording); ++simIdx)
				{
					de::MovePtr<tcu::TestCaseGroup> simGroup(new tcu::TestCaseGroup(testCtx, recording[simIdx].name, ""));

					if(!recording[simIdx].multipleRecording)
					{
						TestParams	testParams =
						{
							reservedSizes[sizeIdx].commandPoolReservedSize,
							maxCommandBuffers[cbIdx].commandPoolMaxCommandBuffers,
							1u,
							false
						};
						addFunctionCase(simGroup.get(), "reserved_size", "", verifyCommandPoolReservedSize, testParams);
					}

					for (int iterIdx = 0; iterIdx < DE_LENGTH_OF_ARRAY(iterations); ++iterIdx)
					{
						TestParams	testParams =
						{
							reservedSizes[sizeIdx].commandPoolReservedSize,
							maxCommandBuffers[cbIdx].commandPoolMaxCommandBuffers,
							iterations[iterIdx].count,
							recording[simIdx].multipleRecording
						};
						std::ostringstream testName;
						testName << "allocated_size_" << iterations[iterIdx].name;
						addFunctionCase(simGroup.get(), testName.str(), "", checkSupport, verifyCommandPoolAllocEqualsCommandBufferAlloc, testParams);
					}

					sizeGroup->addChild(simGroup.release());
				}
				cbGroup->addChild(sizeGroup.release());
			}
			memConGroup->addChild(cbGroup.release());
		}
		group->addChild(memConGroup.release());
	}

	return group.release();
}

}	// sc

}	// vkt
