Refactor RenderPass logic

This commit is contained in:
2021-07-30 17:45:02 +02:00
parent 582a82d9b4
commit b00d888471
5 changed files with 270 additions and 206 deletions

View File

@@ -30,7 +30,7 @@ namespace openVulkanoCpp::Vulkan
swapChain.Init(device.get(), surface, window);
swapChainRenderPass.Init(device.get(), &swapChain);
swapChainRenderPass.Init(device.get(), &swapChain, true, true);
pipeline.Init(device->device);

View File

@@ -1,3 +1,9 @@
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
#include "FrameBuffer.hpp"
#include "RenderPass.hpp"
@@ -14,12 +20,17 @@ void openVulkanoCpp::Vulkan::FrameBuffer::Init(Device* device, vk::Extent3D size
}
}
void openVulkanoCpp::Vulkan::FrameBuffer::InitRenderPass(RenderPass* renderPass)
void openVulkanoCpp::Vulkan::FrameBuffer::RegisterRenderPass(RenderPass* renderPass)
{
if (!device) throw std::
runtime_error("The frame buffer needs to be initialized before binding it to a render pass");
this->renderPass = renderPass;
CreateFrameBuffer();
if (!renderPasses.empty())
{
//TODO check compatibility
// https://registry.khronos.org/vulkan/specs/1.3-extensions/html/vkspec.html#renderpass-compatibility
}
renderPasses.push_back(renderPass);
if (renderPasses.size() == 1) CreateFrameBuffer();
}
void openVulkanoCpp::Vulkan::FrameBuffer::Resize(vk::Extent3D size)
@@ -29,7 +40,10 @@ void openVulkanoCpp::Vulkan::FrameBuffer::Resize(vk::Extent3D size)
if (depthBuffer) depthBuffer.Close();
if (useDepthBuffer) CreateDepthStencil();
CreateFrameBuffer();
renderPass->UpdateBeginInfo();
for(RenderPass* renderPass : renderPasses)
{
renderPass->Resize(size);
}
}
void openVulkanoCpp::Vulkan::FrameBuffer::CreateDepthStencil()
@@ -54,7 +68,7 @@ void openVulkanoCpp::Vulkan::FrameBuffer::CreateFrameBuffer()
{
vk::ImageView attachments[2]; // First attachment is the color buffer, second (optional) the depth buffer
if (useDepthBuffer) attachments[1] = depthBuffer.view; //Depth buffer is the same for all frame buffers
const vk::FramebufferCreateInfo fbCreateInfo({}, renderPass->renderPass, useDepthBuffer ? 2 : 1, attachments, size.width,
const vk::FramebufferCreateInfo fbCreateInfo({}, renderPasses[0]->renderPass, useDepthBuffer ? 2 : 1, attachments, size.width,
size.height, 1);
auto images = GetImages();

View File

@@ -1,14 +1,20 @@
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
#pragma once
#include <cstdint>
#include <vulkan/vulkan.hpp>
#include "Base/ICloseable.hpp"
#include "Image.hpp"
#include "Device.hpp"
#include <cstdint>
#include <vulkan/vulkan.hpp>
namespace openVulkanoCpp
namespace openVulkanoCpp::Vulkan
{
namespace Vulkan
{
class RenderPass;
class FrameBuffer : ICloseable
@@ -17,7 +23,7 @@ namespace openVulkanoCpp
std::vector<vk::Framebuffer> frameBuffers;
vk::Format depthBufferFormat = vk::Format::eUndefined, colorFormat = vk::Format::eUndefined;
vk::Extent3D size;
RenderPass* renderPass;
std::vector<RenderPass*> renderPasses;
bool useDepthBuffer;
Device* device = nullptr;
protected:
@@ -43,7 +49,7 @@ namespace openVulkanoCpp
}
public:
void InitRenderPass(RenderPass* renderPass);
void RegisterRenderPass(RenderPass* renderPass);
protected:
void Resize(vk::Extent3D size);
@@ -103,5 +109,4 @@ namespace openVulkanoCpp
return frameBuffers[currentFrameBufferId];
}
};
}
}

View File

@@ -0,0 +1,100 @@
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
#include "RenderPass.hpp"
#include "FrameBuffer.hpp"
#include "Base/EngineConfiguration.hpp"
namespace openVulkanoCpp::Vulkan
{
void RenderPass::Init(Device* device, FrameBuffer* frameBuffer, bool clearColor, bool clearDepth)
{
m_device = device->device;
m_frameBuffer = frameBuffer;
m_useClearColor = clearColor;
m_useClearDepth = clearDepth;
CreateRenderPass();
frameBuffer->RegisterRenderPass(this);
m_beginInfo.renderPass = renderPass;
m_beginInfo.renderArea = vk::Rect2D(vk::Offset2D(), m_frameBuffer->GetSize2D());
if (clearColor) SetClearColor(EngineConfiguration::GetEngineConfiguration()->GetFrameBufferClearColor());
if (clearDepth) SetClearDepth();
}
void RenderPass::Close()
{
m_device.destroy(renderPass);
m_frameBuffer = nullptr;
}
void RenderPass::UpdateBeginInfo()
{
uint32_t size = 0;
vk::ClearValue* clearValues = nullptr;
if (m_useClearColor) { size++; clearValues = m_clearValues.data(); }
else if (m_useClearDepth) clearValues = &m_clearValues[1];
if (m_useClearDepth) size++;
m_beginInfo.clearValueCount = size;
m_beginInfo.pClearValues = clearValues;
}
void RenderPass::Begin(vk::CommandBuffer& commandBuffer, bool primaryBuffer)
{
m_beginInfo.framebuffer = m_frameBuffer->GetCurrentFrameBuffer();
commandBuffer.beginRenderPass(m_beginInfo, primaryBuffer ? vk::SubpassContents::eInline : vk::SubpassContents::eSecondaryCommandBuffers);
}
void RenderPass::End(vk::CommandBuffer& commandBuffer)
{
commandBuffer.endRenderPass();
}
void RenderPass::CreateRenderPass()
{
std::vector<vk::AttachmentDescription> attachments;
attachments.reserve(m_frameBuffer->UseDepthBuffer() ? 2 : 1);
// Color attachment
attachments.emplace_back(vk::AttachmentDescriptionFlags(), m_frameBuffer->GetColorFormat(), vk::SampleCountFlagBits::e1,
m_useClearColor ? vk::AttachmentLoadOp::eClear : vk::AttachmentLoadOp::eLoad, vk::AttachmentStoreOp::eStore, vk::AttachmentLoadOp::eLoad,
vk::AttachmentStoreOp::eStore, vk::ImageLayout::eUndefined, vk::ImageLayout::ePresentSrcKHR);
vk::AttachmentReference* depthReference = nullptr;
if (m_frameBuffer->UseDepthBuffer())
{ // Depth attachment
attachments.emplace_back(vk::AttachmentDescriptionFlags(), m_frameBuffer->GetDepthFormat(), vk::SampleCountFlagBits::e1,
m_useClearDepth ? vk::AttachmentLoadOp::eClear : vk::AttachmentLoadOp::eLoad, vk::AttachmentStoreOp::eDontCare, m_useClearDepth ? vk::AttachmentLoadOp::eClear : vk::AttachmentLoadOp::eLoad,
vk::AttachmentStoreOp::eDontCare, vk::ImageLayout::eUndefined, vk::ImageLayout::eDepthStencilAttachmentOptimal);
depthReference = new vk::AttachmentReference(1, vk::ImageLayout::eDepthStencilAttachmentOptimal);
}
std::vector<vk::AttachmentReference> colorAttachmentReferences;
colorAttachmentReferences.emplace_back(0, vk::ImageLayout::eColorAttachmentOptimal);
std::vector<vk::SubpassDescription> subPasses;
subPasses.emplace_back(vk::SubpassDescriptionFlags(), vk::PipelineBindPoint::eGraphics, 0, nullptr,
colorAttachmentReferences.size(), colorAttachmentReferences.data(), nullptr, depthReference, 0, nullptr);
std::vector<vk::SubpassDependency> subPassDependencies;
subPassDependencies.emplace_back(0, VK_SUBPASS_EXTERNAL, vk::PipelineStageFlagBits::eColorAttachmentOutput,
vk::PipelineStageFlagBits::eBottomOfPipe, vk::AccessFlagBits::eColorAttachmentRead | vk::AccessFlagBits::eColorAttachmentWrite,
vk::AccessFlagBits::eMemoryRead, vk::DependencyFlagBits::eByRegion);
subPassDependencies.emplace_back(VK_SUBPASS_EXTERNAL, 0, vk::PipelineStageFlagBits::eBottomOfPipe,
vk::PipelineStageFlagBits::eColorAttachmentOutput, vk::AccessFlagBits::eMemoryRead,
vk::AccessFlagBits::eColorAttachmentRead | vk::AccessFlagBits::eColorAttachmentWrite,
vk::DependencyFlagBits::eByRegion);
const vk::RenderPassCreateInfo createInfo(vk::RenderPassCreateFlags(), attachments.size(), attachments.data(),
subPasses.size(), subPasses.data(), subPassDependencies.size(), subPassDependencies.data());
CreateRenderPass(createInfo);
delete depthReference;
}
void RenderPass::CreateRenderPass(const vk::RenderPassCreateInfo& renderPassCreateInfo)
{
renderPass = m_device.createRenderPass(renderPassCreateInfo);
}
}

View File

@@ -6,25 +6,21 @@
#pragma once
#include <vulkan/vulkan.hpp>
#include "Device.hpp"
#include "FrameBuffer.hpp"
#include "Base/EngineConfiguration.hpp"
#include <vulkan/vulkan.hpp>
namespace openVulkanoCpp
namespace openVulkanoCpp::Vulkan
{
namespace Vulkan
{
class FrameBuffer;
class RenderPass : virtual public ICloseable
{
{ //TODO allow to control the render rect size
protected:
vk::Device device;
vk::RenderPassBeginInfo beginInfo;
vk::ClearColorValue clearColor;
vk::ClearDepthStencilValue clearDepth;
std::vector<vk::ClearValue> clearValues;
FrameBuffer* frameBuffer = nullptr;
bool useClearColor = false, useClearDepth = true;
vk::Device m_device;
vk::RenderPassBeginInfo m_beginInfo;
std::array<vk::ClearValue, 2> m_clearValues;
FrameBuffer* m_frameBuffer = nullptr;
bool m_useClearColor = false, m_useClearDepth = true;
public:
vk::RenderPass renderPass;
@@ -33,123 +29,72 @@ namespace openVulkanoCpp
~RenderPass() override
{
if (frameBuffer) RenderPass::Close();
if (m_frameBuffer) RenderPass::Close();
}
void Init(Device* device, FrameBuffer* frameBuffer)
{
this->device = device->device;
this->frameBuffer = frameBuffer;
CreateRenderPass();
frameBuffer->InitRenderPass(this);
SetClearColor(EngineConfiguration::GetEngineConfiguration()->GetFrameBufferClearColor());
SetClearDepth();
}
void Init(Device* device, FrameBuffer* frameBuffer, bool clearColor = false, bool clearDepth = false);
void Close() override
{
device.destroy(renderPass);
frameBuffer = nullptr;
clearValues.clear();
}
void Close() override;
void SetClearColor(vk::ClearColorValue clearColor = vk::ClearColorValue(std::array<float, 4>{ 0.39f, 0.58f, 0.93f, 1.0f }))
{
this->clearColor = clearColor;
useClearColor = true;
m_clearValues[0] = clearColor;
if (!m_useClearColor)
{
m_useClearColor = true;
//TODO recreate
}
UpdateBeginInfo();
}
void DisableClearColor()
{
useClearColor = false;
if (m_useClearColor)
{
m_useClearColor = false;
//TODO recreate
UpdateBeginInfo();
}
}
void SetClearDepth(vk::ClearDepthStencilValue clearDepth = vk::ClearDepthStencilValue(1, 0))
{
this->clearDepth = clearDepth;
useClearDepth = true;
m_clearValues[1] = clearDepth;
if (!m_useClearDepth)
{
m_useClearDepth = true;
//TODO recreate
}
UpdateBeginInfo();
}
void DisableClearDepth()
{
useClearDepth = false;
}
virtual void UpdateBeginInfo()
{ //TODO allow to control the render rect size
clearValues.clear();
if (useClearColor) clearValues.emplace_back(clearColor);
if(frameBuffer->UseDepthBuffer() && useClearDepth) clearValues.emplace_back(clearDepth);
beginInfo = vk::RenderPassBeginInfo(renderPass, vk::Framebuffer(),
vk::Rect2D(vk::Offset2D(), frameBuffer->GetSize2D()),
clearValues.size(), clearValues.data());
}
virtual void Begin(vk::CommandBuffer& commandBuffer)
if (m_useClearDepth)
{
beginInfo.framebuffer = frameBuffer->GetCurrentFrameBuffer();
commandBuffer.beginRenderPass(beginInfo, vk::SubpassContents::eSecondaryCommandBuffers);
m_useClearDepth = false;
//TODO recreate
UpdateBeginInfo();
}
}
virtual void End(vk::CommandBuffer& commandBuffer)
void Resize(vk::Extent3D size)
{
commandBuffer.endRenderPass();
m_beginInfo.renderArea.extent.width = size.width;
m_beginInfo.renderArea.extent.height = size.height;
}
FrameBuffer* GetFrameBuffer() const
{
return frameBuffer;
}
virtual void UpdateBeginInfo();
virtual void Begin(vk::CommandBuffer& commandBuffer, bool primaryBuffer = false);
virtual void End(vk::CommandBuffer& commandBuffer);
[[nodiscard]] FrameBuffer* GetFrameBuffer() const { return m_frameBuffer; }
protected:
virtual void CreateRenderPass()
{
std::vector<vk::AttachmentDescription> attachments;
attachments.reserve(frameBuffer->UseDepthBuffer() ? 2 : 1);
virtual void CreateRenderPass();
// Color attachment
attachments.emplace_back(vk::AttachmentDescriptionFlags(), frameBuffer->GetColorFormat(), vk::SampleCountFlagBits::e1,
vk::AttachmentLoadOp::eClear, vk::AttachmentStoreOp::eStore, vk::AttachmentLoadOp::eLoad,
vk::AttachmentStoreOp::eStore, vk::ImageLayout::eUndefined, vk::ImageLayout::ePresentSrcKHR);
vk::AttachmentReference* depthReference = nullptr;;
if (frameBuffer->UseDepthBuffer())
{ // Depth attachment
attachments.emplace_back(vk::AttachmentDescriptionFlags(), frameBuffer->GetDepthFormat(), vk::SampleCountFlagBits::e1,
vk::AttachmentLoadOp::eClear, vk::AttachmentStoreOp::eDontCare, vk::AttachmentLoadOp::eClear,
vk::AttachmentStoreOp::eDontCare, vk::ImageLayout::eUndefined, vk::ImageLayout::eDepthStencilAttachmentOptimal);
depthReference = new vk::AttachmentReference(1, vk::ImageLayout::eDepthStencilAttachmentOptimal);
}
std::vector<vk::AttachmentReference> colorAttachmentReferences;
colorAttachmentReferences.emplace_back(0, vk::ImageLayout::eColorAttachmentOptimal);
std::vector<vk::SubpassDescription> subPasses;
subPasses.emplace_back(vk::SubpassDescriptionFlags(), vk::PipelineBindPoint::eGraphics, 0, nullptr,
colorAttachmentReferences.size(), colorAttachmentReferences.data(), nullptr, depthReference, 0, nullptr);
std::vector<vk::SubpassDependency> subPassDependencies;
subPassDependencies.emplace_back(0, VK_SUBPASS_EXTERNAL, vk::PipelineStageFlagBits::eColorAttachmentOutput,
vk::PipelineStageFlagBits::eBottomOfPipe, vk::AccessFlagBits::eColorAttachmentRead | vk::AccessFlagBits::eColorAttachmentWrite,
vk::AccessFlagBits::eMemoryRead, vk::DependencyFlagBits::eByRegion);
subPassDependencies.emplace_back(VK_SUBPASS_EXTERNAL, 0, vk::PipelineStageFlagBits::eBottomOfPipe,
vk::PipelineStageFlagBits::eColorAttachmentOutput, vk::AccessFlagBits::eMemoryRead,
vk::AccessFlagBits::eColorAttachmentRead | vk::AccessFlagBits::eColorAttachmentWrite,
vk::DependencyFlagBits::eByRegion);
const vk::RenderPassCreateInfo createInfo(vk::RenderPassCreateFlags(), attachments.size(), attachments.data(),
subPasses.size(), subPasses.data(), subPassDependencies.size(), subPassDependencies.data());
CreateRenderPass(createInfo);
delete depthReference;
}
void CreateRenderPass(const vk::RenderPassCreateInfo& renderPassCreateInfo)
{
renderPass = device.createRenderPass(renderPassCreateInfo);
}
void CreateRenderPass(const vk::RenderPassCreateInfo& renderPassCreateInfo);
};
}
}