/*------------------------------------------------------------------------
 * Vulkan Conformance Tests
 * ------------------------
 *
 * Copyright (c) 2017 The Khronos Group Inc.
 * Copyright (c) 2017 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  vktSparseResourcesImageAlignedMipSize.cpp
 * \brief Aligned mip size tests.
 *//*--------------------------------------------------------------------*/

#include "vktSparseResourcesBufferSparseBinding.hpp"
#include "vktSparseResourcesTestsUtil.hpp"
#include "vktSparseResourcesBase.hpp"
#include "vktTestCaseUtil.hpp"

#include "vkDefs.hpp"
#include "vkRef.hpp"
#include "vkRefUtil.hpp"
#include "vkPlatform.hpp"
#include "vkPrograms.hpp"
#include "vkMemUtil.hpp"
#include "vkBuilderUtil.hpp"
#include "vkImageUtil.hpp"
#include "vkQueryUtil.hpp"
#include "vkTypeUtil.hpp"

#include "deUniquePtr.hpp"
#include "deStringUtil.hpp"

#include <string>
#include <vector>

using namespace vk;

namespace vkt
{
namespace sparse
{
namespace
{

class ImageAlignedMipSizeCase : public TestCase
{
public:
	ImageAlignedMipSizeCase			(tcu::TestContext&	testCtx,
									 const std::string&	name,
									 const std::string&	description,
									 const ImageType	imageType,
									 const tcu::UVec3&	imageSize,
									 const VkFormat		format);

	void			initPrograms	(SourceCollections&	sourceCollections) const {DE_UNREF(sourceCollections);};
	TestInstance*	createInstance	(Context&			context) const;
	virtual void	checkSupport	(Context&			context) const;

private:
	const ImageType		m_imageType;
	const tcu::UVec3	m_imageSize;
	const VkFormat		m_format;
};

ImageAlignedMipSizeCase::ImageAlignedMipSizeCase	(tcu::TestContext&	testCtx,
													 const std::string&	name,
													 const std::string&	description,
													 const ImageType	imageType,
													 const tcu::UVec3&	imageSize,
													 const VkFormat		format)
	: TestCase		(testCtx, name, description)
	, m_imageType	(imageType)
	, m_imageSize	(imageSize)
	, m_format		(format)
{
}

void ImageAlignedMipSizeCase::checkSupport (Context& context) const
{
	const InstanceInterface&	instance		= context.getInstanceInterface();
	const VkPhysicalDevice		physicalDevice	= context.getPhysicalDevice();

	// Check the image size does not exceed device limits
	if (!isImageSizeSupported(instance, physicalDevice, m_imageType, m_imageSize))
		TCU_THROW(NotSupportedError, "Image size not supported for device");

	// Check if device supports sparse operations for image type
	if (!checkSparseSupportForImageType(instance, physicalDevice, m_imageType))
		TCU_THROW(NotSupportedError, "Sparse residency for image type is not supported");
}

class ImageAlignedMipSizeInstance : public SparseResourcesBaseInstance
{
public:
	ImageAlignedMipSizeInstance	(Context&			context,
								 const ImageType	imageType,
								 const tcu::UVec3&	imageSize,
								 const VkFormat		format);

	tcu::TestStatus	iterate		(void);

private:
	const ImageType		m_imageType;
	const tcu::UVec3	m_imageSize;
	const VkFormat		m_format;
};

ImageAlignedMipSizeInstance::ImageAlignedMipSizeInstance	(Context&			context,
															 const ImageType	imageType,
															 const tcu::UVec3&	imageSize,
															 const VkFormat		format)
	: SparseResourcesBaseInstance	(context)
	, m_imageType					(imageType)
	, m_imageSize					(imageSize)
	, m_format						(format)
{
}

tcu::TestStatus ImageAlignedMipSizeInstance::iterate (void)
{
	const InstanceInterface&				instance					= m_context.getInstanceInterface();
	const VkPhysicalDevice					physicalDevice				= m_context.getPhysicalDevice();
	const VkPhysicalDeviceProperties		physicalDeviceProperties	= getPhysicalDeviceProperties(instance, physicalDevice);
	VkImageCreateInfo						imageCreateInfo;
	VkSparseImageMemoryRequirements			aspectRequirements;
	VkExtent3D								imageGranularity;
	const VkPhysicalDeviceSparseProperties	sparseProperties			= physicalDeviceProperties.sparseProperties;
	const PlanarFormatDescription			formatDescription			= getPlanarFormatDescription(m_format);


	imageCreateInfo.sType					= VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
	imageCreateInfo.pNext					= DE_NULL;
	imageCreateInfo.flags					= VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT | VK_IMAGE_CREATE_SPARSE_BINDING_BIT;
	imageCreateInfo.imageType				= mapImageType(m_imageType);
	imageCreateInfo.format					= m_format;
	imageCreateInfo.extent					= makeExtent3D(getLayerSize(m_imageType, m_imageSize));
	imageCreateInfo.arrayLayers				= getNumLayers(m_imageType, m_imageSize);
	imageCreateInfo.samples					= VK_SAMPLE_COUNT_1_BIT;
	imageCreateInfo.tiling					= VK_IMAGE_TILING_OPTIMAL;
	imageCreateInfo.initialLayout			= VK_IMAGE_LAYOUT_UNDEFINED;
	imageCreateInfo.usage					= VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
											  VK_IMAGE_USAGE_STORAGE_BIT;
	imageCreateInfo.sharingMode				= VK_SHARING_MODE_EXCLUSIVE;
	imageCreateInfo.queueFamilyIndexCount	= 0u;
	imageCreateInfo.pQueueFamilyIndices		= DE_NULL;

	if (m_imageType == IMAGE_TYPE_CUBE || m_imageType == IMAGE_TYPE_CUBE_ARRAY)
	{
		imageCreateInfo.flags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
	}

	// Check if device supports sparse operations for image format
	if (!checkSparseSupportForImageFormat(instance, physicalDevice, imageCreateInfo))
		TCU_THROW(NotSupportedError, "The image format does not support sparse operations");

	{
		VkImageFormatProperties imageFormatProperties;

		if (instance.getPhysicalDeviceImageFormatProperties(physicalDevice,
			imageCreateInfo.format,
			imageCreateInfo.imageType,
			imageCreateInfo.tiling,
			imageCreateInfo.usage,
			imageCreateInfo.flags,
			&imageFormatProperties) == VK_ERROR_FORMAT_NOT_SUPPORTED)
		{
			TCU_THROW(NotSupportedError, "Image format does not support sparse operations");
		}

		imageCreateInfo.mipLevels = getMipmapCount(m_format, formatDescription, imageFormatProperties, imageCreateInfo.extent);
	}

	{
		QueueRequirementsVec queueRequirements;
		queueRequirements.push_back(QueueRequirements(VK_QUEUE_SPARSE_BINDING_BIT, 1u));

		createDeviceSupportingQueues(queueRequirements);
	}

	{
		const DeviceInterface&								deviceInterface				= getDeviceInterface();

		// Create sparse image
		const Unique<VkImage>								imageSparse					(createImage(deviceInterface, getDevice(), &imageCreateInfo));

		// Get sparse image sparse memory requirements
		const std::vector<VkSparseImageMemoryRequirements>	sparseMemoryRequirements	= getImageSparseMemoryRequirements(deviceInterface, getDevice(), *imageSparse);

		DE_ASSERT(sparseMemoryRequirements.size() != 0);

		const deUint32										colorAspectIndex			= getSparseAspectRequirementsIndex(sparseMemoryRequirements, VK_IMAGE_ASPECT_COLOR_BIT);

		if (colorAspectIndex == NO_MATCH_FOUND)
			TCU_THROW(NotSupportedError, "Not supported image aspect - the test supports currently only VK_IMAGE_ASPECT_COLOR_BIT");

		aspectRequirements	= sparseMemoryRequirements[colorAspectIndex];
		imageGranularity	= aspectRequirements.formatProperties.imageGranularity;
	}

	if (sparseProperties.residencyAlignedMipSize)
	{
		deUint32	lod	= 0;
		VkExtent3D	extent;

		do
		{
			extent = mipLevelExtents(imageCreateInfo.extent, lod);
			if (   extent.width  % imageGranularity.width  != 0
				|| extent.height % imageGranularity.height != 0
				|| extent.depth  % imageGranularity.depth  != 0)
			{
				break;
			}

			lod++;
		}
		while (extent.width != 1 || extent.height != 1 || extent.depth != 1);

		if (lod != aspectRequirements.imageMipTailFirstLod)
			return tcu::TestStatus::fail("Unexpected first LOD for mip tail.");
		else
			return tcu::TestStatus::pass("pass");
	}
	else if (aspectRequirements.formatProperties.flags & VK_SPARSE_IMAGE_FORMAT_ALIGNED_MIP_SIZE_BIT)
	{
		return tcu::TestStatus::fail("Aligned mip size flag doesn't match in device and image properties.");
	}
	else
	{
		return tcu::TestStatus::pass("Aligned mip size not enabled.");
	}
}

TestInstance* ImageAlignedMipSizeCase::createInstance (Context& context) const
{
	return new ImageAlignedMipSizeInstance(context, m_imageType, m_imageSize, m_format);
}

} // anonymous ns

tcu::TestCaseGroup* createImageAlignedMipSizeTests (tcu::TestContext& testCtx)
{
	de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "aligned_mip_size", "Aligned mip size"));

	const std::vector<TestImageParameters> imageParameters =
	{
		{ IMAGE_TYPE_2D,		 { tcu::UVec3(512u, 256u, 1u) },	getTestFormats(IMAGE_TYPE_2D) },
		{ IMAGE_TYPE_2D_ARRAY,	 { tcu::UVec3(512u, 256u, 6u) },	getTestFormats(IMAGE_TYPE_2D_ARRAY) },
		{ IMAGE_TYPE_CUBE,		 { tcu::UVec3(256u, 256u, 1u) },	getTestFormats(IMAGE_TYPE_CUBE) },
		{ IMAGE_TYPE_CUBE_ARRAY, { tcu::UVec3(256u, 256u, 6u) },	getTestFormats(IMAGE_TYPE_CUBE_ARRAY) },
		{ IMAGE_TYPE_3D,		 { tcu::UVec3(512u, 256u, 16u) },	getTestFormats(IMAGE_TYPE_3D) }
	};

	for (size_t imageTypeNdx = 0; imageTypeNdx < imageParameters.size(); ++imageTypeNdx)
	{
		const ImageType					imageType = imageParameters[imageTypeNdx].imageType;
		de::MovePtr<tcu::TestCaseGroup> imageTypeGroup(new tcu::TestCaseGroup(testCtx, getImageTypeName(imageType).c_str(), ""));

		for (size_t formatNdx = 0; formatNdx < imageParameters[imageTypeNdx].formats.size(); ++formatNdx)
		{
			VkFormat			format				= imageParameters[imageTypeNdx].formats[formatNdx].format;
			tcu::UVec3			imageSizeAlignment	= getImageSizeAlignment(format);
			const std::string	name				= getImageFormatID(format);
			const tcu::UVec3	imageSize			= imageParameters[imageTypeNdx].imageSizes[0];

			// skip test for images with odd sizes for some YCbCr formats
			if ((imageSize.x() % imageSizeAlignment.x()) != 0)
				continue;
			if ((imageSize.y() % imageSizeAlignment.y()) != 0)
				continue;

			imageTypeGroup->addChild(new ImageAlignedMipSizeCase(testCtx, name.c_str(), "", imageType, imageSize, format));
		}
		testGroup->addChild(imageTypeGroup.release());
	}

	return testGroup.release();
}

} // sparse
} // vkt
