mirror of
https://github.com/slendidev/lunar.git
synced 2025-12-08 10:29:52 +02:00
3
.clangd
3
.clangd
@@ -1,5 +1,6 @@
|
||||
CompileFlags:
|
||||
Add: [
|
||||
"-isystem", "/nix/store/9hy16b0ba5bz0gd309rvhh119mn44f4j-libcxx-21.1.2-dev/include/c++/v1",
|
||||
"-isystem", "/nix/store/jkqdwnd0ifr3fkjif3lz003an2fhbh17-glibc-2.40-66-dev/include"
|
||||
"-isystem", "/nix/store/jkqdwnd0ifr3fkjif3lz003an2fhbh17-glibc-2.40-66-dev/include",
|
||||
"-I/nix/store/sqkna0r9zvxi7qdf8n6qckhibp1z2422-vulkan-utility-libraries-1.4.328.0/include"
|
||||
]
|
||||
|
||||
15
flake.nix
15
flake.nix
@@ -17,20 +17,22 @@
|
||||
let
|
||||
pkgs = import nixpkgs { inherit system; };
|
||||
nativeBuildInputs = with pkgs; [
|
||||
cmake
|
||||
meson
|
||||
ninja
|
||||
pkg-config
|
||||
];
|
||||
buildInputs = with pkgs; [
|
||||
vulkan-loader
|
||||
vulkan-memory-allocator
|
||||
vulkan-validation-layers
|
||||
vulkan-utility-libraries
|
||||
vk-bootstrap
|
||||
openxr-loader
|
||||
wayland
|
||||
zlib
|
||||
sdl3
|
||||
];
|
||||
buildInputs = with pkgs; [
|
||||
meson
|
||||
ninja
|
||||
pkg-config
|
||||
];
|
||||
in
|
||||
{
|
||||
devShells.default =
|
||||
@@ -62,7 +64,8 @@
|
||||
CompileFlags:
|
||||
Add: [
|
||||
"-isystem", "${pkgs.llvmPackages_21.libcxx.dev}/include/c++/v1",
|
||||
"-isystem", "${pkgs.glibc.dev}/include"
|
||||
"-isystem", "${pkgs.glibc.dev}/include",
|
||||
"-I${pkgs.vulkan-utility-libraries}/include"
|
||||
]
|
||||
EOF
|
||||
'';
|
||||
|
||||
@@ -35,6 +35,7 @@ add_project_arguments(
|
||||
exe = executable('vr-compositor',
|
||||
[
|
||||
'src/main.cpp',
|
||||
'src/Util.cpp',
|
||||
'src/Logger.cpp',
|
||||
'src/Application.cpp',
|
||||
],
|
||||
|
||||
@@ -1,19 +1,48 @@
|
||||
#include "Application.h"
|
||||
|
||||
#include <SDL3/SDL_init.h>
|
||||
#include <cmath>
|
||||
#include <iostream>
|
||||
#include <print>
|
||||
|
||||
#include <SDL3/SDL_init.h>
|
||||
#include <SDL3/SDL_video.h>
|
||||
#include <SDL3/SDL_vulkan.h>
|
||||
#include <VkBootstrap.h>
|
||||
#include <openxr/openxr.h>
|
||||
|
||||
#include "Util.h"
|
||||
#include "vulkan/vulkan_core.h"
|
||||
|
||||
namespace Lunar {
|
||||
|
||||
Application::Application()
|
||||
{
|
||||
if (!SDL_Init(SDL_INIT_VIDEO)) {
|
||||
std::println(std::cerr, "Failed to initialize SDL.");
|
||||
throw std::runtime_error("App init fail");
|
||||
}
|
||||
|
||||
m_window = SDL_CreateWindow(
|
||||
"Lunar", 1280, 720, SDL_WINDOW_VULKAN | SDL_WINDOW_RESIZABLE);
|
||||
if (!m_window) {
|
||||
m_logger.err("Failed to create SDL window");
|
||||
throw std::runtime_error("App init fail");
|
||||
}
|
||||
|
||||
vk_init();
|
||||
swapchain_init();
|
||||
commands_init();
|
||||
sync_init();
|
||||
|
||||
m_logger.info("App init done!");
|
||||
}
|
||||
|
||||
auto Application::vk_init() -> void
|
||||
{
|
||||
vkb::InstanceBuilder instance_builder {};
|
||||
instance_builder.request_validation_layers()
|
||||
instance_builder
|
||||
.enable_extension(VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME)
|
||||
.request_validation_layers()
|
||||
.set_app_name("Lunar")
|
||||
.set_engine_name("Lunar")
|
||||
.require_api_version(1, 0, 0)
|
||||
@@ -51,51 +80,279 @@ Application::Application()
|
||||
throw std::runtime_error("App init fail");
|
||||
}
|
||||
|
||||
m_vkb_instance = instance_builder_ret.value();
|
||||
|
||||
if (!SDL_Init(SDL_INIT_VIDEO)) {
|
||||
std::println(std::cerr, "Failed to initialize SDL.");
|
||||
throw std::runtime_error("App init fail");
|
||||
}
|
||||
|
||||
m_window = SDL_CreateWindow(
|
||||
"Lunar", 1280, 720, SDL_WINDOW_VULKAN | SDL_WINDOW_RESIZABLE);
|
||||
if (!m_window) {
|
||||
m_logger.err("Failed to create SDL window");
|
||||
throw std::runtime_error("App init fail");
|
||||
}
|
||||
m_vkb.instance = instance_builder_ret.value();
|
||||
|
||||
if (!SDL_Vulkan_CreateSurface(
|
||||
m_window, m_vkb_instance, nullptr, &m_vk_surface)) {
|
||||
m_window, m_vkb.instance, nullptr, &m_vk.surface)) {
|
||||
m_logger.err("Failed to create vulkan surface");
|
||||
throw std::runtime_error("App init fail");
|
||||
}
|
||||
|
||||
vkb::PhysicalDeviceSelector phys_device_selector { m_vkb_instance };
|
||||
phys_device_selector.set_surface(m_vk_surface)
|
||||
.add_required_extensions({ VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME,
|
||||
vkb::PhysicalDeviceSelector phys_device_selector { m_vkb.instance };
|
||||
phys_device_selector.set_surface(m_vk.surface)
|
||||
.add_desired_extensions({
|
||||
VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME,
|
||||
VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME,
|
||||
VK_EXT_EXTERNAL_MEMORY_DMA_BUF_EXTENSION_NAME,
|
||||
VK_EXT_QUEUE_FAMILY_FOREIGN_EXTENSION_NAME,
|
||||
VK_EXT_IMAGE_DRM_FORMAT_MODIFIER_EXTENSION_NAME,
|
||||
VK_KHR_IMAGE_FORMAT_LIST_EXTENSION_NAME });
|
||||
VK_KHR_IMAGE_FORMAT_LIST_EXTENSION_NAME,
|
||||
VK_KHR_BIND_MEMORY_2_EXTENSION_NAME,
|
||||
VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME,
|
||||
VK_KHR_MAINTENANCE1_EXTENSION_NAME,
|
||||
VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME,
|
||||
});
|
||||
auto physical_device_selector_return { phys_device_selector.select() };
|
||||
if (!physical_device_selector_return) {
|
||||
std::println(std::cerr, "Failed to find Vulkan device. Error: {}",
|
||||
std::println(std::cerr,
|
||||
"Failed to find Vulkan physical device. Error: {}",
|
||||
physical_device_selector_return.error().message());
|
||||
throw std::runtime_error("App init fail");
|
||||
}
|
||||
auto phys_device = physical_device_selector_return.value();
|
||||
m_vkb.phys_dev = physical_device_selector_return.value();
|
||||
|
||||
m_logger.info("App init done!");
|
||||
vkb::DeviceBuilder device_builder { m_vkb.phys_dev };
|
||||
auto dev_ret { device_builder.build() };
|
||||
if (!dev_ret) {
|
||||
std::println(std::cerr, "Failed to create Vulkan device. Error: {}",
|
||||
dev_ret.error().message());
|
||||
throw std::runtime_error("App init fail");
|
||||
}
|
||||
m_vkb.dev = dev_ret.value();
|
||||
|
||||
auto queue_ret { m_vkb.dev.get_queue(vkb::QueueType::graphics) };
|
||||
if (!queue_ret) {
|
||||
std::println(std::cerr, "Failed to get graphics queue. Error: {}",
|
||||
queue_ret.error().message());
|
||||
throw std::runtime_error("App init fail");
|
||||
}
|
||||
m_vk.graphics_queue = queue_ret.value();
|
||||
|
||||
auto queue_family_ret { m_vkb.dev.get_queue_index(
|
||||
vkb::QueueType::graphics) };
|
||||
if (!queue_family_ret) {
|
||||
std::println(std::cerr, "Failed to get graphics queue. Error: {}",
|
||||
queue_family_ret.error().message());
|
||||
throw std::runtime_error("App init fail");
|
||||
}
|
||||
m_vk.graphics_queue_family = queue_family_ret.value();
|
||||
}
|
||||
|
||||
auto Application::swapchain_init() -> void
|
||||
{
|
||||
int w, h;
|
||||
SDL_GetWindowSize(m_window, &w, &h);
|
||||
create_swapchain(w, h);
|
||||
}
|
||||
|
||||
auto Application::commands_init() -> void
|
||||
{
|
||||
VkCommandPoolCreateInfo ci {
|
||||
.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
|
||||
.pNext = nullptr,
|
||||
.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,
|
||||
.queueFamilyIndex = m_vk.graphics_queue_family,
|
||||
};
|
||||
for (unsigned i = 0; i < FRAME_OVERLAP; i++) {
|
||||
VK_CHECK(m_logger,
|
||||
vkCreateCommandPool(
|
||||
m_vkb.dev, &ci, nullptr, &m_vk.frames.at(i).command_pool));
|
||||
|
||||
VkCommandBufferAllocateInfo ai {
|
||||
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
|
||||
.pNext = nullptr,
|
||||
.commandPool = m_vk.frames.at(i).command_pool,
|
||||
.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
|
||||
.commandBufferCount = 1,
|
||||
};
|
||||
|
||||
VK_CHECK(m_logger,
|
||||
vkAllocateCommandBuffers(
|
||||
m_vkb.dev, &ai, &m_vk.frames.at(i).main_command_buffer));
|
||||
}
|
||||
}
|
||||
|
||||
auto Application::sync_init() -> void
|
||||
{
|
||||
VkFenceCreateInfo fence_ci {
|
||||
.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
|
||||
.pNext = nullptr,
|
||||
.flags = VK_FENCE_CREATE_SIGNALED_BIT,
|
||||
};
|
||||
VkSemaphoreCreateInfo semaphore_ci {
|
||||
.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
|
||||
.pNext = nullptr,
|
||||
.flags = 0,
|
||||
};
|
||||
for (auto &frame_data : m_vk.frames) {
|
||||
VK_CHECK(m_logger,
|
||||
vkCreateFence(
|
||||
m_vkb.dev, &fence_ci, nullptr, &frame_data.render_fence));
|
||||
|
||||
VK_CHECK(m_logger,
|
||||
vkCreateSemaphore(m_vkb.dev, &semaphore_ci, nullptr,
|
||||
&frame_data.swapchain_semaphore));
|
||||
}
|
||||
}
|
||||
|
||||
auto Application::render() -> void
|
||||
{
|
||||
defer(m_vk.frame_number++);
|
||||
|
||||
VK_CHECK(m_logger,
|
||||
vkWaitForFences(m_vkb.dev, 1, &m_vk.get_current_frame().render_fence,
|
||||
true, 1'000'000'000));
|
||||
VK_CHECK(m_logger,
|
||||
vkResetFences(m_vkb.dev, 1, &m_vk.get_current_frame().render_fence));
|
||||
|
||||
uint32_t swapchain_image_idx;
|
||||
VK_CHECK(m_logger,
|
||||
vkAcquireNextImageKHR(m_vkb.dev, m_vk.swapchain, 1000000000,
|
||||
m_vk.get_current_frame().swapchain_semaphore, nullptr,
|
||||
&swapchain_image_idx));
|
||||
|
||||
auto cmd { m_vk.get_current_frame().main_command_buffer };
|
||||
VK_CHECK(m_logger, vkResetCommandBuffer(cmd, 0));
|
||||
VkCommandBufferBeginInfo cmd_begin_info {
|
||||
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
|
||||
.pNext = nullptr,
|
||||
.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
|
||||
.pInheritanceInfo = nullptr,
|
||||
};
|
||||
VK_CHECK(m_logger, vkBeginCommandBuffer(cmd, &cmd_begin_info));
|
||||
|
||||
vkutil::transition_image(cmd, m_vk.swapchain_images.at(swapchain_image_idx),
|
||||
VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL);
|
||||
|
||||
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.swapchain_images[swapchain_image_idx],
|
||||
VK_IMAGE_LAYOUT_GENERAL, &clear_value, 1, &clear_range);
|
||||
|
||||
vkutil::transition_image(cmd, m_vk.swapchain_images[swapchain_image_idx],
|
||||
VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);
|
||||
|
||||
VK_CHECK(m_logger, vkEndCommandBuffer(cmd));
|
||||
|
||||
VkSemaphore render_semaphore
|
||||
= m_vk.present_semaphores.at(swapchain_image_idx);
|
||||
VkPipelineStageFlags wait_stage
|
||||
= VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
||||
VkSubmitInfo submit_info {
|
||||
.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
|
||||
.pNext = nullptr,
|
||||
.waitSemaphoreCount = 1,
|
||||
.pWaitSemaphores = &m_vk.get_current_frame().swapchain_semaphore,
|
||||
.pWaitDstStageMask = &wait_stage,
|
||||
.commandBufferCount = 1,
|
||||
.pCommandBuffers = &cmd,
|
||||
.signalSemaphoreCount = 1,
|
||||
.pSignalSemaphores = &render_semaphore,
|
||||
};
|
||||
|
||||
VK_CHECK(m_logger,
|
||||
vkQueueSubmit(m_vk.graphics_queue, 1, &submit_info,
|
||||
m_vk.get_current_frame().render_fence));
|
||||
|
||||
VkPresentInfoKHR present_info = {};
|
||||
present_info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
|
||||
present_info.pNext = nullptr;
|
||||
present_info.pSwapchains = &m_vk.swapchain;
|
||||
present_info.swapchainCount = 1;
|
||||
|
||||
present_info.pWaitSemaphores = &render_semaphore;
|
||||
present_info.waitSemaphoreCount = 1;
|
||||
|
||||
present_info.pImageIndices = &swapchain_image_idx;
|
||||
|
||||
VK_CHECK(m_logger, vkQueuePresentKHR(m_vk.graphics_queue, &present_info));
|
||||
}
|
||||
|
||||
auto Application::create_swapchain(uint32_t width, uint32_t height) -> void
|
||||
{
|
||||
vkb::SwapchainBuilder builder { m_vkb.phys_dev, m_vkb.dev, m_vk.surface };
|
||||
m_vk.swapchain_image_format = VK_FORMAT_B8G8R8A8_UNORM;
|
||||
auto const swapchain_ret { builder
|
||||
.set_desired_format({
|
||||
.format = m_vk.swapchain_image_format,
|
||||
.colorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR,
|
||||
})
|
||||
.set_desired_present_mode(VK_PRESENT_MODE_FIFO_KHR)
|
||||
.set_desired_extent(width, height)
|
||||
.add_image_usage_flags(VK_IMAGE_USAGE_TRANSFER_DST_BIT)
|
||||
.build() };
|
||||
if (!swapchain_ret) {
|
||||
std::println(std::cerr, "Failed to create swapchain. Error: {}",
|
||||
swapchain_ret.error().message());
|
||||
throw std::runtime_error("App init fail");
|
||||
}
|
||||
m_vkb.swapchain = swapchain_ret.value();
|
||||
|
||||
m_vk.swapchain = m_vkb.swapchain.swapchain;
|
||||
m_vk.swapchain_extent = m_vkb.swapchain.extent;
|
||||
m_vk.swapchain_images = m_vkb.swapchain.get_images().value();
|
||||
m_vk.swapchain_image_views = m_vkb.swapchain.get_image_views().value();
|
||||
|
||||
VkSemaphoreCreateInfo semaphore_ci {
|
||||
.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
|
||||
.pNext = nullptr,
|
||||
.flags = 0,
|
||||
};
|
||||
m_vk.present_semaphores.resize(m_vk.swapchain_images.size());
|
||||
for (auto &semaphore : m_vk.present_semaphores) {
|
||||
VK_CHECK(m_logger,
|
||||
vkCreateSemaphore(m_vkb.dev, &semaphore_ci, nullptr, &semaphore));
|
||||
}
|
||||
}
|
||||
|
||||
auto Application::destroy_swapchain() -> void
|
||||
{
|
||||
if (m_vk.swapchain == VK_NULL_HANDLE)
|
||||
return;
|
||||
|
||||
for (auto const semaphore : m_vk.present_semaphores) {
|
||||
vkDestroySemaphore(m_vkb.dev, semaphore, nullptr);
|
||||
}
|
||||
for (auto const &iv : m_vk.swapchain_image_views) {
|
||||
vkDestroyImageView(m_vkb.dev, iv, nullptr);
|
||||
}
|
||||
vkDestroySwapchainKHR(m_vkb.dev, m_vk.swapchain, nullptr);
|
||||
|
||||
m_vk.swapchain = VK_NULL_HANDLE;
|
||||
m_vk.swapchain_image_views.clear();
|
||||
m_vk.swapchain_images.clear();
|
||||
m_vk.present_semaphores.clear();
|
||||
}
|
||||
|
||||
Application::~Application()
|
||||
{
|
||||
SDL_Vulkan_DestroySurface(m_vkb_instance, m_vk_surface, nullptr);
|
||||
vkDeviceWaitIdle(m_vkb.dev);
|
||||
|
||||
for (auto &frame_data : m_vk.frames) {
|
||||
vkDestroyCommandPool(m_vkb.dev, frame_data.command_pool, nullptr);
|
||||
|
||||
vkDestroyFence(m_vkb.dev, frame_data.render_fence, nullptr);
|
||||
vkDestroySemaphore(m_vkb.dev, frame_data.swapchain_semaphore, nullptr);
|
||||
}
|
||||
|
||||
destroy_swapchain();
|
||||
|
||||
SDL_Vulkan_DestroySurface(m_vkb.instance, m_vk.surface, nullptr);
|
||||
SDL_DestroyWindow(m_window);
|
||||
SDL_Quit();
|
||||
|
||||
vkb::destroy_instance(m_vkb_instance);
|
||||
vkb::destroy_device(m_vkb.dev);
|
||||
vkb::destroy_instance(m_vkb.instance);
|
||||
|
||||
m_logger.info("App destroy done!");
|
||||
}
|
||||
@@ -109,7 +366,8 @@ auto Application::run() -> void
|
||||
if (e.type == SDL_EVENT_QUIT)
|
||||
m_running = false;
|
||||
}
|
||||
// nothing else
|
||||
|
||||
render();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <SDL3/SDL_video.h>
|
||||
#include <VkBootstrap.h>
|
||||
#include <vulkan/vulkan_core.h>
|
||||
@@ -8,6 +10,15 @@
|
||||
|
||||
namespace Lunar {
|
||||
|
||||
struct FrameData {
|
||||
VkCommandPool command_pool;
|
||||
VkCommandBuffer main_command_buffer;
|
||||
VkSemaphore swapchain_semaphore;
|
||||
VkFence render_fence;
|
||||
};
|
||||
|
||||
constexpr unsigned FRAME_OVERLAP = 2;
|
||||
|
||||
struct Application {
|
||||
Application();
|
||||
~Application();
|
||||
@@ -15,8 +26,45 @@ struct Application {
|
||||
auto run() -> void;
|
||||
|
||||
private:
|
||||
vkb::Instance m_vkb_instance;
|
||||
VkSurfaceKHR m_vk_surface { nullptr };
|
||||
auto vk_init() -> void;
|
||||
auto swapchain_init() -> void;
|
||||
auto commands_init() -> void;
|
||||
auto sync_init() -> void;
|
||||
|
||||
auto render() -> void;
|
||||
|
||||
auto create_swapchain(uint32_t width, uint32_t height) -> void;
|
||||
auto destroy_swapchain() -> void;
|
||||
|
||||
struct {
|
||||
vkb::Instance instance;
|
||||
vkb::PhysicalDevice phys_dev;
|
||||
vkb::Device dev;
|
||||
vkb::Swapchain swapchain;
|
||||
} m_vkb;
|
||||
|
||||
struct {
|
||||
VkSwapchainKHR swapchain { VK_NULL_HANDLE };
|
||||
VkFormat swapchain_image_format;
|
||||
VkSurfaceKHR surface { nullptr };
|
||||
|
||||
VkQueue graphics_queue { nullptr };
|
||||
uint32_t graphics_queue_family { 0 };
|
||||
|
||||
std::vector<VkImage> swapchain_images;
|
||||
std::vector<VkImageView> swapchain_image_views;
|
||||
std::vector<VkSemaphore> present_semaphores;
|
||||
VkExtent2D swapchain_extent;
|
||||
|
||||
std::array<FrameData, FRAME_OVERLAP> frames;
|
||||
auto get_current_frame() -> FrameData &
|
||||
{
|
||||
return frames.at(frame_number % frames.size());
|
||||
}
|
||||
|
||||
uint64_t frame_number { 0 };
|
||||
} m_vk;
|
||||
|
||||
SDL_Window *m_window { nullptr };
|
||||
Logger m_logger { "Lunar" };
|
||||
|
||||
|
||||
40
src/Util.cpp
Normal file
40
src/Util.cpp
Normal file
@@ -0,0 +1,40 @@
|
||||
#include "Util.h"
|
||||
|
||||
namespace vkutil {
|
||||
|
||||
void transition_image(VkCommandBuffer cmd, VkImage image,
|
||||
VkImageLayout current_layout, VkImageLayout new_layout)
|
||||
{
|
||||
VkImageAspectFlags aspect_mask
|
||||
= (new_layout == VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL)
|
||||
? VK_IMAGE_ASPECT_DEPTH_BIT
|
||||
: VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
|
||||
VkImageMemoryBarrier image_barrier {
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
|
||||
.pNext = nullptr,
|
||||
|
||||
.srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT,
|
||||
.dstAccessMask
|
||||
= VK_ACCESS_MEMORY_WRITE_BIT | VK_ACCESS_MEMORY_READ_BIT,
|
||||
.oldLayout = current_layout,
|
||||
.newLayout = new_layout,
|
||||
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.image = image,
|
||||
.subresourceRange = {
|
||||
.aspectMask = aspect_mask,
|
||||
.baseMipLevel = 0,
|
||||
.levelCount = 1,
|
||||
.baseArrayLayer = 0,
|
||||
.layerCount = 1,
|
||||
},
|
||||
};
|
||||
|
||||
vkCmdPipelineBarrier(cmd,
|
||||
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
|
||||
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0, nullptr, 0, nullptr, 1,
|
||||
&image_barrier);
|
||||
}
|
||||
|
||||
} // namespace vkutil
|
||||
20
src/Util.h
20
src/Util.h
@@ -1,6 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include <string_view>
|
||||
|
||||
#include <vulkan/vk_enum_string_helper.h>
|
||||
#include <vulkan/vulkan.h>
|
||||
|
||||
using namespace std::string_view_literals;
|
||||
|
||||
template<typename F> struct privDefer {
|
||||
@@ -24,3 +28,19 @@ template<typename F> privDefer<F> defer_func(F f) { return privDefer<F>(f); }
|
||||
#else
|
||||
# define ALIGN(a) __attribute__((aligned(a)))
|
||||
#endif
|
||||
|
||||
#define VK_CHECK(logger, x) \
|
||||
do { \
|
||||
VkResult err { x }; \
|
||||
if (err) { \
|
||||
(logger).err("Detected Vulkan error: {}", string_VkResult(err)); \
|
||||
throw std::runtime_error("Vulkan error"); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
namespace vkutil {
|
||||
|
||||
void transition_image(VkCommandBuffer cmd, VkImage image,
|
||||
VkImageLayout current_layout, VkImageLayout new_layout);
|
||||
|
||||
} // namespace vkutil
|
||||
|
||||
Reference in New Issue
Block a user