Fixed resizing, moved depth image to swapchain create cycle.
Also acheived (surface) format selection.
This commit is contained in:
parent
593eec8b8e
commit
9c514b658a
@ -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)
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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;
|
||||
};
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
vk::Extent2D Swapchain::Capabilities::chooseExtent(vk::Extent2D extent) {
|
||||
if (surface_caps.currentExtent.width != UINT32_MAX)
|
||||
return surface_caps.currentExtent;
|
||||
|
||||
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 format = vk::Format::eB8G8R8A8Unorm;
|
||||
|
||||
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,6 +64,58 @@ 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++) {
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
||||
@ -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();
|
||||
};
|
||||
@ -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) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user