diff --git a/openVulkanoCpp/Vulkan/Context.cpp b/openVulkanoCpp/Vulkan/Context.cpp index 0397eee..35aa90a 100644 --- a/openVulkanoCpp/Vulkan/Context.cpp +++ b/openVulkanoCpp/Vulkan/Context.cpp @@ -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); diff --git a/openVulkanoCpp/Vulkan/FrameBuffer.cpp b/openVulkanoCpp/Vulkan/FrameBuffer.cpp index e8ee4d9..bd0ad9f 100644 --- a/openVulkanoCpp/Vulkan/FrameBuffer.cpp +++ b/openVulkanoCpp/Vulkan/FrameBuffer.cpp @@ -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(); diff --git a/openVulkanoCpp/Vulkan/FrameBuffer.hpp b/openVulkanoCpp/Vulkan/FrameBuffer.hpp index a467823..2a0d2a0 100644 --- a/openVulkanoCpp/Vulkan/FrameBuffer.hpp +++ b/openVulkanoCpp/Vulkan/FrameBuffer.hpp @@ -1,107 +1,112 @@ +/* + * 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 -#include + #include "Base/ICloseable.hpp" #include "Image.hpp" #include "Device.hpp" +#include +#include -namespace openVulkanoCpp + +namespace openVulkanoCpp::Vulkan { - namespace Vulkan + class RenderPass; + + class FrameBuffer : ICloseable { - class RenderPass; + Image depthBuffer; + std::vector frameBuffers; + vk::Format depthBufferFormat = vk::Format::eUndefined, colorFormat = vk::Format::eUndefined; + vk::Extent3D size; + std::vector renderPasses; + bool useDepthBuffer; + Device* device = nullptr; + protected: + uint32_t currentFrameBufferId = 0; - class FrameBuffer : ICloseable + FrameBuffer() = default; + + virtual ~FrameBuffer() { - Image depthBuffer; - std::vector frameBuffers; - vk::Format depthBufferFormat = vk::Format::eUndefined, colorFormat = vk::Format::eUndefined; - vk::Extent3D size; - RenderPass* renderPass; - bool useDepthBuffer; - Device* device = nullptr; - protected: - uint32_t currentFrameBufferId = 0; + if (device) FrameBuffer::Close(); + } - FrameBuffer() = default; + void Init(Device* device, vk::Extent3D size, bool useDepthBuffer = true); - virtual ~FrameBuffer() - { - if (device) FrameBuffer::Close(); - } + void SetCurrentFrameId(uint32_t id) + { + currentFrameBufferId = id; + } - void Init(Device* device, vk::Extent3D size, bool useDepthBuffer = true); + uint32_t GetCurrentFrameId() const + { + return currentFrameBufferId; + } - void SetCurrentFrameId(uint32_t id) - { - currentFrameBufferId = id; - } + public: + void RegisterRenderPass(RenderPass* renderPass); - uint32_t GetCurrentFrameId() const - { - return currentFrameBufferId; - } + protected: + void Resize(vk::Extent3D size); - public: - void InitRenderPass(RenderPass* renderPass); + void Close() override + { + DestroyFrameBuffer(); + if(depthBuffer) depthBuffer.Close(); + device = nullptr; + } - protected: - void Resize(vk::Extent3D size); + protected: - void Close() override - { - DestroyFrameBuffer(); - if(depthBuffer) depthBuffer.Close(); - device = nullptr; - } + virtual void CreateDepthStencil(); - protected: + virtual void CreateFrameBuffer(); - virtual void CreateDepthStencil(); + void DestroyFrameBuffer(); - virtual void CreateFrameBuffer(); + virtual vk::Format FindColorFormat() = 0; - void DestroyFrameBuffer(); + virtual vk::Format FindDepthFormat() + { + return device->GetSupportedDepthFormat(); + } - virtual vk::Format FindColorFormat() = 0; + public: + virtual vk::Format GetColorFormat() + { + return colorFormat; + } - virtual vk::Format FindDepthFormat() - { - return device->GetSupportedDepthFormat(); - } + virtual vk::Format GetDepthFormat() + { + return depthBufferFormat; + } - public: - virtual vk::Format GetColorFormat() - { - return colorFormat; - } + virtual std::vector GetImages() = 0; - virtual vk::Format GetDepthFormat() - { - return depthBufferFormat; - } + bool UseDepthBuffer() const + { + return useDepthBuffer; + } - virtual std::vector GetImages() = 0; + vk::Extent3D GetSize3D() const + { + return size; + } - bool UseDepthBuffer() const - { - return useDepthBuffer; - } + vk::Extent2D GetSize2D() const + { + return { size.width, size.height }; + } - vk::Extent3D GetSize3D() const - { - return size; - } - - vk::Extent2D GetSize2D() const - { - return { size.width, size.height }; - } - - vk::Framebuffer& GetCurrentFrameBuffer() - { - return frameBuffers[currentFrameBufferId]; - } - }; - } + vk::Framebuffer& GetCurrentFrameBuffer() + { + return frameBuffers[currentFrameBufferId]; + } + }; } diff --git a/openVulkanoCpp/Vulkan/RenderPass.cpp b/openVulkanoCpp/Vulkan/RenderPass.cpp new file mode 100644 index 0000000..ddbf248 --- /dev/null +++ b/openVulkanoCpp/Vulkan/RenderPass.cpp @@ -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 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 colorAttachmentReferences; + colorAttachmentReferences.emplace_back(0, vk::ImageLayout::eColorAttachmentOptimal); + + std::vector subPasses; + subPasses.emplace_back(vk::SubpassDescriptionFlags(), vk::PipelineBindPoint::eGraphics, 0, nullptr, + colorAttachmentReferences.size(), colorAttachmentReferences.data(), nullptr, depthReference, 0, nullptr); + std::vector 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); + } +} \ No newline at end of file diff --git a/openVulkanoCpp/Vulkan/RenderPass.hpp b/openVulkanoCpp/Vulkan/RenderPass.hpp index 2eb3eb6..fcb5d94 100644 --- a/openVulkanoCpp/Vulkan/RenderPass.hpp +++ b/openVulkanoCpp/Vulkan/RenderPass.hpp @@ -6,150 +6,95 @@ #pragma once -#include #include "Device.hpp" -#include "FrameBuffer.hpp" -#include "Base/EngineConfiguration.hpp" +#include -namespace openVulkanoCpp +namespace openVulkanoCpp::Vulkan { - namespace Vulkan - { - class RenderPass : virtual public ICloseable + class FrameBuffer; + + class RenderPass : virtual public ICloseable + { //TODO allow to control the render rect size + protected: + vk::Device m_device; + vk::RenderPassBeginInfo m_beginInfo; + std::array m_clearValues; + FrameBuffer* m_frameBuffer = nullptr; + bool m_useClearColor = false, m_useClearDepth = true; + + public: + vk::RenderPass renderPass; + + RenderPass() = default; + + ~RenderPass() override { - protected: - vk::Device device; - vk::RenderPassBeginInfo beginInfo; - vk::ClearColorValue clearColor; - vk::ClearDepthStencilValue clearDepth; - std::vector clearValues; - FrameBuffer* frameBuffer = nullptr; - bool useClearColor = false, useClearDepth = true; + if (m_frameBuffer) RenderPass::Close(); + } - public: - vk::RenderPass renderPass; + void Init(Device* device, FrameBuffer* frameBuffer, bool clearColor = false, bool clearDepth = false); - RenderPass() = default; + void Close() override; - ~RenderPass() override + void SetClearColor(vk::ClearColorValue clearColor = vk::ClearColorValue(std::array{ 0.39f, 0.58f, 0.93f, 1.0f })) + { + m_clearValues[0] = clearColor; + if (!m_useClearColor) { - if (frameBuffer) RenderPass::Close(); + m_useClearColor = true; + //TODO recreate } + UpdateBeginInfo(); + } - void Init(Device* device, FrameBuffer* frameBuffer) + void DisableClearColor() + { + if (m_useClearColor) { - this->device = device->device; - this->frameBuffer = frameBuffer; - CreateRenderPass(); - frameBuffer->InitRenderPass(this); - SetClearColor(EngineConfiguration::GetEngineConfiguration()->GetFrameBufferClearColor()); - SetClearDepth(); - } - - void Close() override - { - device.destroy(renderPass); - frameBuffer = nullptr; - clearValues.clear(); - } - - void SetClearColor(vk::ClearColorValue clearColor = vk::ClearColorValue(std::array{ 0.39f, 0.58f, 0.93f, 1.0f })) - { - this->clearColor = clearColor; - useClearColor = true; + m_useClearColor = false; + //TODO recreate UpdateBeginInfo(); } + } - void DisableClearColor() + void SetClearDepth(vk::ClearDepthStencilValue clearDepth = vk::ClearDepthStencilValue(1, 0)) + { + m_clearValues[1] = clearDepth; + if (!m_useClearDepth) { - useClearColor = false; + m_useClearDepth = true; + //TODO recreate + } + UpdateBeginInfo(); + } + + void DisableClearDepth() + { + if (m_useClearDepth) + { + m_useClearDepth = false; + //TODO recreate UpdateBeginInfo(); } + } - void SetClearDepth(vk::ClearDepthStencilValue clearDepth = vk::ClearDepthStencilValue(1, 0)) - { - this->clearDepth = clearDepth; - useClearDepth = true; - UpdateBeginInfo(); - } + void Resize(vk::Extent3D size) + { + m_beginInfo.renderArea.extent.width = size.width; + m_beginInfo.renderArea.extent.height = size.height; + } - void DisableClearDepth() - { - useClearDepth = false; - } + virtual void UpdateBeginInfo(); - 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); + virtual void Begin(vk::CommandBuffer& commandBuffer, bool primaryBuffer = false); - beginInfo = vk::RenderPassBeginInfo(renderPass, vk::Framebuffer(), - vk::Rect2D(vk::Offset2D(), frameBuffer->GetSize2D()), - clearValues.size(), clearValues.data()); - } + virtual void End(vk::CommandBuffer& commandBuffer); - virtual void Begin(vk::CommandBuffer& commandBuffer) - { - beginInfo.framebuffer = frameBuffer->GetCurrentFrameBuffer(); - commandBuffer.beginRenderPass(beginInfo, vk::SubpassContents::eSecondaryCommandBuffers); - } + [[nodiscard]] FrameBuffer* GetFrameBuffer() const { return m_frameBuffer; } - virtual void End(vk::CommandBuffer& commandBuffer) - { - commandBuffer.endRenderPass(); - } + protected: + virtual void CreateRenderPass(); - FrameBuffer* GetFrameBuffer() const - { - return frameBuffer; - } - - protected: - virtual void CreateRenderPass() - { - std::vector attachments; - attachments.reserve(frameBuffer->UseDepthBuffer() ? 2 : 1); - - // 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 colorAttachmentReferences; - colorAttachmentReferences.emplace_back(0, vk::ImageLayout::eColorAttachmentOptimal); - - std::vector subPasses; - subPasses.emplace_back(vk::SubpassDescriptionFlags(), vk::PipelineBindPoint::eGraphics, 0, nullptr, - colorAttachmentReferences.size(), colorAttachmentReferences.data(), nullptr, depthReference, 0, nullptr); - std::vector 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); + }; } \ No newline at end of file