// 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_DEVICE_HPP_
#define VK_DEVICE_HPP_

#include "VkObject.hpp"
#include "VkSampler.hpp"
#include "Reactor/Routine.hpp"
#include "System/LRUCache.hpp"

#include "marl/mutex.h"
#include "marl/tsa.h"

#include <map>
#include <memory>
#include <unordered_map>

namespace marl {
class Scheduler;
}
namespace sw {
class Blitter;
}

namespace vk {

class PhysicalDevice;
class Queue;

namespace dbg {
class Context;
class Server;
}  // namespace dbg

class Device
{
public:
	static constexpr VkSystemAllocationScope GetAllocationScope() { return VK_SYSTEM_ALLOCATION_SCOPE_DEVICE; }

	Device(const VkDeviceCreateInfo *pCreateInfo, void *mem, PhysicalDevice *physicalDevice, const VkPhysicalDeviceFeatures *enabledFeatures, const std::shared_ptr<marl::Scheduler> &scheduler);
	void destroy(const VkAllocationCallbacks *pAllocator);

	static size_t ComputeRequiredAllocationSize(const VkDeviceCreateInfo *pCreateInfo);

	bool hasExtension(const char *extensionName) const;
	VkQueue getQueue(uint32_t queueFamilyIndex, uint32_t queueIndex) const;
	VkResult waitForFences(uint32_t fenceCount, const VkFence *pFences, VkBool32 waitAll, uint64_t timeout);
	VkResult waitIdle();
	void getDescriptorSetLayoutSupport(const VkDescriptorSetLayoutCreateInfo *pCreateInfo,
	                                   VkDescriptorSetLayoutSupport *pSupport) const;
	PhysicalDevice *getPhysicalDevice() const { return physicalDevice; }
	void updateDescriptorSets(uint32_t descriptorWriteCount, const VkWriteDescriptorSet *pDescriptorWrites,
	                          uint32_t descriptorCopyCount, const VkCopyDescriptorSet *pDescriptorCopies);
	void getRequirements(VkMemoryDedicatedRequirements *requirements) const;
	const VkPhysicalDeviceFeatures &getEnabledFeatures() const { return enabledFeatures; }
	sw::Blitter *getBlitter() const { return blitter.get(); }

	class SamplingRoutineCache
	{
	public:
		SamplingRoutineCache()
		    : cache(1024)
		{}
		~SamplingRoutineCache() {}

		struct Key
		{
			uint32_t instruction;
			uint32_t sampler;
			uint32_t imageView;

			inline bool operator==(const Key &rhs) const;

			struct Hash
			{
				inline std::size_t operator()(const Key &key) const noexcept;
			};
		};

		// getOrCreate() queries the cache for a Routine with the given key.
		// If one is found, it is returned, otherwise createRoutine(key) is
		// called, the returned Routine is added to the cache, and it is
		// returned.
		// Function must be a function of the signature:
		//     std::shared_ptr<rr::Routine>(const Key &)
		template<typename Function>
		std::shared_ptr<rr::Routine> getOrCreate(const Key &key, Function &&createRoutine)
		{
			auto it = snapshot.find(key);
			if(it != snapshot.end()) { return it->second; }

			marl::lock lock(mutex);
			if(auto existingRoutine = cache.lookup(key))
			{
				return existingRoutine;
			}

			std::shared_ptr<rr::Routine> newRoutine = createRoutine(key);
			cache.add(key, newRoutine);
			snapshotNeedsUpdate = true;

			return newRoutine;
		}

		void updateSnapshot();

	private:
		bool snapshotNeedsUpdate = false;
		std::unordered_map<Key, std::shared_ptr<rr::Routine>, Key::Hash> snapshot;

		marl::mutex mutex;
		sw::LRUCache<Key, std::shared_ptr<rr::Routine>, Key::Hash> cache GUARDED_BY(mutex);
	};

	SamplingRoutineCache *getSamplingRoutineCache() const;
	void updateSamplingRoutineSnapshotCache();

	class SamplerIndexer
	{
	public:
		~SamplerIndexer();

		uint32_t index(const SamplerState &samplerState);
		void remove(const SamplerState &samplerState);

	private:
		struct Identifier
		{
			uint32_t id;
			uint32_t count;  // Number of samplers sharing this state identifier.
		};

		marl::mutex mutex;
		std::map<SamplerState, Identifier> map GUARDED_BY(mutex);

		uint32_t nextID = 0;
	};

	uint32_t indexSampler(const SamplerState &samplerState);
	void removeSampler(const SamplerState &samplerState);

	std::shared_ptr<vk::dbg::Context> getDebuggerContext() const
	{
#ifdef ENABLE_VK_DEBUGGER
		return debugger.context;
#else
		return nullptr;
#endif  // ENABLE_VK_DEBUGGER
	}

private:
	PhysicalDevice *const physicalDevice = nullptr;
	Queue *const queues = nullptr;
	uint32_t queueCount = 0;
	std::unique_ptr<sw::Blitter> blitter;
	uint32_t enabledExtensionCount = 0;
	typedef char ExtensionName[VK_MAX_EXTENSION_NAME_SIZE];
	ExtensionName *extensions = nullptr;
	const VkPhysicalDeviceFeatures enabledFeatures = {};

	std::shared_ptr<marl::Scheduler> scheduler;
	std::unique_ptr<SamplingRoutineCache> samplingRoutineCache;
	std::unique_ptr<SamplerIndexer> samplerIndexer;

#ifdef ENABLE_VK_DEBUGGER
	struct
	{
		std::shared_ptr<vk::dbg::Context> context;
		std::shared_ptr<vk::dbg::Server> server;
	} debugger;
#endif  // ENABLE_VK_DEBUGGER
};

using DispatchableDevice = DispatchableObject<Device, VkDevice>;

static inline Device *Cast(VkDevice object)
{
	return DispatchableDevice::Cast(object);
}

inline bool vk::Device::SamplingRoutineCache::Key::operator==(const Key &rhs) const
{
	return instruction == rhs.instruction && sampler == rhs.sampler && imageView == rhs.imageView;
}

inline std::size_t vk::Device::SamplingRoutineCache::Key::Hash::operator()(const Key &key) const noexcept
{
	// Combine three 32-bit integers into a 64-bit hash.
	// 2642239 is the largest prime which when cubed is smaller than 2^64.
	uint64_t hash = key.instruction;
	hash = (hash * 2642239) ^ key.sampler;
	hash = (hash * 2642239) ^ key.imageView;
	return static_cast<std::size_t>(hash);  // Truncates to 32-bits on 32-bit platforms.
}

}  // namespace vk

#endif  // VK_DEVICE_HPP_
