From b68d43fe06f091e60ca1c1b4c442badf42fa7943 Mon Sep 17 00:00:00 2001 From: Artur Wasmut <awasmut@uni-koblenz.de> Date: Wed, 12 May 2021 21:13:00 +0200 Subject: [PATCH] initial implementation of a cheap renderpass struct/class. --- config/Sources.cmake | 3 + include/vkcv/Core.hpp | 13 ++- include/vkcv/Handles.hpp | 2 +- include/vkcv/Renderpass.hpp | 54 ++++++++++++ projects/first_triangle/src/main.cpp | 32 +++++++ src/vkcv/Core.cpp | 126 ++++++++++++++++++++++++++- src/vkcv/Renderpass.cpp | 16 ++++ 7 files changed, 242 insertions(+), 4 deletions(-) create mode 100644 include/vkcv/Renderpass.hpp create mode 100644 src/vkcv/Renderpass.cpp diff --git a/config/Sources.cmake b/config/Sources.cmake index 80fa3a09..d98c51c1 100644 --- a/config/Sources.cmake +++ b/config/Sources.cmake @@ -7,6 +7,9 @@ set(vkcv_sources ${vkcv_include}/vkcv/Core.hpp ${vkcv_source}/vkcv/Core.cpp + ${vkcv_include}/vkcv/Renderpass.hpp + ${vkcv_source}/vkcv/Renderpass.cpp + ${vkcv_include}/vkcv/Handles.hpp ${vkcv_source}/vkcv/Handles.cpp diff --git a/include/vkcv/Core.hpp b/include/vkcv/Core.hpp index 7a7f3be7..475099ab 100644 --- a/include/vkcv/Core.hpp +++ b/include/vkcv/Core.hpp @@ -6,6 +6,7 @@ #include <vulkan/vulkan.hpp> #include "vkcv/Context.hpp" +#include "vkcv/Renderpass.hpp" #include "vkcv/Handles.hpp" namespace vkcv @@ -29,11 +30,15 @@ namespace vkcv Core() = delete; Context m_Context; + + uint64_t m_NextPassId; + std::vector<vk::RenderPass> m_Renderpasses; + public: /** * Destructor of #Core destroys the Vulkan objects contained in the core's context. */ - ~Core() noexcept = default; + ~Core() noexcept; /** * Copy-constructor of #Core is deleted! @@ -93,7 +98,11 @@ namespace vkcv // TODO: BufferHandle createBuffer(const Buffer &buf); - PassHandle createRenderPass(const Renderpass &pass) ; + + [[nodiscard]] + bool createRenderpass(const Renderpass &pass, RenderpassHandle &handle); + + // TODO: PipelineHandle createPipeline(const Pipeline &pipeline); }; diff --git a/include/vkcv/Handles.hpp b/include/vkcv/Handles.hpp index 4ec2bc05..0d8e4a89 100644 --- a/include/vkcv/Handles.hpp +++ b/include/vkcv/Handles.hpp @@ -11,6 +11,6 @@ namespace vkcv { // Handle returned for any buffer created with the core/context objects struct BufferHandle {uint64_t id;}; - struct PassHandle {uint64_t id;}; + struct RenderpassHandle {uint64_t id;}; struct PipelineHandle {uint64_t id;}; } diff --git a/include/vkcv/Renderpass.hpp b/include/vkcv/Renderpass.hpp new file mode 100644 index 00000000..7f2ad91c --- /dev/null +++ b/include/vkcv/Renderpass.hpp @@ -0,0 +1,54 @@ +#pragma once + +#include <vector> + +namespace vkcv +{ + enum class AttachmentLayout + { + UNDEFINED, + GENERAL, + + COLOR_ATTACHMENT, + SHADER_READ_ONLY, + + DEPTH_STENCIL_ATTACHMENT, + DEPTH_STENCIL_READ_ONLY, + + TRANSFER_SRC, + TRANSFER_DST, + + PRESENTATION + }; + + enum class AttachmentOperation + { + LOAD, + CLEAR, + STORE, + DONT_CARE + }; + + struct AttachmentDescription + { + AttachmentDescription() = delete; + AttachmentDescription(AttachmentLayout initial, + AttachmentLayout in_pass, + AttachmentLayout final, + AttachmentOperation store_op, + AttachmentOperation load_op) noexcept; + + AttachmentLayout layout_initial; + AttachmentLayout layout_in_pass; + AttachmentLayout layout_final; + + AttachmentOperation store_operation; + AttachmentOperation load_operation; + }; + + struct Renderpass + { + Renderpass() noexcept = default; + std::vector<AttachmentDescription> attachments{}; + }; +} \ No newline at end of file diff --git a/projects/first_triangle/src/main.cpp b/projects/first_triangle/src/main.cpp index 0c981a25..87a7d11e 100644 --- a/projects/first_triangle/src/main.cpp +++ b/projects/first_triangle/src/main.cpp @@ -33,6 +33,38 @@ int main(int argc, const char** argv) { default: std::cout << "Unknown GPU vendor?! Either you're on an exotic system or your driver is broken..." << std::endl; } + // an example attachment for passes that output to the window + vkcv::AttachmentDescription present_color_attachment(vkcv::AttachmentLayout::UNDEFINED, + vkcv::AttachmentLayout::COLOR_ATTACHMENT, + vkcv::AttachmentLayout::PRESENTATION, + vkcv::AttachmentOperation::STORE, + vkcv::AttachmentOperation::CLEAR); + // an example attachment for passes that output to a depth buffer + vkcv::AttachmentDescription present_depth_attachment(vkcv::AttachmentLayout::UNDEFINED, + vkcv::AttachmentLayout::DEPTH_STENCIL_ATTACHMENT, + vkcv::AttachmentLayout::DEPTH_STENCIL_READ_ONLY, + vkcv::AttachmentOperation::STORE, + vkcv::AttachmentOperation::CLEAR); + + // this pass will output to the window, and produce a depth buffer + vkcv::Renderpass test_pass{}; + test_pass.attachments.push_back(present_color_attachment); + test_pass.attachments.push_back(present_depth_attachment); + + std::vector<vkcv::RenderpassHandle> test_handles{}; + // render pass creation test + for(uint32_t i = 0; i < 1000; i++) + { + vkcv::RenderpassHandle tmp_handle{}; + if(!core.createRenderpass(test_pass, tmp_handle)) + { + std::cout << "Oops. Something went wrong in the renderpass creation. Exiting." << std::endl; + return EXIT_FAILURE; + } + test_handles.push_back(tmp_handle); + } + std::cout << "Wow. You just made 1000 render passes. (That are all identical, though...)" << std::endl; + /* * BufferHandle triangleVertices = core.createBuffer(vertices); * BufferHandle triangleIndices = core.createBuffer(indices); diff --git a/src/vkcv/Core.cpp b/src/vkcv/Core.cpp index 0c32f4e4..4ba377d9 100644 --- a/src/vkcv/Core.cpp +++ b/src/vkcv/Core.cpp @@ -8,6 +8,51 @@ namespace vkcv { + static vk::ImageLayout getVkLayoutFromAttachLayout(AttachmentLayout layout) + { + switch(layout) + { + case AttachmentLayout::GENERAL: + return vk::ImageLayout::eGeneral; + case AttachmentLayout::COLOR_ATTACHMENT: + return vk::ImageLayout::eColorAttachmentOptimal; + case AttachmentLayout::SHADER_READ_ONLY: + return vk::ImageLayout::eShaderReadOnlyOptimal; + case AttachmentLayout::DEPTH_STENCIL_ATTACHMENT: + return vk::ImageLayout::eDepthStencilAttachmentOptimal; + case AttachmentLayout::DEPTH_STENCIL_READ_ONLY: + return vk::ImageLayout::eDepthStencilReadOnlyOptimal; + case AttachmentLayout::PRESENTATION: + return vk::ImageLayout::ePresentSrcKHR; + default: + return vk::ImageLayout::eUndefined; + } + } + + static vk::AttachmentStoreOp getVkStoreOpFromAttachOp(AttachmentOperation op) + { + switch(op) + { + case AttachmentOperation::STORE: + return vk::AttachmentStoreOp::eStore; + default: + return vk::AttachmentStoreOp::eDontCare; + } + } + + static vk::AttachmentLoadOp getVKLoadOpFromAttachOp(AttachmentOperation op) + { + switch(op) + { + case AttachmentOperation::LOAD: + return vk::AttachmentLoadOp::eLoad; + case AttachmentOperation::CLEAR: + return vk::AttachmentLoadOp::eClear; + default: + return vk::AttachmentLoadOp::eDontCare; + } + } + /** * @brief The physical device is evaluated by three categories: * discrete GPU vs. integrated GPU, amount of queues and its abilities, and VRAM.physicalDevice. @@ -268,6 +313,85 @@ namespace vkcv } Core::Core(Context &&context) noexcept : - m_Context(std::move(context)) + m_Context(std::move(context)), + m_NextPassId(0), + m_Renderpasses{} {} + + Core::~Core() noexcept + { + for(const auto &pass : m_Renderpasses) + m_Context.m_Device.destroy(pass); + m_Renderpasses.clear(); + m_NextPassId = 0; + } + + bool Core::createRenderpass(const Renderpass &pass, RenderpassHandle &handle) + { + // description of all {color, input, depth/stencil} attachments of the render pass + std::vector<vk::AttachmentDescription> attachmentDescriptions{}; + + // individual references to color attachments (of a subpass) + std::vector<vk::AttachmentReference> colorAttachmentReferences{}; + // individual reference to depth attachment (of a subpass) + vk::AttachmentReference depthAttachmentReference{}; + + for(uint32_t i = 0; i < pass.attachments.size(); i++) + { + // TODO: Renderpass struct should hold proper format information + vk::Format format; + + if(pass.attachments[i].layout_in_pass == AttachmentLayout::DEPTH_STENCIL_ATTACHMENT) + { + format = vk::Format::eD16Unorm; // depth attachments; + + depthAttachmentReference.attachment = i; + depthAttachmentReference.layout = getVkLayoutFromAttachLayout(pass.attachments[i].layout_in_pass); + } + else + { + format = vk::Format::eB8G8R8A8Srgb; // color attachments, compatible with swapchain + vk::AttachmentReference attachmentRef(i, getVkLayoutFromAttachLayout(pass.attachments[i].layout_in_pass)); + colorAttachmentReferences.push_back(attachmentRef); + } + + vk::AttachmentDescription attachmentDesc({}, + format, + vk::SampleCountFlagBits::e1, + getVKLoadOpFromAttachOp(pass.attachments[i].load_operation), + getVkStoreOpFromAttachOp(pass.attachments[i].load_operation), + vk::AttachmentLoadOp::eDontCare, + vk::AttachmentStoreOp::eDontCare, + getVkLayoutFromAttachLayout(pass.attachments[i].layout_initial), + getVkLayoutFromAttachLayout(pass.attachments[i].layout_final)); + attachmentDescriptions.push_back(attachmentDesc); + } + + vk::SubpassDescription subpassDescription({}, + vk::PipelineBindPoint::eGraphics, + 0, + {}, + static_cast<uint32_t>(colorAttachmentReferences.size()), + colorAttachmentReferences.data(), + {}, + &depthAttachmentReference, + 0, + {}); + + vk::RenderPassCreateInfo passInfo({}, + static_cast<uint32_t>(attachmentDescriptions.size()), + attachmentDescriptions.data(), + 1, + &subpassDescription, + 0, + {}); + + vk::RenderPass vkObject{nullptr}; + if(m_Context.m_Device.createRenderPass(&passInfo, nullptr, &vkObject) != vk::Result::eSuccess) + return false; + + m_Renderpasses.push_back(vkObject); + handle.id = m_NextPassId++; + return true; + } } diff --git a/src/vkcv/Renderpass.cpp b/src/vkcv/Renderpass.cpp new file mode 100644 index 00000000..e9f2459b --- /dev/null +++ b/src/vkcv/Renderpass.cpp @@ -0,0 +1,16 @@ +#include "vkcv/Renderpass.hpp" + +namespace vkcv +{ + AttachmentDescription::AttachmentDescription(AttachmentLayout initial, + AttachmentLayout in_pass, + AttachmentLayout final, + AttachmentOperation store_op, + AttachmentOperation load_op) noexcept : + layout_initial{initial}, + layout_in_pass{in_pass}, + layout_final{final}, + store_operation{store_op}, + load_operation{load_op} + {}; +} \ No newline at end of file -- GitLab