/*-------------------------------------------------------------------------
 * Vulkan Conformance Tests
 * ------------------------
 *
 * Copyright (c) 2016 Google 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 Descriptor pool tests
 *//*--------------------------------------------------------------------*/

#include "vktApiDescriptorPoolTests.hpp"
#include "vktTestCaseUtil.hpp"

#include "vkDefs.hpp"
#include "vkRef.hpp"
#include "vkRefUtil.hpp"
#include "vkPlatform.hpp"
#include "vkDeviceUtil.hpp"
#include "vkQueryUtil.hpp"

#include "tcuCommandLine.hpp"
#include "tcuTestLog.hpp"
#include "tcuPlatform.hpp"

#include "deUniquePtr.hpp"
#include "deSharedPtr.hpp"
#include "deInt32.h"
#include "deSTLUtil.hpp"

#define VK_DESCRIPTOR_TYPE_LAST (VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT + 1)

namespace vkt
{
namespace api
{

namespace
{

using namespace std;
using namespace vk;

struct ResetDescriptorPoolTestParams
{
	ResetDescriptorPoolTestParams	(deUint32 numIterations, bool freeDescriptorSets = false)
		: m_numIterations		(numIterations)
		, m_freeDescriptorSets	(freeDescriptorSets)
	{}

	deUint32	m_numIterations;
	bool		m_freeDescriptorSets;
};

tcu::TestStatus resetDescriptorPoolTest (Context& context, const ResetDescriptorPoolTestParams params)
{
	const deUint32				numDescriptorSetsPerIter = 2048;
	const DeviceInterface&		vkd						 = context.getDeviceInterface();
	const VkDevice				device					 = context.getDevice();

	const VkDescriptorPoolSize descriptorPoolSize =
	{
		VK_DESCRIPTOR_TYPE_SAMPLER, // type
		numDescriptorSetsPerIter	// descriptorCount
	};

	const VkDescriptorPoolCreateInfo descriptorPoolInfo =
	{
		VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,																			// sType
		NULL,																													// pNext
		(params.m_freeDescriptorSets) ? (VkDescriptorPoolCreateFlags)VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT : 0u,	// flags
		numDescriptorSetsPerIter,																								// maxSets
		1,																														// poolSizeCount
		&descriptorPoolSize																										// pPoolSizes
	};

	{
		const Unique<VkDescriptorPool> descriptorPool(
			createDescriptorPool(vkd, device,
								 &descriptorPoolInfo));

		const VkDescriptorSetLayoutBinding descriptorSetLayoutBinding =
		{
			0,							// binding
			VK_DESCRIPTOR_TYPE_SAMPLER, // descriptorType
			1,							// descriptorCount
			VK_SHADER_STAGE_ALL,		// stageFlags
			NULL						// pImmutableSamplers
		};

		const VkDescriptorSetLayoutCreateInfo descriptorSetLayoutInfo =
		{
			VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,	// sType
			NULL,													// pNext
			0,														// flags
			1,														// bindingCount
			&descriptorSetLayoutBinding								// pBindings
		};

		{
			typedef de::SharedPtr<Unique<VkDescriptorSetLayout> > DescriptorSetLayoutPtr;

			vector<DescriptorSetLayoutPtr> descriptorSetLayouts;
			descriptorSetLayouts.reserve(numDescriptorSetsPerIter);

			for (deUint32 ndx = 0; ndx < numDescriptorSetsPerIter; ++ndx)
			{
				descriptorSetLayouts.push_back(
					DescriptorSetLayoutPtr(
						new Unique<VkDescriptorSetLayout>(
							createDescriptorSetLayout(vkd, device,
													  &descriptorSetLayoutInfo))));
			}

			vector<VkDescriptorSetLayout> descriptorSetLayoutsRaw(numDescriptorSetsPerIter);

			for (deUint32 ndx = 0; ndx < numDescriptorSetsPerIter; ++ndx)
			{
				descriptorSetLayoutsRaw[ndx] = **descriptorSetLayouts[ndx];
			}

			const VkDescriptorSetAllocateInfo descriptorSetInfo =
			{
				VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, // sType
				NULL,											// pNext
				*descriptorPool,								// descriptorPool
				numDescriptorSetsPerIter,						// descriptorSetCount
				&descriptorSetLayoutsRaw[0]						// pSetLayouts
			};

			vector<VkDescriptorSet> testSets(numDescriptorSetsPerIter);

			for (deUint32 ndx = 0; ndx < params.m_numIterations; ++ndx)
			{
				// The test should crash in this loop at some point if there is a memory leak
				VK_CHECK(vkd.allocateDescriptorSets(device, &descriptorSetInfo, &testSets[0]));
				if (params.m_freeDescriptorSets)
					VK_CHECK(vkd.freeDescriptorSets(device, *descriptorPool, 1, &testSets[0]));
				VK_CHECK(vkd.resetDescriptorPool(device, *descriptorPool, 0));
			}

		}
	}

	// If it didn't crash, pass
	return tcu::TestStatus::pass("Pass");
}

tcu::TestStatus outOfPoolMemoryTest (Context& context)
{
	const DeviceInterface&	vkd							= context.getDeviceInterface();
	const VkDevice			device						= context.getDevice();
	const bool				expectOutOfPoolMemoryError	= context.isDeviceFunctionalitySupported("VK_KHR_maintenance1");
	deUint32				numErrorsReturned			= 0;

	const struct FailureCase
	{
		deUint32	poolDescriptorCount;		//!< total number of descriptors (of a given type) in the descriptor pool
		deUint32	poolMaxSets;				//!< max number of descriptor sets that can be allocated from the pool
		deUint32	bindingCount;				//!< number of bindings per descriptor set layout
		deUint32	bindingDescriptorCount;		//!< number of descriptors in a binding (array size) (in all bindings)
		deUint32	descriptorSetCount;			//!< number of descriptor sets to allocate
		string		description;				//!< the log message for this failure condition
	} failureCases[] =
	{
		//	pool			pool		binding		binding		alloc set
		//	descr. count	max sets	count		array size	count
		{	4u,				2u,			1u,			1u,			3u,		"Out of descriptor sets",											},
		{	3u,				4u,			1u,			1u,			4u,		"Out of descriptors (due to the number of sets)",					},
		{	2u,				1u,			3u,			1u,			1u,		"Out of descriptors (due to the number of bindings)",				},
		{	3u,				2u,			1u,			2u,			2u,		"Out of descriptors (due to descriptor array size)",				},
		{	5u,				1u,			2u,			3u,			1u,		"Out of descriptors (due to descriptor array size in all bindings)",},
	};

	context.getTestContext().getLog()
		<< tcu::TestLog::Message
		<< "Creating a descriptor pool with insufficient resources. Descriptor set allocation is likely to fail."
		<< tcu::TestLog::EndMessage;

	for (deUint32 failureCaseNdx = 0u; failureCaseNdx < DE_LENGTH_OF_ARRAY(failureCases); ++failureCaseNdx)
	{
		const FailureCase& params = failureCases[failureCaseNdx];
		context.getTestContext().getLog() << tcu::TestLog::Message << "Checking: " << params.description << tcu::TestLog::EndMessage;

		for (VkDescriptorType	descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER;
								descriptorType < VK_DESCRIPTOR_TYPE_LAST;
								descriptorType = static_cast<VkDescriptorType>(descriptorType + 1))
		{
			context.getTestContext().getLog() << tcu::TestLog::Message << "- " << getDescriptorTypeName(descriptorType) << tcu::TestLog::EndMessage;

			const VkDescriptorPoolSize					descriptorPoolSize =
			{
				descriptorType,												// type
				params.poolDescriptorCount,									// descriptorCount
			};

			const VkDescriptorPoolCreateInfo			descriptorPoolCreateInfo =
			{
				VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,				// VkStructureType                sType;
				DE_NULL,													// const void*                    pNext;
				(VkDescriptorPoolCreateFlags)0,								// VkDescriptorPoolCreateFlags    flags;
				params.poolMaxSets,											// uint32_t                       maxSets;
				1u,															// uint32_t                       poolSizeCount;
				&descriptorPoolSize,										// const VkDescriptorPoolSize*    pPoolSizes;
			};

			const Unique<VkDescriptorPool>				descriptorPool(createDescriptorPool(vkd, device, &descriptorPoolCreateInfo));

			VkShaderStageFlags stageFlags = (descriptorType != VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT) ? VK_SHADER_STAGE_ALL : VK_SHADER_STAGE_FRAGMENT_BIT;
			const VkDescriptorSetLayoutBinding			descriptorSetLayoutBinding =
			{
				0u,															// uint32_t              binding;
				descriptorType,												// VkDescriptorType      descriptorType;
				params.bindingDescriptorCount,								// uint32_t              descriptorCount;
				stageFlags,													// VkShaderStageFlags    stageFlags;
				DE_NULL,													// const VkSampler*      pImmutableSamplers;
			};

			vector<VkDescriptorSetLayoutBinding>	descriptorSetLayoutBindings (params.bindingCount, descriptorSetLayoutBinding);

			for (deUint32 binding = 0; binding < deUint32(descriptorSetLayoutBindings.size()); ++binding)
			{
				descriptorSetLayoutBindings[binding].binding = binding;
			}

			const VkDescriptorSetLayoutCreateInfo		descriptorSetLayoutInfo =
			{
				VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,		// VkStructureType                        sType;
				DE_NULL,													// const void*                            pNext;
				(VkDescriptorSetLayoutCreateFlags)0,						// VkDescriptorSetLayoutCreateFlags       flags;
				static_cast<deUint32>(descriptorSetLayoutBindings.size()),	// uint32_t                               bindingCount;
				&descriptorSetLayoutBindings[0],							// const VkDescriptorSetLayoutBinding*    pBindings;
			};

			const Unique<VkDescriptorSetLayout>			descriptorSetLayout	(createDescriptorSetLayout(vkd, device, &descriptorSetLayoutInfo));
			const vector<VkDescriptorSetLayout>			rawSetLayouts		(params.descriptorSetCount, *descriptorSetLayout);
			vector<VkDescriptorSet>						rawDescriptorSets	(params.descriptorSetCount, DE_NULL);

			const VkDescriptorSetAllocateInfo			descriptorSetAllocateInfo =
			{
				VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,				// VkStructureType                 sType;
				DE_NULL,													// const void*                     pNext;
				*descriptorPool,											// VkDescriptorPool                descriptorPool;
				static_cast<deUint32>(rawSetLayouts.size()),				// uint32_t                        descriptorSetCount;
				&rawSetLayouts[0],											// const VkDescriptorSetLayout*    pSetLayouts;
			};

			const VkResult result = vkd.allocateDescriptorSets(device, &descriptorSetAllocateInfo, &rawDescriptorSets[0]);

			if (result != VK_SUCCESS)
			{
				++numErrorsReturned;

				if (expectOutOfPoolMemoryError && result != VK_ERROR_OUT_OF_POOL_MEMORY)
					return tcu::TestStatus::fail("Expected VK_ERROR_OUT_OF_POOL_MEMORY but got " + string(getResultName(result)) + " instead");
			}
			else
				context.getTestContext().getLog() << tcu::TestLog::Message << "  Allocation was successful anyway" << tcu::TestLog::EndMessage;
		}
	}

	if (numErrorsReturned == 0u)
		return tcu::TestStatus::pass("Not validated");
	else
		return tcu::TestStatus::pass("Pass");
}

} // anonymous

tcu::TestCaseGroup* createDescriptorPoolTests (tcu::TestContext& testCtx)
{
	const deUint32 numIterationsHigh = 4096;

	de::MovePtr<tcu::TestCaseGroup> descriptorPoolTests(
		new tcu::TestCaseGroup(testCtx, "descriptor_pool", "Descriptor Pool Tests"));

	addFunctionCase(descriptorPoolTests.get(),
					"repeated_reset_short",
					"Test 2 cycles of vkAllocateDescriptorSets and vkResetDescriptorPool (should pass)",
					resetDescriptorPoolTest, ResetDescriptorPoolTestParams(2U));
	addFunctionCase(descriptorPoolTests.get(),
					"repeated_reset_long",
					"Test many cycles of vkAllocateDescriptorSets and vkResetDescriptorPool",
					resetDescriptorPoolTest, ResetDescriptorPoolTestParams(numIterationsHigh));
	addFunctionCase(descriptorPoolTests.get(),
					"repeated_free_reset_short",
					"Test 2 cycles of vkAllocateDescriptorSets, vkFreeDescriptorSets and vkResetDescriptorPool (should pass)",
					resetDescriptorPoolTest, ResetDescriptorPoolTestParams(2U, true));
	addFunctionCase(descriptorPoolTests.get(),
					"repeated_free_reset_long",
					"Test many cycles of vkAllocateDescriptorSets, vkFreeDescriptorSets and vkResetDescriptorPool",
					resetDescriptorPoolTest, ResetDescriptorPoolTestParams(numIterationsHigh, true));
	addFunctionCase(descriptorPoolTests.get(),
					"out_of_pool_memory",
					"Test that when we run out of descriptors a correct error code is returned",
					outOfPoolMemoryTest);

	return descriptorPoolTests.release();
}

} // api
} // vkt
