Newer
Older
ForwardPlusRenderer / include / SwapChain.h
#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