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 20)
|
||||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
|
|
||||||
|
if(WIN32)
|
||||||
|
set(CMAKE_CXX_FLAGS "-D_DEBUG")
|
||||||
|
else()
|
||||||
set(CMAKE_CXX_FLAGS "-D_DEBUG -Wall")
|
set(CMAKE_CXX_FLAGS "-D_DEBUG -Wall")
|
||||||
|
endif()
|
||||||
|
|
||||||
project(Pleascach)
|
project(Pleascach)
|
||||||
|
|
||||||
|
|||||||
@ -3,5 +3,5 @@
|
|||||||
## Constant Improvements
|
## Constant Improvements
|
||||||
- Add more comments
|
- Add more comments
|
||||||
## Long Term Improvements
|
## Long Term Improvements
|
||||||
- Properly query surface to find supported formats for surfaces
|
- ~~Properly query surface to find supported formats for surfaces~~
|
||||||
- Add pipeline caching
|
- Add pipeline caching
|
||||||
|
|||||||
@ -6,7 +6,7 @@
|
|||||||
struct RenderPass {
|
struct RenderPass {
|
||||||
vk::RenderPass render_pass;
|
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);
|
void cleanup(vk::Device dev);
|
||||||
|
|
||||||
|
|||||||
@ -148,73 +148,14 @@ Renderer::Renderer(Window& win) : win(win) {
|
|||||||
|
|
||||||
queue = dev.getQueue(queue_family, 0);
|
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 });
|
render_fence = dev.createFence(vk::FenceCreateInfo { .flags = vk::FenceCreateFlagBits::eSignaled });
|
||||||
|
|
||||||
image_wait_semaphore = dev.createSemaphore(vk::SemaphoreCreateInfo{});
|
image_wait_semaphore = dev.createSemaphore(vk::SemaphoreCreateInfo{});
|
||||||
render_wait_semaphore = dev.createSemaphore(vk::SemaphoreCreateInfo{});
|
render_wait_semaphore = dev.createSemaphore(vk::SemaphoreCreateInfo{});
|
||||||
|
|
||||||
render_pass = std::make_unique<RenderPass>(dev);
|
auto color_format = Swapchain::Capabilities(phys_dev, surface).chooseFormat().format;
|
||||||
swapchain = std::make_unique<Swapchain>(dev, surface, win.getDimensions(), *render_pass, depth_image_view);
|
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);
|
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) */
|
/* check if the swapchain is still good (no resize) */
|
||||||
auto image_ret = dev.acquireNextImageKHR(*swapchain, UINT64_MAX, image_wait_semaphore);
|
auto image_ret = dev.acquireNextImageKHR(*swapchain, UINT64_MAX, image_wait_semaphore);
|
||||||
if (image_ret.result == vk::Result::eErrorOutOfDateKHR) {
|
if (image_ret.result == vk::Result::eErrorOutOfDateKHR) {
|
||||||
swapchain->recreate(win.getDimensions());
|
swapchain->recreate();
|
||||||
}
|
}
|
||||||
|
|
||||||
current_image_idx = image_ret.value;
|
current_image_idx = image_ret.value;
|
||||||
@ -313,23 +254,22 @@ void Renderer::present() {
|
|||||||
break;
|
break;
|
||||||
case vk::Result::eSuboptimalKHR:
|
case vk::Result::eSuboptimalKHR:
|
||||||
case vk::Result::eErrorOutOfDateKHR:
|
case vk::Result::eErrorOutOfDateKHR:
|
||||||
Log::info("Recreating swapchain");
|
Log::info("Recreating swapchain\n");
|
||||||
swapchain->recreate(win.getDimensions());
|
swapchain->recreate();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
Log::error("Failed to present surface.");
|
Log::error("Failed to present surface.\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Renderer::~Renderer() {
|
Renderer::~Renderer() {
|
||||||
dev.destroyImage(depth_image);
|
|
||||||
dev.destroyImageView(depth_image_view);
|
|
||||||
dev.freeMemory(depth_alloc);
|
|
||||||
|
|
||||||
|
|
||||||
swapchain.reset();
|
swapchain.reset();
|
||||||
dev.waitIdle();
|
|
||||||
|
dev.destroySemaphore(image_wait_semaphore);
|
||||||
|
dev.destroySemaphore(render_wait_semaphore);
|
||||||
|
dev.destroyFence(render_fence);
|
||||||
|
|
||||||
command_buffer->cleanup(dev);
|
command_buffer->cleanup(dev);
|
||||||
render_pass->cleanup(dev);
|
render_pass->cleanup(dev);
|
||||||
dev.destroy();
|
dev.destroy();
|
||||||
|
|||||||
@ -37,8 +37,4 @@ struct Renderer {
|
|||||||
std::unique_ptr<RenderPass> render_pass;
|
std::unique_ptr<RenderPass> render_pass;
|
||||||
|
|
||||||
uint32_t current_image_idx;
|
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 <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)
|
#include <Memory/Memory.hpp>
|
||||||
: dev(dev), surface(surface), render_pass(render_pass), depth_image_view(depth_image_view) {
|
|
||||||
create(extent);
|
#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) {
|
Swapchain::Capabilities::Capabilities(vk::PhysicalDevice phys_dev, vk::SurfaceKHR surface) {
|
||||||
this->extent = extent;
|
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,
|
.surface = surface,
|
||||||
/* at least double-buffered */
|
.minImageCount = caps.surface_caps.maxImageCount,
|
||||||
.minImageCount = 3,
|
|
||||||
.imageFormat = format,
|
.imageFormat = format,
|
||||||
.imageColorSpace = vk::ColorSpaceKHR::eSrgbNonlinear,
|
.imageColorSpace = sFormat.colorSpace,
|
||||||
.imageExtent = extent,
|
.imageExtent = extent,
|
||||||
.imageArrayLayers = 1,
|
.imageArrayLayers = 1,
|
||||||
.imageUsage = vk::ImageUsageFlagBits::eColorAttachment,
|
.imageUsage = vk::ImageUsageFlagBits::eColorAttachment,
|
||||||
@ -34,10 +64,62 @@ void Swapchain::create(const vk::Extent2D& extent, vk::SwapchainKHR old_swapchai
|
|||||||
swapchain = dev.createSwapchainKHR(swap_info);
|
swapchain = dev.createSwapchainKHR(swap_info);
|
||||||
|
|
||||||
images = dev.getSwapchainImagesKHR(swapchain);
|
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());
|
views.resize(images.size());
|
||||||
framebuffers.resize(images.size());
|
framebuffers.resize(images.size());
|
||||||
for (size_t i = 0; i < views.size(); i++) {
|
for (size_t i = 0; i < views.size(); i++) {
|
||||||
auto color_image_info = vk::ImageViewCreateInfo{
|
auto color_image_info = vk::ImageViewCreateInfo {
|
||||||
.image = images[i],
|
.image = images[i],
|
||||||
.viewType = vk::ImageViewType::e2D,
|
.viewType = vk::ImageViewType::e2D,
|
||||||
.format = format,
|
.format = format,
|
||||||
@ -69,21 +151,32 @@ void Swapchain::create(const vk::Extent2D& extent, vk::SwapchainKHR old_swapchai
|
|||||||
|
|
||||||
framebuffers[i] = dev.createFramebuffer(framebuffer_info);
|
framebuffers[i] = dev.createFramebuffer(framebuffer_info);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Swapchain::recreate(const vk::Extent2D& extent) {
|
void Swapchain::recreate() {
|
||||||
dev.waitIdle();
|
dev.waitIdle();
|
||||||
cleanup();
|
cleanup();
|
||||||
create(extent, swapchain);
|
auto save = swapchain;
|
||||||
|
create(swapchain);
|
||||||
|
dev.destroySwapchainKHR(save);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Swapchain::cleanup() {
|
void Swapchain::cleanup() {
|
||||||
|
dev.waitIdle();
|
||||||
for(auto& fb : framebuffers)
|
for(auto& fb : framebuffers)
|
||||||
dev.destroyFramebuffer(fb);
|
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() {
|
Swapchain::~Swapchain() {
|
||||||
cleanup();
|
cleanup();
|
||||||
|
dev.destroySwapchainKHR(swapchain);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -6,27 +6,46 @@
|
|||||||
|
|
||||||
#include <Renderer/RenderPass.hpp>
|
#include <Renderer/RenderPass.hpp>
|
||||||
|
|
||||||
|
struct Window;
|
||||||
|
|
||||||
struct Swapchain {
|
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;
|
vk::SwapchainKHR swapchain;
|
||||||
inline operator vk::SwapchainKHR& () {
|
inline operator vk::SwapchainKHR& () {
|
||||||
return swapchain;
|
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;
|
vk::SurfaceKHR surface;
|
||||||
std::vector<vk::Image> images;
|
std::vector<vk::Image> images;
|
||||||
std::vector<vk::ImageView> views;
|
std::vector<vk::ImageView> views;
|
||||||
std::vector<vk::Framebuffer> framebuffers;
|
std::vector<vk::Framebuffer> framebuffers;
|
||||||
|
|
||||||
RenderPass render_pass;
|
vk::Image depth_image;
|
||||||
vk::ImageView depth_image_view;
|
vk::ImageView depth_image_view;
|
||||||
|
vk::DeviceMemory depth_alloc;
|
||||||
|
|
||||||
|
vk::Format format;
|
||||||
|
|
||||||
|
RenderPass render_pass;
|
||||||
|
|
||||||
vk::Extent2D extent;
|
vk::Extent2D extent;
|
||||||
|
|
||||||
void create(const vk::Extent2D& extent, vk::SwapchainKHR old_swapchain = nullptr);
|
void create(vk::SwapchainKHR old_swapchain = nullptr);
|
||||||
void recreate(const vk::Extent2D& extent);
|
void recreate();
|
||||||
void cleanup();
|
void cleanup();
|
||||||
~Swapchain();
|
~Swapchain();
|
||||||
};
|
};
|
||||||
@ -8,7 +8,11 @@ namespace Log {
|
|||||||
DEBUG = 0x04,
|
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>
|
template<typename ...Args>
|
||||||
static void print(MessageLevelBit level, const std::string& fmt, Args... args) {
|
static void print(MessageLevelBit level, const std::string& fmt, Args... args) {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user