diff --git a/CMakeLists.txt b/CMakeLists.txt index ff0d299..1217602 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -39,6 +39,7 @@ add_executable(vk_expe src/vk/Context.cpp src/vk/Fence.cpp src/vk/Semaphore.cpp + src/vk/Framebuffer.cpp src/vk/Swapchain.cpp src/vk/Memory.cpp src/vk/Buffer.cpp diff --git a/src/VulkanTutorial.cpp b/src/VulkanTutorial.cpp index f98ba2a..b20d2aa 100644 --- a/src/VulkanTutorial.cpp +++ b/src/VulkanTutorial.cpp @@ -276,7 +276,7 @@ void VulkanTutorial::draw_frame() { )) throw std::runtime_error("failed to submit draw command buffer"); - m_swapchain.swap_buffers({1, done_semaphores}); + m_swapchain.swap_buffers(done_semaphores); } void VulkanTutorial::invalidate_swapchain() { @@ -317,8 +317,6 @@ void VulkanTutorial::destroy_swapchain_objects() { m_context.destroy_descriptor_pool(m_descriptor_pool); - for(VkFramebuffer framebuffer: m_framebuffers) - m_context.destroy_framebuffer(framebuffer); m_framebuffers.clear(); m_context.destroy_pipeline(m_pipeline); @@ -569,28 +567,15 @@ void VulkanTutorial::create_graphic_pipeline() { } void VulkanTutorial::create_framebuffers() { - m_framebuffers.resize(m_swapchain.image_count()); - - for(size_t index = 0; index < m_framebuffers.size(); index += 1) { + m_framebuffers.clear(); + for(size_t index = 0; index < m_swapchain.image_count(); index += 1) { VkImageView view = m_swapchain.image_view(index); - - VkFramebufferCreateInfo framebuffer_info { - .sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, - .renderPass = m_render_pass, - .attachmentCount = 1, - .pAttachments = &view, - .width = m_swapchain.extent().width, - .height = m_swapchain.extent().height, - .layers = 1, - }; - - if(vkCreateFramebuffer( - m_context.device(), - &framebuffer_info, - nullptr, - &m_framebuffers[index] - ) != VK_SUCCESS) - throw std::runtime_error("failed to create framebuffer"); + m_framebuffers.emplace_back( + m_context, + m_render_pass, + &view, + m_swapchain.extent() + ); } } diff --git a/src/VulkanTutorial.h b/src/VulkanTutorial.h index d178cd3..f6c3a6a 100644 --- a/src/VulkanTutorial.h +++ b/src/VulkanTutorial.h @@ -1,6 +1,7 @@ // Copyright 2022 Simon Boyé #pragma once +#include #include #include #include @@ -75,7 +76,7 @@ private: VkDescriptorSetLayout m_descriptor_set_layout = VK_NULL_HANDLE; VkPipelineLayout m_pipeline_layout = VK_NULL_HANDLE; VkPipeline m_pipeline = VK_NULL_HANDLE; - std::vector m_framebuffers; + std::vector m_framebuffers; VkCommandPool m_command_pool = VK_NULL_HANDLE; vk::Buffer m_vertex_buffer; vk::Buffer m_index_buffer; diff --git a/src/core/utils.cpp b/src/core/utils.cpp index 55a392c..080be59 100644 --- a/src/core/utils.cpp +++ b/src/core/utils.cpp @@ -24,4 +24,3 @@ std::vector read_binary_file(const char* path) { return buffer; } - diff --git a/src/core/utils.h b/src/core/utils.h index 2c14b56..12aa350 100644 --- a/src/core/utils.h +++ b/src/core/utils.h @@ -57,6 +57,17 @@ public: assert((size == 0 && m_data == nullptr) || (size != 0 && m_data != nullptr)); } + Array(T* item) + : m_size(1) + , m_data(item) + {} + + template + Array(T (&array)[Size]) + : m_size(Size) + , m_data(array) + {} + Array(const std::vector& vector) : m_size(vector.size()) , m_data(vector.data()) diff --git a/src/vk/Framebuffer.cpp b/src/vk/Framebuffer.cpp new file mode 100644 index 0000000..497c0e8 --- /dev/null +++ b/src/vk/Framebuffer.cpp @@ -0,0 +1,86 @@ +// Copyright 2022 Simon Boyé + +#include +#include + +#include + + +namespace vk { + + +Framebuffer::Framebuffer() noexcept { +} + +Framebuffer::Framebuffer( + Context& context, + VkRenderPass render_pass, + Array attachments, + uint32_t width, uint32_t height, uint32_t layers +) + : m_context(&context) +{ + assert(m_context); + assert(render_pass); + + VkFramebufferCreateInfo create_info { + .sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, + .renderPass = render_pass, + .attachmentCount = uint32_t(attachments.size()), + .pAttachments = attachments.data(), + .width = width, + .height = height, + .layers = layers, + }; + if(vkCreateFramebuffer( + context.device(), + &create_info, + nullptr, + &m_framebuffer + ) != VK_SUCCESS) + throw std::runtime_error("failed to create framebuffer"); +} + +Framebuffer::Framebuffer( + Context& context, + VkRenderPass render_pass, + Array attachments, + VkExtent2D extent, uint32_t layers +) + : Framebuffer(context, render_pass, attachments, extent.width, extent.height, layers) +{} + +Framebuffer::Framebuffer(Framebuffer&& other) noexcept +{ + swap(*this, other); +} + +Framebuffer::~Framebuffer() noexcept { + if(!is_null()) + destroy(); +} + + +Framebuffer& Framebuffer::operator=(Framebuffer&& other) noexcept { + swap(*this, other); + if(other) + other.destroy(); + return *this; +} + + +void Framebuffer::destroy() noexcept { + assert(!is_null()); + assert(m_context); + + vkDestroyFramebuffer( + m_context->device(), + m_framebuffer, + nullptr + ); + + m_framebuffer = nullptr; +} + + +} diff --git a/src/vk/Framebuffer.h b/src/vk/Framebuffer.h new file mode 100644 index 0000000..920b22e --- /dev/null +++ b/src/vk/Framebuffer.h @@ -0,0 +1,74 @@ +// Copyright 2022 Simon Boyé +#pragma once + +#include + +#include + +#include + + +namespace vk { + + +class Framebuffer { +public: + Framebuffer() noexcept; + Framebuffer( + Context& context, + VkRenderPass render_pass, + Array attachments, + uint32_t width, uint32_t height, uint32_t layers=1 + ); + Framebuffer( + Context& context, + VkRenderPass render_pass, + Array attachments, + VkExtent2D extent, uint32_t layers=1 + ); + Framebuffer(const Framebuffer&) = delete; + Framebuffer(Framebuffer&& other) noexcept; + ~Framebuffer() noexcept; + + Framebuffer& operator=(const Framebuffer&) = delete; + Framebuffer& operator=(Framebuffer&& other) noexcept; + + explicit inline operator bool() const noexcept { + return !is_null(); + } + + inline bool is_null() const noexcept { + return m_framebuffer == VK_NULL_HANDLE; + } + + inline const Context* context() const noexcept { + return m_context; + } + + inline Context* context() noexcept { + return m_context; + } + + inline operator VkFramebuffer() noexcept { + return m_framebuffer; + } + + inline VkFramebuffer framebuffer() noexcept { + return m_framebuffer; + } + + friend inline void swap(Framebuffer& framebuffer_0, Framebuffer& framebuffer_1) noexcept { + using std::swap; + swap(framebuffer_0.m_context, framebuffer_1.m_context); + swap(framebuffer_0.m_framebuffer, framebuffer_1.m_framebuffer); + } + + void destroy() noexcept; + +private: + Context* m_context = nullptr; + VkFramebuffer m_framebuffer = VK_NULL_HANDLE; +}; + + +}