#ifndef VK_VIDEO_H
#define VK_VIDEO_H

#include "rendering.h"
#include "tier0/platform.h"
#include "tier1/utlvector.h"
#include "vulkan/vulkan.h"
#include "vulkan/vulkan_core.h"

#ifndef VULKAN_RENDERING_IMPL
#error "Not a vulkan rendering implementation. Do not use this file!"
#endif

#include "vk_mem_alloc.h"

struct vk_framedata_t {
	VkSemaphore draw;
	VkSemaphore present;
	VkFence fence;
};

struct vk_shader_t
{
	void Create( const char *szPath, VkShaderStageFlagBits shaderStage );
	void Create( CUtlBuffer<uint8_t> &spirv, VkShaderStageFlagBits shaderStage );
	void Destroy( void );

	VkShaderModule m_shaderModule = NULL;
	VkPipelineShaderStageCreateInfo m_stageCreateInfo;
};

struct vk_tripipeline_t
{	
	void Create(
		CUtlVector<vk_shader_t> &shaders,
		CUtlVector<VkDescriptorSetLayoutBinding> &bindings,
		uint32_t pushConstantsSize,
		CUtlVector<VkFormat> formats
		/* the rest of the stuff is set by the dynamic state */
		/* literally */
	);
	void Destroy();
	CUtlVector<vk_shader_t> m_shaders;
	VkDescriptorSetLayout m_descriptorSetLayout;
	VkPipelineLayout m_layout;
	VkPipeline m_pipeline;
};

struct vk_comppipeline_t
{
	void Create(
		vk_shader_t &shader,
		CUtlVector<VkDescriptorSetLayoutBinding> &bindings,
		uint32_t pushConstantsSize
	);
	void Destroy();
	VkDescriptorSetLayout m_descriptorSetLayout;
	VkPipelineLayout m_layout;
	VkPipeline m_pipeline;
};

struct vk_buffer_t
{
	void Create(size_t size, VkBufferUsageFlags usage);
	void Destroy();
	void *Map(size_t offset, size_t size);
	void Unmap();

	void CopyTo(struct vk_image2d_t *image);
	void CopyTo(struct vk_buffer_t *buffer);

	
	size_t m_nSize;
	VkBuffer m_buffer;
	VmaAllocation m_memory;
	VkDeviceAddress m_address;
};

struct vk_image2d_t
{
	void Create(size_t x, size_t y, VkFormat format, VkImageUsageFlags usage, VkSampleCountFlagBits samples);
	void Destroy();
	
	void CopyTo(struct vk_image2d_t *image);
	void CopyTo(struct vk_buffer_t *buffer);

	
	uint32_t m_X;
	uint32_t m_Y;
	VkFormat m_format;
	VkImage m_image;
	VkImageView m_imageView;
	VmaAllocation m_memory;
};

interface IVulkan
{
public:
	static void Init();
	static void CreatePipelines();
	static void Frame();
	static void Deinit();
};

#endif
