Fixed resizing, moved depth image to swapchain create cycle.

Also acheived (surface) format selection.
This commit is contained in:
connellpaxton 2024-01-22 13:51:19 -05:00
parent 593eec8b8e
commit 9c514b658a
8 changed files with 154 additions and 98 deletions

View File

@ -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)

View File

@ -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

View File

@ -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);

View File

@ -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<RenderPass>(dev);
swapchain = std::make_unique<Swapchain>(dev, surface, win.getDimensions(), *render_pass, depth_image_view);
auto color_format = Swapchain::Capabilities(phys_dev, surface).chooseFormat().format;
render_pass = std::make_unique<RenderPass>(dev, color_format);
swapchain = std::make_unique<Swapchain>(win, dev, phys_dev, surface, *render_pass);
command_buffer = std::make_unique<CommandBuffer>(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();

View File

@ -37,8 +37,4 @@ struct Renderer {
std::unique_ptr<RenderPass> render_pass;
uint32_t current_image_idx;
vk::Image depth_image;
vk::ImageView depth_image_view;
vk::DeviceMemory depth_alloc;
};

View File

@ -1,21 +1,51 @@
#include <Renderer/Swapchain.hpp>
#include <Window/Window.hpp>
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 <Memory/Memory.hpp>
#include <util/log.hpp>
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);
}

View File

@ -6,27 +6,46 @@
#include <Renderer/RenderPass.hpp>
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<vk::SurfaceFormatKHR> formats;
std::vector<vk::PresentModeKHR> 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<vk::Image> images;
std::vector<vk::ImageView> views;
std::vector<vk::Framebuffer> 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();
};

View File

@ -8,7 +8,11 @@ namespace Log {
DEBUG = 0x04,
};
static const MessageLevelBit log_mask = static_cast<MessageLevelBit>(~0);
inline MessageLevelBit operator | (MessageLevelBit a, MessageLevelBit b) {
return static_cast<MessageLevelBit>(static_cast<uint32_t>(a) | static_cast<uint32_t>(b));
}
static const MessageLevelBit log_mask = ERROR | INFO;
template<typename ...Args>
static void print(MessageLevelBit level, const std::string& fmt, Args... args) {