mirror of
https://github.com/slendidev/lunar.git
synced 2025-12-08 10:29:52 +02:00
Render to offscreen image and window resizing
Signed-off-by: Slendi <slendi@socopon.com>
This commit is contained in:
10
meson.build
10
meson.build
@@ -1,6 +1,10 @@
|
|||||||
project('vr-compositor', 'cpp',
|
project('vr-compositor', 'cpp',
|
||||||
version: '0.1',
|
version: '0.1',
|
||||||
default_options: ['cpp_std=c++23']
|
default_options: [
|
||||||
|
'cpp_std=c++23',
|
||||||
|
'warning_level=everything',
|
||||||
|
'werror=true',
|
||||||
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
cc = meson.get_compiler('cpp')
|
cc = meson.get_compiler('cpp')
|
||||||
@@ -25,16 +29,14 @@ vkbootstrap_dep = cc.find_library(
|
|||||||
)
|
)
|
||||||
|
|
||||||
add_project_arguments(
|
add_project_arguments(
|
||||||
'-Wall',
|
|
||||||
'-Wextra',
|
|
||||||
'-Wpedantic',
|
'-Wpedantic',
|
||||||
'-Werror',
|
|
||||||
language : ['c', 'cpp']
|
language : ['c', 'cpp']
|
||||||
)
|
)
|
||||||
|
|
||||||
exe = executable('vr-compositor',
|
exe = executable('vr-compositor',
|
||||||
[
|
[
|
||||||
'src/main.cpp',
|
'src/main.cpp',
|
||||||
|
'src/Impls.cpp',
|
||||||
'src/Util.cpp',
|
'src/Util.cpp',
|
||||||
'src/Logger.cpp',
|
'src/Logger.cpp',
|
||||||
'src/Application.cpp',
|
'src/Application.cpp',
|
||||||
|
|||||||
16
src/AllocatedImage.h
Normal file
16
src/AllocatedImage.h
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <vk_mem_alloc.h>
|
||||||
|
#include <vulkan/vulkan_core.h>
|
||||||
|
|
||||||
|
namespace Lunar {
|
||||||
|
|
||||||
|
struct AllocatedImage {
|
||||||
|
VkImage image;
|
||||||
|
VkImageView image_view;
|
||||||
|
VmaAllocation allocation;
|
||||||
|
VkExtent3D extent;
|
||||||
|
VkFormat format;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Lunar
|
||||||
@@ -4,14 +4,15 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <print>
|
#include <print>
|
||||||
|
|
||||||
|
#include <SDL3/SDL_events.h>
|
||||||
#include <SDL3/SDL_init.h>
|
#include <SDL3/SDL_init.h>
|
||||||
#include <SDL3/SDL_video.h>
|
#include <SDL3/SDL_video.h>
|
||||||
#include <SDL3/SDL_vulkan.h>
|
#include <SDL3/SDL_vulkan.h>
|
||||||
#include <VkBootstrap.h>
|
#include <VkBootstrap.h>
|
||||||
#include <openxr/openxr.h>
|
#include <openxr/openxr.h>
|
||||||
|
#include <vulkan/vulkan_core.h>
|
||||||
|
|
||||||
#include "Util.h"
|
#include "Util.h"
|
||||||
#include "vulkan/vulkan_core.h"
|
|
||||||
|
|
||||||
namespace Lunar {
|
namespace Lunar {
|
||||||
|
|
||||||
@@ -45,7 +46,7 @@ auto Application::vk_init() -> void
|
|||||||
.request_validation_layers()
|
.request_validation_layers()
|
||||||
.set_app_name("Lunar")
|
.set_app_name("Lunar")
|
||||||
.set_engine_name("Lunar")
|
.set_engine_name("Lunar")
|
||||||
.require_api_version(1, 0, 0)
|
.require_api_version(1, 3, 0)
|
||||||
.set_debug_callback_user_data_pointer(this)
|
.set_debug_callback_user_data_pointer(this)
|
||||||
.set_debug_callback(
|
.set_debug_callback(
|
||||||
[](VkDebugUtilsMessageSeverityFlagBitsEXT message_severity,
|
[](VkDebugUtilsMessageSeverityFlagBitsEXT message_severity,
|
||||||
@@ -101,6 +102,7 @@ auto Application::vk_init() -> void
|
|||||||
VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME,
|
VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME,
|
||||||
VK_KHR_MAINTENANCE1_EXTENSION_NAME,
|
VK_KHR_MAINTENANCE1_EXTENSION_NAME,
|
||||||
VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME,
|
VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME,
|
||||||
|
VK_KHR_COPY_COMMANDS_2_EXTENSION_NAME,
|
||||||
});
|
});
|
||||||
auto physical_device_selector_return { phys_device_selector.select() };
|
auto physical_device_selector_return { phys_device_selector.select() };
|
||||||
if (!physical_device_selector_return) {
|
if (!physical_device_selector_return) {
|
||||||
@@ -139,6 +141,15 @@ auto Application::vk_init() -> void
|
|||||||
throw std::runtime_error("App init fail");
|
throw std::runtime_error("App init fail");
|
||||||
}
|
}
|
||||||
m_vk.graphics_queue_family = queue_family_ret.value();
|
m_vk.graphics_queue_family = queue_family_ret.value();
|
||||||
|
|
||||||
|
VmaAllocatorCreateInfo allocator_ci {};
|
||||||
|
allocator_ci.physicalDevice = m_vkb.phys_dev;
|
||||||
|
allocator_ci.device = m_vkb.dev;
|
||||||
|
allocator_ci.instance = m_vkb.instance;
|
||||||
|
vmaCreateAllocator(&allocator_ci, &m_vk.allocator);
|
||||||
|
|
||||||
|
m_vk.deletion_queue.emplace(
|
||||||
|
[this]() { vmaDestroyAllocator(m_vk.allocator); });
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Application::swapchain_init() -> void
|
auto Application::swapchain_init() -> void
|
||||||
@@ -146,6 +157,7 @@ auto Application::swapchain_init() -> void
|
|||||||
int w, h;
|
int w, h;
|
||||||
SDL_GetWindowSize(m_window, &w, &h);
|
SDL_GetWindowSize(m_window, &w, &h);
|
||||||
create_swapchain(w, h);
|
create_swapchain(w, h);
|
||||||
|
create_draw_image(static_cast<uint32_t>(w), static_cast<uint32_t>(h));
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Application::commands_init() -> void
|
auto Application::commands_init() -> void
|
||||||
@@ -202,6 +214,11 @@ auto Application::render() -> void
|
|||||||
{
|
{
|
||||||
defer(m_vk.frame_number++);
|
defer(m_vk.frame_number++);
|
||||||
|
|
||||||
|
if (m_vk.swapchain == VK_NULL_HANDLE
|
||||||
|
|| m_vk.swapchain_extent.width == 0 || m_vk.swapchain_extent.height == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
VK_CHECK(m_logger,
|
VK_CHECK(m_logger,
|
||||||
vkWaitForFences(m_vkb.dev, 1, &m_vk.get_current_frame().render_fence,
|
vkWaitForFences(m_vkb.dev, 1, &m_vk.get_current_frame().render_fence,
|
||||||
true, 1'000'000'000));
|
true, 1'000'000'000));
|
||||||
@@ -209,13 +226,25 @@ auto Application::render() -> void
|
|||||||
vkResetFences(m_vkb.dev, 1, &m_vk.get_current_frame().render_fence));
|
vkResetFences(m_vkb.dev, 1, &m_vk.get_current_frame().render_fence));
|
||||||
|
|
||||||
uint32_t swapchain_image_idx;
|
uint32_t swapchain_image_idx;
|
||||||
VK_CHECK(m_logger,
|
auto const acquire_result = vkAcquireNextImageKHR(m_vkb.dev, m_vk.swapchain,
|
||||||
vkAcquireNextImageKHR(m_vkb.dev, m_vk.swapchain, 1000000000,
|
1000000000, m_vk.get_current_frame().swapchain_semaphore, nullptr,
|
||||||
m_vk.get_current_frame().swapchain_semaphore, nullptr,
|
&swapchain_image_idx);
|
||||||
&swapchain_image_idx));
|
if (acquire_result == VK_ERROR_OUT_OF_DATE_KHR
|
||||||
|
|| acquire_result == VK_SUBOPTIMAL_KHR) {
|
||||||
|
int width {}, height {};
|
||||||
|
SDL_GetWindowSize(m_window, &width, &height);
|
||||||
|
recreate_swapchain(
|
||||||
|
static_cast<uint32_t>(width), static_cast<uint32_t>(height));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
VK_CHECK(m_logger, acquire_result);
|
||||||
|
|
||||||
auto cmd { m_vk.get_current_frame().main_command_buffer };
|
auto cmd { m_vk.get_current_frame().main_command_buffer };
|
||||||
VK_CHECK(m_logger, vkResetCommandBuffer(cmd, 0));
|
VK_CHECK(m_logger, vkResetCommandBuffer(cmd, 0));
|
||||||
|
|
||||||
|
m_vk.draw_extent.width = m_vk.draw_image.extent.width;
|
||||||
|
m_vk.draw_extent.height = m_vk.draw_image.extent.height;
|
||||||
|
|
||||||
VkCommandBufferBeginInfo cmd_begin_info {
|
VkCommandBufferBeginInfo cmd_begin_info {
|
||||||
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
|
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
|
||||||
.pNext = nullptr,
|
.pNext = nullptr,
|
||||||
@@ -224,26 +253,23 @@ auto Application::render() -> void
|
|||||||
};
|
};
|
||||||
VK_CHECK(m_logger, vkBeginCommandBuffer(cmd, &cmd_begin_info));
|
VK_CHECK(m_logger, vkBeginCommandBuffer(cmd, &cmd_begin_info));
|
||||||
|
|
||||||
vkutil::transition_image(cmd, m_vk.swapchain_images.at(swapchain_image_idx),
|
vkutil::transition_image(cmd, m_vk.draw_image.image,
|
||||||
VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL);
|
VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL);
|
||||||
|
|
||||||
VkClearColorValue clear_value;
|
draw_background(cmd);
|
||||||
float flash { std::abs(std::sin(m_vk.frame_number / 60.f)) };
|
|
||||||
clear_value = { { 0x64 / 255.0f * flash, 0x95 / 255.0f * flash,
|
|
||||||
0xED / 255.0f * flash, 1.0f } };
|
|
||||||
|
|
||||||
VkImageSubresourceRange clear_range {
|
vkutil::transition_image(cmd, m_vk.draw_image.image,
|
||||||
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
|
VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
|
||||||
.baseMipLevel = 0,
|
|
||||||
.levelCount = 1,
|
vkutil::transition_image(cmd, m_vk.swapchain_images.at(swapchain_image_idx),
|
||||||
.baseArrayLayer = 0,
|
VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
|
||||||
.layerCount = 1,
|
|
||||||
};
|
vkutil::copy_image_to_image(cmd, m_vk.draw_image.image,
|
||||||
vkCmdClearColorImage(cmd, m_vk.swapchain_images[swapchain_image_idx],
|
m_vk.swapchain_images.at(swapchain_image_idx), m_vk.draw_extent,
|
||||||
VK_IMAGE_LAYOUT_GENERAL, &clear_value, 1, &clear_range);
|
m_vk.swapchain_extent);
|
||||||
|
|
||||||
vkutil::transition_image(cmd, m_vk.swapchain_images[swapchain_image_idx],
|
vkutil::transition_image(cmd, m_vk.swapchain_images[swapchain_image_idx],
|
||||||
VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);
|
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);
|
||||||
|
|
||||||
VK_CHECK(m_logger, vkEndCommandBuffer(cmd));
|
VK_CHECK(m_logger, vkEndCommandBuffer(cmd));
|
||||||
|
|
||||||
@@ -278,7 +304,35 @@ auto Application::render() -> void
|
|||||||
|
|
||||||
present_info.pImageIndices = &swapchain_image_idx;
|
present_info.pImageIndices = &swapchain_image_idx;
|
||||||
|
|
||||||
VK_CHECK(m_logger, vkQueuePresentKHR(m_vk.graphics_queue, &present_info));
|
auto const present_result
|
||||||
|
= vkQueuePresentKHR(m_vk.graphics_queue, &present_info);
|
||||||
|
if (present_result == VK_ERROR_OUT_OF_DATE_KHR
|
||||||
|
|| present_result == VK_SUBOPTIMAL_KHR) {
|
||||||
|
int width {}, height {};
|
||||||
|
SDL_GetWindowSize(m_window, &width, &height);
|
||||||
|
recreate_swapchain(
|
||||||
|
static_cast<uint32_t>(width), static_cast<uint32_t>(height));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
VK_CHECK(m_logger, present_result);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto Application::draw_background(VkCommandBuffer cmd) -> void
|
||||||
|
{
|
||||||
|
VkClearColorValue clear_value;
|
||||||
|
float flash { std::abs(std::sin(m_vk.frame_number / 60.f)) };
|
||||||
|
clear_value = { { 0x64 / 255.0f * flash, 0x95 / 255.0f * flash,
|
||||||
|
0xED / 255.0f * flash, 1.0f } };
|
||||||
|
|
||||||
|
VkImageSubresourceRange clear_range {
|
||||||
|
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
|
||||||
|
.baseMipLevel = 0,
|
||||||
|
.levelCount = 1,
|
||||||
|
.baseArrayLayer = 0,
|
||||||
|
.layerCount = 1,
|
||||||
|
};
|
||||||
|
vkCmdClearColorImage(cmd, m_vk.draw_image.image, VK_IMAGE_LAYOUT_GENERAL,
|
||||||
|
&clear_value, 1, &clear_range);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Application::create_swapchain(uint32_t width, uint32_t height) -> void
|
auto Application::create_swapchain(uint32_t width, uint32_t height) -> void
|
||||||
@@ -318,6 +372,71 @@ auto Application::create_swapchain(uint32_t width, uint32_t height) -> void
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto Application::create_draw_image(uint32_t width, uint32_t height) -> void
|
||||||
|
{
|
||||||
|
destroy_draw_image();
|
||||||
|
|
||||||
|
m_vk.draw_image.format = VK_FORMAT_R16G16B16A16_SFLOAT;
|
||||||
|
m_vk.draw_image.extent = {
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
1,
|
||||||
|
};
|
||||||
|
|
||||||
|
VkImageCreateInfo rimg_ci { vkinit::image_create_info(
|
||||||
|
m_vk.draw_image.format,
|
||||||
|
VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT
|
||||||
|
| VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
|
||||||
|
m_vk.draw_image.extent) };
|
||||||
|
VmaAllocationCreateInfo rimg_alloci {};
|
||||||
|
rimg_alloci.usage = VMA_MEMORY_USAGE_GPU_ONLY;
|
||||||
|
rimg_alloci.requiredFlags
|
||||||
|
= VkMemoryPropertyFlags(VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
|
||||||
|
|
||||||
|
vmaCreateImage(m_vk.allocator, &rimg_ci, &rimg_alloci,
|
||||||
|
&m_vk.draw_image.image, &m_vk.draw_image.allocation, nullptr);
|
||||||
|
|
||||||
|
VkImageViewCreateInfo rview_ci
|
||||||
|
= vkinit::imageview_create_info(m_vk.draw_image.format,
|
||||||
|
m_vk.draw_image.image, VK_IMAGE_ASPECT_COLOR_BIT);
|
||||||
|
VK_CHECK(m_logger,
|
||||||
|
vkCreateImageView(
|
||||||
|
m_vkb.dev, &rview_ci, nullptr, &m_vk.draw_image.image_view));
|
||||||
|
}
|
||||||
|
|
||||||
|
auto Application::destroy_draw_image() -> void
|
||||||
|
{
|
||||||
|
if (m_vk.draw_image.image_view != VK_NULL_HANDLE) {
|
||||||
|
vkDestroyImageView(m_vkb.dev, m_vk.draw_image.image_view, nullptr);
|
||||||
|
m_vk.draw_image.image_view = VK_NULL_HANDLE;
|
||||||
|
}
|
||||||
|
if (m_vk.draw_image.image != VK_NULL_HANDLE) {
|
||||||
|
vmaDestroyImage(
|
||||||
|
m_vk.allocator, m_vk.draw_image.image, m_vk.draw_image.allocation);
|
||||||
|
m_vk.draw_image.image = VK_NULL_HANDLE;
|
||||||
|
m_vk.draw_image.allocation = nullptr;
|
||||||
|
}
|
||||||
|
m_vk.draw_image.extent = { 0, 0, 0 };
|
||||||
|
}
|
||||||
|
|
||||||
|
auto Application::recreate_swapchain(uint32_t width, uint32_t height) -> void
|
||||||
|
{
|
||||||
|
vkDeviceWaitIdle(m_vkb.dev);
|
||||||
|
|
||||||
|
if (width == 0 || height == 0) {
|
||||||
|
destroy_swapchain();
|
||||||
|
destroy_draw_image();
|
||||||
|
m_vk.swapchain_extent = { 0, 0 };
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
destroy_swapchain();
|
||||||
|
destroy_draw_image();
|
||||||
|
|
||||||
|
create_swapchain(width, height);
|
||||||
|
create_draw_image(width, height);
|
||||||
|
}
|
||||||
|
|
||||||
auto Application::destroy_swapchain() -> void
|
auto Application::destroy_swapchain() -> void
|
||||||
{
|
{
|
||||||
if (m_vk.swapchain == VK_NULL_HANDLE)
|
if (m_vk.swapchain == VK_NULL_HANDLE)
|
||||||
@@ -335,6 +454,7 @@ auto Application::destroy_swapchain() -> void
|
|||||||
m_vk.swapchain_image_views.clear();
|
m_vk.swapchain_image_views.clear();
|
||||||
m_vk.swapchain_images.clear();
|
m_vk.swapchain_images.clear();
|
||||||
m_vk.present_semaphores.clear();
|
m_vk.present_semaphores.clear();
|
||||||
|
m_vk.swapchain_extent = { 0, 0 };
|
||||||
}
|
}
|
||||||
|
|
||||||
Application::~Application()
|
Application::~Application()
|
||||||
@@ -346,9 +466,14 @@ Application::~Application()
|
|||||||
|
|
||||||
vkDestroyFence(m_vkb.dev, frame_data.render_fence, nullptr);
|
vkDestroyFence(m_vkb.dev, frame_data.render_fence, nullptr);
|
||||||
vkDestroySemaphore(m_vkb.dev, frame_data.swapchain_semaphore, nullptr);
|
vkDestroySemaphore(m_vkb.dev, frame_data.swapchain_semaphore, nullptr);
|
||||||
|
|
||||||
|
frame_data.deletion_queue.flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
destroy_swapchain();
|
destroy_swapchain();
|
||||||
|
destroy_draw_image();
|
||||||
|
|
||||||
|
m_vk.deletion_queue.flush();
|
||||||
|
|
||||||
SDL_Vulkan_DestroySurface(m_vkb.instance, m_vk.surface, nullptr);
|
SDL_Vulkan_DestroySurface(m_vkb.instance, m_vk.surface, nullptr);
|
||||||
SDL_DestroyWindow(m_window);
|
SDL_DestroyWindow(m_window);
|
||||||
@@ -366,8 +491,14 @@ auto Application::run() -> void
|
|||||||
|
|
||||||
while (m_running) {
|
while (m_running) {
|
||||||
while (SDL_PollEvent(&e)) {
|
while (SDL_PollEvent(&e)) {
|
||||||
if (e.type == SDL_EVENT_QUIT)
|
if (e.type == SDL_EVENT_QUIT) {
|
||||||
m_running = false;
|
m_running = false;
|
||||||
|
} else if (e.type == SDL_EVENT_WINDOW_RESIZED) {
|
||||||
|
int width {}, height {};
|
||||||
|
SDL_GetWindowSize(m_window, &width, &height);
|
||||||
|
recreate_swapchain(
|
||||||
|
static_cast<uint32_t>(width), static_cast<uint32_t>(height));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
render();
|
render();
|
||||||
|
|||||||
@@ -4,9 +4,12 @@
|
|||||||
|
|
||||||
#include <SDL3/SDL_video.h>
|
#include <SDL3/SDL_video.h>
|
||||||
#include <VkBootstrap.h>
|
#include <VkBootstrap.h>
|
||||||
|
#include <vk_mem_alloc.h>
|
||||||
#include <vulkan/vulkan_core.h>
|
#include <vulkan/vulkan_core.h>
|
||||||
|
|
||||||
#include "src/Logger.h"
|
#include "AllocatedImage.h"
|
||||||
|
#include "DeletionQueue.h"
|
||||||
|
#include "Logger.h"
|
||||||
|
|
||||||
namespace Lunar {
|
namespace Lunar {
|
||||||
|
|
||||||
@@ -15,6 +18,8 @@ struct FrameData {
|
|||||||
VkCommandBuffer main_command_buffer;
|
VkCommandBuffer main_command_buffer;
|
||||||
VkSemaphore swapchain_semaphore;
|
VkSemaphore swapchain_semaphore;
|
||||||
VkFence render_fence;
|
VkFence render_fence;
|
||||||
|
|
||||||
|
DeletionQueue deletion_queue;
|
||||||
};
|
};
|
||||||
|
|
||||||
constexpr unsigned FRAME_OVERLAP = 2;
|
constexpr unsigned FRAME_OVERLAP = 2;
|
||||||
@@ -31,9 +36,13 @@ private:
|
|||||||
auto commands_init() -> void;
|
auto commands_init() -> void;
|
||||||
auto sync_init() -> void;
|
auto sync_init() -> void;
|
||||||
|
|
||||||
|
auto draw_background(VkCommandBuffer cmd) -> void;
|
||||||
auto render() -> void;
|
auto render() -> void;
|
||||||
|
|
||||||
auto create_swapchain(uint32_t width, uint32_t height) -> void;
|
auto create_swapchain(uint32_t width, uint32_t height) -> void;
|
||||||
|
auto create_draw_image(uint32_t width, uint32_t height) -> void;
|
||||||
|
auto destroy_draw_image() -> void;
|
||||||
|
auto recreate_swapchain(uint32_t width, uint32_t height) -> void;
|
||||||
auto destroy_swapchain() -> void;
|
auto destroy_swapchain() -> void;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
@@ -62,6 +71,13 @@ private:
|
|||||||
return frames.at(frame_number % frames.size());
|
return frames.at(frame_number % frames.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AllocatedImage draw_image {};
|
||||||
|
VkExtent2D draw_extent {};
|
||||||
|
|
||||||
|
VmaAllocator allocator;
|
||||||
|
|
||||||
|
DeletionQueue deletion_queue;
|
||||||
|
|
||||||
uint64_t frame_number { 0 };
|
uint64_t frame_number { 0 };
|
||||||
} m_vk;
|
} m_vk;
|
||||||
|
|
||||||
|
|||||||
25
src/DeletionQueue.h
Normal file
25
src/DeletionQueue.h
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <deque>
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
|
namespace Lunar {
|
||||||
|
|
||||||
|
struct DeletionQueue {
|
||||||
|
std::deque<std::function<void()>> deletors;
|
||||||
|
|
||||||
|
auto emplace(std::function<void()> &&fn) -> void
|
||||||
|
{
|
||||||
|
deletors.emplace_back(fn);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto flush() -> void
|
||||||
|
{
|
||||||
|
for (auto it = deletors.rbegin(); it != deletors.rend(); it++) {
|
||||||
|
(*it)();
|
||||||
|
}
|
||||||
|
deletors.clear();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Lunar
|
||||||
2
src/Impls.cpp
Normal file
2
src/Impls.cpp
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
#define VMA_IMPLEMENTATION
|
||||||
|
#include <vk_mem_alloc.h>
|
||||||
92
src/Util.cpp
92
src/Util.cpp
@@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
namespace vkutil {
|
namespace vkutil {
|
||||||
|
|
||||||
void transition_image(VkCommandBuffer cmd, VkImage image,
|
auto transition_image(VkCommandBuffer cmd, VkImage image,
|
||||||
VkImageLayout current_layout, VkImageLayout new_layout)
|
VkImageLayout current_layout, VkImageLayout new_layout) -> void
|
||||||
{
|
{
|
||||||
VkImageAspectFlags aspect_mask
|
VkImageAspectFlags aspect_mask
|
||||||
= (new_layout == VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL)
|
= (new_layout == VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL)
|
||||||
@@ -31,10 +31,94 @@ void transition_image(VkCommandBuffer cmd, VkImage image,
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
vkCmdPipelineBarrier(cmd,
|
vkCmdPipelineBarrier(cmd, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
|
||||||
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
|
|
||||||
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0, nullptr, 0, nullptr, 1,
|
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0, nullptr, 0, nullptr, 1,
|
||||||
&image_barrier);
|
&image_barrier);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto copy_image_to_image(VkCommandBuffer cmd, VkImage source,
|
||||||
|
VkImage destination, VkExtent2D src_size, VkExtent2D dst_size) -> void
|
||||||
|
{
|
||||||
|
VkImageBlit2 blit_region {};
|
||||||
|
blit_region.sType = VK_STRUCTURE_TYPE_IMAGE_BLIT_2;
|
||||||
|
blit_region.pNext = nullptr;
|
||||||
|
|
||||||
|
blit_region.srcOffsets[0] = { 0, 0, 0 };
|
||||||
|
blit_region.srcOffsets[1] = { static_cast<int32_t>(src_size.width),
|
||||||
|
static_cast<int32_t>(src_size.height), 1 };
|
||||||
|
|
||||||
|
blit_region.dstOffsets[0] = { 0, 0, 0 };
|
||||||
|
blit_region.dstOffsets[1] = { static_cast<int32_t>(dst_size.width),
|
||||||
|
static_cast<int32_t>(dst_size.height), 1 };
|
||||||
|
|
||||||
|
blit_region.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||||
|
blit_region.srcSubresource.baseArrayLayer = 0;
|
||||||
|
blit_region.srcSubresource.layerCount = 1;
|
||||||
|
blit_region.srcSubresource.mipLevel = 0;
|
||||||
|
|
||||||
|
blit_region.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||||
|
blit_region.dstSubresource.baseArrayLayer = 0;
|
||||||
|
blit_region.dstSubresource.layerCount = 1;
|
||||||
|
blit_region.dstSubresource.mipLevel = 0;
|
||||||
|
|
||||||
|
VkBlitImageInfo2 blit_info {};
|
||||||
|
blit_info.sType = VK_STRUCTURE_TYPE_BLIT_IMAGE_INFO_2;
|
||||||
|
blit_info.pNext = nullptr;
|
||||||
|
blit_info.dstImage = destination;
|
||||||
|
blit_info.dstImageLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
|
||||||
|
blit_info.srcImage = source;
|
||||||
|
blit_info.srcImageLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
|
||||||
|
blit_info.filter = VK_FILTER_LINEAR;
|
||||||
|
blit_info.regionCount = 1;
|
||||||
|
blit_info.pRegions = &blit_region;
|
||||||
|
|
||||||
|
vkCmdBlitImage2(cmd, &blit_info);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace vkutil
|
} // namespace vkutil
|
||||||
|
|
||||||
|
namespace vkinit {
|
||||||
|
|
||||||
|
auto image_create_info(VkFormat format, VkImageUsageFlags usage_flags,
|
||||||
|
VkExtent3D extent) -> VkImageCreateInfo
|
||||||
|
{
|
||||||
|
VkImageCreateInfo info = {};
|
||||||
|
info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
|
||||||
|
info.pNext = nullptr;
|
||||||
|
|
||||||
|
info.imageType = VK_IMAGE_TYPE_2D;
|
||||||
|
|
||||||
|
info.format = format;
|
||||||
|
info.extent = extent;
|
||||||
|
|
||||||
|
info.mipLevels = 1;
|
||||||
|
info.arrayLayers = 1;
|
||||||
|
|
||||||
|
info.samples = VK_SAMPLE_COUNT_1_BIT;
|
||||||
|
|
||||||
|
info.tiling = VK_IMAGE_TILING_OPTIMAL;
|
||||||
|
info.usage = usage_flags;
|
||||||
|
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto imageview_create_info(VkFormat format, VkImage image,
|
||||||
|
VkImageAspectFlags aspect_flags) -> VkImageViewCreateInfo
|
||||||
|
{
|
||||||
|
VkImageViewCreateInfo info = {};
|
||||||
|
info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
|
||||||
|
info.pNext = nullptr;
|
||||||
|
|
||||||
|
info.viewType = VK_IMAGE_VIEW_TYPE_2D;
|
||||||
|
info.image = image;
|
||||||
|
info.format = format;
|
||||||
|
info.subresourceRange.baseMipLevel = 0;
|
||||||
|
info.subresourceRange.levelCount = 1;
|
||||||
|
info.subresourceRange.baseArrayLayer = 0;
|
||||||
|
info.subresourceRange.layerCount = 1;
|
||||||
|
info.subresourceRange.aspectMask = aspect_flags;
|
||||||
|
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace vkinit
|
||||||
|
|||||||
15
src/Util.h
15
src/Util.h
@@ -40,7 +40,18 @@ template<typename F> privDefer<F> defer_func(F f) { return privDefer<F>(f); }
|
|||||||
|
|
||||||
namespace vkutil {
|
namespace vkutil {
|
||||||
|
|
||||||
void transition_image(VkCommandBuffer cmd, VkImage image,
|
auto transition_image(VkCommandBuffer cmd, VkImage image,
|
||||||
VkImageLayout current_layout, VkImageLayout new_layout);
|
VkImageLayout current_layout, VkImageLayout new_layout) -> void;
|
||||||
|
auto copy_image_to_image(VkCommandBuffer cmd, VkImage source,
|
||||||
|
VkImage destination, VkExtent2D src_size, VkExtent2D dst_size) -> void;
|
||||||
|
|
||||||
} // namespace vkutil
|
} // namespace vkutil
|
||||||
|
|
||||||
|
namespace vkinit {
|
||||||
|
|
||||||
|
auto image_create_info(VkFormat format, VkImageUsageFlags usage_flags,
|
||||||
|
VkExtent3D extent) -> VkImageCreateInfo;
|
||||||
|
auto imageview_create_info(VkFormat format, VkImage image,
|
||||||
|
VkImageAspectFlags aspect_flags) -> VkImageViewCreateInfo;
|
||||||
|
|
||||||
|
} // namespace vkinit
|
||||||
|
|||||||
Reference in New Issue
Block a user