mirror of
https://github.com/slendidev/lunar.git
synced 2026-01-30 16:28:58 +02:00
@@ -405,22 +405,35 @@ 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");
|
||||
auto const *display_env = getenv("DISPLAY");
|
||||
auto const *wayland_env = getenv("WAYLAND_DISPLAY");
|
||||
bool const has_display
|
||||
= (display_env && *display_env) || (wayland_env && *wayland_env);
|
||||
m_backend = has_display ? Backend::SDL : Backend::KMS;
|
||||
|
||||
if (m_backend == Backend::SDL) {
|
||||
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_renderer = std::make_unique<VulkanRenderer>(m_window, m_logger);
|
||||
|
||||
m_window_focused
|
||||
= (SDL_GetWindowFlags(m_window) & SDL_WINDOW_INPUT_FOCUS) != 0;
|
||||
} else {
|
||||
m_logger.info("No display server detected; using KMS backend");
|
||||
m_renderer = std::make_unique<VulkanRenderer>(
|
||||
VulkanRenderer::KmsSurfaceConfig {}, m_logger);
|
||||
m_window_focused = true;
|
||||
}
|
||||
|
||||
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_renderer = std::make_unique<VulkanRenderer>(m_window, m_logger);
|
||||
|
||||
m_window_focused
|
||||
= (SDL_GetWindowFlags(m_window) & SDL_WINDOW_INPUT_FOCUS) != 0;
|
||||
m_renderer->set_antialiasing_immediate(
|
||||
VulkanRenderer::AntiAliasingKind::MSAA_4X);
|
||||
|
||||
@@ -429,7 +442,8 @@ Application::Application()
|
||||
|
||||
init_input();
|
||||
|
||||
mouse_captured(true);
|
||||
if (m_backend == Backend::SDL)
|
||||
mouse_captured(true);
|
||||
|
||||
m_logger.info("App init done!");
|
||||
|
||||
@@ -452,14 +466,20 @@ Application::~Application()
|
||||
|
||||
shutdown_input();
|
||||
|
||||
SDL_DestroyWindow(m_window);
|
||||
SDL_Quit();
|
||||
if (m_backend == Backend::SDL) {
|
||||
SDL_DestroyWindow(m_window);
|
||||
SDL_Quit();
|
||||
}
|
||||
|
||||
m_logger.info("App destroy done!");
|
||||
}
|
||||
|
||||
auto Application::binary_directory() const -> std::filesystem::path
|
||||
{
|
||||
if (m_backend != Backend::SDL) {
|
||||
return std::filesystem::current_path();
|
||||
}
|
||||
|
||||
auto const *base_path = SDL_GetBasePath();
|
||||
if (!base_path) {
|
||||
return std::filesystem::current_path();
|
||||
@@ -533,15 +553,28 @@ auto Application::run() -> void
|
||||
|
||||
{
|
||||
SDL_Event e;
|
||||
bool const use_sdl = (m_backend == Backend::SDL);
|
||||
bool const use_imgui = use_sdl;
|
||||
|
||||
ImGuiIO &io = ImGui::GetIO();
|
||||
io.IniFilename = nullptr;
|
||||
if (use_imgui) {
|
||||
ImGuiIO &io = ImGui::GetIO();
|
||||
io.IniFilename = nullptr;
|
||||
}
|
||||
|
||||
uint64_t last { 0 };
|
||||
float fps { 0.0f };
|
||||
while (m_running) {
|
||||
GZoneScopedN("Frame");
|
||||
uint64_t now { SDL_GetTicks() };
|
||||
uint64_t now { 0 };
|
||||
if (use_sdl) {
|
||||
now = SDL_GetTicks();
|
||||
} else {
|
||||
auto const now_tp = std::chrono::steady_clock::now();
|
||||
now = static_cast<uint64_t>(
|
||||
std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||
now_tp.time_since_epoch())
|
||||
.count());
|
||||
}
|
||||
uint64_t dt { now - last };
|
||||
float dt_seconds { static_cast<float>(dt) / 1000.0f };
|
||||
last = now;
|
||||
@@ -554,48 +587,50 @@ auto Application::run() -> void
|
||||
m_key_state_previous = m_key_state;
|
||||
process_libinput_events();
|
||||
|
||||
while (SDL_PollEvent(&e)) {
|
||||
bool forward_to_imgui { false };
|
||||
if (e.type == SDL_EVENT_QUIT) {
|
||||
m_running = false;
|
||||
} else if (e.type == SDL_EVENT_WINDOW_RESIZED) {
|
||||
int width {}, height {};
|
||||
SDL_GetWindowSize(m_window, &width, &height);
|
||||
m_renderer->resize(static_cast<uint32_t>(width),
|
||||
static_cast<uint32_t>(height));
|
||||
clamp_mouse_to_window(width, height);
|
||||
forward_to_imgui = true;
|
||||
} else if (e.type == SDL_EVENT_WINDOW_FOCUS_GAINED) {
|
||||
m_window_focused = true;
|
||||
forward_to_imgui = true;
|
||||
} else if (e.type == SDL_EVENT_WINDOW_FOCUS_LOST) {
|
||||
m_window_focused = false;
|
||||
m_ctrl_pressed_count = 0;
|
||||
m_key_state.fill(false);
|
||||
m_key_state_previous.fill(false);
|
||||
m_mouse_dx = 0.0;
|
||||
if (use_sdl) {
|
||||
while (SDL_PollEvent(&e)) {
|
||||
bool forward_to_imgui { false };
|
||||
if (e.type == SDL_EVENT_QUIT) {
|
||||
m_running = false;
|
||||
} else if (e.type == SDL_EVENT_WINDOW_RESIZED) {
|
||||
int width {}, height {};
|
||||
SDL_GetWindowSize(m_window, &width, &height);
|
||||
m_renderer->resize(static_cast<uint32_t>(width),
|
||||
static_cast<uint32_t>(height));
|
||||
clamp_mouse_to_window(width, height);
|
||||
forward_to_imgui = true;
|
||||
} else if (e.type == SDL_EVENT_WINDOW_FOCUS_GAINED) {
|
||||
m_window_focused = true;
|
||||
forward_to_imgui = true;
|
||||
} else if (e.type == SDL_EVENT_WINDOW_FOCUS_LOST) {
|
||||
m_window_focused = false;
|
||||
m_ctrl_pressed_count = 0;
|
||||
m_key_state.fill(false);
|
||||
m_key_state_previous.fill(false);
|
||||
m_mouse_dx = 0.0;
|
||||
|
||||
m_mouse_dy = 0.0;
|
||||
forward_to_imgui = true;
|
||||
} else if (e.type == SDL_EVENT_MOUSE_MOTION) {
|
||||
m_mouse_x = e.motion.x;
|
||||
m_mouse_y = e.motion.y;
|
||||
m_mouse_dx = e.motion.xrel;
|
||||
m_mouse_dy = e.motion.yrel;
|
||||
forward_to_imgui = true;
|
||||
} else if (e.type == SDL_EVENT_MOUSE_BUTTON_DOWN
|
||||
|| e.type == SDL_EVENT_MOUSE_BUTTON_UP) {
|
||||
m_mouse_x = e.button.x;
|
||||
m_mouse_y = e.button.y;
|
||||
forward_to_imgui = true;
|
||||
} else if (e.type == SDL_EVENT_MOUSE_WHEEL) {
|
||||
m_mouse_x = e.wheel.mouse_x;
|
||||
m_mouse_y = e.wheel.mouse_y;
|
||||
forward_to_imgui = true;
|
||||
m_mouse_dy = 0.0;
|
||||
forward_to_imgui = true;
|
||||
} else if (e.type == SDL_EVENT_MOUSE_MOTION) {
|
||||
m_mouse_x = e.motion.x;
|
||||
m_mouse_y = e.motion.y;
|
||||
m_mouse_dx = e.motion.xrel;
|
||||
m_mouse_dy = e.motion.yrel;
|
||||
forward_to_imgui = true;
|
||||
} else if (e.type == SDL_EVENT_MOUSE_BUTTON_DOWN
|
||||
|| e.type == SDL_EVENT_MOUSE_BUTTON_UP) {
|
||||
m_mouse_x = e.button.x;
|
||||
m_mouse_y = e.button.y;
|
||||
forward_to_imgui = true;
|
||||
} else if (e.type == SDL_EVENT_MOUSE_WHEEL) {
|
||||
m_mouse_x = e.wheel.mouse_x;
|
||||
m_mouse_y = e.wheel.mouse_y;
|
||||
forward_to_imgui = true;
|
||||
}
|
||||
|
||||
if (forward_to_imgui && use_imgui)
|
||||
ImGui_ImplSDL3_ProcessEvent(&e);
|
||||
}
|
||||
|
||||
if (forward_to_imgui)
|
||||
ImGui_ImplSDL3_ProcessEvent(&e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -687,7 +722,7 @@ auto Application::run() -> void
|
||||
m_mouse_dy = 0.0;
|
||||
}
|
||||
|
||||
{
|
||||
if (use_imgui) {
|
||||
GZoneScopedN("ImGui");
|
||||
ImGui_ImplSDL3_NewFrame();
|
||||
ImGui_ImplVulkan_NewFrame();
|
||||
@@ -909,14 +944,19 @@ auto Application::init_input() -> void
|
||||
throw std::runtime_error("App init fail");
|
||||
}
|
||||
|
||||
int width {}, height {};
|
||||
SDL_GetWindowSize(m_window, &width, &height);
|
||||
float mouse_x {}, mouse_y {};
|
||||
SDL_GetMouseState(&mouse_x, &mouse_y);
|
||||
m_mouse_x = mouse_x;
|
||||
m_mouse_y = mouse_y;
|
||||
ImGui::GetIO().AddMousePosEvent(
|
||||
static_cast<float>(m_mouse_x), static_cast<float>(m_mouse_y));
|
||||
if (m_backend == Backend::SDL) {
|
||||
int width {}, height {};
|
||||
SDL_GetWindowSize(m_window, &width, &height);
|
||||
float mouse_x {}, mouse_y {};
|
||||
SDL_GetMouseState(&mouse_x, &mouse_y);
|
||||
m_mouse_x = mouse_x;
|
||||
m_mouse_y = mouse_y;
|
||||
ImGui::GetIO().AddMousePosEvent(
|
||||
static_cast<float>(m_mouse_x), static_cast<float>(m_mouse_y));
|
||||
} else {
|
||||
m_mouse_x = 0.0;
|
||||
m_mouse_y = 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
auto Application::shutdown_input() -> void
|
||||
@@ -973,7 +1013,8 @@ auto Application::handle_keyboard_event(libinput_event_keyboard *event) -> void
|
||||
}
|
||||
}
|
||||
|
||||
if (pressed && key == KEY_F11 && m_ctrl_pressed_count > 0) {
|
||||
if (m_backend == Backend::SDL && pressed && key == KEY_F11
|
||||
&& m_ctrl_pressed_count > 0) {
|
||||
bool const new_show_imgui { !m_show_imgui };
|
||||
m_show_imgui = new_show_imgui;
|
||||
mouse_captured(!new_show_imgui);
|
||||
@@ -1007,18 +1048,21 @@ auto Application::handle_keyboard_event(libinput_event_keyboard *event) -> void
|
||||
}
|
||||
}
|
||||
|
||||
if (auto imgui_key { linux_key_to_imgui(key) }) {
|
||||
if (m_show_imgui)
|
||||
ImGui::GetIO().AddKeyEvent(*imgui_key, pressed);
|
||||
}
|
||||
if (m_backend == Backend::SDL) {
|
||||
if (auto imgui_key { linux_key_to_imgui(key) }) {
|
||||
if (m_show_imgui)
|
||||
ImGui::GetIO().AddKeyEvent(*imgui_key, pressed);
|
||||
}
|
||||
|
||||
if (m_show_imgui && pressed) {
|
||||
bool const shift_pressed { is_key_down(KEY_LEFTSHIFT)
|
||||
|| is_key_down(KEY_RIGHTSHIFT) || (key == KEY_LEFTSHIFT && pressed)
|
||||
|| (key == KEY_RIGHTSHIFT && pressed) };
|
||||
if (m_show_imgui && pressed) {
|
||||
bool const shift_pressed { is_key_down(KEY_LEFTSHIFT)
|
||||
|| is_key_down(KEY_RIGHTSHIFT)
|
||||
|| (key == KEY_LEFTSHIFT && pressed)
|
||||
|| (key == KEY_RIGHTSHIFT && pressed) };
|
||||
|
||||
if (auto ch { linux_key_to_char(key, shift_pressed) })
|
||||
ImGui::GetIO().AddInputCharacter(*ch);
|
||||
if (auto ch { linux_key_to_char(key, shift_pressed) })
|
||||
ImGui::GetIO().AddInputCharacter(*ch);
|
||||
}
|
||||
}
|
||||
|
||||
if (key < m_key_state.size())
|
||||
@@ -1039,6 +1083,11 @@ auto Application::clamp_mouse_to_window(int width, int height) -> void
|
||||
|
||||
auto Application::mouse_captured(bool new_state) -> void
|
||||
{
|
||||
if (m_backend != Backend::SDL) {
|
||||
m_mouse_captured = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!SDL_SetWindowRelativeMouseMode(m_window, new_state)) {
|
||||
m_logger.err("Failed to capture mouse");
|
||||
return;
|
||||
|
||||
@@ -38,6 +38,11 @@ struct Application {
|
||||
static auto the() -> Application &;
|
||||
|
||||
private:
|
||||
enum class Backend {
|
||||
SDL,
|
||||
KMS,
|
||||
};
|
||||
|
||||
Application();
|
||||
~Application();
|
||||
|
||||
@@ -50,6 +55,7 @@ private:
|
||||
auto clamp_mouse_to_window(int width, int height) -> void;
|
||||
|
||||
SDL_Window *m_window { nullptr };
|
||||
Backend m_backend { Backend::SDL };
|
||||
Logger m_logger { "Lunar" };
|
||||
std::unique_ptr<VulkanRenderer> m_renderer;
|
||||
Skybox m_skybox;
|
||||
|
||||
@@ -620,6 +620,9 @@ VulkanRenderer::VulkanRenderer(SDL_Window *window, Logger &logger)
|
||||
throw std::runtime_error("VulkanRenderer requires a valid window");
|
||||
}
|
||||
|
||||
m_use_kms = false;
|
||||
m_imgui_enabled = true;
|
||||
|
||||
vk_init();
|
||||
swapchain_init();
|
||||
commands_init();
|
||||
@@ -630,6 +633,22 @@ VulkanRenderer::VulkanRenderer(SDL_Window *window, Logger &logger)
|
||||
imgui_init();
|
||||
}
|
||||
|
||||
VulkanRenderer::VulkanRenderer(KmsSurfaceConfig /*config*/, Logger &logger)
|
||||
: gl(*this)
|
||||
, m_logger(logger)
|
||||
{
|
||||
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()
|
||||
{
|
||||
m_device.waitIdle();
|
||||
@@ -671,8 +690,12 @@ VulkanRenderer::~VulkanRenderer()
|
||||
}
|
||||
|
||||
if (m_vk.surface) {
|
||||
SDL_Vulkan_DestroySurface(
|
||||
m_vkb.instance, static_cast<VkSurfaceKHR>(m_vk.surface), nullptr);
|
||||
if (m_use_kms) {
|
||||
m_instance.destroySurfaceKHR(m_vk.surface);
|
||||
} else {
|
||||
SDL_Vulkan_DestroySurface(m_vkb.instance,
|
||||
static_cast<VkSurfaceKHR>(m_vk.surface), nullptr);
|
||||
}
|
||||
m_vk.surface = nullptr;
|
||||
}
|
||||
|
||||
@@ -847,6 +870,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
|
||||
{
|
||||
VULKAN_HPP_DEFAULT_DISPATCHER.init(vkGetInstanceProcAddr);
|
||||
@@ -884,6 +1008,9 @@ auto VulkanRenderer::vk_init() -> void
|
||||
|
||||
return VK_FALSE;
|
||||
});
|
||||
if (m_use_kms) {
|
||||
instance_builder.enable_extension(VK_KHR_DISPLAY_EXTENSION_NAME);
|
||||
}
|
||||
#ifndef NDEBUG
|
||||
instance_builder.request_validation_layers();
|
||||
#endif
|
||||
@@ -898,13 +1025,17 @@ auto VulkanRenderer::vk_init() -> void
|
||||
m_instance = vk::Instance { m_vkb.instance.instance };
|
||||
VULKAN_HPP_DEFAULT_DISPATCHER.init(m_instance);
|
||||
|
||||
VkSurfaceKHR raw_surface {};
|
||||
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");
|
||||
if (m_use_kms) {
|
||||
setup_kms_surface();
|
||||
} else {
|
||||
VkSurfaceKHR raw_surface {};
|
||||
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 };
|
||||
VkPhysicalDeviceVulkan13Features features_13 {};
|
||||
@@ -946,6 +1077,10 @@ auto VulkanRenderer::vk_init() -> void
|
||||
|
||||
m_logger.info("Chosen Vulkan physical device: {}",
|
||||
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();
|
||||
m_vk.supported_framebuffer_samples
|
||||
@@ -974,6 +1109,13 @@ auto VulkanRenderer::vk_init() -> void
|
||||
}
|
||||
m_vk.graphics_queue_family = queue_family_ret.value();
|
||||
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 {};
|
||||
allocator_ci.physicalDevice = m_vkb.phys_dev.physical_device;
|
||||
@@ -985,12 +1127,21 @@ auto VulkanRenderer::vk_init() -> void
|
||||
|
||||
auto VulkanRenderer::swapchain_init() -> void
|
||||
{
|
||||
int w, h;
|
||||
SDL_GetWindowSize(m_window, &w, &h);
|
||||
create_swapchain(static_cast<uint32_t>(w), static_cast<uint32_t>(h));
|
||||
create_draw_image(static_cast<uint32_t>(w), static_cast<uint32_t>(h));
|
||||
create_msaa_color_image(static_cast<uint32_t>(w), static_cast<uint32_t>(h));
|
||||
create_depth_image(static_cast<uint32_t>(w), static_cast<uint32_t>(h));
|
||||
uint32_t width { 0 };
|
||||
uint32_t height { 0 };
|
||||
if (m_use_kms) {
|
||||
width = m_kms_extent.width;
|
||||
height = m_kms_extent.height;
|
||||
} 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
|
||||
@@ -1404,10 +1555,14 @@ auto VulkanRenderer::render(std::function<void(GL &)> const &record) -> void
|
||||
m_vk.swapchain, 1'000'000'000, frame.swapchain_semaphore.get(), {});
|
||||
if (acquire_result.result == vk::Result::eErrorOutOfDateKHR
|
||||
|| acquire_result.result == vk::Result::eSuboptimalKHR) {
|
||||
int width {}, height {};
|
||||
SDL_GetWindowSize(m_window, &width, &height);
|
||||
recreate_swapchain(
|
||||
static_cast<uint32_t>(width), static_cast<uint32_t>(height));
|
||||
if (m_use_kms) {
|
||||
recreate_swapchain(m_kms_extent.width, m_kms_extent.height);
|
||||
} else {
|
||||
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.result);
|
||||
@@ -1463,7 +1618,10 @@ auto VulkanRenderer::render(std::function<void(GL &)> const &record) -> void
|
||||
vk::ImageLayout::eTransferDstOptimal,
|
||||
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),
|
||||
vk::ImageLayout::eColorAttachmentOptimal,
|
||||
@@ -1577,10 +1735,14 @@ auto VulkanRenderer::render(std::function<void(GL &)> const &record) -> void
|
||||
auto const present_result = m_vk.graphics_queue.presentKHR(present_info);
|
||||
if (present_result == vk::Result::eErrorOutOfDateKHR
|
||||
|| present_result == vk::Result::eSuboptimalKHR) {
|
||||
int width {}, height {};
|
||||
SDL_GetWindowSize(m_window, &width, &height);
|
||||
recreate_swapchain(
|
||||
static_cast<uint32_t>(width), static_cast<uint32_t>(height));
|
||||
if (m_use_kms) {
|
||||
recreate_swapchain(m_kms_extent.width, m_kms_extent.height);
|
||||
} else {
|
||||
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);
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <mutex>
|
||||
#include <optional>
|
||||
#include <span>
|
||||
#include <string>
|
||||
#include <variant>
|
||||
#include <vector>
|
||||
|
||||
@@ -130,7 +131,10 @@ struct VulkanRenderer {
|
||||
MSAA_8X,
|
||||
};
|
||||
|
||||
struct KmsSurfaceConfig { };
|
||||
|
||||
VulkanRenderer(SDL_Window *window, Logger &logger);
|
||||
VulkanRenderer(KmsSurfaceConfig config, Logger &logger);
|
||||
~VulkanRenderer();
|
||||
|
||||
auto render(std::function<void(GL &)> const &record = {}) -> void;
|
||||
@@ -232,6 +236,7 @@ private:
|
||||
|
||||
auto vk_init() -> void;
|
||||
auto swapchain_init() -> void;
|
||||
auto setup_kms_surface() -> void;
|
||||
auto commands_init() -> void;
|
||||
auto sync_init() -> void;
|
||||
auto descriptors_init() -> void;
|
||||
@@ -359,10 +364,25 @@ private:
|
||||
vk::UniqueSampler default_sampler_nearest;
|
||||
} 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 };
|
||||
Logger &m_logger;
|
||||
std::mutex m_command_mutex;
|
||||
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 };
|
||||
};
|
||||
|
||||
} // namespace Lunar
|
||||
|
||||
Reference in New Issue
Block a user