/*-------------------------------------------------------------------------
* Vulkan CTS
* ----------
*
* Copyright (c) 2019 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.
*/

#include "deSTLUtil.hpp"
#include "deString.h"
#include "vkQueryUtil.hpp"
#include "vkDeviceFeatures.inl"
#include "vkDeviceFeatures.hpp"

namespace vk
{

DeviceFeatures::DeviceFeatures	(const InstanceInterface&			vki,
								 const deUint32						apiVersion,
								 const VkPhysicalDevice				physicalDevice,
								 const std::vector<std::string>&	instanceExtensions,
								 const std::vector<std::string>&	deviceExtensions,
								 const deBool						enableAllFeatures)
{
	VkPhysicalDeviceRobustness2FeaturesEXT*			robustness2Features			= nullptr;
	VkPhysicalDeviceImageRobustnessFeaturesEXT*		imageRobustnessFeatures		= nullptr;
	VkPhysicalDeviceFragmentShadingRateFeaturesKHR*	fragmentShadingRateFeatures	= nullptr;
	VkPhysicalDeviceShadingRateImageFeaturesNV*		shadingRateImageFeatures	= nullptr;
	VkPhysicalDeviceFragmentDensityMapFeaturesEXT*	fragmentDensityMapFeatures	= nullptr;

	m_coreFeatures2		= initVulkanStructure();
	m_vulkan11Features	= initVulkanStructure();
	m_vulkan12Features	= initVulkanStructure();

	if (isInstanceExtensionSupported(apiVersion, instanceExtensions, "VK_KHR_get_physical_device_properties2"))
	{
		const std::vector<VkExtensionProperties>	deviceExtensionProperties	= enumerateDeviceExtensionProperties(vki, physicalDevice, DE_NULL);
		void**										nextPtr						= &m_coreFeatures2.pNext;
		std::vector<FeatureStructWrapperBase*>		featuresToFillFromBlob;
		bool										vk12Supported				= (apiVersion >= VK_MAKE_VERSION(1, 2, 0));

		// in vk12 we have blob structures combining features of couple previously
		// available feature structures, that now in vk12 must be removed from chain
		if (vk12Supported)
		{
			addToChainVulkanStructure(&nextPtr, m_vulkan11Features);
			addToChainVulkanStructure(&nextPtr, m_vulkan12Features);
		}

		// iterate over data for all feature that are defined in specification
		for (const auto& featureStructCreationData : featureStructCreationArray)
		{
			const char* featureName = featureStructCreationData.name;

			// check if this feature is available on current device
			if (de::contains(deviceExtensions.begin(), deviceExtensions.end(), featureName) &&
				verifyFeatureAddCriteria(featureStructCreationData, deviceExtensionProperties))
			{
				FeatureStructWrapperBase* p = (*featureStructCreationData.creatorFunction)();
				if (p == DE_NULL)
					continue;

				// if feature struct is part of VkPhysicalDeviceVulkan1{1,2}Features
				// we dont add it to the chain but store and fill later from blob data
				bool featureFilledFromBlob = false;
				if (vk12Supported)
					featureFilledFromBlob = isPartOfBlobFeatures(p->getFeatureDesc().sType);

				if (featureFilledFromBlob)
					featuresToFillFromBlob.push_back(p);
				else
				{
					VkStructureType	structType		= p->getFeatureDesc().sType;
					void*			rawStructPtr	= p->getFeatureTypeRaw();

					if (structType == VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_FEATURES_EXT)
						robustness2Features = reinterpret_cast<VkPhysicalDeviceRobustness2FeaturesEXT*>(rawStructPtr);
					else if (structType == VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_ROBUSTNESS_FEATURES_EXT)
						imageRobustnessFeatures = reinterpret_cast<VkPhysicalDeviceImageRobustnessFeaturesEXT*>(rawStructPtr);
					else if (structType == VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_FEATURES_KHR)
						fragmentShadingRateFeatures = reinterpret_cast<VkPhysicalDeviceFragmentShadingRateFeaturesKHR*>(rawStructPtr);
					else if (structType == VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADING_RATE_IMAGE_FEATURES_NV)
						shadingRateImageFeatures = reinterpret_cast<VkPhysicalDeviceShadingRateImageFeaturesNV*>(rawStructPtr);
					else if (structType == VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_FEATURES_EXT)
						fragmentDensityMapFeatures = reinterpret_cast<VkPhysicalDeviceFragmentDensityMapFeaturesEXT*>(rawStructPtr);

					// add to chain
					*nextPtr	= rawStructPtr;
					nextPtr		= p->getFeatureTypeNext();
				}
				m_features.push_back(p);
			}
		}

		vki.getPhysicalDeviceFeatures2(physicalDevice, &m_coreFeatures2);

		// fill data from VkPhysicalDeviceVulkan1{1,2}Features
		if (vk12Supported)
		{
			AllFeaturesBlobs allBlobs =
			{
				m_vulkan11Features,
				m_vulkan12Features,
				// add blobs from future vulkan versions here
			};

			for (auto feature : featuresToFillFromBlob)
				feature->initializeFeatureFromBlob(allBlobs);
		}
	}
	else
		m_coreFeatures2.features = getPhysicalDeviceFeatures(vki, physicalDevice);

	// 'enableAllFeatures' is used to create a complete list of supported features.
	if (!enableAllFeatures)
	{
		// Disable robustness by default, as it has an impact on performance on some HW.
		if (robustness2Features)
		{
			robustness2Features->robustBufferAccess2	= false;
			robustness2Features->robustImageAccess2		= false;
			robustness2Features->nullDescriptor			= false;
		}
		if (imageRobustnessFeatures)
		{
			imageRobustnessFeatures->robustImageAccess	= false;
		}
		m_coreFeatures2.features.robustBufferAccess = false;

		// Disable VK_EXT_fragment_density_map and VK_NV_shading_rate_image features
		// that must: not be enabled if KHR fragment shading rate features are enabled.
		if (fragmentShadingRateFeatures &&
			(fragmentShadingRateFeatures->pipelineFragmentShadingRate ||
				fragmentShadingRateFeatures->primitiveFragmentShadingRate ||
				fragmentShadingRateFeatures->attachmentFragmentShadingRate))
		{
			if (shadingRateImageFeatures)
				shadingRateImageFeatures->shadingRateImage = false;
			if (fragmentDensityMapFeatures)
				fragmentDensityMapFeatures->fragmentDensityMap = false;
		}
	}
}

bool DeviceFeatures::verifyFeatureAddCriteria (const FeatureStructCreationData& item, const std::vector<VkExtensionProperties>& properties)
{
	if (deStringEqual(item.name, VK_KHR_VULKAN_MEMORY_MODEL_EXTENSION_NAME))
	{
		for (const auto& property : properties)
		{
			if (deStringEqual(property.extensionName, item.name))
				return (property.specVersion == item.specVersion);
		}
	}

	return true;
}

bool DeviceFeatures::contains (const std::string& feature, bool throwIfNotExists) const
{
	for (const auto f : m_features)
	{
		if (deStringEqual(f->getFeatureDesc().name, feature.c_str()))
			return true;
	}

	if (throwIfNotExists)
		TCU_THROW(NotSupportedError, "Feature " + feature + " is not supported");

	return false;
}

bool DeviceFeatures::isDeviceFeatureInitialized (VkStructureType sType) const
{
	for (const auto f : m_features)
	{
		if (f->getFeatureDesc().sType == sType)
			return true;
	}
	return false;
}

DeviceFeatures::~DeviceFeatures (void)
{
	for (auto p : m_features)
		delete p;

	m_features.clear();
}

} // vk

