#ifndef APPLICATION_HPP #define APPLICATION_HPP #include "mini/commandbuffer.hpp" #include "mini/commandpool.hpp" #include "mini/image.hpp" #include "mini/semaphore.hpp" #include #include #include #include #include class SwapchainContext; /// /// Main application class, wrapping around the Vulkan device. /// class Application { public: /// /// Create the application. /// /// @param device Vulkan device /// @param physicalDevice Vulkan physical device /// @param graphicsQueue Vulkan queue for graphics operations /// @param graphicsQueueFamilyIndex The family index of the graphics queue /// /// @throws LSFG::vulkan_error if any Vulkan call fails. /// Application(VkDevice device, VkPhysicalDevice physicalDevice, VkQueue graphicsQueue, uint32_t graphicsQueueFamilyIndex); /// /// Add a swapchain to the application. /// /// @param handle The Vulkan handle of the swapchain. /// @param format The format of the swapchain. /// @param extent The extent of the images. /// @param images The swapchain images. /// /// @throws LSFG::vulkan_error if any Vulkan call fails. /// void addSwapchain(VkSwapchainKHR handle, VkFormat format, VkExtent2D extent, const std::vector& images); /// /// Present the next frame on a given swapchain. /// /// @param handle The Vulkan handle of the swapchain to present on. /// @param queue The Vulkan queue to present the frame on. /// @param semaphores The semaphores to wait on before presenting. /// @param idx The index of the swapchain image to present. /// @param pNext Pointer to the next structure in a chain, if any. /// /// @throws LSFG::vulkan_error if any Vulkan call fails. /// void presentSwapchain(VkSwapchainKHR handle, VkQueue queue, const std::vector& semaphores, uint32_t idx, const void* pNext); /// /// Remove a swapchain from the application. /// /// @param handle The Vulkan handle of the swapchain state to remove. /// @return true if the swapchain was removed, false if it was already retired. /// bool removeSwapchain(VkSwapchainKHR handle); /// Get the Vulkan device. [[nodiscard]] VkDevice getDevice() const { return this->device; } /// Get the Vulkan physical device. [[nodiscard]] VkPhysicalDevice getPhysicalDevice() const { return this->physicalDevice; } /// Get the Vulkan graphics queue. [[nodiscard]] VkQueue getGraphicsQueue() const { return this->graphicsQueue; } /// Get the graphics queue family index. [[nodiscard]] uint32_t getGraphicsQueueFamilyIndex() const { return this->graphicsQueueFamilyIndex; } // Non-copyable and non-movable Application(const Application&) = delete; Application& operator=(const Application&) = delete; Application(Application&&) = delete; Application& operator=(Application&&) = delete; /// Destructor, cleans up resources. ~Application(); private: // (non-owned resources) VkDevice device; VkPhysicalDevice physicalDevice; VkQueue graphicsQueue; uint32_t graphicsQueueFamilyIndex; // (owned resources) std::unordered_map swapchains; }; /// /// An application's Vulkan swapchain and it's associated resources. /// class SwapchainContext { public: /// /// Create the swapchain context. /// /// @param app The application context to use. /// @param swapchain The Vulkan swapchain handle. /// @param format The format of the swapchain images. /// @param extent The extent of the swapchain images. /// @param images The swapchain images. /// /// @throws LSFG::vulkan_error if any Vulkan call fails. /// SwapchainContext(const Application& app, VkSwapchainKHR swapchain, VkFormat format, VkExtent2D extent, const std::vector& images); /// /// Present the next frame /// /// @param app The application context to use /// @param queue The Vulkan queue to present the frame on. /// @param semaphores The semaphores to wait on before presenting. /// @param idx The index of the swapchain image to present. /// @param pNext Pointer to the next structure in a chain, if any. /// /// @throws LSFG::vulkan_error if any Vulkan call fails. /// void present(const Application& app, VkQueue queue, const std::vector& semaphores, uint32_t idx, const void* pNext); /// Get the Vulkan swapchain handle. [[nodiscard]] VkSwapchainKHR handle() const { return this->swapchain; } /// Get the format of the swapchain images. [[nodiscard]] VkFormat getFormat() const { return this->format; } /// Get the extent of the swapchain images. [[nodiscard]] VkExtent2D getExtent() const { return this->extent; } /// Get the swapchain images. [[nodiscard]] const std::vector& getImages() const { return this->images; } // Non-copyable, trivially moveable and destructible SwapchainContext(const SwapchainContext&) = delete; SwapchainContext& operator=(const SwapchainContext&) = delete; SwapchainContext(SwapchainContext&&) = default; SwapchainContext& operator=(SwapchainContext&&) = default; ~SwapchainContext() = default; private: // (non-owned resources) VkSwapchainKHR swapchain; VkFormat format; VkExtent2D extent; std::vector images; // (owned resources) Mini::CommandPool cmdPool; std::array cmdBufs1; std::array, 8> cmdBufs2; std::array copySemaphores1; // copy current swap to frame std::array copySemaphores2; // (for present) std::array, 8> acquireSemaphores; // acquire new swapchain image std::array, 8> renderSemaphores; // fg is done std::array, 8> prevPresentSemaphores; // for inorder fg std::array, 8> presentSemaphores; // copy is done, ready to present Mini::Image frame_0, frame_1; std::vector outImgs; std::shared_ptr lsfgId; uint64_t frameIdx{0}; std::optional deferredIdx; // index of the frame to present next }; #endif // APPLICATION_HPP