// Copyright 2018 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.

#ifndef VK_OBJECT_HPP_
#define VK_OBJECT_HPP_

#include "VkConfig.h"
#include "VkDebug.hpp"
#include "VkMemory.h"

#include <vulkan/vulkan_core.h>
#include <vulkan/vk_icd.h>

namespace vk
{
// For use in the placement new to make it verbose that we're allocating an object using device memory
static constexpr VkAllocationCallbacks* DEVICE_MEMORY = nullptr;

template<typename T, typename VkT, typename CreateInfo>
static VkResult Create(const VkAllocationCallbacks* pAllocator, const CreateInfo* pCreateInfo, VkT* outObject)
{
	*outObject = VK_NULL_HANDLE;

	size_t size = T::ComputeRequiredAllocationSize(pCreateInfo);
	void* memory = nullptr;
	if(size)
	{
		memory = vk::allocate(size, REQUIRED_MEMORY_ALIGNMENT, pAllocator, T::GetAllocationScope());
		if(!memory)
		{
			return VK_ERROR_OUT_OF_HOST_MEMORY;
		}
	}

	auto object = new (pAllocator) T(pCreateInfo, memory);

	if(!object)
	{
		vk::deallocate(memory, pAllocator);
		return VK_ERROR_OUT_OF_HOST_MEMORY;
	}

	*outObject = *object;

	return VK_SUCCESS;
}

template<typename T, typename VkT>
class ObjectBase
{
public:
	using VkType = VkT;

	void destroy(const VkAllocationCallbacks* pAllocator) {} // Method defined by objects to delete their content, if necessary

	void* operator new(size_t count, const VkAllocationCallbacks* pAllocator)
	{
		return vk::allocate(count, alignof(T), pAllocator, T::GetAllocationScope());
	}

	void operator delete(void* ptr, const VkAllocationCallbacks* pAllocator)
	{
		// Should never happen
		ASSERT(false);
	}

	template<typename CreateInfo>
	static VkResult Create(const VkAllocationCallbacks* pAllocator, const CreateInfo* pCreateInfo, VkT* outObject)
	{
		return vk::Create<T, VkT, CreateInfo>(pAllocator, pCreateInfo, outObject);
	}

	static constexpr VkSystemAllocationScope GetAllocationScope() { return VK_SYSTEM_ALLOCATION_SCOPE_OBJECT; }

protected:
	// All derived classes should have deleted destructors
	~ObjectBase() {}
};

template<typename T, typename VkT>
class Object : public ObjectBase<T, VkT>
{
public:
	operator VkT()
	{
		return reinterpret_cast<VkT>(this);
	}
};

template<typename T, typename VkT>
class DispatchableObject
{
	VK_LOADER_DATA loaderData = { ICD_LOADER_MAGIC };

	T object;
public:
	static constexpr VkSystemAllocationScope GetAllocationScope() { return T::GetAllocationScope(); }

	template<typename ...Args>
	DispatchableObject(Args... args) : object(args...)
	{
	}

	~DispatchableObject() = delete;

	void destroy(const VkAllocationCallbacks* pAllocator)
	{
		object.destroy(pAllocator);
	}

	void* operator new(size_t count, const VkAllocationCallbacks* pAllocator)
	{
		return vk::allocate(count, alignof(T), pAllocator, T::GetAllocationScope());
	}

	void operator delete(void* ptr, const VkAllocationCallbacks* pAllocator)
	{
		// Should never happen
		ASSERT(false);
	}

	template<typename CreateInfo>
	static VkResult Create(const VkAllocationCallbacks* pAllocator, const CreateInfo* pCreateInfo, VkT* outObject)
	{
		return vk::Create<DispatchableObject<T, VkT>, VkT, CreateInfo>(pAllocator, pCreateInfo, outObject);
	}

	template<typename CreateInfo>
	static size_t ComputeRequiredAllocationSize(const CreateInfo* pCreateInfo)
	{
		return T::ComputeRequiredAllocationSize(pCreateInfo);
	}

	static inline T* Cast(VkT vkObject)
	{
		return &(reinterpret_cast<DispatchableObject<T, VkT>*>(vkObject)->object);
	}

	operator VkT()
	{
		return reinterpret_cast<VkT>(this);
	}
};

} // namespace vk

#endif // VK_OBJECT_HPP_
