#pragma once #include "../../VulkanRenderer.h" namespace PB::Renderer { struct Mesh; class VulkanManager { public: // === Public functions === // /* Static class so (de)constructors have been deleted to stop accidental creation */ VulkanManager() = delete; ~VulkanManager() = delete; /* Shorthand for calling all the initialisation functions, returns false if any fail */ static bool Init(GLFWwindow* window); /* Frees ALL allocated Vulkan resources */ static bool Cleanup(); /* Creates the global Vulkan instance, which connects the application to Vulkan. Defines the application info and imports the needed (GLFW) extensions. */ static bool CreateInstance(); /* Ties a surface to the window to present images. Abstracts platform specific code. Required for creating a swap chain. */ static bool CreateSurface(GLFWwindow* window); /* Scans for all available GPUs and picks the first one that supports the necessary capabilities. Only looks for discrete (non-integrated) GPUs and uses that for all rendering. */ static bool PickPhysicalDevice(); /* Creates a logical device which handles the commands from Vulkan to hardware instructions. Also requests the queues needed. */ static bool CreateLogicalDevice(); /* Creates a swap chain with suitable image formats, present modes and image dimensions. The swap chain is the series of images that are displayed to the screen. */ static bool CreateSwapChain(GLFWwindow* window); /* Each swap chain image requires a view, which describes how shaders and the pipeline interact with the image data. */ static bool CreateImageViews(); /* Defines the attachments (such as color and depth) and defines how they are rendered. Also defines the subpasses and dependencies between them. */ static bool CreateRenderPass(); /* Creates a framebuffer for each swap chain image, pairing the render pass with the relevant image. Each framebuffer is a specific set of attachments used drawing a render pass instance. */ static bool CreateFramebuffer(); /* Assembles shaders, fixed function state and creates the render pipeline. Also checks that the render pass is compatible. */ static bool CreateGraphicsPipeline(); /* Allocates a command pool and command buffers. The buffers represent the exact instructions the GPU will execute. */ static bool CreateCommandBuffers(); /* Creates sync between coordinate operations between different parts of the rendering. Required to stop race conditions between frames. */ static bool CreateSemaphores(); /* Draws a frame to the screen using the command buffers and sync objects. */ static bool RenderPass(GLFWwindow* window); static void CreateNewRenderObject(Color color, const Mesh& mesh); private: // === Internal helper structs === // struct RenderObject { VkBuffer VertexBuffer{}; VkDeviceMemory VertexBufferMemory{}; VkBuffer IndexBuffer{}; VkDeviceMemory IndexBufferMemory{}; Color DrawColor; uint32_t IndexCount{}; }; struct QueueFamilyIndices { static constexpr uint32_t UNDEFINED_UINT32_VALUE = 0xFFFFFFFF; uint32_t graphicsFamily = UNDEFINED_UINT32_VALUE; uint32_t presentFamily = UNDEFINED_UINT32_VALUE; [[nodiscard]] bool Complete() const { return graphicsFamily != UNDEFINED_UINT32_VALUE && presentFamily != UNDEFINED_UINT32_VALUE; } }; struct SwapChainSupportDetails { VkSurfaceCapabilitiesKHR capabilities; std::vector formats; std::vector presentModes; }; struct BufferCreationInfo { VkDeviceSize size; VkBufferUsageFlags usage; VkMemoryPropertyFlags properties; }; // === Vulkan init helpers === // static bool IsDeviceSuitable(VulkanHandle device); static QueueFamilyIndices FindQueueFamilies(VulkanHandle device); static bool CheckDeviceExtensionSupport(VulkanHandle device); static SwapChainSupportDetails QuerySwapChainSupport(); static VkSurfaceFormatKHR ChooseSurfaceFormat(const std::vector& availableFormats); static VkPresentModeKHR ChoosePresentMode(const std::vector& availablePresentModes); static VkExtent2D ChooseSwapExtent(const VkSurfaceCapabilitiesKHR& capabilities, GLFWwindow* window); static VkShaderModule CreateShaderModule(const std::string& filename); // === Vulkan render helpers === // static VkResult RenderPassInternal(); static void RecreateSwapChain(GLFWwindow* window); static void CleanupSwapChain(); static VkResult RecordCommandBuffer(uint32_t imageIndex); static uint32_t FindMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags properties); static void CreateBuffer(VkBuffer& buffer, VkDeviceMemory& memory, const BufferCreationInfo& info); // === Custom resources === // static std::vector s_RenderObjects; // === Vulkan resources === // static VkInstance s_Instance; static VkSurfaceKHR s_Surface; static VkPhysicalDevice s_PhysicalDevice; static QueueFamilyIndices s_QueueIndices; static VkDevice s_Device; static VkQueue s_GraphicsQueue; static VkQueue s_PresentQueue; static VkSwapchainKHR s_SwapChain; static std::vector s_SwapChainImages; static std::vector s_SwapChainImageViews; static VkFormat s_SwapChainImageFormat; static VkExtent2D s_SwapChainExtent; static VkRenderPass s_RenderPass; static std::vector s_Framebuffers; static VkPipelineLayout s_PipelineLayout; static VkPipeline s_RenderPipeline; static VkCommandPool s_CommandPool; static std::vector s_CommandBuffers; static VkSemaphore s_ImageAvailableSemaphore; static VkSemaphore s_RenderFinishedSemaphore; }; }