Newer
Older
ForwardPlusRenderer / src / RenderPass.cpp
#include <stdafx.h>
#include "RenderPass.h"

#include "Context.h"
#include "Device.h"
#include "Buffer/DepthBuffer.h"
namespace fpr
{
vk::RenderPass& RenderPass::GetvkRenderPass() FPR_NOEXCEPT
{
  return m_render_pass.get();
}

RenderPass::RenderPass(const RenderPassOptions& options, fpr::Device* device)
{
  //Construct render pass based on passed options
  vk::SubpassDescription subpass;
  subpass.pipelineBindPoint = vk::PipelineBindPoint::eGraphics;
  subpass.setPDepthStencilAttachment(&options.depth_attachment_ref);
  subpass.setColorAttachments(options.color_attachment_refs);


  std::vector<vk::SubpassDescription> subpasses = { subpass };

  vk::RenderPassCreateInfo render_pass_create_info;
  render_pass_create_info.setAttachments(options.attachments);
  render_pass_create_info.setSubpasses(subpasses);
  render_pass_create_info.setDependencies(options.dependencies);

  auto [result_signal, render_pass] = device->GetLogicalDeviceHandle().createRenderPassUnique(render_pass_create_info);

  assert(("Render pass creation was not successful", result_signal == vk::Result::eSuccess));
  m_render_pass = std::move(render_pass);
}

RenderPassOptions RenderPass::MakeDefaultRenderPass(vk::Format swapchain_format, vk::Format depth_image_format)
{
  //Default render pass does write to the depth buffer, only the color attachmnt.
  vk::AttachmentDescription color_attachment;
  color_attachment.format         = swapchain_format;
  color_attachment.samples        = vk::SampleCountFlagBits::e1;
  color_attachment.loadOp         = vk::AttachmentLoadOp::eClear;
  color_attachment.storeOp        = vk::AttachmentStoreOp::eStore;
  color_attachment.stencilLoadOp  = vk::AttachmentLoadOp::eDontCare;
  color_attachment.stencilStoreOp = vk::AttachmentStoreOp::eDontCare;
  color_attachment.initialLayout  = vk::ImageLayout::eUndefined;
  color_attachment.finalLayout    = vk::ImageLayout::ePresentSrcKHR;


  vk::AttachmentDescription depth_attachment;
  depth_attachment.format         = depth_image_format;
  depth_attachment.samples        = vk::SampleCountFlagBits::e1;
  depth_attachment.loadOp         = vk::AttachmentLoadOp::eLoad;
  depth_attachment.storeOp        = vk::AttachmentStoreOp::eStore;
  depth_attachment.stencilLoadOp  = vk::AttachmentLoadOp::eDontCare;
  depth_attachment.stencilStoreOp = vk::AttachmentStoreOp::eDontCare;
  depth_attachment.initialLayout  = vk::ImageLayout::eDepthStencilReadOnlyOptimal;
  depth_attachment.finalLayout    = vk::ImageLayout::eDepthStencilReadOnlyOptimal;
  vk::AttachmentReference color_attachment_ref;
  color_attachment_ref.attachment = 0;
  color_attachment_ref.layout     = vk::ImageLayout::eColorAttachmentOptimal;

  vk::AttachmentReference depth_attachment_ref;
  depth_attachment_ref.attachment = 1;
  depth_attachment_ref.layout     = vk::ImageLayout::eDepthStencilReadOnlyOptimal;

  //Subpass dependencies to synchronise the two renderpasses, to allow for maximum performance and to transition between optimal image layouts.
  //As per the Vulkan documentation, warning against RAW and WAW errors.
  std::vector<vk::SubpassDependency> subpasses(2);
  subpasses[0].srcSubpass    = VK_SUBPASS_EXTERNAL;
  subpasses[0].dstSubpass    = 0;
  subpasses[0].srcStageMask  = vk::PipelineStageFlagBits::eColorAttachmentOutput;
  subpasses[0].dstStageMask  = vk::PipelineStageFlagBits::eColorAttachmentOutput;
  subpasses[0].dstAccessMask = vk::AccessFlagBits::eColorAttachmentWrite;

   subpasses[1].srcSubpass    = 0;
   subpasses[1].dstSubpass      = VK_SUBPASS_EXTERNAL;
   subpasses[1].srcStageMask    = vk::PipelineStageFlagBits::eColorAttachmentOutput;
   subpasses[1].srcAccessMask   = vk::AccessFlagBits::eColorAttachmentRead |
   vk::AccessFlagBits::eColorAttachmentWrite; subpasses[1].dstStageMask    = vk::PipelineStageFlagBits::eTopOfPipe;
   subpasses[1].dstAccessMask   = vk::AccessFlagBits::eMemoryRead;
   subpasses[1].dependencyFlags = {};

  std::vector<vk::AttachmentDescription> attachment_descs = { color_attachment, depth_attachment };
  std::vector<vk::AttachmentReference>   attachment_refs  = { color_attachment_ref };

  RenderPassOptions options;
  options.attachments           = attachment_descs;
  options.dependencies          = subpasses;
  options.color_attachment_refs = attachment_refs;
  options.depth_attachment_ref  = depth_attachment_ref;

  return options;
}

RenderPassOptions RenderPass::MakeDefaultDepthPass(vk::Format depth_image_format)
{
  //Depth pre pass only writes to depth buffer.
  vk::AttachmentReference depth_attachment_ref;
  depth_attachment_ref.attachment = 0;
  depth_attachment_ref.layout     = vk::ImageLayout::eDepthStencilAttachmentOptimal;

  vk::AttachmentDescription depth_attachment;
  depth_attachment.format         = depth_image_format;
  depth_attachment.samples        = vk::SampleCountFlagBits::e1;
  depth_attachment.loadOp         = vk::AttachmentLoadOp::eClear;
  depth_attachment.storeOp        = vk::AttachmentStoreOp::eStore;
  depth_attachment.stencilLoadOp  = vk::AttachmentLoadOp::eClear;
  depth_attachment.stencilStoreOp = vk::AttachmentStoreOp::eStore;
  depth_attachment.initialLayout  = vk::ImageLayout::eUndefined;
  depth_attachment.finalLayout    = vk::ImageLayout::eDepthStencilReadOnlyOptimal;

  //Transition into optimal layout for depth sampling.
  vk::SubpassDependency dependency;
  dependency.srcSubpass    = VK_SUBPASS_EXTERNAL;
  dependency.dstSubpass    = 0;
  dependency.srcStageMask  = vk::PipelineStageFlagBits::eEarlyFragmentTests;
  dependency.dstStageMask  = vk::PipelineStageFlagBits::eEarlyFragmentTests;
  dependency.srcAccessMask = vk::AccessFlagBits::eDepthStencilAttachmentWrite;
  dependency.dstAccessMask = vk::AccessFlagBits::eDepthStencilAttachmentWrite |
      vk::AccessFlagBits::eDepthStencilAttachmentRead;
  dependency.dependencyFlags = {};

  std::vector<vk::AttachmentDescription> attachments{ depth_attachment };
  std::vector<vk::SubpassDependency>     dependencies{ dependency };

  RenderPassOptions options;
  options.attachments          = attachments;
  options.dependencies         = dependencies;
  options.depth_attachment_ref = depth_attachment_ref;

  return options;
}
} // namespace fpr