diff --git a/config/Sources.cmake b/config/Sources.cmake index 1865bd81606ca70794b4bfb98868b9af47904279..d74c407b876be65af141559d96351429fad5c6d4 100644 --- a/config/Sources.cmake +++ b/config/Sources.cmake @@ -42,6 +42,9 @@ set(vkcv_sources ${vkcv_source}/vkcv/ImageManager.cpp ${vkcv_include}/vkcv/Logger.hpp + + ${vkcv_include}/vkcv/Surface.hpp + ${vkcv_source}/vkcv/Surface.cpp ${vkcv_include}/vkcv/Swapchain.hpp ${vkcv_source}/vkcv/Swapchain.cpp diff --git a/include/vkcv/Surface.hpp b/include/vkcv/Surface.hpp new file mode 100644 index 0000000000000000000000000000000000000000..18f5a8b909ed505a8d59294c12ae9b5ad1b2b9d9 --- /dev/null +++ b/include/vkcv/Surface.hpp @@ -0,0 +1,82 @@ +#pragma once +/** + * @authors Tobias Frisch + * @file vkcv/Surface.hpp + * @brief Class to manage the surface used by a swapchain. + */ + +#include <vulkan/vulkan.hpp> + +#include "Context.hpp" +#include "Window.hpp" + +namespace vkcv { + + const uint32_t MIN_SURFACE_SIZE = 2; + + class Surface { + private: + friend class Swapchain; + friend class SwapchainManager; + + const Context *m_Context; + vk::SurfaceKHR m_Handle; + uint32_t m_PresentQueueIndex; + vk::Extent2D m_Extent; + vk::Format m_Format; + vk::ColorSpaceKHR m_ColorSpace; + + Surface(const Context &context, + const vk::SurfaceKHR &handle, + uint32_t presentQueueIndex, + const vk::Extent2D &extent, + vk::Format format, + vk::ColorSpaceKHR colorSpace); + + vk::SwapchainKHR createVulkanSwapchain(const Window &window, + const vk::SwapchainKHR &oldSwapchain); + + public: + Surface(const Surface& other) = default; + + Surface(Surface&& other) noexcept; + + Surface& operator=(const Surface& other) = default; + + Surface& operator=(Surface&& other) noexcept; + + ~Surface(); + + /** + * @brief Creates a surface via a window and a current context + * + * @param window Window + * @param context Context + * @return Created surface + */ + static Surface create(const Window &window, + const Context &context); + + /** + * @brief Returns the Vulkan-Surface of the object. + * + * @return Current Vulkan-Surface + */ + [[nodiscard]] + vk::SurfaceKHR getSurface() const; + + [[nodiscard]] + uint32_t getPresentQueueIndex() const; + + [[nodiscard]] + const vk::Extent2D& getExtent() const; + + [[nodiscard]] + vk::Format getFormat() const; + + [[nodiscard]] + vk::ColorSpaceKHR getColorSpace() const; + + }; + +} diff --git a/include/vkcv/Swapchain.hpp b/include/vkcv/Swapchain.hpp index dc23bb9bf93c4c1733cb67944575b9fa669cb5c0..811da063c2fa3e58335769709aa806d86ad4ae97 100644 --- a/include/vkcv/Swapchain.hpp +++ b/include/vkcv/Swapchain.hpp @@ -9,59 +9,35 @@ #include <vulkan/vulkan.hpp> #include "Context.hpp" +#include "Surface.hpp" #include "Window.hpp" namespace vkcv { - const uint32_t MIN_SWAPCHAIN_SIZE = 2; - class Swapchain final { private: friend class Core; friend class Window; friend class SwapchainManager; - - struct Surface - { - vk::SurfaceKHR handle; - std::vector<vk::SurfaceFormatKHR> formats; - vk::SurfaceCapabilitiesKHR capabilities; - std::vector<vk::PresentModeKHR> presentModes; - uint32_t presentQueueIndex; - }; - + + const Context *m_Context; Surface m_Surface; - vk::SwapchainKHR m_Swapchain; - vk::Format m_Format; - vk::ColorSpaceKHR m_ColorSpace; - vk::PresentModeKHR m_PresentMode; - uint32_t m_ImageCount; - - vk::Extent2D m_Extent; - std::atomic<bool> m_RecreationRequired; /** * Constructor of a SwapChain object * glfw is not initialized in this class because ist must be sure that there exists a context first * glfw is already initialized by the window class + * + * @param context Current context * @param surface used by the swapchain * @param swapchain to show images in the window - * @param format of the swapchain - * @param colorSpace of the swapchain - * @param presentMode of the swapchain - * @param imageCount of the swapchain - * @param extent of the swapchain */ - Swapchain(const Surface &surface, - vk::SwapchainKHR swapchain, - vk::Format format, - vk::ColorSpaceKHR colorSpace, - vk::PresentModeKHR presentMode, - uint32_t imageCount, - vk::Extent2D extent) noexcept; + Swapchain(const Context &context, + const Surface &surface, + vk::SwapchainKHR swapchain) noexcept; /** * checks if the update flag is true @@ -96,7 +72,7 @@ namespace vkcv * @return current surface */ [[nodiscard]] - vk::SurfaceKHR getSurface() const; + const Surface& getSurface() const; /** * gets the chosen swapchain format @@ -133,7 +109,7 @@ namespace vkcv * @return the familyQueueIndex for the surface */ [[nodiscard]] - const uint32_t& getPresentQueueIndex() const; + uint32_t getPresentQueueIndex() const; }; diff --git a/src/vkcv/Core.cpp b/src/vkcv/Core.cpp index 158411a1b63e63f4bb363fae84c561864deeca8a..cd24d9e0991b1401aa2443166ba638c017c6a6f9 100644 --- a/src/vkcv/Core.cpp +++ b/src/vkcv/Core.cpp @@ -152,7 +152,7 @@ namespace vkcv width = extent.width; height = extent.height; - if ((width < MIN_SWAPCHAIN_SIZE) || (height < MIN_SWAPCHAIN_SIZE)) { + if ((width < MIN_SURFACE_SIZE) || (height < MIN_SURFACE_SIZE)) { return false; } diff --git a/src/vkcv/Surface.cpp b/src/vkcv/Surface.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3fa601b7bed751b1eb70538a0e2cf10c0b7b50f7 --- /dev/null +++ b/src/vkcv/Surface.cpp @@ -0,0 +1,258 @@ + +#include <vkcv/Surface.hpp> +#include <vkcv/Logger.hpp> + +#include <GLFW/glfw3.h> + +namespace vkcv { + + /** + * @brief Creates vulkan surface and checks availability. + * + * @param[in,out] window Current window for the surface + * @param[in,out] instance Vulkan-Instance + * @param[in,out] physicalDevice Vulkan-PhysicalDevice + * @param[out] surface Vulkan-Surface + * @return Created vulkan surface + */ + bool createVulkanSurface(GLFWwindow* window, + const vk::Instance& instance, + const vk::PhysicalDevice& physicalDevice, + vk::SurfaceKHR& surface) { + VkSurfaceKHR api_surface; + + if (glfwCreateWindowSurface(VkInstance(instance), window, nullptr, &api_surface) != VK_SUCCESS) { + vkcv_log(LogLevel::ERROR, "Failed to create a window surface"); + return false; + } + + vk::Bool32 surfaceSupport = false; + surface = vk::SurfaceKHR(api_surface); + + if ((physicalDevice.getSurfaceSupportKHR(0, surface, &surfaceSupport) != vk::Result::eSuccess) || + (!surfaceSupport)) { + vkcv_log(LogLevel::ERROR, "Surface is not supported by the device"); + instance.destroy(surface); + surface = nullptr; + return false; + } + + return true; + } + + /** + * @brief Chooses an Extent and clamps values to the available capabilities. + * + * @param physicalDevice Vulkan-PhysicalDevice + * @param surface Vulkan-Surface of the swapchain + * @param window Window of the current application + * @return Chosen Extent for the surface + */ + vk::Extent2D chooseExtent(vk::PhysicalDevice physicalDevice, vk::SurfaceKHR surface, const Window &window) { + int fb_width, fb_height; + window.getFramebufferSize(fb_width, fb_height); + + VkExtent2D extent2D = { + static_cast<uint32_t>(fb_width), + static_cast<uint32_t>(fb_height) + }; + + vk::SurfaceCapabilitiesKHR surfaceCapabilities; + if(physicalDevice.getSurfaceCapabilitiesKHR(surface, &surfaceCapabilities) != vk::Result::eSuccess) { + vkcv_log(LogLevel::WARNING, "The capabilities of the surface can not be retrieved"); + + extent2D.width = std::max(MIN_SURFACE_SIZE, extent2D.width); + extent2D.height = std::max(MIN_SURFACE_SIZE, extent2D.height); + } else { + 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)); + } + + return extent2D; + } + + /** + * @brief Chooses Surface Format for the current surface + * + * @param physicalDevice Vulkan-PhysicalDevice + * @param surface Vulkan-Surface of the swapchain + * @return Available Format + */ + vk::SurfaceFormatKHR chooseSurfaceFormat(vk::PhysicalDevice physicalDevice, vk::SurfaceKHR surface) { + std::vector<vk::SurfaceFormatKHR> availableFormats = physicalDevice.getSurfaceFormatsKHR(surface); + + for (const auto& availableFormat : availableFormats) { + if (availableFormat.format == vk::Format::eB8G8R8A8Unorm && availableFormat.colorSpace == vk::ColorSpaceKHR::eSrgbNonlinear) { + return availableFormat; + } + } + + return availableFormats[0]; + } + + /** + * @brief Returns vk::PresentModeKHR::eMailbox if available or + * vk::PresentModeKHR::eFifo otherwise + * + * @param physicalDevice Vulkan-PhysicalDevice + * @param surface Vulkan-Surface of the swapchain + * @return Available PresentationMode + */ + vk::PresentModeKHR choosePresentMode(vk::PhysicalDevice physicalDevice, vk::SurfaceKHR surface) { + std::vector<vk::PresentModeKHR> availablePresentModes = physicalDevice.getSurfacePresentModesKHR(surface); + + for (const auto& availablePresentMode : availablePresentModes) { + if (availablePresentMode == vk::PresentModeKHR::eMailbox) { + return availablePresentMode; + } + } + // The FIFO present mode is guaranteed by the spec to be supported + return vk::PresentModeKHR::eFifo; + } + + /** + * @brief Returns the minImageCount +1 for at least double buffering, + * if it's greater than maxImageCount return maxImageCount + * + * @param physicalDevice Vulkan-PhysicalDevice + * @param surface Vulkan-Surface of the swapchain + * @return Available image count + */ + uint32_t chooseImageCount(vk::PhysicalDevice physicalDevice, vk::SurfaceKHR surface) { + vk::SurfaceCapabilitiesKHR surfaceCapabilities = physicalDevice.getSurfaceCapabilitiesKHR(surface); + + // minImageCount should always be at least 2; set to 3 for triple buffering + uint32_t imageCount = surfaceCapabilities.minImageCount + 1; + + // check if requested image count is supported + if (surfaceCapabilities.maxImageCount > 0 && imageCount > surfaceCapabilities.maxImageCount) { + imageCount = surfaceCapabilities.maxImageCount; + } + + return imageCount; + } + + Surface::Surface(const Context &context, + const vk::SurfaceKHR &handle, + uint32_t presentQueueIndex, + const vk::Extent2D &extent, + vk::Format format, + vk::ColorSpaceKHR colorSpace) + : m_Context(&context), + m_Handle(handle), + m_PresentQueueIndex(presentQueueIndex), + m_Extent(extent), + m_Format(format), + m_ColorSpace(colorSpace) { + } + + vk::SwapchainKHR Surface::createVulkanSwapchain(const Window &window, + const vk::SwapchainKHR &oldSwapchain) { + if ((!m_Context) || (!m_Handle)) + return nullptr; + + const vk::PhysicalDevice& physicalDevice = m_Context->getPhysicalDevice(); + const vk::Device& device = m_Context->getDevice(); + + m_Extent = chooseExtent(physicalDevice, m_Handle, window); + + if ((m_Extent.width < MIN_SURFACE_SIZE) || (m_Extent.height < MIN_SURFACE_SIZE)) { + return nullptr; + } + + vk::SurfaceFormatKHR chosenSurfaceFormat = chooseSurfaceFormat(physicalDevice, m_Handle); + vk::PresentModeKHR chosenPresentMode = choosePresentMode(physicalDevice, m_Handle); + uint32_t chosenImageCount = chooseImageCount(physicalDevice, m_Handle); + + m_Format = chosenSurfaceFormat.format; + m_ColorSpace = chosenSurfaceFormat.colorSpace; + + vk::SwapchainCreateInfoKHR swapchainCreateInfo ( + vk::SwapchainCreateFlagsKHR(), + m_Handle, + chosenImageCount, + m_Format, + m_ColorSpace, + m_Extent, + 1, + vk::ImageUsageFlagBits::eColorAttachment | vk::ImageUsageFlagBits::eStorage, + vk::SharingMode::eExclusive, + 0, + nullptr, + vk::SurfaceTransformFlagBitsKHR::eIdentity, + vk::CompositeAlphaFlagBitsKHR::eOpaque, + chosenPresentMode, + true, + oldSwapchain + ); + + return device.createSwapchainKHR(swapchainCreateInfo); + } + + Surface::Surface(Surface &&other) noexcept + : m_Context(other.m_Context), + m_Handle(other.m_Handle), + m_PresentQueueIndex(other.m_PresentQueueIndex), + m_Extent(other.m_Extent), + m_Format(other.m_Format), + m_ColorSpace(other.m_ColorSpace) { + other.m_Context = nullptr; + other.m_Handle = nullptr; + } + + Surface &Surface::operator=(Surface &&other) noexcept { + m_Context = other.m_Context; + m_Handle = other.m_Handle; + m_PresentQueueIndex = other.m_PresentQueueIndex; + m_Extent = other.m_Extent; + m_Format = other.m_Format; + m_ColorSpace = other.m_ColorSpace; + + other.m_Context = nullptr; + other.m_Handle = nullptr; + return *this; + } + + Surface::~Surface() { + // needs to be destroyed by creator + } + + Surface Surface::create(const Window &window, const Context &context) { + const vk::Instance& instance = context.getInstance(); + const vk::PhysicalDevice& physicalDevice = context.getPhysicalDevice(); + + uint32_t presentQueueIndex = 0; + + vk::SurfaceKHR surfaceHandle; + if (!createVulkanSurface(window.getWindow(), instance, physicalDevice, surfaceHandle)) + surfaceHandle = nullptr; + else + presentQueueIndex = QueueManager::checkSurfaceSupport(physicalDevice, surfaceHandle); + + const vk::Extent2D extent = chooseExtent(physicalDevice, surfaceHandle, window); + const vk::SurfaceFormatKHR format = chooseSurfaceFormat(physicalDevice, surfaceHandle); + + return { context, surfaceHandle, presentQueueIndex, extent, format.format, format.colorSpace }; + } + + vk::SurfaceKHR Surface::getSurface() const { + return m_Handle; + } + + uint32_t Surface::getPresentQueueIndex() const { + return m_PresentQueueIndex; + } + + const vk::Extent2D& Surface::getExtent() const { + return m_Extent; + } + + vk::Format Surface::getFormat() const { + return m_Format; + } + + vk::ColorSpaceKHR Surface::getColorSpace() const { + return m_ColorSpace; + } + +} diff --git a/src/vkcv/Swapchain.cpp b/src/vkcv/Swapchain.cpp index 79289110307712a1d6a27ecd1b1eb7df71492522..2ca69e7d58991ee67d8e72261e1cddf65de60ed0 100644 --- a/src/vkcv/Swapchain.cpp +++ b/src/vkcv/Swapchain.cpp @@ -5,198 +5,43 @@ namespace vkcv { - /** - * creates surface and checks availability - * @param window current window for the surface - * @param instance Vulkan-Instance - * @param physicalDevice Vulkan-PhysicalDevice - * @return created surface - */ - vk::SurfaceKHR createSurface(GLFWwindow* window, const vk::Instance& instance, const vk::PhysicalDevice& physicalDevice) { - //create surface - VkSurfaceKHR surface; - if (glfwCreateWindowSurface(VkInstance(instance), window, nullptr, &surface) != VK_SUCCESS) { - throw std::runtime_error("failed to create a window surface!"); - } - vk::Bool32 surfaceSupport = false; - if (physicalDevice.getSurfaceSupportKHR(0, vk::SurfaceKHR(surface), &surfaceSupport) != vk::Result::eSuccess && surfaceSupport != true) { - throw std::runtime_error("surface is not supported by the device!"); - } - return vk::SurfaceKHR(surface); - } - - Swapchain::Swapchain(const Surface &surface, - vk::SwapchainKHR swapchain, - vk::Format format, - vk::ColorSpaceKHR colorSpace, - vk::PresentModeKHR presentMode, - uint32_t imageCount, - vk::Extent2D extent) noexcept : - m_Surface(surface), - m_Swapchain(swapchain), - m_Format(format), - m_ColorSpace(colorSpace), - m_PresentMode(presentMode), - m_ImageCount(imageCount), - m_Extent(extent), - m_RecreationRequired(false) - {} + Swapchain::Swapchain(const Context &context, + const Surface &surface, + vk::SwapchainKHR swapchain) noexcept + : m_Context(&context), + m_Surface(surface), + m_Swapchain(swapchain), + m_RecreationRequired(false) { + } Swapchain::Swapchain(const Swapchain &other) : - m_Surface(other.m_Surface), - m_Swapchain(other.m_Swapchain), - m_Format(other.m_Format), - m_ColorSpace(other.m_ColorSpace), - m_PresentMode(other.m_PresentMode), - m_ImageCount(other.m_ImageCount), - m_Extent(other.m_Extent), - m_RecreationRequired(other.m_RecreationRequired.load()) - {} + m_Context(other.m_Context), + m_Surface(other.m_Surface), + m_Swapchain(other.m_Swapchain), + m_RecreationRequired(other.m_RecreationRequired.load()) { + } const vk::SwapchainKHR& Swapchain::getSwapchain() const { return m_Swapchain; } - vk::SurfaceKHR Swapchain::getSurface() const { - return m_Surface.handle; + const Surface& Swapchain::getSurface() const { + return m_Surface; } vk::Format Swapchain::getFormat() const{ - return m_Format; - } - - /** - * chooses Extent and clapms values to the available - * @param physicalDevice Vulkan-PhysicalDevice - * @param surface of the swapchain - * @param window of the current application - * @return chosen Extent for the surface - */ - vk::Extent2D chooseExtent(vk::PhysicalDevice physicalDevice, vk::SurfaceKHR surface, const Window &window) { - int fb_width, fb_height; - window.getFramebufferSize(fb_width, fb_height); - - VkExtent2D extent2D = { - static_cast<uint32_t>(fb_width), - static_cast<uint32_t>(fb_height) - }; - - vk::SurfaceCapabilitiesKHR surfaceCapabilities; - if(physicalDevice.getSurfaceCapabilitiesKHR(surface, &surfaceCapabilities) != vk::Result::eSuccess) { - vkcv_log(LogLevel::WARNING, "The capabilities of the surface can not be retrieved"); - - extent2D.width = std::max(MIN_SWAPCHAIN_SIZE, extent2D.width); - extent2D.height = std::max(MIN_SWAPCHAIN_SIZE, extent2D.height); - } else { - 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)); - } - - return extent2D; - } - - /** - * chooses Surface Format for the current surface - * @param physicalDevice Vulkan-PhysicalDevice - * @param surface of the swapchain - * @return available Format - */ - vk::SurfaceFormatKHR chooseSurfaceFormat(vk::PhysicalDevice physicalDevice, vk::SurfaceKHR surface) { - std::vector<vk::SurfaceFormatKHR> availableFormats = physicalDevice.getSurfaceFormatsKHR(surface); - - for (const auto& availableFormat : availableFormats) { - if (availableFormat.format == vk::Format::eB8G8R8A8Unorm && availableFormat.colorSpace == vk::ColorSpaceKHR::eSrgbNonlinear) { - return availableFormat; - } - } - - return availableFormats[0]; - } - - /** - * returns vk::PresentModeKHR::eMailbox if available or vk::PresentModeKHR::eFifo otherwise - * @param physicalDevice Vulkan-PhysicalDevice - * @param surface of the swapchain - * @return available PresentationMode - */ - vk::PresentModeKHR choosePresentMode(vk::PhysicalDevice physicalDevice, vk::SurfaceKHR surface) { - std::vector<vk::PresentModeKHR> availablePresentModes = physicalDevice.getSurfacePresentModesKHR(surface); - - for (const auto& availablePresentMode : availablePresentModes) { - if (availablePresentMode == vk::PresentModeKHR::eMailbox) { - return availablePresentMode; - } - } - // The FIFO present mode is guaranteed by the spec to be supported - return vk::PresentModeKHR::eFifo; - } - - /** - * returns the minImageCount +1 for at least double buffering, if it's greater than maxImageCount return maxImageCount - * @param physicalDevice Vulkan-PhysicalDevice - * @param surface of the swapchain - * @return available ImageCount - */ - uint32_t chooseImageCount(vk::PhysicalDevice physicalDevice, vk::SurfaceKHR surface) { - vk::SurfaceCapabilitiesKHR surfaceCapabilities = physicalDevice.getSurfaceCapabilitiesKHR(surface); - - // minImageCount should always be at least 2; set to 3 for triple buffering - uint32_t imageCount = surfaceCapabilities.minImageCount + 1; - - // check if requested image count is supported - if (surfaceCapabilities.maxImageCount > 0 && imageCount > surfaceCapabilities.maxImageCount) { - imageCount = surfaceCapabilities.maxImageCount; - } - - return imageCount; + return m_Surface.getFormat(); } Swapchain Swapchain::create(const Window &window, const Context &context) { - const vk::Instance& instance = context.getInstance(); - const vk::PhysicalDevice& physicalDevice = context.getPhysicalDevice(); - const vk::Device& device = context.getDevice(); - - Surface surface; - surface.handle = createSurface(window.getWindow(), instance, physicalDevice); - surface.formats = physicalDevice.getSurfaceFormatsKHR(surface.handle); - surface.capabilities = physicalDevice.getSurfaceCapabilitiesKHR(surface.handle); - surface.presentModes = physicalDevice.getSurfacePresentModesKHR(surface.handle); - surface.presentQueueIndex = QueueManager::checkSurfaceSupport(physicalDevice, surface.handle); + Surface surface = Surface::create(window, context); - vk::Extent2D chosenExtent = chooseExtent(physicalDevice, surface.handle, window); - vk::SurfaceFormatKHR chosenSurfaceFormat = chooseSurfaceFormat(physicalDevice, surface.handle); - vk::PresentModeKHR chosenPresentMode = choosePresentMode(physicalDevice, surface.handle); - uint32_t chosenImageCount = chooseImageCount(physicalDevice, surface.handle); + vk::SwapchainKHR swapchain = surface.createVulkanSwapchain( + window, nullptr + ); - vk::SwapchainCreateInfoKHR swapchainCreateInfo( - vk::SwapchainCreateFlagsKHR(), - surface.handle, - chosenImageCount, - chosenSurfaceFormat.format, - chosenSurfaceFormat.colorSpace, - chosenExtent, - 1, - vk::ImageUsageFlagBits::eColorAttachment | vk::ImageUsageFlagBits::eStorage, - vk::SharingMode::eExclusive, - 0, - nullptr, - vk::SurfaceTransformFlagBitsKHR::eIdentity, - vk::CompositeAlphaFlagBitsKHR::eOpaque, - chosenPresentMode, - true, - nullptr - ); - - vk::SwapchainKHR swapchain = device.createSwapchainKHR(swapchainCreateInfo); - - return Swapchain(surface, - swapchain, - chosenSurfaceFormat.format, - chosenSurfaceFormat.colorSpace, - chosenPresentMode, - chosenImageCount, - chosenExtent); + return { context, surface, swapchain }; } bool Swapchain::shouldUpdateSwapchain() const { @@ -209,40 +54,18 @@ namespace vkcv } vk::SwapchainKHR oldSwapchain = m_Swapchain; - vk::Extent2D extent2D = chooseExtent(context.getPhysicalDevice(), m_Surface.handle, window); - if ((extent2D.width >= MIN_SWAPCHAIN_SIZE) && (extent2D.height >= MIN_SWAPCHAIN_SIZE)) { - vk::SwapchainCreateInfoKHR swapchainCreateInfo( - vk::SwapchainCreateFlagsKHR(), - m_Surface.handle, - m_ImageCount, - m_Format, - m_ColorSpace, - extent2D, - 1, - vk::ImageUsageFlagBits::eColorAttachment | vk::ImageUsageFlagBits::eStorage, - vk::SharingMode::eExclusive, - 0, - nullptr, - vk::SurfaceTransformFlagBitsKHR::eIdentity, - vk::CompositeAlphaFlagBitsKHR::eOpaque, - m_PresentMode, - true, - oldSwapchain - ); - - m_Swapchain = context.getDevice().createSwapchainKHR(swapchainCreateInfo); - } else { - m_Swapchain = nullptr; - + m_Swapchain = m_Surface.createVulkanSwapchain( + window, oldSwapchain + ); + + if (!m_Swapchain) { signalSwapchainRecreation(); } if (oldSwapchain) { context.getDevice().destroySwapchainKHR(oldSwapchain); } - - m_Extent = extent2D; } void Swapchain::signalSwapchainRecreation() { @@ -250,7 +73,7 @@ namespace vkcv } const vk::Extent2D& Swapchain::getExtent() const { - return m_Extent; + return m_Surface.getExtent(); } Swapchain::~Swapchain() { @@ -258,10 +81,16 @@ namespace vkcv } uint32_t Swapchain::getImageCount() const { - return m_ImageCount; + uint32_t imageCount = 0; + + if (vk::Result::eSuccess != m_Context->getDevice().getSwapchainImagesKHR(m_Swapchain, &imageCount, nullptr)) + return 0; + else + return imageCount; } - const uint32_t &Swapchain::getPresentQueueIndex() const { - return m_Surface.presentQueueIndex; + uint32_t Swapchain::getPresentQueueIndex() const { + return m_Surface.getPresentQueueIndex(); } + } diff --git a/src/vkcv/SwapchainManager.cpp b/src/vkcv/SwapchainManager.cpp index 0caea9fd0fe47b4f51a53adac9134fb7f81a205a..369e077aabc7a5a80bc4dd668d9c6eea1277e66f 100644 --- a/src/vkcv/SwapchainManager.cpp +++ b/src/vkcv/SwapchainManager.cpp @@ -40,9 +40,9 @@ namespace vkcv { swapchain.m_Swapchain = nullptr; } - if (swapchain.m_Surface.handle) { - m_context->getInstance().destroySurfaceKHR(swapchain.m_Surface.handle); - swapchain.m_Surface.handle = nullptr; + if (swapchain.m_Surface.m_Handle) { + m_context->getInstance().destroySurfaceKHR(swapchain.m_Surface.m_Handle); + swapchain.m_Surface.m_Handle = nullptr; } }