#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