#pragma once #include <stdafx.h> #include "Buffer/DepthBuffer.h" #include "VulkanWindow.h" namespace fpr { class RenderPass; class SwapChain { ViewportConstants m_viewport_push_constant; static constexpr glm::vec2 DEFAULT_TILE_SIZE = { 32, 32, }; // Tile are used use to subdivide the view frustum for light culling. using SwapchainDetails = std::tuple<vk::SurfaceCapabilitiesKHR, std::vector<vk::SurfaceFormatKHR>, std::vector<vk::PresentModeKHR>>; using SwapChainImage = std::pair<vk::Image, vk::UniqueImageView>; vk::PresentModeKHR m_present_mode; vk::UniqueSwapchainKHR m_swapchain; vk::SurfaceFormatKHR m_surface_format; std::unique_ptr<fpr::DepthBuffer> m_depth_buffer; std::vector<SwapChainImage> m_swapchain_images; std::vector<vk::UniqueCommandBuffer> m_command_buffers; std::vector<vk::UniqueFramebuffer> m_swapchain_framebuffers; std::vector<vk::UniqueSemaphore> m_image_ready_semaphores; std::vector<vk::UniqueSemaphore> m_render_done_semaphores; std::vector<vk::UniqueSemaphore> m_compute_semaphores; vk::UniqueFence m_draw_fence; std::vector<vk::UniqueSemaphore> m_earlyz_semaphores; uint32_t MAX_IMAGES_IN_FLIGHT = 2; //Want at least double buffering if possible. uint32_t m_current_frame = 0; vk::Extent2D m_extent; bool is_recreation = false; //Resizing requires swapchain recreation. Most of the time, not needed std::vector<vk::UniqueFramebuffer> m_depth_framebuffers; std::vector<vk::UniqueCommandBuffer> m_depth_command_buffers; std::vector<vk::UniqueCommandBuffer> m_compute_command_buffers; vk::UniqueSwapchainKHR m_old_swapchain; static constexpr vk::ImageAspectFlagBits ASPECT_FLAGS = vk::ImageAspectFlagBits::eColor; static constexpr vk::ImageViewType IMAGE_VIEW_TYPE = vk::ImageViewType::e2D; static constexpr vk::ColorSpaceKHR wanted_color_space = vk::ColorSpaceKHR::eSrgbNonlinear; static constexpr std::array<vk::Format, 2> wanted_formats = { vk::Format::eR8G8B8A8Srgb, vk::Format::eB8G8R8A8Srgb }; std::array<vk::ClearValue, 2> m_clear_values = { vk::ClearValue().setColor( vk::ClearColorValue().setFloat32({ 1.0f, 0.4f, 0.8f, 1.0f })), vk::ClearValue().depthStencil = 1.0f }; SwapchainDetails QuerySwapChainDetails(fpr::Device* device, vk::SurfaceKHR& surface); vk::SurfaceFormatKHR QueryFirstSuitableFormat(const std::vector<vk::SurfaceFormatKHR>& formats); vk::Extent2D QueryExtenfromCapabilities(vk::SurfaceCapabilitiesKHR capabilities); void CreateSynchronisation(fpr::Device* device); void SyncDepthPass(fpr::Device* device); void SyncColorPass(fpr::Device* device); void SyncPresentation(fpr::Device* device, uint32_t inmage_index); void SyncCompute(fpr::Device* device); void CreateSwapchain(fpr::Device* device, vk::SurfaceKHR& surface); void CreateImageViews(fpr::Device* device); void CreateFrameBuffers(fpr::Device* device); void CreateRenderPasses(fpr::Device* device); public: const ViewportConstants& GetViewportConstants() const FPR_NOEXCEPT; void RecordCommands(); void CreateCommandBuffers(); vk::Result SubmitFrame(); void RecordRenderCommands(); void RecordDepthCommands(); void RecordComputeCommands(); const std::vector<SwapChainImage>& GetImages(); fpr::DepthBuffer* GetDepthBuffer() FPR_NOEXCEPT; const vk::Extent2D& GetCurrentExtent(); const vk::Format& GetSwapchainImageFormat() const FPR_NOEXCEPT; uint32_t GetCurrentFrameIdx() const; uint32_t GetMaxFrameIdx() const; vk::UniqueSwapchainKHR& GetUniqueHandle(); SwapChain( fpr::Device* device, vk::SurfaceKHR& surface, std::optional<vk::UniqueSwapchainKHR> old_swapchain = std::nullopt, glm::ivec2 tile_size = DEFAULT_TILE_SIZE); SwapChain(const SwapChain& other) = delete; SwapChain(const SwapChain&& other) = delete; SwapChain operator=(const SwapChain& other) = delete; SwapChain operator=(const SwapChain&& other) = delete; }; } // namespace fpr