// Copyright 2020 The SwiftShader Authors. All Rights Reserved.
//
// 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 "VkPipelineCache.hpp"
#include <cstring>

namespace vk {

SpecializationInfo::SpecializationInfo(const VkSpecializationInfo *specializationInfo)
{
	if(specializationInfo)
	{
		auto *ptr = reinterpret_cast<VkSpecializationInfo *>(
		    allocate(sizeof(VkSpecializationInfo), REQUIRED_MEMORY_ALIGNMENT, DEVICE_MEMORY));
		info = std::shared_ptr<VkSpecializationInfo>(ptr, Deleter());

		info->mapEntryCount = specializationInfo->mapEntryCount;
		info->pMapEntries = nullptr;
		info->dataSize = specializationInfo->dataSize;
		info->pData = nullptr;

		if(specializationInfo->mapEntryCount > 0)
		{
			size_t entriesSize = specializationInfo->mapEntryCount * sizeof(VkSpecializationMapEntry);
			VkSpecializationMapEntry *mapEntries = reinterpret_cast<VkSpecializationMapEntry *>(
			    allocate(entriesSize, REQUIRED_MEMORY_ALIGNMENT, DEVICE_MEMORY));
			memcpy(mapEntries, specializationInfo->pMapEntries, entriesSize);
			info->pMapEntries = mapEntries;
		}

		if(specializationInfo->dataSize > 0)
		{
			void *data = allocate(specializationInfo->dataSize, REQUIRED_MEMORY_ALIGNMENT, DEVICE_MEMORY);
			memcpy(data, specializationInfo->pData, specializationInfo->dataSize);
			info->pData = data;
		}
	}
}

void SpecializationInfo::Deleter::operator()(VkSpecializationInfo *info) const
{
	if(info)
	{
		deallocate(const_cast<VkSpecializationMapEntry *>(info->pMapEntries), DEVICE_MEMORY);
		deallocate(const_cast<void *>(info->pData), DEVICE_MEMORY);
		deallocate(info, DEVICE_MEMORY);
	}
}

bool SpecializationInfo::operator<(const SpecializationInfo &specializationInfo) const
{
	// Check that either both or neither keys have specialization info.
	if((info.get() == nullptr) != (specializationInfo.info.get() == nullptr))
	{
		return info.get() == nullptr;
	}

	if(!info)
	{
		ASSERT(!specializationInfo.info);
		return false;
	}

	if(info->mapEntryCount != specializationInfo.info->mapEntryCount)
	{
		return info->mapEntryCount < specializationInfo.info->mapEntryCount;
	}

	if(info->dataSize != specializationInfo.info->dataSize)
	{
		return info->dataSize < specializationInfo.info->dataSize;
	}

	if(info->mapEntryCount > 0)
	{
		int cmp = memcmp(info->pMapEntries, specializationInfo.info->pMapEntries, info->mapEntryCount * sizeof(VkSpecializationMapEntry));
		if(cmp != 0)
		{
			return cmp < 0;
		}
	}

	if(info->dataSize > 0)
	{
		int cmp = memcmp(info->pData, specializationInfo.info->pData, info->dataSize);
		if(cmp != 0)
		{
			return cmp < 0;
		}
	}

	return false;
}

}  // namespace vk
