mirror of
https://github.com/slendidev/lunar.git
synced 2026-01-30 16:28:58 +02:00
Compare commits
2 Commits
402cdd43da
...
5ca02ed9e2
| Author | SHA1 | Date | |
|---|---|---|---|
| 5ca02ed9e2 | |||
| 9f2dab344d |
File diff suppressed because it is too large
Load Diff
@@ -3,11 +3,15 @@
|
|||||||
#include <array>
|
#include <array>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
|
#include <functional>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include <SDL3/SDL_video.h>
|
#include <SDL3/SDL_video.h>
|
||||||
#include <imgui.h>
|
#include <imgui.h>
|
||||||
#include <linux/input-event-codes.h>
|
#include <linux/input-event-codes.h>
|
||||||
|
#include <openxr/openxr.h>
|
||||||
|
|
||||||
#include "Loader.h"
|
#include "Loader.h"
|
||||||
#include "Logger.h"
|
#include "Logger.h"
|
||||||
@@ -22,6 +26,7 @@ struct udev;
|
|||||||
namespace Lunar {
|
namespace Lunar {
|
||||||
|
|
||||||
struct VulkanRenderer;
|
struct VulkanRenderer;
|
||||||
|
struct OpenXrState;
|
||||||
|
|
||||||
struct Application {
|
struct Application {
|
||||||
auto run() -> void;
|
auto run() -> void;
|
||||||
@@ -38,6 +43,11 @@ struct Application {
|
|||||||
static auto the() -> Application &;
|
static auto the() -> Application &;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
enum class Backend {
|
||||||
|
SDL,
|
||||||
|
KMS,
|
||||||
|
};
|
||||||
|
|
||||||
Application();
|
Application();
|
||||||
~Application();
|
~Application();
|
||||||
|
|
||||||
@@ -47,9 +57,25 @@ private:
|
|||||||
auto shutdown_input() -> void;
|
auto shutdown_input() -> void;
|
||||||
auto process_libinput_events() -> void;
|
auto process_libinput_events() -> void;
|
||||||
auto handle_keyboard_event(libinput_event_keyboard *event) -> void;
|
auto handle_keyboard_event(libinput_event_keyboard *event) -> void;
|
||||||
|
auto handle_pointer_motion(libinput_event_pointer *event) -> void;
|
||||||
|
auto handle_pointer_button(libinput_event_pointer *event) -> void;
|
||||||
|
auto handle_pointer_axis(libinput_event_pointer *event) -> void;
|
||||||
|
auto handle_pointer_frame() -> void;
|
||||||
|
auto handle_pointer_end_frame() -> void;
|
||||||
|
auto handle_pointer_cancel() -> void;
|
||||||
|
auto handle_keyboard_key(std::optional<uint32_t> key, bool pressed) -> void;
|
||||||
auto clamp_mouse_to_window(int width, int height) -> void;
|
auto clamp_mouse_to_window(int width, int height) -> void;
|
||||||
|
auto init_openxr() -> void;
|
||||||
|
auto init_openxr_session() -> void;
|
||||||
|
auto shutdown_openxr() -> void;
|
||||||
|
auto poll_openxr_events() -> void;
|
||||||
|
auto render_openxr_frame(
|
||||||
|
std::function<void(VulkanRenderer::GL &)> const &record,
|
||||||
|
float dt_seconds) -> bool;
|
||||||
|
auto update_camera_from_xr_view(XrView const &view) -> void;
|
||||||
|
|
||||||
SDL_Window *m_window { nullptr };
|
SDL_Window *m_window { nullptr };
|
||||||
|
Backend m_backend { Backend::SDL };
|
||||||
Logger m_logger { "Lunar" };
|
Logger m_logger { "Lunar" };
|
||||||
std::unique_ptr<VulkanRenderer> m_renderer;
|
std::unique_ptr<VulkanRenderer> m_renderer;
|
||||||
Skybox m_skybox;
|
Skybox m_skybox;
|
||||||
@@ -58,6 +84,8 @@ private:
|
|||||||
udev *m_udev { nullptr };
|
udev *m_udev { nullptr };
|
||||||
libinput *m_libinput { nullptr };
|
libinput *m_libinput { nullptr };
|
||||||
|
|
||||||
|
std::unique_ptr<OpenXrState> m_openxr {};
|
||||||
|
|
||||||
bool m_running { true };
|
bool m_running { true };
|
||||||
bool m_mouse_captured { false };
|
bool m_mouse_captured { false };
|
||||||
bool m_show_imgui { false };
|
bool m_show_imgui { false };
|
||||||
|
|||||||
@@ -611,15 +611,24 @@ auto VulkanRenderer::GL::bind_pipeline_if_needed() -> void
|
|||||||
vk::PipelineBindPoint::eGraphics, m_active_pipeline->get());
|
vk::PipelineBindPoint::eGraphics, m_active_pipeline->get());
|
||||||
}
|
}
|
||||||
|
|
||||||
VulkanRenderer::VulkanRenderer(SDL_Window *window, Logger &logger)
|
VulkanRenderer::VulkanRenderer(SDL_Window *window, Logger &logger,
|
||||||
|
std::span<std::string const> instance_extensions,
|
||||||
|
std::span<std::string const> device_extensions)
|
||||||
: gl(*this)
|
: gl(*this)
|
||||||
, m_window(window)
|
, m_window(window)
|
||||||
, m_logger(logger)
|
, m_logger(logger)
|
||||||
|
, m_extra_instance_extensions(
|
||||||
|
instance_extensions.begin(), instance_extensions.end())
|
||||||
|
, m_extra_device_extensions(
|
||||||
|
device_extensions.begin(), device_extensions.end())
|
||||||
{
|
{
|
||||||
if (m_window == nullptr) {
|
if (m_window == nullptr) {
|
||||||
throw std::runtime_error("VulkanRenderer requires a valid window");
|
throw std::runtime_error("VulkanRenderer requires a valid window");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_use_kms = false;
|
||||||
|
m_imgui_enabled = true;
|
||||||
|
|
||||||
vk_init();
|
vk_init();
|
||||||
swapchain_init();
|
swapchain_init();
|
||||||
commands_init();
|
commands_init();
|
||||||
@@ -630,6 +639,28 @@ VulkanRenderer::VulkanRenderer(SDL_Window *window, Logger &logger)
|
|||||||
imgui_init();
|
imgui_init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VulkanRenderer::VulkanRenderer(KmsSurfaceConfig /*config*/, Logger &logger,
|
||||||
|
std::span<std::string const> instance_extensions,
|
||||||
|
std::span<std::string const> device_extensions)
|
||||||
|
: gl(*this)
|
||||||
|
, m_logger(logger)
|
||||||
|
, m_extra_instance_extensions(
|
||||||
|
instance_extensions.begin(), instance_extensions.end())
|
||||||
|
, m_extra_device_extensions(
|
||||||
|
device_extensions.begin(), device_extensions.end())
|
||||||
|
{
|
||||||
|
m_use_kms = true;
|
||||||
|
m_imgui_enabled = false;
|
||||||
|
|
||||||
|
vk_init();
|
||||||
|
swapchain_init();
|
||||||
|
commands_init();
|
||||||
|
sync_init();
|
||||||
|
descriptors_init();
|
||||||
|
pipelines_init();
|
||||||
|
default_data_init();
|
||||||
|
}
|
||||||
|
|
||||||
VulkanRenderer::~VulkanRenderer()
|
VulkanRenderer::~VulkanRenderer()
|
||||||
{
|
{
|
||||||
m_device.waitIdle();
|
m_device.waitIdle();
|
||||||
@@ -671,8 +702,12 @@ VulkanRenderer::~VulkanRenderer()
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (m_vk.surface) {
|
if (m_vk.surface) {
|
||||||
SDL_Vulkan_DestroySurface(
|
if (m_use_kms) {
|
||||||
m_vkb.instance, static_cast<VkSurfaceKHR>(m_vk.surface), nullptr);
|
m_instance.destroySurfaceKHR(m_vk.surface);
|
||||||
|
} else {
|
||||||
|
SDL_Vulkan_DestroySurface(m_vkb.instance,
|
||||||
|
static_cast<VkSurfaceKHR>(m_vk.surface), nullptr);
|
||||||
|
}
|
||||||
m_vk.surface = nullptr;
|
m_vk.surface = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -685,6 +720,26 @@ auto VulkanRenderer::resize(uint32_t width, uint32_t height) -> void
|
|||||||
recreate_swapchain(width, height);
|
recreate_swapchain(width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto VulkanRenderer::set_offscreen_extent(vk::Extent2D extent) -> void
|
||||||
|
{
|
||||||
|
if (extent.width == 0 || extent.height == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_vk.draw_image.extent.width == extent.width
|
||||||
|
&& m_vk.draw_image.extent.height == extent.height) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_device.waitIdle();
|
||||||
|
destroy_draw_image();
|
||||||
|
destroy_msaa_color_image();
|
||||||
|
destroy_depth_image();
|
||||||
|
create_draw_image(extent.width, extent.height);
|
||||||
|
create_msaa_color_image(extent.width, extent.height);
|
||||||
|
create_depth_image(extent.width, extent.height);
|
||||||
|
}
|
||||||
|
|
||||||
auto VulkanRenderer::set_antialiasing(AntiAliasingKind kind) -> void
|
auto VulkanRenderer::set_antialiasing(AntiAliasingKind kind) -> void
|
||||||
{
|
{
|
||||||
enqueue_render_command(RenderCommand {
|
enqueue_render_command(RenderCommand {
|
||||||
@@ -847,6 +902,107 @@ auto VulkanRenderer::immediate_submit(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto VulkanRenderer::setup_kms_surface() -> void
|
||||||
|
{
|
||||||
|
auto const devices = m_instance.enumeratePhysicalDevices();
|
||||||
|
if (devices.empty()) {
|
||||||
|
m_logger.err("No Vulkan physical devices available for KMS");
|
||||||
|
throw std::runtime_error("App init fail");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto const &device : devices) {
|
||||||
|
auto const displays = device.getDisplayPropertiesKHR();
|
||||||
|
if (displays.empty()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto const &display_props : displays) {
|
||||||
|
auto const modes
|
||||||
|
= device.getDisplayModePropertiesKHR(display_props.display);
|
||||||
|
if (modes.empty()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto const best_mode_it = std::max_element(modes.begin(),
|
||||||
|
modes.end(), [](auto const &lhs, auto const &rhs) {
|
||||||
|
auto const lhs_extent = lhs.parameters.visibleRegion;
|
||||||
|
auto const rhs_extent = rhs.parameters.visibleRegion;
|
||||||
|
auto const lhs_area
|
||||||
|
= static_cast<uint64_t>(lhs_extent.width)
|
||||||
|
* static_cast<uint64_t>(lhs_extent.height);
|
||||||
|
auto const rhs_area
|
||||||
|
= static_cast<uint64_t>(rhs_extent.width)
|
||||||
|
* static_cast<uint64_t>(rhs_extent.height);
|
||||||
|
if (lhs_area == rhs_area) {
|
||||||
|
return lhs.parameters.refreshRate
|
||||||
|
< rhs.parameters.refreshRate;
|
||||||
|
}
|
||||||
|
return lhs_area < rhs_area;
|
||||||
|
});
|
||||||
|
|
||||||
|
auto const planes = device.getDisplayPlanePropertiesKHR();
|
||||||
|
std::optional<uint32_t> plane_index;
|
||||||
|
uint32_t plane_stack_index { 0 };
|
||||||
|
for (uint32_t i = 0; i < planes.size(); ++i) {
|
||||||
|
auto const supported_displays
|
||||||
|
= device.getDisplayPlaneSupportedDisplaysKHR(i);
|
||||||
|
if (std::find(supported_displays.begin(),
|
||||||
|
supported_displays.end(), display_props.display)
|
||||||
|
!= supported_displays.end()) {
|
||||||
|
plane_index = i;
|
||||||
|
plane_stack_index = planes[i].currentStackIndex;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!plane_index) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto const extent = best_mode_it->parameters.visibleRegion;
|
||||||
|
KmsState state {};
|
||||||
|
state.display = display_props.display;
|
||||||
|
state.mode = best_mode_it->displayMode;
|
||||||
|
state.extent = extent;
|
||||||
|
state.plane_index = *plane_index;
|
||||||
|
state.plane_stack_index = plane_stack_index;
|
||||||
|
if (display_props.displayName) {
|
||||||
|
state.display_name = display_props.displayName;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_kms_state = state;
|
||||||
|
m_kms_extent = extent;
|
||||||
|
m_kms_physical_device = device;
|
||||||
|
m_kms_physical_device_set = true;
|
||||||
|
|
||||||
|
m_logger.info("Using KMS display {} ({}x{} @ {} mHz)",
|
||||||
|
state.display_name.empty() ? "unnamed" : state.display_name,
|
||||||
|
extent.width, extent.height,
|
||||||
|
best_mode_it->parameters.refreshRate);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_kms_state) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!m_kms_state) {
|
||||||
|
m_logger.err("No suitable KMS display found");
|
||||||
|
throw std::runtime_error("App init fail");
|
||||||
|
}
|
||||||
|
|
||||||
|
vk::DisplaySurfaceCreateInfoKHR surface_info {};
|
||||||
|
surface_info.displayMode = m_kms_state->mode;
|
||||||
|
surface_info.planeIndex = m_kms_state->plane_index;
|
||||||
|
surface_info.planeStackIndex = m_kms_state->plane_stack_index;
|
||||||
|
surface_info.transform = vk::SurfaceTransformFlagBitsKHR::eIdentity;
|
||||||
|
surface_info.alphaMode = vk::DisplayPlaneAlphaFlagBitsKHR::eOpaque;
|
||||||
|
surface_info.globalAlpha = 1.0f;
|
||||||
|
surface_info.imageExtent = m_kms_state->extent;
|
||||||
|
|
||||||
|
m_vk.surface = m_instance.createDisplayPlaneSurfaceKHR(surface_info);
|
||||||
|
}
|
||||||
|
|
||||||
auto VulkanRenderer::vk_init() -> void
|
auto VulkanRenderer::vk_init() -> void
|
||||||
{
|
{
|
||||||
VULKAN_HPP_DEFAULT_DISPATCHER.init(vkGetInstanceProcAddr);
|
VULKAN_HPP_DEFAULT_DISPATCHER.init(vkGetInstanceProcAddr);
|
||||||
@@ -884,6 +1040,12 @@ auto VulkanRenderer::vk_init() -> void
|
|||||||
|
|
||||||
return VK_FALSE;
|
return VK_FALSE;
|
||||||
});
|
});
|
||||||
|
if (m_use_kms) {
|
||||||
|
instance_builder.enable_extension(VK_KHR_DISPLAY_EXTENSION_NAME);
|
||||||
|
}
|
||||||
|
for (auto const &extension : m_extra_instance_extensions) {
|
||||||
|
instance_builder.enable_extension(extension.c_str());
|
||||||
|
}
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
instance_builder.request_validation_layers();
|
instance_builder.request_validation_layers();
|
||||||
#endif
|
#endif
|
||||||
@@ -898,13 +1060,17 @@ auto VulkanRenderer::vk_init() -> void
|
|||||||
m_instance = vk::Instance { m_vkb.instance.instance };
|
m_instance = vk::Instance { m_vkb.instance.instance };
|
||||||
VULKAN_HPP_DEFAULT_DISPATCHER.init(m_instance);
|
VULKAN_HPP_DEFAULT_DISPATCHER.init(m_instance);
|
||||||
|
|
||||||
VkSurfaceKHR raw_surface {};
|
if (m_use_kms) {
|
||||||
if (!SDL_Vulkan_CreateSurface(
|
setup_kms_surface();
|
||||||
m_window, m_vkb.instance, nullptr, &raw_surface)) {
|
} else {
|
||||||
m_logger.err("Failed to create vulkan surface");
|
VkSurfaceKHR raw_surface {};
|
||||||
throw std::runtime_error("App init fail");
|
if (!SDL_Vulkan_CreateSurface(
|
||||||
|
m_window, m_vkb.instance, nullptr, &raw_surface)) {
|
||||||
|
m_logger.err("Failed to create vulkan surface");
|
||||||
|
throw std::runtime_error("App init fail");
|
||||||
|
}
|
||||||
|
m_vk.surface = vk::SurfaceKHR { raw_surface };
|
||||||
}
|
}
|
||||||
m_vk.surface = vk::SurfaceKHR { raw_surface };
|
|
||||||
|
|
||||||
vkb::PhysicalDeviceSelector phys_device_selector { m_vkb.instance };
|
vkb::PhysicalDeviceSelector phys_device_selector { m_vkb.instance };
|
||||||
VkPhysicalDeviceVulkan13Features features_13 {};
|
VkPhysicalDeviceVulkan13Features features_13 {};
|
||||||
@@ -917,21 +1083,25 @@ auto VulkanRenderer::vk_init() -> void
|
|||||||
buffer_device_address_features.sType
|
buffer_device_address_features.sType
|
||||||
= VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES;
|
= VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES;
|
||||||
buffer_device_address_features.bufferDeviceAddress = VK_TRUE;
|
buffer_device_address_features.bufferDeviceAddress = VK_TRUE;
|
||||||
|
std::vector<char const *> 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_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,
|
||||||
|
VK_KHR_COPY_COMMANDS_2_EXTENSION_NAME,
|
||||||
|
VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME,
|
||||||
|
};
|
||||||
|
for (auto const &extension : m_extra_device_extensions) {
|
||||||
|
desired_extensions.push_back(extension.c_str());
|
||||||
|
}
|
||||||
phys_device_selector.set_surface(m_vk.surface)
|
phys_device_selector.set_surface(m_vk.surface)
|
||||||
.add_desired_extensions({
|
.add_desired_extensions(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_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,
|
|
||||||
VK_KHR_COPY_COMMANDS_2_EXTENSION_NAME,
|
|
||||||
VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME,
|
|
||||||
})
|
|
||||||
.set_required_features_13(features_13)
|
.set_required_features_13(features_13)
|
||||||
.add_required_extension_features(buffer_device_address_features);
|
.add_required_extension_features(buffer_device_address_features);
|
||||||
auto physical_device_selector_return { phys_device_selector.select() };
|
auto physical_device_selector_return { phys_device_selector.select() };
|
||||||
@@ -946,6 +1116,10 @@ auto VulkanRenderer::vk_init() -> void
|
|||||||
|
|
||||||
m_logger.info("Chosen Vulkan physical device: {}",
|
m_logger.info("Chosen Vulkan physical device: {}",
|
||||||
m_vkb.phys_dev.properties.deviceName);
|
m_vkb.phys_dev.properties.deviceName);
|
||||||
|
if (m_use_kms && m_kms_physical_device_set
|
||||||
|
&& m_physical_device != m_kms_physical_device) {
|
||||||
|
m_logger.warn("KMS display is not on the selected physical device");
|
||||||
|
}
|
||||||
|
|
||||||
auto const props = m_physical_device.getProperties();
|
auto const props = m_physical_device.getProperties();
|
||||||
m_vk.supported_framebuffer_samples
|
m_vk.supported_framebuffer_samples
|
||||||
@@ -974,6 +1148,13 @@ auto VulkanRenderer::vk_init() -> void
|
|||||||
}
|
}
|
||||||
m_vk.graphics_queue_family = queue_family_ret.value();
|
m_vk.graphics_queue_family = queue_family_ret.value();
|
||||||
m_vk.graphics_queue = m_device.getQueue(m_vk.graphics_queue_family, 0);
|
m_vk.graphics_queue = m_device.getQueue(m_vk.graphics_queue_family, 0);
|
||||||
|
if (m_use_kms) {
|
||||||
|
if (!m_physical_device.getSurfaceSupportKHR(
|
||||||
|
m_vk.graphics_queue_family, m_vk.surface)) {
|
||||||
|
m_logger.err("Selected device does not support KMS surface");
|
||||||
|
throw std::runtime_error("App init fail");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
VmaAllocatorCreateInfo allocator_ci {};
|
VmaAllocatorCreateInfo allocator_ci {};
|
||||||
allocator_ci.physicalDevice = m_vkb.phys_dev.physical_device;
|
allocator_ci.physicalDevice = m_vkb.phys_dev.physical_device;
|
||||||
@@ -985,12 +1166,21 @@ auto VulkanRenderer::vk_init() -> void
|
|||||||
|
|
||||||
auto VulkanRenderer::swapchain_init() -> void
|
auto VulkanRenderer::swapchain_init() -> void
|
||||||
{
|
{
|
||||||
int w, h;
|
uint32_t width { 0 };
|
||||||
SDL_GetWindowSize(m_window, &w, &h);
|
uint32_t height { 0 };
|
||||||
create_swapchain(static_cast<uint32_t>(w), static_cast<uint32_t>(h));
|
if (m_use_kms) {
|
||||||
create_draw_image(static_cast<uint32_t>(w), static_cast<uint32_t>(h));
|
width = m_kms_extent.width;
|
||||||
create_msaa_color_image(static_cast<uint32_t>(w), static_cast<uint32_t>(h));
|
height = m_kms_extent.height;
|
||||||
create_depth_image(static_cast<uint32_t>(w), static_cast<uint32_t>(h));
|
} else {
|
||||||
|
int w {}, h {};
|
||||||
|
SDL_GetWindowSize(m_window, &w, &h);
|
||||||
|
width = static_cast<uint32_t>(w);
|
||||||
|
height = static_cast<uint32_t>(h);
|
||||||
|
}
|
||||||
|
create_swapchain(width, height);
|
||||||
|
create_draw_image(width, height);
|
||||||
|
create_msaa_color_image(width, height);
|
||||||
|
create_depth_image(width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto VulkanRenderer::commands_init() -> void
|
auto VulkanRenderer::commands_init() -> void
|
||||||
@@ -1404,10 +1594,14 @@ auto VulkanRenderer::render(std::function<void(GL &)> const &record) -> void
|
|||||||
m_vk.swapchain, 1'000'000'000, frame.swapchain_semaphore.get(), {});
|
m_vk.swapchain, 1'000'000'000, frame.swapchain_semaphore.get(), {});
|
||||||
if (acquire_result.result == vk::Result::eErrorOutOfDateKHR
|
if (acquire_result.result == vk::Result::eErrorOutOfDateKHR
|
||||||
|| acquire_result.result == vk::Result::eSuboptimalKHR) {
|
|| acquire_result.result == vk::Result::eSuboptimalKHR) {
|
||||||
int width {}, height {};
|
if (m_use_kms) {
|
||||||
SDL_GetWindowSize(m_window, &width, &height);
|
recreate_swapchain(m_kms_extent.width, m_kms_extent.height);
|
||||||
recreate_swapchain(
|
} else {
|
||||||
static_cast<uint32_t>(width), static_cast<uint32_t>(height));
|
int width {}, height {};
|
||||||
|
SDL_GetWindowSize(m_window, &width, &height);
|
||||||
|
recreate_swapchain(
|
||||||
|
static_cast<uint32_t>(width), static_cast<uint32_t>(height));
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
VK_CHECK(m_logger, acquire_result.result);
|
VK_CHECK(m_logger, acquire_result.result);
|
||||||
@@ -1463,7 +1657,10 @@ auto VulkanRenderer::render(std::function<void(GL &)> const &record) -> void
|
|||||||
vk::ImageLayout::eTransferDstOptimal,
|
vk::ImageLayout::eTransferDstOptimal,
|
||||||
vk::ImageLayout::eColorAttachmentOptimal);
|
vk::ImageLayout::eColorAttachmentOptimal);
|
||||||
|
|
||||||
draw_imgui(cmd, m_vk.swapchain_image_views.at(swapchain_image_idx).get());
|
if (m_imgui_enabled) {
|
||||||
|
draw_imgui(
|
||||||
|
cmd, m_vk.swapchain_image_views.at(swapchain_image_idx).get());
|
||||||
|
}
|
||||||
|
|
||||||
vkutil::transition_image(cmd, m_vk.swapchain_images.at(swapchain_image_idx),
|
vkutil::transition_image(cmd, m_vk.swapchain_images.at(swapchain_image_idx),
|
||||||
vk::ImageLayout::eColorAttachmentOptimal,
|
vk::ImageLayout::eColorAttachmentOptimal,
|
||||||
@@ -1577,15 +1774,100 @@ auto VulkanRenderer::render(std::function<void(GL &)> const &record) -> void
|
|||||||
auto const present_result = m_vk.graphics_queue.presentKHR(present_info);
|
auto const present_result = m_vk.graphics_queue.presentKHR(present_info);
|
||||||
if (present_result == vk::Result::eErrorOutOfDateKHR
|
if (present_result == vk::Result::eErrorOutOfDateKHR
|
||||||
|| present_result == vk::Result::eSuboptimalKHR) {
|
|| present_result == vk::Result::eSuboptimalKHR) {
|
||||||
int width {}, height {};
|
if (m_use_kms) {
|
||||||
SDL_GetWindowSize(m_window, &width, &height);
|
recreate_swapchain(m_kms_extent.width, m_kms_extent.height);
|
||||||
recreate_swapchain(
|
} else {
|
||||||
static_cast<uint32_t>(width), static_cast<uint32_t>(height));
|
int width {}, height {};
|
||||||
|
SDL_GetWindowSize(m_window, &width, &height);
|
||||||
|
recreate_swapchain(
|
||||||
|
static_cast<uint32_t>(width), static_cast<uint32_t>(height));
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
VK_CHECK(m_logger, present_result);
|
VK_CHECK(m_logger, present_result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto VulkanRenderer::render_to_image(vk::Image target_image,
|
||||||
|
vk::Extent2D target_extent, std::function<void(GL &)> const &record) -> void
|
||||||
|
{
|
||||||
|
defer(m_vk.frame_number++);
|
||||||
|
|
||||||
|
if (!target_image || target_extent.width == 0
|
||||||
|
|| target_extent.height == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
process_render_commands();
|
||||||
|
|
||||||
|
auto &frame = m_vk.get_current_frame();
|
||||||
|
VK_CHECK(m_logger,
|
||||||
|
m_device.waitForFences(frame.render_fence.get(), true, 1'000'000'000));
|
||||||
|
frame.deletion_queue.flush();
|
||||||
|
frame.frame_descriptors.clear_pools(m_vkb.dev.device);
|
||||||
|
|
||||||
|
auto raw_fence { static_cast<VkFence>(frame.render_fence.get()) };
|
||||||
|
VK_CHECK(m_logger, vkResetFences(m_vkb.dev.device, 1, &raw_fence));
|
||||||
|
|
||||||
|
auto cmd { frame.main_command_buffer.get() };
|
||||||
|
cmd.reset();
|
||||||
|
|
||||||
|
m_vk.draw_extent.width = m_vk.draw_image.extent.width;
|
||||||
|
m_vk.draw_extent.height = m_vk.draw_image.extent.height;
|
||||||
|
|
||||||
|
vk::CommandBufferBeginInfo cmd_begin_info {};
|
||||||
|
cmd_begin_info.flags = vk::CommandBufferUsageFlagBits::eOneTimeSubmit;
|
||||||
|
VK_CHECK(m_logger,
|
||||||
|
vkBeginCommandBuffer(static_cast<VkCommandBuffer>(cmd),
|
||||||
|
reinterpret_cast<VkCommandBufferBeginInfo *>(&cmd_begin_info)));
|
||||||
|
|
||||||
|
bool const msaa_enabled = m_vk.msaa_samples != vk::SampleCountFlagBits::e1;
|
||||||
|
|
||||||
|
vkutil::transition_image(cmd, m_vk.draw_image.image, m_vk.draw_image_layout,
|
||||||
|
vk::ImageLayout::eColorAttachmentOptimal);
|
||||||
|
m_vk.draw_image_layout = vk::ImageLayout::eColorAttachmentOptimal;
|
||||||
|
|
||||||
|
if (msaa_enabled) {
|
||||||
|
vkutil::transition_image(cmd, m_vk.msaa_color_image.image,
|
||||||
|
m_vk.msaa_color_image_layout,
|
||||||
|
vk::ImageLayout::eColorAttachmentOptimal);
|
||||||
|
m_vk.msaa_color_image_layout = vk::ImageLayout::eColorAttachmentOptimal;
|
||||||
|
}
|
||||||
|
|
||||||
|
vkutil::transition_image(cmd, m_vk.depth_image.image,
|
||||||
|
m_vk.depth_image_layout, vk::ImageLayout::eDepthAttachmentOptimal);
|
||||||
|
m_vk.depth_image_layout = vk::ImageLayout::eDepthAttachmentOptimal;
|
||||||
|
|
||||||
|
gl.begin_drawing(cmd, m_vk.draw_image, &m_vk.depth_image);
|
||||||
|
if (record) {
|
||||||
|
record(gl);
|
||||||
|
}
|
||||||
|
gl.end_drawing();
|
||||||
|
|
||||||
|
vkutil::transition_image(cmd, m_vk.draw_image.image, m_vk.draw_image_layout,
|
||||||
|
vk::ImageLayout::eTransferSrcOptimal);
|
||||||
|
m_vk.draw_image_layout = vk::ImageLayout::eTransferSrcOptimal;
|
||||||
|
|
||||||
|
vkutil::transition_image(cmd, target_image, vk::ImageLayout::eUndefined,
|
||||||
|
vk::ImageLayout::eTransferDstOptimal);
|
||||||
|
|
||||||
|
vkutil::copy_image_to_image(cmd, m_vk.draw_image.image, target_image,
|
||||||
|
m_vk.draw_extent, target_extent);
|
||||||
|
|
||||||
|
vkutil::transition_image(cmd, target_image,
|
||||||
|
vk::ImageLayout::eTransferDstOptimal,
|
||||||
|
vk::ImageLayout::eColorAttachmentOptimal);
|
||||||
|
|
||||||
|
cmd.end();
|
||||||
|
|
||||||
|
auto command_buffer_info { vkinit::command_buffer_submit_info(cmd) };
|
||||||
|
auto submit_info { vkinit::submit_info2(
|
||||||
|
&command_buffer_info, nullptr, nullptr) };
|
||||||
|
|
||||||
|
m_vk.graphics_queue.submit2(submit_info, frame.render_fence.get());
|
||||||
|
VK_CHECK(m_logger,
|
||||||
|
m_device.waitForFences(frame.render_fence.get(), true, 1'000'000'000));
|
||||||
|
}
|
||||||
|
|
||||||
auto VulkanRenderer::draw_imgui(
|
auto VulkanRenderer::draw_imgui(
|
||||||
vk::CommandBuffer cmd, vk::ImageView target_image_view) -> void
|
vk::CommandBuffer cmd, vk::ImageView target_image_view) -> void
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <span>
|
#include <span>
|
||||||
|
#include <string>
|
||||||
#include <variant>
|
#include <variant>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
@@ -130,11 +131,21 @@ struct VulkanRenderer {
|
|||||||
MSAA_8X,
|
MSAA_8X,
|
||||||
};
|
};
|
||||||
|
|
||||||
VulkanRenderer(SDL_Window *window, Logger &logger);
|
struct KmsSurfaceConfig { };
|
||||||
|
|
||||||
|
VulkanRenderer(SDL_Window *window, Logger &logger,
|
||||||
|
std::span<std::string const> instance_extensions = {},
|
||||||
|
std::span<std::string const> device_extensions = {});
|
||||||
|
VulkanRenderer(KmsSurfaceConfig config, Logger &logger,
|
||||||
|
std::span<std::string const> instance_extensions = {},
|
||||||
|
std::span<std::string const> device_extensions = {});
|
||||||
~VulkanRenderer();
|
~VulkanRenderer();
|
||||||
|
|
||||||
auto render(std::function<void(GL &)> const &record = {}) -> void;
|
auto render(std::function<void(GL &)> const &record = {}) -> void;
|
||||||
|
auto render_to_image(vk::Image target_image, vk::Extent2D target_extent,
|
||||||
|
std::function<void(GL &)> const &record = {}) -> void;
|
||||||
auto resize(uint32_t width, uint32_t height) -> void;
|
auto resize(uint32_t width, uint32_t height) -> void;
|
||||||
|
auto set_offscreen_extent(vk::Extent2D extent) -> void;
|
||||||
auto set_antialiasing(AntiAliasingKind kind) -> void;
|
auto set_antialiasing(AntiAliasingKind kind) -> void;
|
||||||
auto set_antialiasing_immediate(AntiAliasingKind kind) -> void;
|
auto set_antialiasing_immediate(AntiAliasingKind kind) -> void;
|
||||||
auto antialiasing() const -> AntiAliasingKind
|
auto antialiasing() const -> AntiAliasingKind
|
||||||
@@ -177,6 +188,16 @@ struct VulkanRenderer {
|
|||||||
auto mesh_pipeline() -> Pipeline & { return m_vk.mesh_pipeline; }
|
auto mesh_pipeline() -> Pipeline & { return m_vk.mesh_pipeline; }
|
||||||
auto triangle_pipeline() -> Pipeline & { return m_vk.triangle_pipeline; }
|
auto triangle_pipeline() -> Pipeline & { return m_vk.triangle_pipeline; }
|
||||||
auto device() const -> vk::Device { return m_device; }
|
auto device() const -> vk::Device { return m_device; }
|
||||||
|
auto instance() const -> vk::Instance { return m_instance; }
|
||||||
|
auto physical_device() const -> vk::PhysicalDevice
|
||||||
|
{
|
||||||
|
return m_physical_device;
|
||||||
|
}
|
||||||
|
auto graphics_queue() const -> vk::Queue { return m_vk.graphics_queue; }
|
||||||
|
auto graphics_queue_family() const -> uint32_t
|
||||||
|
{
|
||||||
|
return m_vk.graphics_queue_family;
|
||||||
|
}
|
||||||
auto draw_image_format() const -> vk::Format
|
auto draw_image_format() const -> vk::Format
|
||||||
{
|
{
|
||||||
return m_vk.draw_image.format;
|
return m_vk.draw_image.format;
|
||||||
@@ -232,6 +253,7 @@ private:
|
|||||||
|
|
||||||
auto vk_init() -> void;
|
auto vk_init() -> void;
|
||||||
auto swapchain_init() -> void;
|
auto swapchain_init() -> void;
|
||||||
|
auto setup_kms_surface() -> void;
|
||||||
auto commands_init() -> void;
|
auto commands_init() -> void;
|
||||||
auto sync_init() -> void;
|
auto sync_init() -> void;
|
||||||
auto descriptors_init() -> void;
|
auto descriptors_init() -> void;
|
||||||
@@ -359,10 +381,27 @@ private:
|
|||||||
vk::UniqueSampler default_sampler_nearest;
|
vk::UniqueSampler default_sampler_nearest;
|
||||||
} m_vk;
|
} m_vk;
|
||||||
|
|
||||||
|
struct KmsState {
|
||||||
|
vk::DisplayKHR display {};
|
||||||
|
vk::DisplayModeKHR mode {};
|
||||||
|
vk::Extent2D extent {};
|
||||||
|
uint32_t plane_index { 0 };
|
||||||
|
uint32_t plane_stack_index { 0 };
|
||||||
|
std::string display_name {};
|
||||||
|
};
|
||||||
|
|
||||||
SDL_Window *m_window { nullptr };
|
SDL_Window *m_window { nullptr };
|
||||||
Logger &m_logger;
|
Logger &m_logger;
|
||||||
std::mutex m_command_mutex;
|
std::mutex m_command_mutex;
|
||||||
std::vector<RenderCommand> m_pending_render_commands;
|
std::vector<RenderCommand> m_pending_render_commands;
|
||||||
|
bool m_use_kms { false };
|
||||||
|
bool m_imgui_enabled { true };
|
||||||
|
std::optional<KmsState> m_kms_state {};
|
||||||
|
vk::PhysicalDevice m_kms_physical_device {};
|
||||||
|
vk::Extent2D m_kms_extent {};
|
||||||
|
bool m_kms_physical_device_set { false };
|
||||||
|
std::vector<std::string> m_extra_instance_extensions {};
|
||||||
|
std::vector<std::string> m_extra_device_extensions {};
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Lunar
|
} // namespace Lunar
|
||||||
|
|||||||
Reference in New Issue
Block a user