From 9c514b658acc69bafc537aa8fb7dc76975932362 Mon Sep 17 00:00:00 2001 From: connellpaxton Date: Mon, 22 Jan 2024 13:51:19 -0500 Subject: [PATCH] Fixed resizing, moved depth image to swapchain create cycle. Also acheived (surface) format selection. --- CMakeLists.txt | 4 ++ README.md | 2 +- Renderer/RenderPass.hpp | 2 +- Renderer/Renderer.cpp | 84 ++++------------------------ Renderer/Renderer.hpp | 4 -- Renderer/Swapchain.cpp | 121 +++++++++++++++++++++++++++++++++++----- Renderer/Swapchain.hpp | 29 ++++++++-- util/log.hpp | 6 +- 8 files changed, 154 insertions(+), 98 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3468108..5f0bc33 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,7 +3,11 @@ set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON) +if(WIN32) +set(CMAKE_CXX_FLAGS "-D_DEBUG") +else() set(CMAKE_CXX_FLAGS "-D_DEBUG -Wall") +endif() project(Pleascach) diff --git a/README.md b/README.md index 885c7ec..a353619 100644 --- a/README.md +++ b/README.md @@ -3,5 +3,5 @@ ## Constant Improvements - Add more comments ## Long Term Improvements -- Properly query surface to find supported formats for surfaces +- ~~Properly query surface to find supported formats for surfaces~~ - Add pipeline caching diff --git a/Renderer/RenderPass.hpp b/Renderer/RenderPass.hpp index 738cd43..0d0d1fa 100644 --- a/Renderer/RenderPass.hpp +++ b/Renderer/RenderPass.hpp @@ -6,7 +6,7 @@ struct RenderPass { vk::RenderPass render_pass; - RenderPass(vk::Device dev, vk::Format image_format = vk::Format::eB8G8R8A8Unorm, vk::Format depth_format = vk::Format::eD16Unorm); + RenderPass(vk::Device dev, vk::Format image_format, vk::Format depth_format = vk::Format::eD16Unorm); void cleanup(vk::Device dev); diff --git a/Renderer/Renderer.cpp b/Renderer/Renderer.cpp index ebd3182..3bb17ea 100644 --- a/Renderer/Renderer.cpp +++ b/Renderer/Renderer.cpp @@ -148,73 +148,14 @@ Renderer::Renderer(Window& win) : win(win) { queue = dev.getQueue(queue_family, 0); - - /* depth image */ - /* 1. create an Image to be the buffer - * 2. find memory req's - * 3. allocate - * 4. set layout - * 5. create attachment view - */ - auto extent = win.getDimensions(); - auto depth_image_info = vk::ImageCreateInfo { - .imageType = vk::ImageType::e2D, - .format = vk::Format::eD16Unorm, - .extent = { - .width = extent.width, - .height = extent.height, - .depth = 1, - }, - .mipLevels = 1, - .arrayLayers = 1, - .samples = vk::SampleCountFlagBits::e1, - .usage = vk::ImageUsageFlagBits::eDepthStencilAttachment, - .sharingMode = vk::SharingMode::eExclusive, - .queueFamilyIndexCount = 0, - .pQueueFamilyIndices = NULL, - .initialLayout = vk::ImageLayout::eUndefined, - }; - - depth_image = dev.createImage(depth_image_info); - - auto depth_mem_reqs = dev.getImageMemoryRequirements(depth_image); - - auto depth_alloc_info = vk::MemoryAllocateInfo { - .allocationSize = depth_mem_reqs.size, - .memoryTypeIndex = mem::choose_heap(phys_dev, depth_mem_reqs, vk::MemoryPropertyFlagBits::eDeviceLocal), - }; - - depth_alloc = dev.allocateMemory(depth_alloc_info); - dev.bindImageMemory(depth_image, depth_alloc, 0); - - auto depth_view_info = vk::ImageViewCreateInfo { - .image = depth_image, - .viewType = vk::ImageViewType::e2D, - .format = vk::Format::eD16Unorm, - .components = { - .r = vk::ComponentSwizzle::eR, - .g = vk::ComponentSwizzle::eG, - .b = vk::ComponentSwizzle::eB, - .a = vk::ComponentSwizzle::eA, - }, - .subresourceRange = { - .aspectMask = vk::ImageAspectFlagBits::eDepth, - .baseMipLevel = 0, - .levelCount = 1, - .baseArrayLayer = 0, - .layerCount = 1, - }, - }; - - depth_image_view = dev.createImageView(depth_view_info); - render_fence = dev.createFence(vk::FenceCreateInfo { .flags = vk::FenceCreateFlagBits::eSignaled }); image_wait_semaphore = dev.createSemaphore(vk::SemaphoreCreateInfo{}); render_wait_semaphore = dev.createSemaphore(vk::SemaphoreCreateInfo{}); - render_pass = std::make_unique(dev); - swapchain = std::make_unique(dev, surface, win.getDimensions(), *render_pass, depth_image_view); + auto color_format = Swapchain::Capabilities(phys_dev, surface).chooseFormat().format; + render_pass = std::make_unique(dev, color_format); + swapchain = std::make_unique(win, dev, phys_dev, surface, *render_pass); command_buffer = std::make_unique(dev, queue_family); @@ -232,7 +173,7 @@ void Renderer::draw() { /* check if the swapchain is still good (no resize) */ auto image_ret = dev.acquireNextImageKHR(*swapchain, UINT64_MAX, image_wait_semaphore); if (image_ret.result == vk::Result::eErrorOutOfDateKHR) { - swapchain->recreate(win.getDimensions()); + swapchain->recreate(); } current_image_idx = image_ret.value; @@ -313,23 +254,22 @@ void Renderer::present() { break; case vk::Result::eSuboptimalKHR: case vk::Result::eErrorOutOfDateKHR: - Log::info("Recreating swapchain"); - swapchain->recreate(win.getDimensions()); + Log::info("Recreating swapchain\n"); + swapchain->recreate(); break; default: - Log::error("Failed to present surface."); + Log::error("Failed to present surface.\n"); break; } } Renderer::~Renderer() { - dev.destroyImage(depth_image); - dev.destroyImageView(depth_image_view); - dev.freeMemory(depth_alloc); - - swapchain.reset(); - dev.waitIdle(); + + dev.destroySemaphore(image_wait_semaphore); + dev.destroySemaphore(render_wait_semaphore); + dev.destroyFence(render_fence); + command_buffer->cleanup(dev); render_pass->cleanup(dev); dev.destroy(); diff --git a/Renderer/Renderer.hpp b/Renderer/Renderer.hpp index 4d78daf..5c4de75 100644 --- a/Renderer/Renderer.hpp +++ b/Renderer/Renderer.hpp @@ -37,8 +37,4 @@ struct Renderer { std::unique_ptr render_pass; uint32_t current_image_idx; - - vk::Image depth_image; - vk::ImageView depth_image_view; - vk::DeviceMemory depth_alloc; }; diff --git a/Renderer/Swapchain.cpp b/Renderer/Swapchain.cpp index 62e692d..ffafcdb 100644 --- a/Renderer/Swapchain.cpp +++ b/Renderer/Swapchain.cpp @@ -1,21 +1,51 @@ #include +#include -Swapchain::Swapchain(vk::Device& dev, const vk::SurfaceKHR& surface, const vk::Extent2D& extent, RenderPass render_pass, vk::ImageView depth_image_view) - : dev(dev), surface(surface), render_pass(render_pass), depth_image_view(depth_image_view) { - create(extent); +#include + +#include + +Swapchain::Swapchain(Window& win, vk::Device dev, vk::PhysicalDevice phys_dev, const vk::SurfaceKHR& surface, RenderPass render_pass) + : win(win), dev(dev), phys_dev(phys_dev), surface(surface), render_pass(render_pass) { + create(); } -void Swapchain::create(const vk::Extent2D& extent, vk::SwapchainKHR old_swapchain) { - this->extent = extent; +Swapchain::Capabilities::Capabilities(vk::PhysicalDevice phys_dev, vk::SurfaceKHR surface) { + surface_caps = phys_dev.getSurfaceCapabilitiesKHR(surface); + formats = phys_dev.getSurfaceFormatsKHR(surface); + present_modes = phys_dev.getSurfacePresentModesKHR(surface); +} - auto format = vk::Format::eB8G8R8A8Unorm; +vk::Extent2D Swapchain::Capabilities::chooseExtent(vk::Extent2D extent) { + if (surface_caps.currentExtent.width != UINT32_MAX) + return surface_caps.currentExtent; - auto swap_info = vk::SwapchainCreateInfoKHR{ + extent.width = std::clamp(extent.width, surface_caps.minImageExtent.width, surface_caps.maxImageExtent.width); + extent.height = std::clamp(extent.height, surface_caps.minImageExtent.height, surface_caps.maxImageExtent.height); + + return extent; +} + +vk::SurfaceFormatKHR Swapchain::Capabilities::chooseFormat() { + for (const auto& format : formats) { + if (format.format == vk::Format::eB8G8R8A8Snorm && format.colorSpace == vk::ColorSpaceKHR::eSrgbNonlinear) + return format; + } + return formats[0]; +} + +void Swapchain::create(vk::SwapchainKHR old_swapchain) { + Capabilities caps(phys_dev, surface); + extent = caps.chooseExtent(win.getDimensions()); + auto sFormat = caps.chooseFormat(); + format = sFormat.format; + + + auto swap_info = vk::SwapchainCreateInfoKHR { .surface = surface, - /* at least double-buffered */ - .minImageCount = 3, + .minImageCount = caps.surface_caps.maxImageCount, .imageFormat = format, - .imageColorSpace = vk::ColorSpaceKHR::eSrgbNonlinear, + .imageColorSpace = sFormat.colorSpace, .imageExtent = extent, .imageArrayLayers = 1, .imageUsage = vk::ImageUsageFlagBits::eColorAttachment, @@ -34,10 +64,62 @@ void Swapchain::create(const vk::Extent2D& extent, vk::SwapchainKHR old_swapchai swapchain = dev.createSwapchainKHR(swap_info); images = dev.getSwapchainImagesKHR(swapchain); + + auto depth_image_info = vk::ImageCreateInfo{ + .imageType = vk::ImageType::e2D, + .format = vk::Format::eD16Unorm, + .extent = { + .width = extent.width, + .height = extent.height, + .depth = 1, + }, + .mipLevels = 1, + .arrayLayers = 1, + .samples = vk::SampleCountFlagBits::e1, + .usage = vk::ImageUsageFlagBits::eDepthStencilAttachment, + .sharingMode = vk::SharingMode::eExclusive, + .queueFamilyIndexCount = 0, + .pQueueFamilyIndices = NULL, + .initialLayout = vk::ImageLayout::eUndefined, + }; + + depth_image = dev.createImage(depth_image_info); + + auto depth_mem_reqs = dev.getImageMemoryRequirements(depth_image); + + auto depth_alloc_info = vk::MemoryAllocateInfo{ + .allocationSize = depth_mem_reqs.size, + .memoryTypeIndex = mem::choose_heap(phys_dev, depth_mem_reqs, vk::MemoryPropertyFlagBits::eDeviceLocal), + }; + + depth_alloc = dev.allocateMemory(depth_alloc_info); + dev.bindImageMemory(depth_image, depth_alloc, 0); + + auto depth_view_info = vk::ImageViewCreateInfo{ + .image = depth_image, + .viewType = vk::ImageViewType::e2D, + .format = vk::Format::eD16Unorm, + .components = { + .r = vk::ComponentSwizzle::eR, + .g = vk::ComponentSwizzle::eG, + .b = vk::ComponentSwizzle::eB, + .a = vk::ComponentSwizzle::eA, + }, + .subresourceRange = { + .aspectMask = vk::ImageAspectFlagBits::eDepth, + .baseMipLevel = 0, + .levelCount = 1, + .baseArrayLayer = 0, + .layerCount = 1, + }, + }; + + depth_image_view = dev.createImageView(depth_view_info); + views.resize(images.size()); framebuffers.resize(images.size()); for (size_t i = 0; i < views.size(); i++) { - auto color_image_info = vk::ImageViewCreateInfo{ + auto color_image_info = vk::ImageViewCreateInfo { .image = images[i], .viewType = vk::ImageViewType::e2D, .format = format, @@ -69,21 +151,32 @@ void Swapchain::create(const vk::Extent2D& extent, vk::SwapchainKHR old_swapchai framebuffers[i] = dev.createFramebuffer(framebuffer_info); } + } -void Swapchain::recreate(const vk::Extent2D& extent) { +void Swapchain::recreate() { dev.waitIdle(); cleanup(); - create(extent, swapchain); + auto save = swapchain; + create(swapchain); + dev.destroySwapchainKHR(save); } void Swapchain::cleanup() { + dev.waitIdle(); for(auto& fb : framebuffers) dev.destroyFramebuffer(fb); - dev.destroySwapchainKHR(swapchain); + for (auto& view : views) + dev.destroyImageView(view); + + dev.destroyImageView(depth_image_view); + dev.destroyImage(depth_image); + dev.freeMemory(depth_alloc); } Swapchain::~Swapchain() { cleanup(); + dev.destroySwapchainKHR(swapchain); } + diff --git a/Renderer/Swapchain.hpp b/Renderer/Swapchain.hpp index 00e2a4d..c3f3bc6 100644 --- a/Renderer/Swapchain.hpp +++ b/Renderer/Swapchain.hpp @@ -6,27 +6,46 @@ #include +struct Window; struct Swapchain { - Swapchain(vk::Device& dev, const vk::SurfaceKHR& surface, const vk::Extent2D& extent, RenderPass render_pass, vk::ImageView depth_image_view); + Swapchain(Window& win, vk::Device dev, vk::PhysicalDevice phys_dev, const vk::SurfaceKHR& surface, RenderPass render_pass); vk::SwapchainKHR swapchain; inline operator vk::SwapchainKHR& () { return swapchain; } - vk::Device& dev; + struct Capabilities { + vk::SurfaceCapabilitiesKHR surface_caps; + std::vector formats; + std::vector present_modes; + Capabilities(vk::PhysicalDevice phys_dev, vk::SurfaceKHR surface); + + vk::Extent2D chooseExtent(vk::Extent2D extent); + vk::SurfaceFormatKHR chooseFormat(); + }; + + + Window& win; + vk::Device dev; + vk::PhysicalDevice phys_dev; vk::SurfaceKHR surface; std::vector images; std::vector views; std::vector framebuffers; - RenderPass render_pass; + vk::Image depth_image; vk::ImageView depth_image_view; + vk::DeviceMemory depth_alloc; + + vk::Format format; + + RenderPass render_pass; vk::Extent2D extent; - void create(const vk::Extent2D& extent, vk::SwapchainKHR old_swapchain = nullptr); - void recreate(const vk::Extent2D& extent); + void create(vk::SwapchainKHR old_swapchain = nullptr); + void recreate(); void cleanup(); ~Swapchain(); }; \ No newline at end of file diff --git a/util/log.hpp b/util/log.hpp index 6150a37..462c1e7 100644 --- a/util/log.hpp +++ b/util/log.hpp @@ -8,7 +8,11 @@ namespace Log { DEBUG = 0x04, }; - static const MessageLevelBit log_mask = static_cast(~0); + inline MessageLevelBit operator | (MessageLevelBit a, MessageLevelBit b) { + return static_cast(static_cast(a) | static_cast(b)); + } + + static const MessageLevelBit log_mask = ERROR | INFO; template static void print(MessageLevelBit level, const std::string& fmt, Args... args) {