diff --git a/include/vkcv/Core.hpp b/include/vkcv/Core.hpp index e102c266f141d238c1ccc6c41f1fbc5192585fc9..0a50765fedb07f1117b5e0ecaa43c03b362c23ce 100644 --- a/include/vkcv/Core.hpp +++ b/include/vkcv/Core.hpp @@ -56,7 +56,7 @@ namespace vkcv * * @param context encapsulates various Vulkan objects */ - Core(Context &&context, Window &window, SwapChain swapChain, std::vector<vk::ImageView> imageViews, + Core(Context &&context, Window &window, const SwapChain& swapChain, std::vector<vk::ImageView> imageViews, const CommandResources& commandResources, const SyncResources& syncResources) noexcept; // explicit destruction of default constructor Core() = delete; @@ -84,13 +84,6 @@ namespace vkcv std::function<void(int, int)> e_resizeHandle; - /** - * recreates the swapchain - * @param[in] width new window width - * @param[in] height new window hight - */ - void recreateSwapchain(int width, int height); - static std::vector<vk::ImageView> createImageViews( Context &context, SwapChain& swapChain); public: @@ -234,8 +227,6 @@ namespace vkcv void renderMesh( const PassHandle &renderpassHandle, const PipelineHandle &pipelineHandle, - const uint32_t width, - const uint32_t height, const size_t pushConstantSize, const void* pushConstantData, const std::vector<VertexBufferBinding> &vertexBufferBindings, diff --git a/include/vkcv/SwapChain.hpp b/include/vkcv/SwapChain.hpp index c4ffae6350fc3631dd837d2900498acff47961a2..53f7b783051307c7d327f20f389d7bef0fb9a16c 100644 --- a/include/vkcv/SwapChain.hpp +++ b/include/vkcv/SwapChain.hpp @@ -3,6 +3,8 @@ #include "Context.hpp" #include "vkcv/Window.hpp" +#include <atomic> + namespace vkcv { class SwapChain final { @@ -15,6 +17,7 @@ namespace vkcv vk::SurfaceCapabilitiesKHR capabilities; std::vector<vk::PresentModeKHR> presentModes; }; + Surface m_Surface; vk::SwapchainKHR m_Swapchain; @@ -22,6 +25,10 @@ namespace vkcv vk::ColorSpaceKHR m_SwapchainColorSpace; vk::PresentModeKHR m_SwapchainPresentMode; uint32_t m_SwapchainImageCount; + + vk::Extent2D m_Extent; + + std::atomic<bool> m_RecreationRequired; /** * Constructor of a SwapChain object @@ -37,11 +44,11 @@ namespace vkcv vk::Format format, vk::ColorSpaceKHR colorSpace, vk::PresentModeKHR presentMode, - uint32_t imageCount) noexcept; + uint32_t imageCount, + vk::Extent2D extent) noexcept; public: - SwapChain(const SwapChain &other) = default; - SwapChain(SwapChain &&other) = default; + SwapChain(const SwapChain& other); /** * @return The swapchain linked with the #SwapChain class @@ -81,12 +88,34 @@ namespace vkcv * @return number of images in swapchain */ uint32_t getImageCount(); + + /** + * TODO + * + * @return + */ + bool shouldUpdateSwapchain() const; + /** + * TODO + * + * context + * window + */ + void updateSwapchain(const Context &context, const Window &window); + /** * - * @param width - * @param height */ - void recreateSwapchain(const Context &context, const Window &window, int width, int height); + void recreateSwapchain(); + + /** + * TODO + * + * @return + */ + [[nodiscard]] + const vk::Extent2D& getExtent() const; + }; } diff --git a/include/vkcv/Window.hpp b/include/vkcv/Window.hpp index 7428c7c73eb481f7352821faed36257211dfd5bf..f71671c935a0a5e17bb517c726d75ffff2973532 100644 --- a/include/vkcv/Window.hpp +++ b/include/vkcv/Window.hpp @@ -17,7 +17,6 @@ namespace vkcv { private: GLFWwindow *m_window; - /** * * @param GLFWwindow of the class diff --git a/projects/first_mesh/src/main.cpp b/projects/first_mesh/src/main.cpp index 0fc580dcd5a36c07e7286ec9a7fd2facbd257494..01d8b74fe39a15459169926645f429805299a786 100644 --- a/projects/first_mesh/src/main.cpp +++ b/projects/first_mesh/src/main.cpp @@ -161,8 +161,6 @@ int main(int argc, const char** argv) { core.renderMesh( trianglePass, trianglePipeline, - window.getWidth(), - window.getHeight(), sizeof(mvp), &mvp, vertexBufferBindings, diff --git a/src/vkcv/Core.cpp b/src/vkcv/Core.cpp index ad6a8756b57657800e873ace705e8b1a4a18eb97..fafdb56066e42b08a77db1c4f9d60270c6854609 100644 --- a/src/vkcv/Core.cpp +++ b/src/vkcv/Core.cpp @@ -52,7 +52,7 @@ namespace vkcv return m_Context; } - Core::Core(Context &&context, Window &window , SwapChain swapChain, std::vector<vk::ImageView> imageViews, + Core::Core(Context &&context, Window &window, const SwapChain& swapChain, std::vector<vk::ImageView> imageViews, const CommandResources& commandResources, const SyncResources& syncResources) noexcept : m_Context(std::move(context)), m_window(window), @@ -72,7 +72,9 @@ namespace vkcv m_ImageManager->m_core = this; - e_resizeHandle = window.e_resize.add( [&](int width, int height) { recreateSwapchain( width ,height ); }); + e_resizeHandle = window.e_resize.add( [&](int width, int height) { + m_swapchain.recreateSwapchain(); + }); } Core::~Core() noexcept { @@ -119,17 +121,26 @@ namespace vkcv } void Core::beginFrame() { + if (m_swapchain.shouldUpdateSwapchain()) { + m_Context.getDevice().waitIdle(); + + for (auto image : m_swapchainImageViews) + m_Context.m_Device.destroyImageView(image); + + m_swapchain.updateSwapchain(m_Context, m_window); + m_swapchainImageViews = createImageViews(m_Context, m_swapchain); + } + if (acquireSwapchainImage() != Result::SUCCESS) { return; } + m_Context.getDevice().waitIdle(); // TODO: this is a sin against graphics programming, but its getting late - Alex } void Core::renderMesh( const PassHandle &renderpassHandle, const PipelineHandle &pipelineHandle, - const uint32_t width, - const uint32_t height, const size_t pushConstantSize, const void *pushConstantData, const std::vector<VertexBufferBinding>& vertexBufferBindings, @@ -142,6 +153,11 @@ namespace vkcv if (m_currentSwapchainImageIndex == std::numeric_limits<uint32_t>::max()) { return; } + + const vk::Extent2D& extent = m_swapchain.getExtent(); + + const uint32_t width = extent.width; + const uint32_t height = extent.height; const vk::RenderPass renderpass = m_PassManager->getVkPass(renderpassHandle); const PassConfig passConfig = m_PassManager->getPassConfig(renderpassHandle); @@ -282,19 +298,6 @@ namespace vkcv vk::Format Core::getSwapchainImageFormat() { return m_swapchain.getSwapchainFormat(); } - - void Core::recreateSwapchain( int width, int height) { - m_Context.getDevice().waitIdle(); - - if(width == 0 || height == 0) - return; - - for (auto image : m_swapchainImageViews) - m_Context.m_Device.destroyImageView(image); - - m_swapchain.recreateSwapchain(m_Context, m_window, width, height); - m_swapchainImageViews = createImageViews(m_Context, m_swapchain); - } void Core::submitCommands(const SubmitInfo &submitInfo, const RecordCommandFunction& record, const FinishCommandFunction& finish) { diff --git a/src/vkcv/SwapChain.cpp b/src/vkcv/SwapChain.cpp index 2a40eba44a1ab85eb5aa835ae97bc4cae5c0a7a6..39c310de60db2c3678749f142c926a26ac127b58 100644 --- a/src/vkcv/SwapChain.cpp +++ b/src/vkcv/SwapChain.cpp @@ -32,14 +32,28 @@ namespace vkcv vk::Format format, vk::ColorSpaceKHR colorSpace, vk::PresentModeKHR presentMode, - uint32_t imageCount) noexcept : + uint32_t imageCount, + vk::Extent2D extent) noexcept : m_Surface(surface), m_Swapchain(swapchain), m_SwapchainFormat(format), m_SwapchainColorSpace(colorSpace), m_SwapchainPresentMode(presentMode), - m_SwapchainImageCount(imageCount) + m_SwapchainImageCount(imageCount), + m_Extent(extent), + m_RecreationRequired(false) {} + + SwapChain::SwapChain(const SwapChain &other) : + m_Surface(other.m_Surface), + m_Swapchain(other.m_Swapchain), + m_SwapchainFormat(other.m_SwapchainFormat), + m_SwapchainColorSpace(other.m_SwapchainColorSpace), + m_SwapchainPresentMode(other.m_SwapchainPresentMode), + m_SwapchainImageCount(other.m_SwapchainImageCount), + m_Extent(other.m_Extent), + m_RecreationRequired(other.m_RecreationRequired.load()) + {} const vk::SwapchainKHR& SwapChain::getSwapchain() const { return m_Swapchain; @@ -70,6 +84,7 @@ namespace vkcv static_cast<uint32_t>(window.getWidth()), static_cast<uint32_t>(window.getHeight()) }; + extent2D.width = std::max(surfaceCapabilities.minImageExtent.width, std::min(surfaceCapabilities.maxImageExtent.width, extent2D.width)); extent2D.height = std::max(surfaceCapabilities.minImageExtent.height, std::min(surfaceCapabilities.maxImageExtent.height, extent2D.height)); @@ -189,34 +204,53 @@ namespace vkcv chosenSurfaceFormat.format, chosenSurfaceFormat.colorSpace, chosenPresentMode, - chosenImageCount); + chosenImageCount, + chosenExtent); } - - void SwapChain::recreateSwapchain( const Context &context, const Window &window, int width, int height){ - vk::SwapchainKHR oldSwapchain = m_Swapchain; - vk::Extent2D extent2D = chooseExtent(context.getPhysicalDevice(), m_Surface.handle, window); - - vk::SwapchainCreateInfoKHR swapchainCreateInfo( - vk::SwapchainCreateFlagsKHR(), - m_Surface.handle, - m_SwapchainImageCount, - m_SwapchainFormat, - m_SwapchainColorSpace, - extent2D, - 1, - vk::ImageUsageFlagBits::eColorAttachment, - vk::SharingMode::eExclusive, - 0, - nullptr, - vk::SurfaceTransformFlagBitsKHR::eIdentity, - vk::CompositeAlphaFlagBitsKHR::eOpaque, - m_SwapchainPresentMode, - true, - oldSwapchain - ); - m_Swapchain = context.getDevice().createSwapchainKHR(swapchainCreateInfo); + + bool SwapChain::shouldUpdateSwapchain() const { + return m_RecreationRequired; + } + + void SwapChain::updateSwapchain(const Context &context, const Window &window) { + if (!m_RecreationRequired.exchange(false)) + return; + + vk::SwapchainKHR oldSwapchain = m_Swapchain; + vk::Extent2D extent2D = chooseExtent(context.getPhysicalDevice(), m_Surface.handle, window); + + vk::SwapchainCreateInfoKHR swapchainCreateInfo( + vk::SwapchainCreateFlagsKHR(), + m_Surface.handle, + m_SwapchainImageCount, + m_SwapchainFormat, + m_SwapchainColorSpace, + extent2D, + 1, + vk::ImageUsageFlagBits::eColorAttachment, + vk::SharingMode::eExclusive, + 0, + nullptr, + vk::SurfaceTransformFlagBitsKHR::eIdentity, + vk::CompositeAlphaFlagBitsKHR::eOpaque, + m_SwapchainPresentMode, + true, + oldSwapchain + ); + + m_Swapchain = context.getDevice().createSwapchainKHR(swapchainCreateInfo); + context.getDevice().destroySwapchainKHR(oldSwapchain); + + m_Extent = extent2D; } + void SwapChain::recreateSwapchain() { + m_RecreationRequired = true; + } + + const vk::Extent2D& SwapChain::getExtent() const { + return m_Extent; + } SwapChain::~SwapChain() { // needs to be destroyed by creator