mirror of
https://github.com/slendidev/lunar.git
synced 2026-06-16 09:19:37 +03:00
Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| efa6e289b6 | |||
| 596af80622 | |||
| f4fad2c1ac | |||
| e9ae017e9b | |||
| cddfa30cfe |
+562
-128
@@ -439,6 +439,14 @@ auto xr_rotate_vector(XrQuaternionf q, smath::Vec3 v) -> smath::Vec3
|
|||||||
return (u * (2.0f * dot)) + (v * (s * s - u_dot)) + (cross * (2.0f * s));
|
return (u * (2.0f * dot)) + (v * (s * s - u_dot)) + (cross * (2.0f * s));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[[maybe_unused]] auto xr_result_to_string(XrInstance instance, XrResult result)
|
||||||
|
-> std::string
|
||||||
|
{
|
||||||
|
std::array<char, XR_MAX_RESULT_STRING_SIZE> buffer {};
|
||||||
|
xrResultToString(instance, result, buffer.data());
|
||||||
|
return std::string { buffer.data() };
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
namespace Lunar {
|
namespace Lunar {
|
||||||
@@ -452,6 +460,7 @@ struct OpenXrSwapchain {
|
|||||||
struct OpenXrState {
|
struct OpenXrState {
|
||||||
bool enabled { false };
|
bool enabled { false };
|
||||||
bool session_running { false };
|
bool session_running { false };
|
||||||
|
bool use_vulkan_enable2 { false };
|
||||||
XrInstance instance { XR_NULL_HANDLE };
|
XrInstance instance { XR_NULL_HANDLE };
|
||||||
XrSystemId system_id { XR_NULL_SYSTEM_ID };
|
XrSystemId system_id { XR_NULL_SYSTEM_ID };
|
||||||
XrSession session { XR_NULL_HANDLE };
|
XrSession session { XR_NULL_HANDLE };
|
||||||
@@ -466,13 +475,22 @@ struct OpenXrState {
|
|||||||
std::vector<OpenXrSwapchain> swapchains {};
|
std::vector<OpenXrSwapchain> swapchains {};
|
||||||
std::vector<std::string> instance_extensions {};
|
std::vector<std::string> instance_extensions {};
|
||||||
std::vector<std::string> device_extensions {};
|
std::vector<std::string> device_extensions {};
|
||||||
PFN_xrGetVulkanGraphicsDevice2KHR get_graphics_device { nullptr };
|
PFN_xrGetVulkanGraphicsDevice2KHR get_graphics_device2 { nullptr };
|
||||||
|
PFN_xrGetVulkanGraphicsDeviceKHR get_graphics_device { nullptr };
|
||||||
|
PFN_xrGetVulkanGraphicsRequirements2KHR get_requirements2 { nullptr };
|
||||||
|
PFN_xrGetVulkanGraphicsRequirementsKHR get_requirements { nullptr };
|
||||||
|
bool hand_tracking_supported { false };
|
||||||
|
XrHandTrackerEXT left_hand_tracker { XR_NULL_HANDLE };
|
||||||
|
XrHandTrackerEXT right_hand_tracker { XR_NULL_HANDLE };
|
||||||
|
PFN_xrCreateHandTrackerEXT create_hand_tracker { nullptr };
|
||||||
|
PFN_xrDestroyHandTrackerEXT destroy_hand_tracker { nullptr };
|
||||||
|
PFN_xrLocateHandJointsEXT locate_hand_joints { nullptr };
|
||||||
};
|
};
|
||||||
|
|
||||||
Application::Application()
|
Application::Application()
|
||||||
{
|
{
|
||||||
auto const *display_env = getenv("DISPLAY");
|
auto const *display_env { getenv("DISPLAY") };
|
||||||
auto const *wayland_env = getenv("WAYLAND_DISPLAY");
|
auto const *wayland_env { getenv("WAYLAND_DISPLAY") };
|
||||||
bool const has_display
|
bool const has_display
|
||||||
= (display_env && *display_env) || (wayland_env && *wayland_env);
|
= (display_env && *display_env) || (wayland_env && *wayland_env);
|
||||||
m_backend = has_display ? Backend::SDL : Backend::KMS;
|
m_backend = has_display ? Backend::SDL : Backend::KMS;
|
||||||
@@ -560,7 +578,7 @@ auto Application::binary_directory() const -> std::filesystem::path
|
|||||||
return std::filesystem::current_path();
|
return std::filesystem::current_path();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto const *base_path = SDL_GetBasePath();
|
auto const *base_path { SDL_GetBasePath() };
|
||||||
if (!base_path) {
|
if (!base_path) {
|
||||||
return std::filesystem::current_path();
|
return std::filesystem::current_path();
|
||||||
}
|
}
|
||||||
@@ -571,9 +589,9 @@ auto Application::asset_directory() -> std::filesystem::path
|
|||||||
{
|
{
|
||||||
std::vector<std::filesystem::path> candidates;
|
std::vector<std::filesystem::path> candidates;
|
||||||
|
|
||||||
auto add_xdg_path = [&](std::filesystem::path const &base) {
|
auto const add_xdg_path { [&](std::filesystem::path const &base) {
|
||||||
candidates.emplace_back(base / "lunar" / "assets");
|
candidates.emplace_back(base / "lunar" / "assets");
|
||||||
};
|
} };
|
||||||
|
|
||||||
if (auto const *xdg_data_home = getenv("XDG_DATA_HOME");
|
if (auto const *xdg_data_home = getenv("XDG_DATA_HOME");
|
||||||
xdg_data_home && *xdg_data_home) {
|
xdg_data_home && *xdg_data_home) {
|
||||||
@@ -600,7 +618,7 @@ auto Application::asset_directory() -> std::filesystem::path
|
|||||||
add_xdg_path("/usr/share");
|
add_xdg_path("/usr/share");
|
||||||
}
|
}
|
||||||
|
|
||||||
auto base_dir { binary_directory() };
|
auto const base_dir { binary_directory() };
|
||||||
candidates.emplace_back(base_dir / "assets");
|
candidates.emplace_back(base_dir / "assets");
|
||||||
candidates.emplace_back(base_dir / "../assets");
|
candidates.emplace_back(base_dir / "../assets");
|
||||||
|
|
||||||
@@ -618,9 +636,9 @@ auto Application::asset_directory() -> std::filesystem::path
|
|||||||
|
|
||||||
auto Application::init_test_meshes() -> void
|
auto Application::init_test_meshes() -> void
|
||||||
{
|
{
|
||||||
auto assets_dir { asset_directory() };
|
auto const assets_dir { asset_directory() };
|
||||||
auto mesh_path { assets_dir / "basicmesh.glb" };
|
auto const mesh_path { assets_dir / "basicmesh.glb" };
|
||||||
auto meshes { Mesh::load_gltf_meshes(*m_renderer, mesh_path) };
|
auto const meshes { Mesh::load_gltf_meshes(*m_renderer, mesh_path) };
|
||||||
if (!meshes) {
|
if (!meshes) {
|
||||||
m_logger.err("Failed to load test mesh: {}", mesh_path.string());
|
m_logger.err("Failed to load test mesh: {}", mesh_path.string());
|
||||||
return;
|
return;
|
||||||
@@ -633,9 +651,9 @@ auto Application::run() -> void
|
|||||||
|
|
||||||
{
|
{
|
||||||
SDL_Event e;
|
SDL_Event e;
|
||||||
bool const use_sdl = (m_backend == Backend::SDL);
|
bool const use_sdl { (m_backend == Backend::SDL) };
|
||||||
bool const openxr_enabled = m_openxr != nullptr;
|
bool const openxr_enabled { m_openxr != nullptr };
|
||||||
bool const use_imgui = use_sdl && !openxr_enabled;
|
bool const use_imgui { use_sdl && !openxr_enabled };
|
||||||
|
|
||||||
if (use_imgui) {
|
if (use_imgui) {
|
||||||
ImGuiIO &io = ImGui::GetIO();
|
ImGuiIO &io = ImGui::GetIO();
|
||||||
@@ -939,31 +957,71 @@ auto Application::run() -> void
|
|||||||
auto view { smath::matrix_look_at(
|
auto view { smath::matrix_look_at(
|
||||||
m_camera.position, m_camera.target, m_camera.up) };
|
m_camera.position, m_camera.target, m_camera.up) };
|
||||||
auto const draw_extent = m_renderer->draw_extent();
|
auto const draw_extent = m_renderer->draw_extent();
|
||||||
auto const aspect = static_cast<float>(draw_extent.width)
|
auto const aspect = draw_extent.height == 0
|
||||||
/ static_cast<float>(draw_extent.height);
|
? 1.0f
|
||||||
auto const proj = smath::matrix_perspective(
|
: static_cast<float>(draw_extent.width)
|
||||||
m_camera.fovy, aspect, 0.1f, 10000.0f);
|
/ static_cast<float>(draw_extent.height);
|
||||||
auto const view_projection = proj * view;
|
auto projection { smath::matrix_perspective(
|
||||||
gl.set_transform(view_projection);
|
m_camera.fovy, aspect, 0.1f, 10000.0f) };
|
||||||
for (auto const &mesh : m_test_meshes) {
|
projection[1][1] *= -1;
|
||||||
for (auto const &surface : mesh->surfaces) {
|
auto view_projection { projection * view };
|
||||||
gl.draw_mesh(mesh->mesh_buffers, smath::Mat4::identity(),
|
|
||||||
surface.count, surface.start_index);
|
auto skybox_view { view };
|
||||||
}
|
skybox_view[3][0] = 0.0f;
|
||||||
}
|
skybox_view[3][1] = 0.0f;
|
||||||
m_skybox.draw(gl, *m_renderer, view_projection);
|
skybox_view[3][2] = 0.0f;
|
||||||
|
m_skybox.draw(gl, *m_renderer, projection * skybox_view);
|
||||||
|
|
||||||
gl.set_transform(view_projection);
|
gl.set_transform(view_projection);
|
||||||
gl.draw_sphere({ 0.0f, 0.0f, 0.0f }, 0.1f, 16, 32,
|
gl.set_texture();
|
||||||
smath::Vec4 { Colors::RED, 1.0f });
|
auto const &meshes { m_test_meshes };
|
||||||
gl.draw_sphere({ 0.0f, 0.0f, 0.0f }, 0.11f, 16, 32,
|
if (meshes.size() > 2 && !meshes[2]->surfaces.empty()) {
|
||||||
smath::Vec4 { Colors::DARK_RED, 1.0f });
|
auto const &surface = meshes[2]->surfaces[0];
|
||||||
|
gl.draw_mesh(meshes[2]->mesh_buffers,
|
||||||
|
view_projection
|
||||||
|
* smath::translate(smath::Vec3 { 0.0f, 0.0f, -5.0f }),
|
||||||
|
surface.count, surface.start_index);
|
||||||
|
}
|
||||||
|
|
||||||
|
gl.push_transform();
|
||||||
|
gl.set_transform(view_projection
|
||||||
|
* smath::translate(smath::Vec3 { 0.0f, 0.0f, 5.0f })
|
||||||
|
* smath::Quaternion<float>::from_axis_angle(
|
||||||
|
smath::Vec3 { 0.0f, 1.0f, 0.0f }, smath::deg(180))
|
||||||
|
.as_matrix());
|
||||||
|
|
||||||
|
gl.set_texture(&m_renderer->white_texture());
|
||||||
|
|
||||||
|
gl.begin(VulkanRenderer::GL::GeometryKind::Quads);
|
||||||
|
|
||||||
|
gl.color(smath::Vec3 { 0.0f, 0.0f, 0.0f });
|
||||||
|
gl.uv(smath::Vec2 { 1.0f, 1.0f });
|
||||||
|
gl.vert(smath::Vec3 { 0.5f, -0.5f, 0.0f });
|
||||||
|
|
||||||
|
gl.color(smath::Vec3 { 0.5f, 0.5f, 0.5f });
|
||||||
|
gl.uv(smath::Vec2 { 1.0f, 0.0f });
|
||||||
|
gl.vert(smath::Vec3 { 0.5f, 0.5f, 0.0f });
|
||||||
|
|
||||||
|
gl.color(smath::Vec3 { 1.0f, 0.0f, 0.0f });
|
||||||
|
gl.uv(smath::Vec2 { 0.0f, 1.0f });
|
||||||
|
gl.vert(smath::Vec3 { -0.5f, -0.5f, 0.0f });
|
||||||
|
|
||||||
|
gl.color(smath::Vec3 { 0.0f, 1.0f, 0.0f });
|
||||||
|
gl.uv(smath::Vec2 { 0.0f, 0.0f });
|
||||||
|
gl.vert(smath::Vec3 { -0.5f, 0.5f, 0.0f });
|
||||||
|
|
||||||
|
gl.end();
|
||||||
|
|
||||||
gl.draw_rectangle({ -0.5f, 0.5f }, { 0.5f, 0.5f });
|
gl.draw_rectangle({ -0.5f, 0.5f }, { 0.5f, 0.5f });
|
||||||
gl.draw_rectangle(
|
gl.draw_rectangle(
|
||||||
{ 0, 0.5f }, { 0.5f, 0.5f }, { Colors::TEAL, 1.0f });
|
{ 0, 0.5f }, { 0.5f, 0.5f }, { Colors::TEAL, 1.0f });
|
||||||
|
|
||||||
gl.set_transform(view_projection);
|
gl.set_transform(view_projection);
|
||||||
gl.draw_sphere(m_camera.target, 0.01f);
|
gl.draw_sphere(m_camera.target, 0.01f);
|
||||||
|
|
||||||
|
if (m_openxr && m_openxr->hand_tracking_supported) {
|
||||||
|
render_hands(gl, view_projection);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if (xr_active) {
|
if (xr_active) {
|
||||||
@@ -1031,6 +1089,9 @@ auto Application::shutdown_input() -> void
|
|||||||
|
|
||||||
auto Application::init_openxr() -> void
|
auto Application::init_openxr() -> void
|
||||||
{
|
{
|
||||||
|
if (auto const *no_xr = getenv("LUNAR_NO_XR"); no_xr && *no_xr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
m_openxr = std::make_unique<OpenXrState>();
|
m_openxr = std::make_unique<OpenXrState>();
|
||||||
|
|
||||||
XrInstanceCreateInfo create_info {};
|
XrInstanceCreateInfo create_info {};
|
||||||
@@ -1044,15 +1105,76 @@ auto Application::init_openxr() -> void
|
|||||||
create_info.applicationInfo.engineVersion = 1;
|
create_info.applicationInfo.engineVersion = 1;
|
||||||
create_info.applicationInfo.apiVersion = XR_CURRENT_API_VERSION;
|
create_info.applicationInfo.apiVersion = XR_CURRENT_API_VERSION;
|
||||||
|
|
||||||
std::array<char const *, 1> const extensions {
|
uint32_t extension_count = 0;
|
||||||
XR_KHR_VULKAN_ENABLE2_EXTENSION_NAME,
|
auto extension_count_result {
|
||||||
|
xrEnumerateInstanceExtensionProperties(
|
||||||
|
nullptr, 0, &extension_count, nullptr),
|
||||||
};
|
};
|
||||||
|
if (XR_FAILED(extension_count_result) || extension_count == 0) {
|
||||||
|
m_logger.warn("OpenXR instance extensions unavailable: {}",
|
||||||
|
xr_result_to_string(XR_NULL_HANDLE, extension_count_result));
|
||||||
|
m_openxr.reset();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<XrExtensionProperties> available_extensions(extension_count);
|
||||||
|
for (auto &extension : available_extensions) {
|
||||||
|
extension = XrExtensionProperties {};
|
||||||
|
extension.type = XR_TYPE_EXTENSION_PROPERTIES;
|
||||||
|
extension.next = nullptr;
|
||||||
|
}
|
||||||
|
auto enumerate_result {
|
||||||
|
xrEnumerateInstanceExtensionProperties(nullptr, extension_count,
|
||||||
|
&extension_count, available_extensions.data()),
|
||||||
|
};
|
||||||
|
if (XR_FAILED(enumerate_result)) {
|
||||||
|
m_logger.warn("Failed to enumerate OpenXR extensions: {}",
|
||||||
|
xr_result_to_string(XR_NULL_HANDLE, enumerate_result));
|
||||||
|
m_openxr.reset();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto const has_extension { [&](char const *name) {
|
||||||
|
return std::any_of(available_extensions.begin(),
|
||||||
|
available_extensions.end(), [&](auto const &extension) {
|
||||||
|
return std::strcmp(extension.extensionName, name) == 0;
|
||||||
|
});
|
||||||
|
} };
|
||||||
|
|
||||||
|
bool const has_enable2 {
|
||||||
|
has_extension(XR_KHR_VULKAN_ENABLE2_EXTENSION_NAME),
|
||||||
|
};
|
||||||
|
bool const has_enable1 = has_extension(XR_KHR_VULKAN_ENABLE_EXTENSION_NAME);
|
||||||
|
if (!has_enable2 && !has_enable1) {
|
||||||
|
m_logger.warn("OpenXR Vulkan extensions missing");
|
||||||
|
m_openxr.reset();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<char const *> extensions {};
|
||||||
|
if (has_enable1) {
|
||||||
|
extensions.push_back(XR_KHR_VULKAN_ENABLE_EXTENSION_NAME);
|
||||||
|
m_openxr->use_vulkan_enable2 = false;
|
||||||
|
} else if (has_enable2) {
|
||||||
|
extensions.push_back(XR_KHR_VULKAN_ENABLE2_EXTENSION_NAME);
|
||||||
|
m_openxr->use_vulkan_enable2 = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool const has_hand_tracking {
|
||||||
|
has_extension(XR_EXT_HAND_TRACKING_EXTENSION_NAME),
|
||||||
|
};
|
||||||
|
if (has_hand_tracking) {
|
||||||
|
extensions.push_back(XR_EXT_HAND_TRACKING_EXTENSION_NAME);
|
||||||
|
m_openxr->hand_tracking_supported = true;
|
||||||
|
}
|
||||||
|
|
||||||
create_info.enabledExtensionCount
|
create_info.enabledExtensionCount
|
||||||
= static_cast<uint32_t>(extensions.size());
|
= static_cast<uint32_t>(extensions.size());
|
||||||
create_info.enabledExtensionNames = extensions.data();
|
create_info.enabledExtensionNames = extensions.data();
|
||||||
|
|
||||||
auto const instance_result
|
auto const instance_result {
|
||||||
= xrCreateInstance(&create_info, &m_openxr->instance);
|
xrCreateInstance(&create_info, &m_openxr->instance),
|
||||||
|
};
|
||||||
if (XR_FAILED(instance_result)) {
|
if (XR_FAILED(instance_result)) {
|
||||||
m_logger.info("OpenXR not available (no instance)");
|
m_logger.info("OpenXR not available (no instance)");
|
||||||
m_openxr.reset();
|
m_openxr.reset();
|
||||||
@@ -1063,8 +1185,9 @@ auto Application::init_openxr() -> void
|
|||||||
system_info.type = XR_TYPE_SYSTEM_GET_INFO;
|
system_info.type = XR_TYPE_SYSTEM_GET_INFO;
|
||||||
system_info.next = nullptr;
|
system_info.next = nullptr;
|
||||||
system_info.formFactor = XR_FORM_FACTOR_HEAD_MOUNTED_DISPLAY;
|
system_info.formFactor = XR_FORM_FACTOR_HEAD_MOUNTED_DISPLAY;
|
||||||
auto const system_result
|
auto const system_result {
|
||||||
= xrGetSystem(m_openxr->instance, &system_info, &m_openxr->system_id);
|
xrGetSystem(m_openxr->instance, &system_info, &m_openxr->system_id),
|
||||||
|
};
|
||||||
if (XR_FAILED(system_result)) {
|
if (XR_FAILED(system_result)) {
|
||||||
m_logger.info("OpenXR system not detected");
|
m_logger.info("OpenXR system not detected");
|
||||||
xrDestroyInstance(m_openxr->instance);
|
xrDestroyInstance(m_openxr->instance);
|
||||||
@@ -1073,20 +1196,24 @@ auto Application::init_openxr() -> void
|
|||||||
}
|
}
|
||||||
|
|
||||||
PFN_xrGetVulkanInstanceExtensionsKHR get_instance_exts {};
|
PFN_xrGetVulkanInstanceExtensionsKHR get_instance_exts {};
|
||||||
auto instance_ext_result = xrGetInstanceProcAddr(m_openxr->instance,
|
auto instance_ext_result {
|
||||||
"xrGetVulkanInstanceExtensionsKHR",
|
xrGetInstanceProcAddr(m_openxr->instance,
|
||||||
reinterpret_cast<PFN_xrVoidFunction *>(&get_instance_exts));
|
"xrGetVulkanInstanceExtensionsKHR",
|
||||||
|
reinterpret_cast<PFN_xrVoidFunction *>(&get_instance_exts)),
|
||||||
|
};
|
||||||
if (XR_FAILED(instance_ext_result) || !get_instance_exts) {
|
if (XR_FAILED(instance_ext_result) || !get_instance_exts) {
|
||||||
m_logger.warn("OpenXR missing Vulkan instance extensions");
|
m_logger.warn("OpenXR missing Vulkan instance extensions (proc)");
|
||||||
xrDestroyInstance(m_openxr->instance);
|
xrDestroyInstance(m_openxr->instance);
|
||||||
m_openxr.reset();
|
m_openxr.reset();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
PFN_xrGetVulkanDeviceExtensionsKHR get_device_exts {};
|
PFN_xrGetVulkanDeviceExtensionsKHR get_device_exts {};
|
||||||
auto device_ext_result = xrGetInstanceProcAddr(m_openxr->instance,
|
auto device_ext_result {
|
||||||
"xrGetVulkanDeviceExtensionsKHR",
|
xrGetInstanceProcAddr(m_openxr->instance,
|
||||||
reinterpret_cast<PFN_xrVoidFunction *>(&get_device_exts));
|
"xrGetVulkanDeviceExtensionsKHR",
|
||||||
|
reinterpret_cast<PFN_xrVoidFunction *>(&get_device_exts)),
|
||||||
|
};
|
||||||
if (XR_FAILED(device_ext_result) || !get_device_exts) {
|
if (XR_FAILED(device_ext_result) || !get_device_exts) {
|
||||||
m_logger.warn("OpenXR missing Vulkan device extensions");
|
m_logger.warn("OpenXR missing Vulkan device extensions");
|
||||||
xrDestroyInstance(m_openxr->instance);
|
xrDestroyInstance(m_openxr->instance);
|
||||||
@@ -1116,7 +1243,7 @@ auto Application::init_openxr() -> void
|
|||||||
m_openxr->instance_extensions = split_extension_list(
|
m_openxr->instance_extensions = split_extension_list(
|
||||||
std::string_view { instance_ext_string.c_str() });
|
std::string_view { instance_ext_string.c_str() });
|
||||||
|
|
||||||
uint32_t device_ext_size = 0;
|
uint32_t device_ext_size { 0 };
|
||||||
device_ext_result = get_device_exts(
|
device_ext_result = get_device_exts(
|
||||||
m_openxr->instance, m_openxr->system_id, 0, &device_ext_size, nullptr);
|
m_openxr->instance, m_openxr->system_id, 0, &device_ext_size, nullptr);
|
||||||
if (XR_FAILED(device_ext_result) || device_ext_size == 0) {
|
if (XR_FAILED(device_ext_result) || device_ext_size == 0) {
|
||||||
@@ -1138,12 +1265,84 @@ auto Application::init_openxr() -> void
|
|||||||
= split_extension_list(std::string_view { device_ext_string.c_str() });
|
= split_extension_list(std::string_view { device_ext_string.c_str() });
|
||||||
m_openxr->enabled = true;
|
m_openxr->enabled = true;
|
||||||
|
|
||||||
auto graphics_device_result = xrGetInstanceProcAddr(m_openxr->instance,
|
if (m_openxr->use_vulkan_enable2) {
|
||||||
"xrGetVulkanGraphicsDevice2KHR",
|
auto const graphics_device_result {
|
||||||
reinterpret_cast<PFN_xrVoidFunction *>(&m_openxr->get_graphics_device));
|
xrGetInstanceProcAddr(m_openxr->instance,
|
||||||
if (XR_FAILED(graphics_device_result) || !m_openxr->get_graphics_device) {
|
"xrGetVulkanGraphicsDevice2KHR",
|
||||||
m_logger.warn("OpenXR missing Vulkan graphics device hook");
|
reinterpret_cast<PFN_xrVoidFunction *>(
|
||||||
m_openxr->get_graphics_device = nullptr;
|
&m_openxr->get_graphics_device2)),
|
||||||
|
};
|
||||||
|
if (XR_FAILED(graphics_device_result)
|
||||||
|
|| !m_openxr->get_graphics_device2) {
|
||||||
|
m_logger.warn("OpenXR missing Vulkan graphics device hook");
|
||||||
|
m_openxr->get_graphics_device2 = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto const requirements_result {
|
||||||
|
xrGetInstanceProcAddr(m_openxr->instance,
|
||||||
|
"xrGetVulkanGraphicsRequirements2KHR",
|
||||||
|
reinterpret_cast<PFN_xrVoidFunction *>(
|
||||||
|
&m_openxr->get_requirements2)),
|
||||||
|
};
|
||||||
|
if (XR_FAILED(requirements_result) || !m_openxr->get_requirements2) {
|
||||||
|
m_logger.warn("OpenXR missing Vulkan requirements hook");
|
||||||
|
m_openxr->get_requirements2 = nullptr;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
auto const graphics_device_result {
|
||||||
|
xrGetInstanceProcAddr(m_openxr->instance,
|
||||||
|
"xrGetVulkanGraphicsDeviceKHR",
|
||||||
|
reinterpret_cast<PFN_xrVoidFunction *>(
|
||||||
|
&m_openxr->get_graphics_device)),
|
||||||
|
};
|
||||||
|
if (XR_FAILED(graphics_device_result)
|
||||||
|
|| !m_openxr->get_graphics_device) {
|
||||||
|
m_logger.warn("OpenXR missing Vulkan graphics device hook");
|
||||||
|
m_openxr->get_graphics_device = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto const requirements_result {
|
||||||
|
xrGetInstanceProcAddr(m_openxr->instance,
|
||||||
|
"xrGetVulkanGraphicsRequirementsKHR",
|
||||||
|
reinterpret_cast<PFN_xrVoidFunction *>(
|
||||||
|
&m_openxr->get_requirements)),
|
||||||
|
};
|
||||||
|
if (XR_FAILED(requirements_result) || !m_openxr->get_requirements) {
|
||||||
|
m_logger.warn("OpenXR missing Vulkan requirements hook");
|
||||||
|
m_openxr->get_requirements = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_openxr->hand_tracking_supported) {
|
||||||
|
auto const create_result {
|
||||||
|
xrGetInstanceProcAddr(m_openxr->instance, "xrCreateHandTrackerEXT",
|
||||||
|
reinterpret_cast<PFN_xrVoidFunction *>(
|
||||||
|
&m_openxr->create_hand_tracker)),
|
||||||
|
};
|
||||||
|
if (XR_FAILED(create_result) || !m_openxr->create_hand_tracker) {
|
||||||
|
m_logger.warn("OpenXR hand tracking create function unavailable");
|
||||||
|
m_openxr->hand_tracking_supported = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto const destroy_result {
|
||||||
|
xrGetInstanceProcAddr(m_openxr->instance, "xrDestroyHandTrackerEXT",
|
||||||
|
reinterpret_cast<PFN_xrVoidFunction *>(
|
||||||
|
&m_openxr->destroy_hand_tracker)),
|
||||||
|
};
|
||||||
|
if (XR_FAILED(destroy_result) || !m_openxr->destroy_hand_tracker) {
|
||||||
|
m_logger.warn("OpenXR hand tracking destroy function unavailable");
|
||||||
|
m_openxr->hand_tracking_supported = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto const locate_result {
|
||||||
|
xrGetInstanceProcAddr(m_openxr->instance, "xrLocateHandJointsEXT",
|
||||||
|
reinterpret_cast<PFN_xrVoidFunction *>(
|
||||||
|
&m_openxr->locate_hand_joints)),
|
||||||
|
};
|
||||||
|
if (XR_FAILED(locate_result) || !m_openxr->locate_hand_joints) {
|
||||||
|
m_logger.warn("OpenXR hand tracking locate function unavailable");
|
||||||
|
m_openxr->hand_tracking_supported = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_logger.info("OpenXR system detected");
|
m_logger.info("OpenXR system detected");
|
||||||
@@ -1154,25 +1353,101 @@ auto Application::init_openxr_session() -> void
|
|||||||
if (!m_openxr || !m_renderer) {
|
if (!m_openxr || !m_renderer) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!m_openxr->get_graphics_device) {
|
|
||||||
m_logger.warn("OpenXR graphics device hook unavailable");
|
|
||||||
shutdown_openxr();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
XrVulkanGraphicsDeviceGetInfoKHR device_info {};
|
|
||||||
device_info.type = XR_TYPE_VULKAN_GRAPHICS_DEVICE_GET_INFO_KHR;
|
|
||||||
device_info.next = nullptr;
|
|
||||||
device_info.systemId = m_openxr->system_id;
|
|
||||||
device_info.vulkanInstance
|
|
||||||
= static_cast<VkInstance>(m_renderer->instance());
|
|
||||||
VkPhysicalDevice xr_physical_device {};
|
VkPhysicalDevice xr_physical_device {};
|
||||||
auto const phys_result = m_openxr->get_graphics_device(
|
XrGraphicsBindingVulkan2KHR binding2 {};
|
||||||
m_openxr->instance, &device_info, &xr_physical_device);
|
XrGraphicsBindingVulkanKHR binding1 {};
|
||||||
if (XR_FAILED(phys_result)) {
|
void *binding_ptr = nullptr;
|
||||||
m_logger.warn("Failed to fetch OpenXR Vulkan device");
|
|
||||||
shutdown_openxr();
|
if (m_openxr->use_vulkan_enable2) {
|
||||||
return;
|
if (!m_openxr->get_graphics_device2 || !m_openxr->get_requirements2) {
|
||||||
|
m_logger.warn("OpenXR graphics device hook unavailable");
|
||||||
|
shutdown_openxr();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
XrGraphicsRequirementsVulkan2KHR requirements {};
|
||||||
|
requirements.type = XR_TYPE_GRAPHICS_REQUIREMENTS_VULKAN2_KHR;
|
||||||
|
requirements.next = nullptr;
|
||||||
|
auto const requirements_result {
|
||||||
|
m_openxr->get_requirements2(
|
||||||
|
m_openxr->instance, m_openxr->system_id, &requirements),
|
||||||
|
};
|
||||||
|
if (XR_FAILED(requirements_result)) {
|
||||||
|
m_logger.warn("OpenXR Vulkan requirements failed: {}",
|
||||||
|
xr_result_to_string(m_openxr->instance, requirements_result));
|
||||||
|
shutdown_openxr();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
XrVulkanGraphicsDeviceGetInfoKHR device_info {};
|
||||||
|
device_info.type = XR_TYPE_VULKAN_GRAPHICS_DEVICE_GET_INFO_KHR;
|
||||||
|
device_info.next = nullptr;
|
||||||
|
device_info.systemId = m_openxr->system_id;
|
||||||
|
device_info.vulkanInstance
|
||||||
|
= static_cast<VkInstance>(m_renderer->instance());
|
||||||
|
auto const phys_result {
|
||||||
|
m_openxr->get_graphics_device2(
|
||||||
|
m_openxr->instance, &device_info, &xr_physical_device),
|
||||||
|
};
|
||||||
|
if (XR_FAILED(phys_result)) {
|
||||||
|
m_logger.warn("Failed to fetch OpenXR Vulkan device: {}",
|
||||||
|
xr_result_to_string(m_openxr->instance, phys_result));
|
||||||
|
shutdown_openxr();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
binding2.type = XR_TYPE_GRAPHICS_BINDING_VULKAN2_KHR;
|
||||||
|
binding2.next = nullptr;
|
||||||
|
binding2.instance = static_cast<VkInstance>(m_renderer->instance());
|
||||||
|
binding2.physicalDevice
|
||||||
|
= static_cast<VkPhysicalDevice>(m_renderer->physical_device());
|
||||||
|
binding2.device = static_cast<VkDevice>(m_renderer->device());
|
||||||
|
binding2.queueFamilyIndex = m_renderer->graphics_queue_family();
|
||||||
|
binding2.queueIndex = 0;
|
||||||
|
binding_ptr = &binding2;
|
||||||
|
} else {
|
||||||
|
if (!m_openxr->get_graphics_device || !m_openxr->get_requirements) {
|
||||||
|
m_logger.warn("OpenXR graphics device hook unavailable");
|
||||||
|
shutdown_openxr();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
XrGraphicsRequirementsVulkanKHR requirements {};
|
||||||
|
requirements.type = XR_TYPE_GRAPHICS_REQUIREMENTS_VULKAN_KHR;
|
||||||
|
requirements.next = nullptr;
|
||||||
|
auto const requirements_result {
|
||||||
|
m_openxr->get_requirements(
|
||||||
|
m_openxr->instance, m_openxr->system_id, &requirements),
|
||||||
|
};
|
||||||
|
if (XR_FAILED(requirements_result)) {
|
||||||
|
m_logger.warn("OpenXR Vulkan requirements failed: {}",
|
||||||
|
xr_result_to_string(m_openxr->instance, requirements_result));
|
||||||
|
shutdown_openxr();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto const phys_result {
|
||||||
|
m_openxr->get_graphics_device(m_openxr->instance,
|
||||||
|
m_openxr->system_id,
|
||||||
|
static_cast<VkInstance>(m_renderer->instance()),
|
||||||
|
&xr_physical_device),
|
||||||
|
};
|
||||||
|
if (XR_FAILED(phys_result)) {
|
||||||
|
m_logger.warn("Failed to fetch OpenXR Vulkan device: {}",
|
||||||
|
xr_result_to_string(m_openxr->instance, phys_result));
|
||||||
|
shutdown_openxr();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
binding1.type = XR_TYPE_GRAPHICS_BINDING_VULKAN_KHR;
|
||||||
|
binding1.next = nullptr;
|
||||||
|
binding1.instance = static_cast<VkInstance>(m_renderer->instance());
|
||||||
|
binding1.physicalDevice
|
||||||
|
= static_cast<VkPhysicalDevice>(m_renderer->physical_device());
|
||||||
|
binding1.device = static_cast<VkDevice>(m_renderer->device());
|
||||||
|
binding1.queueFamilyIndex = m_renderer->graphics_queue_family();
|
||||||
|
binding1.queueIndex = 0;
|
||||||
|
binding_ptr = &binding1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (xr_physical_device
|
if (xr_physical_device
|
||||||
@@ -1180,24 +1455,16 @@ auto Application::init_openxr_session() -> void
|
|||||||
m_logger.warn("OpenXR device differs from selected Vulkan device");
|
m_logger.warn("OpenXR device differs from selected Vulkan device");
|
||||||
}
|
}
|
||||||
|
|
||||||
XrGraphicsBindingVulkan2KHR binding {};
|
|
||||||
binding.type = XR_TYPE_GRAPHICS_BINDING_VULKAN2_KHR;
|
|
||||||
binding.next = nullptr;
|
|
||||||
binding.instance = static_cast<VkInstance>(m_renderer->instance());
|
|
||||||
binding.physicalDevice
|
|
||||||
= static_cast<VkPhysicalDevice>(m_renderer->physical_device());
|
|
||||||
binding.device = static_cast<VkDevice>(m_renderer->device());
|
|
||||||
binding.queueFamilyIndex = m_renderer->graphics_queue_family();
|
|
||||||
binding.queueIndex = 0;
|
|
||||||
|
|
||||||
XrSessionCreateInfo session_info {};
|
XrSessionCreateInfo session_info {};
|
||||||
session_info.type = XR_TYPE_SESSION_CREATE_INFO;
|
session_info.type = XR_TYPE_SESSION_CREATE_INFO;
|
||||||
session_info.next = &binding;
|
session_info.next = binding_ptr;
|
||||||
session_info.systemId = m_openxr->system_id;
|
session_info.systemId = m_openxr->system_id;
|
||||||
auto const session_result = xrCreateSession(
|
auto const session_result {
|
||||||
m_openxr->instance, &session_info, &m_openxr->session);
|
xrCreateSession(m_openxr->instance, &session_info, &m_openxr->session),
|
||||||
|
};
|
||||||
if (XR_FAILED(session_result)) {
|
if (XR_FAILED(session_result)) {
|
||||||
m_logger.warn("Failed to create OpenXR session");
|
m_logger.warn("Failed to create OpenXR session: {}",
|
||||||
|
xr_result_to_string(m_openxr->instance, session_result));
|
||||||
shutdown_openxr();
|
shutdown_openxr();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1207,20 +1474,25 @@ auto Application::init_openxr_session() -> void
|
|||||||
space_info.next = nullptr;
|
space_info.next = nullptr;
|
||||||
space_info.referenceSpaceType = XR_REFERENCE_SPACE_TYPE_LOCAL;
|
space_info.referenceSpaceType = XR_REFERENCE_SPACE_TYPE_LOCAL;
|
||||||
space_info.poseInReferenceSpace.orientation.w = 1.0f;
|
space_info.poseInReferenceSpace.orientation.w = 1.0f;
|
||||||
auto const space_result = xrCreateReferenceSpace(
|
auto const space_result {
|
||||||
m_openxr->session, &space_info, &m_openxr->app_space);
|
xrCreateReferenceSpace(
|
||||||
|
m_openxr->session, &space_info, &m_openxr->app_space),
|
||||||
|
};
|
||||||
if (XR_FAILED(space_result)) {
|
if (XR_FAILED(space_result)) {
|
||||||
m_logger.warn("Failed to create OpenXR space");
|
m_logger.warn("Failed to create OpenXR space: {}",
|
||||||
|
xr_result_to_string(m_openxr->instance, space_result));
|
||||||
shutdown_openxr();
|
shutdown_openxr();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t view_count = 0;
|
uint32_t view_count = 0;
|
||||||
auto const view_count_result
|
auto const view_count_result {
|
||||||
= xrEnumerateViewConfigurationViews(m_openxr->instance,
|
xrEnumerateViewConfigurationViews(m_openxr->instance,
|
||||||
m_openxr->system_id, m_openxr->view_type, 0, &view_count, nullptr);
|
m_openxr->system_id, m_openxr->view_type, 0, &view_count, nullptr),
|
||||||
|
};
|
||||||
if (XR_FAILED(view_count_result) || view_count == 0) {
|
if (XR_FAILED(view_count_result) || view_count == 0) {
|
||||||
m_logger.warn("OpenXR view configuration missing");
|
m_logger.warn("OpenXR view configuration missing: {}",
|
||||||
|
xr_result_to_string(m_openxr->instance, view_count_result));
|
||||||
shutdown_openxr();
|
shutdown_openxr();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1230,11 +1502,14 @@ auto Application::init_openxr_session() -> void
|
|||||||
config.type = XR_TYPE_VIEW_CONFIGURATION_VIEW;
|
config.type = XR_TYPE_VIEW_CONFIGURATION_VIEW;
|
||||||
config.next = nullptr;
|
config.next = nullptr;
|
||||||
}
|
}
|
||||||
auto const view_result = xrEnumerateViewConfigurationViews(
|
auto const view_result {
|
||||||
m_openxr->instance, m_openxr->system_id, m_openxr->view_type,
|
xrEnumerateViewConfigurationViews(m_openxr->instance,
|
||||||
view_count, &view_count, m_openxr->view_configs.data());
|
m_openxr->system_id, m_openxr->view_type, view_count, &view_count,
|
||||||
|
m_openxr->view_configs.data()),
|
||||||
|
};
|
||||||
if (XR_FAILED(view_result)) {
|
if (XR_FAILED(view_result)) {
|
||||||
m_logger.warn("Failed to enumerate OpenXR views");
|
m_logger.warn("Failed to enumerate OpenXR views: {}",
|
||||||
|
xr_result_to_string(m_openxr->instance, view_result));
|
||||||
shutdown_openxr();
|
shutdown_openxr();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1246,27 +1521,33 @@ auto Application::init_openxr_session() -> void
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint32_t format_count = 0;
|
uint32_t format_count = 0;
|
||||||
auto const format_count_result = xrEnumerateSwapchainFormats(
|
auto const format_count_result {
|
||||||
m_openxr->session, 0, &format_count, nullptr);
|
xrEnumerateSwapchainFormats(
|
||||||
|
m_openxr->session, 0, &format_count, nullptr),
|
||||||
|
};
|
||||||
if (XR_FAILED(format_count_result) || format_count == 0) {
|
if (XR_FAILED(format_count_result) || format_count == 0) {
|
||||||
m_logger.warn("OpenXR swapchain formats unavailable");
|
m_logger.warn("OpenXR swapchain formats unavailable: {}",
|
||||||
|
xr_result_to_string(m_openxr->instance, format_count_result));
|
||||||
shutdown_openxr();
|
shutdown_openxr();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
std::vector<int64_t> formats(format_count);
|
std::vector<int64_t> formats(format_count);
|
||||||
auto const format_result = xrEnumerateSwapchainFormats(
|
auto const format_result {
|
||||||
m_openxr->session, format_count, &format_count, formats.data());
|
xrEnumerateSwapchainFormats(
|
||||||
|
m_openxr->session, format_count, &format_count, formats.data()),
|
||||||
|
};
|
||||||
if (XR_FAILED(format_result)) {
|
if (XR_FAILED(format_result)) {
|
||||||
m_logger.warn("Failed to enumerate OpenXR swapchain formats");
|
m_logger.warn("Failed to enumerate OpenXR swapchain formats: {}",
|
||||||
|
xr_result_to_string(m_openxr->instance, format_result));
|
||||||
shutdown_openxr();
|
shutdown_openxr();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::array<int64_t, 4> const preferred_formats {
|
std::array<int64_t, 4> const preferred_formats {
|
||||||
static_cast<int64_t>(VK_FORMAT_B8G8R8A8_SRGB),
|
|
||||||
static_cast<int64_t>(VK_FORMAT_B8G8R8A8_UNORM),
|
static_cast<int64_t>(VK_FORMAT_B8G8R8A8_UNORM),
|
||||||
static_cast<int64_t>(VK_FORMAT_R8G8B8A8_SRGB),
|
static_cast<int64_t>(VK_FORMAT_B8G8R8A8_SRGB),
|
||||||
static_cast<int64_t>(VK_FORMAT_R8G8B8A8_UNORM),
|
static_cast<int64_t>(VK_FORMAT_R8G8B8A8_UNORM),
|
||||||
|
static_cast<int64_t>(VK_FORMAT_R8G8B8A8_SRGB),
|
||||||
};
|
};
|
||||||
m_openxr->color_format = formats.front();
|
m_openxr->color_format = formats.front();
|
||||||
for (auto const preferred : preferred_formats) {
|
for (auto const preferred : preferred_formats) {
|
||||||
@@ -1280,7 +1561,7 @@ auto Application::init_openxr_session() -> void
|
|||||||
m_openxr->swapchains.clear();
|
m_openxr->swapchains.clear();
|
||||||
m_openxr->swapchains.resize(view_count);
|
m_openxr->swapchains.resize(view_count);
|
||||||
for (uint32_t i = 0; i < view_count; ++i) {
|
for (uint32_t i = 0; i < view_count; ++i) {
|
||||||
auto const &view_config = m_openxr->view_configs[i];
|
auto const &view_config { m_openxr->view_configs[i] };
|
||||||
XrSwapchainCreateInfo swapchain_info {};
|
XrSwapchainCreateInfo swapchain_info {};
|
||||||
swapchain_info.type = XR_TYPE_SWAPCHAIN_CREATE_INFO;
|
swapchain_info.type = XR_TYPE_SWAPCHAIN_CREATE_INFO;
|
||||||
swapchain_info.next = nullptr;
|
swapchain_info.next = nullptr;
|
||||||
@@ -1295,10 +1576,13 @@ auto Application::init_openxr_session() -> void
|
|||||||
swapchain_info.arraySize = 1;
|
swapchain_info.arraySize = 1;
|
||||||
swapchain_info.mipCount = 1;
|
swapchain_info.mipCount = 1;
|
||||||
|
|
||||||
auto const swapchain_result = xrCreateSwapchain(m_openxr->session,
|
auto const swapchain_result {
|
||||||
&swapchain_info, &m_openxr->swapchains[i].handle);
|
xrCreateSwapchain(m_openxr->session, &swapchain_info,
|
||||||
|
&m_openxr->swapchains[i].handle),
|
||||||
|
};
|
||||||
if (XR_FAILED(swapchain_result)) {
|
if (XR_FAILED(swapchain_result)) {
|
||||||
m_logger.warn("Failed to create OpenXR swapchain");
|
m_logger.warn("Failed to create OpenXR swapchain: {}",
|
||||||
|
xr_result_to_string(m_openxr->instance, swapchain_result));
|
||||||
shutdown_openxr();
|
shutdown_openxr();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1306,11 +1590,14 @@ auto Application::init_openxr_session() -> void
|
|||||||
m_openxr->swapchains[i].extent
|
m_openxr->swapchains[i].extent
|
||||||
= vk::Extent2D { swapchain_info.width, swapchain_info.height };
|
= vk::Extent2D { swapchain_info.width, swapchain_info.height };
|
||||||
|
|
||||||
uint32_t image_count = 0;
|
uint32_t image_count { 0 };
|
||||||
auto const image_count_result = xrEnumerateSwapchainImages(
|
auto const image_count_result {
|
||||||
m_openxr->swapchains[i].handle, 0, &image_count, nullptr);
|
xrEnumerateSwapchainImages(
|
||||||
|
m_openxr->swapchains[i].handle, 0, &image_count, nullptr),
|
||||||
|
};
|
||||||
if (XR_FAILED(image_count_result) || image_count == 0) {
|
if (XR_FAILED(image_count_result) || image_count == 0) {
|
||||||
m_logger.warn("Failed to enumerate OpenXR swapchain images");
|
m_logger.warn("Failed to enumerate OpenXR swapchain images: {}",
|
||||||
|
xr_result_to_string(m_openxr->instance, image_count_result));
|
||||||
shutdown_openxr();
|
shutdown_openxr();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1320,12 +1607,15 @@ auto Application::init_openxr_session() -> void
|
|||||||
image.type = XR_TYPE_SWAPCHAIN_IMAGE_VULKAN_KHR;
|
image.type = XR_TYPE_SWAPCHAIN_IMAGE_VULKAN_KHR;
|
||||||
image.next = nullptr;
|
image.next = nullptr;
|
||||||
}
|
}
|
||||||
auto const image_result = xrEnumerateSwapchainImages(
|
auto const image_result {
|
||||||
m_openxr->swapchains[i].handle, image_count, &image_count,
|
xrEnumerateSwapchainImages(m_openxr->swapchains[i].handle,
|
||||||
reinterpret_cast<XrSwapchainImageBaseHeader *>(
|
image_count, &image_count,
|
||||||
m_openxr->swapchains[i].images.data()));
|
reinterpret_cast<XrSwapchainImageBaseHeader *>(
|
||||||
|
m_openxr->swapchains[i].images.data())),
|
||||||
|
};
|
||||||
if (XR_FAILED(image_result)) {
|
if (XR_FAILED(image_result)) {
|
||||||
m_logger.warn("Failed to read OpenXR swapchain images");
|
m_logger.warn("Failed to read OpenXR swapchain images: {}",
|
||||||
|
xr_result_to_string(m_openxr->instance, image_result));
|
||||||
shutdown_openxr();
|
shutdown_openxr();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1334,6 +1624,33 @@ auto Application::init_openxr_session() -> void
|
|||||||
if (!m_openxr->swapchains.empty()) {
|
if (!m_openxr->swapchains.empty()) {
|
||||||
m_renderer->set_offscreen_extent(m_openxr->swapchains.front().extent);
|
m_renderer->set_offscreen_extent(m_openxr->swapchains.front().extent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (m_openxr->hand_tracking_supported && m_openxr->create_hand_tracker) {
|
||||||
|
XrHandTrackerCreateInfoEXT left_info {};
|
||||||
|
left_info.type = XR_TYPE_HAND_TRACKER_CREATE_INFO_EXT;
|
||||||
|
left_info.next = nullptr;
|
||||||
|
left_info.hand = XR_HAND_LEFT_EXT;
|
||||||
|
left_info.handJointSet = XR_HAND_JOINT_SET_DEFAULT_EXT;
|
||||||
|
auto const left_result { m_openxr->create_hand_tracker(
|
||||||
|
m_openxr->session, &left_info, &m_openxr->left_hand_tracker) };
|
||||||
|
if (XR_FAILED(left_result)) {
|
||||||
|
m_logger.warn("Failed to create left hand tracker");
|
||||||
|
m_openxr->left_hand_tracker = XR_NULL_HANDLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
XrHandTrackerCreateInfoEXT right_info {};
|
||||||
|
right_info.type = XR_TYPE_HAND_TRACKER_CREATE_INFO_EXT;
|
||||||
|
right_info.next = nullptr;
|
||||||
|
right_info.hand = XR_HAND_RIGHT_EXT;
|
||||||
|
right_info.handJointSet = XR_HAND_JOINT_SET_DEFAULT_EXT;
|
||||||
|
auto const right_result { m_openxr->create_hand_tracker(
|
||||||
|
m_openxr->session, &right_info, &m_openxr->right_hand_tracker) };
|
||||||
|
if (XR_FAILED(right_result)) {
|
||||||
|
m_logger.warn("Failed to create right hand tracker");
|
||||||
|
m_openxr->right_hand_tracker = XR_NULL_HANDLE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
m_logger.info("OpenXR session initialized");
|
m_logger.info("OpenXR session initialized");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1351,6 +1668,18 @@ auto Application::shutdown_openxr() -> void
|
|||||||
}
|
}
|
||||||
m_openxr->swapchains.clear();
|
m_openxr->swapchains.clear();
|
||||||
|
|
||||||
|
if (m_openxr->left_hand_tracker != XR_NULL_HANDLE
|
||||||
|
&& m_openxr->destroy_hand_tracker) {
|
||||||
|
m_openxr->destroy_hand_tracker(m_openxr->left_hand_tracker);
|
||||||
|
m_openxr->left_hand_tracker = XR_NULL_HANDLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_openxr->right_hand_tracker != XR_NULL_HANDLE
|
||||||
|
&& m_openxr->destroy_hand_tracker) {
|
||||||
|
m_openxr->destroy_hand_tracker(m_openxr->right_hand_tracker);
|
||||||
|
m_openxr->right_hand_tracker = XR_NULL_HANDLE;
|
||||||
|
}
|
||||||
|
|
||||||
if (m_openxr->app_space != XR_NULL_HANDLE) {
|
if (m_openxr->app_space != XR_NULL_HANDLE) {
|
||||||
xrDestroySpace(m_openxr->app_space);
|
xrDestroySpace(m_openxr->app_space);
|
||||||
m_openxr->app_space = XR_NULL_HANDLE;
|
m_openxr->app_space = XR_NULL_HANDLE;
|
||||||
@@ -1381,9 +1710,10 @@ auto Application::poll_openxr_events() -> void
|
|||||||
while (xrPollEvent(m_openxr->instance, &event) == XR_SUCCESS) {
|
while (xrPollEvent(m_openxr->instance, &event) == XR_SUCCESS) {
|
||||||
switch (event.type) {
|
switch (event.type) {
|
||||||
case XR_TYPE_EVENT_DATA_SESSION_STATE_CHANGED: {
|
case XR_TYPE_EVENT_DATA_SESSION_STATE_CHANGED: {
|
||||||
auto const &state_event
|
auto const &state_event {
|
||||||
= *reinterpret_cast<XrEventDataSessionStateChanged const *>(
|
*reinterpret_cast<XrEventDataSessionStateChanged const *>(
|
||||||
&event);
|
&event)
|
||||||
|
};
|
||||||
m_openxr->session_state = state_event.state;
|
m_openxr->session_state = state_event.state;
|
||||||
if (state_event.state == XR_SESSION_STATE_READY
|
if (state_event.state == XR_SESSION_STATE_READY
|
||||||
&& !m_openxr->session_running) {
|
&& !m_openxr->session_running) {
|
||||||
@@ -1461,7 +1791,7 @@ auto Application::render_openxr_frame(
|
|||||||
XrViewState view_state {};
|
XrViewState view_state {};
|
||||||
view_state.type = XR_TYPE_VIEW_STATE;
|
view_state.type = XR_TYPE_VIEW_STATE;
|
||||||
view_state.next = nullptr;
|
view_state.next = nullptr;
|
||||||
uint32_t view_count = static_cast<uint32_t>(m_openxr->views.size());
|
auto view_count { static_cast<uint32_t>(m_openxr->views.size()) };
|
||||||
view_count = std::min(
|
view_count = std::min(
|
||||||
view_count, static_cast<uint32_t>(m_openxr->swapchains.size()));
|
view_count, static_cast<uint32_t>(m_openxr->swapchains.size()));
|
||||||
if (XR_FAILED(xrLocateViews(m_openxr->session, &locate_info, &view_state,
|
if (XR_FAILED(xrLocateViews(m_openxr->session, &locate_info, &view_state,
|
||||||
@@ -1469,6 +1799,8 @@ auto Application::render_openxr_frame(
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
update_hands(frame_state.predictedDisplayTime);
|
||||||
|
|
||||||
std::vector<XrCompositionLayerProjectionView> projection_views(view_count);
|
std::vector<XrCompositionLayerProjectionView> projection_views(view_count);
|
||||||
for (auto &projection_view : projection_views) {
|
for (auto &projection_view : projection_views) {
|
||||||
projection_view = XrCompositionLayerProjectionView {};
|
projection_view = XrCompositionLayerProjectionView {};
|
||||||
@@ -1476,8 +1808,8 @@ auto Application::render_openxr_frame(
|
|||||||
projection_view.next = nullptr;
|
projection_view.next = nullptr;
|
||||||
}
|
}
|
||||||
for (uint32_t i = 0; i < view_count; ++i) {
|
for (uint32_t i = 0; i < view_count; ++i) {
|
||||||
auto &swapchain = m_openxr->swapchains[i];
|
auto const &swapchain { m_openxr->swapchains[i] };
|
||||||
uint32_t image_index = 0;
|
uint32_t image_index { 0 };
|
||||||
XrSwapchainImageAcquireInfo acquire_info {};
|
XrSwapchainImageAcquireInfo acquire_info {};
|
||||||
acquire_info.type = XR_TYPE_SWAPCHAIN_IMAGE_ACQUIRE_INFO;
|
acquire_info.type = XR_TYPE_SWAPCHAIN_IMAGE_ACQUIRE_INFO;
|
||||||
acquire_info.next = nullptr;
|
acquire_info.next = nullptr;
|
||||||
@@ -1522,8 +1854,9 @@ auto Application::render_openxr_frame(
|
|||||||
layer.viewCount = view_count;
|
layer.viewCount = view_count;
|
||||||
layer.views = projection_views.data();
|
layer.views = projection_views.data();
|
||||||
|
|
||||||
XrCompositionLayerBaseHeader const *layers[]
|
XrCompositionLayerBaseHeader const *layers[] {
|
||||||
= { reinterpret_cast<XrCompositionLayerBaseHeader *>(&layer) };
|
reinterpret_cast<XrCompositionLayerBaseHeader *>(&layer)
|
||||||
|
};
|
||||||
XrFrameEndInfo end_info {};
|
XrFrameEndInfo end_info {};
|
||||||
end_info.type = XR_TYPE_FRAME_END_INFO;
|
end_info.type = XR_TYPE_FRAME_END_INFO;
|
||||||
end_info.next = nullptr;
|
end_info.next = nullptr;
|
||||||
@@ -1536,12 +1869,13 @@ auto Application::render_openxr_frame(
|
|||||||
|
|
||||||
auto Application::update_camera_from_xr_view(XrView const &view) -> void
|
auto Application::update_camera_from_xr_view(XrView const &view) -> void
|
||||||
{
|
{
|
||||||
auto const &pose = view.pose;
|
auto const &pose { view.pose };
|
||||||
smath::Vec3 position { pose.position.x, pose.position.y, pose.position.z };
|
smath::Vec3 const position { pose.position.x, pose.position.y,
|
||||||
auto forward
|
pose.position.z };
|
||||||
= xr_rotate_vector(pose.orientation, smath::Vec3 { 0.0f, 0.0f, -1.0f });
|
auto const forward { xr_rotate_vector(
|
||||||
auto up
|
pose.orientation, smath::Vec3 { 0.0f, 0.0f, -1.0f }) };
|
||||||
= xr_rotate_vector(pose.orientation, smath::Vec3 { 0.0f, 1.0f, 0.0f });
|
auto const up { xr_rotate_vector(
|
||||||
|
pose.orientation, smath::Vec3 { 0.0f, 1.0f, 0.0f }) };
|
||||||
m_camera.position = position;
|
m_camera.position = position;
|
||||||
m_camera.target = position + forward;
|
m_camera.target = position + forward;
|
||||||
m_camera.up = up;
|
m_camera.up = up;
|
||||||
@@ -1549,6 +1883,106 @@ auto Application::update_camera_from_xr_view(XrView const &view) -> void
|
|||||||
m_cursor = PolarCoordinate::from_vec3(m_camera.target - m_camera.position);
|
m_cursor = PolarCoordinate::from_vec3(m_camera.target - m_camera.position);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto Application::update_hands(XrTime display_time) -> void
|
||||||
|
{
|
||||||
|
if (!m_openxr || !m_openxr->hand_tracking_supported) {
|
||||||
|
m_left_hand_valid = false;
|
||||||
|
m_right_hand_valid = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_openxr->left_hand_tracker != XR_NULL_HANDLE
|
||||||
|
&& m_openxr->locate_hand_joints) {
|
||||||
|
XrHandJointsLocateInfoEXT locate_info {};
|
||||||
|
locate_info.type = XR_TYPE_HAND_JOINTS_LOCATE_INFO_EXT;
|
||||||
|
locate_info.next = nullptr;
|
||||||
|
locate_info.baseSpace = m_openxr->app_space;
|
||||||
|
locate_info.time = display_time;
|
||||||
|
|
||||||
|
XrHandJointLocationEXT locations[XR_HAND_JOINT_COUNT_EXT];
|
||||||
|
XrHandJointLocationsEXT locations_info {};
|
||||||
|
locations_info.type = XR_TYPE_HAND_JOINT_LOCATIONS_EXT;
|
||||||
|
locations_info.next = nullptr;
|
||||||
|
locations_info.jointCount = XR_HAND_JOINT_COUNT_EXT;
|
||||||
|
locations_info.jointLocations = locations;
|
||||||
|
|
||||||
|
if (XR_SUCCEEDED(m_openxr->locate_hand_joints(
|
||||||
|
m_openxr->left_hand_tracker, &locate_info, &locations_info))) {
|
||||||
|
m_left_hand_valid = (locations[0].locationFlags
|
||||||
|
& XR_SPACE_LOCATION_POSITION_VALID_BIT)
|
||||||
|
!= 0;
|
||||||
|
if (m_left_hand_valid) {
|
||||||
|
for (uint32_t j { 0 }; j < XR_HAND_JOINT_COUNT_EXT; j++) {
|
||||||
|
m_left_joints[j]
|
||||||
|
= smath::Vec3 { locations[j].pose.position.x,
|
||||||
|
locations[j].pose.position.y,
|
||||||
|
locations[j].pose.position.z };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
m_left_hand_valid = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_openxr->right_hand_tracker != XR_NULL_HANDLE
|
||||||
|
&& m_openxr->locate_hand_joints) {
|
||||||
|
XrHandJointsLocateInfoEXT locate_info {};
|
||||||
|
locate_info.type = XR_TYPE_HAND_JOINTS_LOCATE_INFO_EXT;
|
||||||
|
locate_info.next = nullptr;
|
||||||
|
locate_info.baseSpace = m_openxr->app_space;
|
||||||
|
locate_info.time = display_time;
|
||||||
|
|
||||||
|
XrHandJointLocationEXT locations[XR_HAND_JOINT_COUNT_EXT];
|
||||||
|
XrHandJointLocationsEXT locations_info {};
|
||||||
|
locations_info.type = XR_TYPE_HAND_JOINT_LOCATIONS_EXT;
|
||||||
|
locations_info.next = nullptr;
|
||||||
|
locations_info.jointCount = XR_HAND_JOINT_COUNT_EXT;
|
||||||
|
locations_info.jointLocations = locations;
|
||||||
|
|
||||||
|
if (XR_SUCCEEDED(m_openxr->locate_hand_joints(
|
||||||
|
m_openxr->right_hand_tracker, &locate_info, &locations_info))) {
|
||||||
|
m_right_hand_valid = (locations[0].locationFlags
|
||||||
|
& XR_SPACE_LOCATION_POSITION_VALID_BIT)
|
||||||
|
!= 0;
|
||||||
|
if (m_right_hand_valid) {
|
||||||
|
for (uint32_t j { 0 }; j < XR_HAND_JOINT_COUNT_EXT; j++) {
|
||||||
|
m_right_joints[j]
|
||||||
|
= smath::Vec3 { locations[j].pose.position.x,
|
||||||
|
locations[j].pose.position.y,
|
||||||
|
locations[j].pose.position.z };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
m_right_hand_valid = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto Application::render_hands(
|
||||||
|
VulkanRenderer::GL &gl, smath::Mat4 const &view_projection) -> void
|
||||||
|
{
|
||||||
|
gl.set_texture(&m_renderer->white_texture());
|
||||||
|
auto constexpr radius { 0.005f };
|
||||||
|
|
||||||
|
if (m_left_hand_valid) {
|
||||||
|
for (uint32_t j { 0 }; j < XR_HAND_JOINT_COUNT_EXT; j++) {
|
||||||
|
auto const &pos { m_left_joints[j] };
|
||||||
|
gl.set_transform(view_projection * smath::translate(pos));
|
||||||
|
gl.draw_sphere(smath::Vec3 { 0.0f, 0.0f, 0.0f }, radius, 8, 16,
|
||||||
|
smath::Vec4 { 1.0f, 0.0f, 0.0f, 1.0f });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_right_hand_valid) {
|
||||||
|
for (uint32_t j { 0 }; j < XR_HAND_JOINT_COUNT_EXT; j++) {
|
||||||
|
auto const &pos { m_right_joints[j] };
|
||||||
|
gl.set_transform(view_projection * smath::translate(pos));
|
||||||
|
gl.draw_sphere(smath::Vec3 { 0.0f, 0.0f, 0.0f }, radius, 8, 16,
|
||||||
|
smath::Vec4 { 1.0f, 0.0f, 0.0f, 1.0f });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
auto Application::process_libinput_events() -> void
|
auto Application::process_libinput_events() -> void
|
||||||
{
|
{
|
||||||
if (!m_libinput)
|
if (!m_libinput)
|
||||||
|
|||||||
@@ -13,6 +13,8 @@
|
|||||||
#include <linux/input-event-codes.h>
|
#include <linux/input-event-codes.h>
|
||||||
#include <openxr/openxr.h>
|
#include <openxr/openxr.h>
|
||||||
|
|
||||||
|
#include "smath.hpp"
|
||||||
|
|
||||||
#include "Loader.h"
|
#include "Loader.h"
|
||||||
#include "Logger.h"
|
#include "Logger.h"
|
||||||
#include "Skybox.h"
|
#include "Skybox.h"
|
||||||
@@ -73,6 +75,9 @@ private:
|
|||||||
std::function<void(VulkanRenderer::GL &)> const &record,
|
std::function<void(VulkanRenderer::GL &)> const &record,
|
||||||
float dt_seconds) -> bool;
|
float dt_seconds) -> bool;
|
||||||
auto update_camera_from_xr_view(XrView const &view) -> void;
|
auto update_camera_from_xr_view(XrView const &view) -> void;
|
||||||
|
auto update_hands(XrTime display_time) -> void;
|
||||||
|
auto render_hands(
|
||||||
|
VulkanRenderer::GL &gl, smath::Mat4 const &view_projection) -> void;
|
||||||
|
|
||||||
SDL_Window *m_window { nullptr };
|
SDL_Window *m_window { nullptr };
|
||||||
Backend m_backend { Backend::SDL };
|
Backend m_backend { Backend::SDL };
|
||||||
@@ -104,6 +109,13 @@ private:
|
|||||||
|
|
||||||
Camera m_camera;
|
Camera m_camera;
|
||||||
PolarCoordinate m_cursor;
|
PolarCoordinate m_cursor;
|
||||||
|
|
||||||
|
static inline std::array<smath::Vec3, XR_HAND_JOINT_COUNT_EXT>
|
||||||
|
m_left_joints {};
|
||||||
|
static inline std::array<smath::Vec3, XR_HAND_JOINT_COUNT_EXT>
|
||||||
|
m_right_joints {};
|
||||||
|
static inline bool m_left_hand_valid { false };
|
||||||
|
static inline bool m_right_hand_valid { false };
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Lunar
|
} // namespace Lunar
|
||||||
|
|||||||
+77
-22
@@ -426,37 +426,66 @@ auto VulkanRenderer::GL::draw_sphere(smath::Vec3 center, float radius,
|
|||||||
if (sphere_color.has_value())
|
if (sphere_color.has_value())
|
||||||
color(*sphere_color);
|
color(*sphere_color);
|
||||||
|
|
||||||
|
begin(GeometryKind::Triangles);
|
||||||
|
|
||||||
for (int y = 0; y < rings; y++) {
|
for (int y = 0; y < rings; y++) {
|
||||||
float const v = static_cast<float>(y + 1) / static_cast<float>(rings);
|
float const v1 = static_cast<float>(y) / static_cast<float>(rings);
|
||||||
|
float const v2 = static_cast<float>(y + 1) / static_cast<float>(rings);
|
||||||
|
|
||||||
float const theta = v * pi;
|
float const theta1 = v1 * pi;
|
||||||
|
float const theta2 = v2 * pi;
|
||||||
|
|
||||||
float const s = std::sin(theta);
|
float const s1 = std::sin(theta1);
|
||||||
float const c = std::cos(theta);
|
float const c1 = std::cos(theta1);
|
||||||
|
float const s2 = std::sin(theta2);
|
||||||
|
float const c2 = std::cos(theta2);
|
||||||
|
|
||||||
begin(GeometryKind::TriangleStrip);
|
for (int x = 0; x < segments; x++) {
|
||||||
|
float const u1
|
||||||
for (int x = 0; x <= segments; x++) {
|
|
||||||
float const u
|
|
||||||
= static_cast<float>(x) / static_cast<float>(segments);
|
= static_cast<float>(x) / static_cast<float>(segments);
|
||||||
float const phi = u * (2.0f * pi);
|
float const u2
|
||||||
|
= static_cast<float>(x + 1) / static_cast<float>(segments);
|
||||||
|
|
||||||
float const sp = std::sin(phi);
|
float const phi1 = u1 * (2.0f * pi);
|
||||||
float const cp = std::cos(phi);
|
float const phi2 = u2 * (2.0f * pi);
|
||||||
|
|
||||||
// Vertex on ring y+1
|
float const sp1 = std::sin(phi1);
|
||||||
{
|
float const cp1 = std::cos(phi1);
|
||||||
smath::Vec3 n { s * cp, c, s * sp };
|
float const sp2 = std::sin(phi2);
|
||||||
normal(n);
|
float const cp2 = std::cos(phi2);
|
||||||
uv(smath::Vec2 { u, 1.0f - v });
|
|
||||||
|
|
||||||
smath::Vec3 p { center + n * radius };
|
smath::Vec3 n1 { s1 * cp1, c1, s1 * sp1 };
|
||||||
vert(p);
|
smath::Vec3 n2 { s1 * cp2, c1, s1 * sp2 };
|
||||||
}
|
smath::Vec3 n3 { s2 * cp1, c2, s2 * sp1 };
|
||||||
|
smath::Vec3 n4 { s2 * cp2, c2, s2 * sp2 };
|
||||||
|
|
||||||
|
normal(n1);
|
||||||
|
uv(smath::Vec2 { u1, 1.0f - v1 });
|
||||||
|
vert(center + n1 * radius);
|
||||||
|
|
||||||
|
normal(n2);
|
||||||
|
uv(smath::Vec2 { u2, 1.0f - v1 });
|
||||||
|
vert(center + n2 * radius);
|
||||||
|
|
||||||
|
normal(n3);
|
||||||
|
uv(smath::Vec2 { u1, 1.0f - v2 });
|
||||||
|
vert(center + n3 * radius);
|
||||||
|
|
||||||
|
normal(n2);
|
||||||
|
uv(smath::Vec2 { u2, 1.0f - v1 });
|
||||||
|
vert(center + n2 * radius);
|
||||||
|
|
||||||
|
normal(n4);
|
||||||
|
uv(smath::Vec2 { u2, 1.0f - v2 });
|
||||||
|
vert(center + n4 * radius);
|
||||||
|
|
||||||
|
normal(n3);
|
||||||
|
uv(smath::Vec2 { u1, 1.0f - v2 });
|
||||||
|
vert(center + n3 * radius);
|
||||||
}
|
}
|
||||||
|
|
||||||
end();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
end();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto VulkanRenderer::GL::draw_mesh(GPUMeshBuffers const &mesh,
|
auto VulkanRenderer::GL::draw_mesh(GPUMeshBuffers const &mesh,
|
||||||
@@ -910,19 +939,35 @@ auto VulkanRenderer::setup_kms_surface() -> void
|
|||||||
throw std::runtime_error("App init fail");
|
throw std::runtime_error("App init fail");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_logger.info("Found {} Vulkan physical device(s)", devices.size());
|
||||||
|
|
||||||
for (auto const &device : devices) {
|
for (auto const &device : devices) {
|
||||||
|
auto const props = device.getProperties();
|
||||||
|
m_logger.info("Checking device: {}", std::string(props.deviceName));
|
||||||
|
|
||||||
auto const displays = device.getDisplayPropertiesKHR();
|
auto const displays = device.getDisplayPropertiesKHR();
|
||||||
if (displays.empty()) {
|
if (displays.empty()) {
|
||||||
|
m_logger.info(" Device has no display properties");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_logger.info(" Device has {} display(s)", displays.size());
|
||||||
|
|
||||||
for (auto const &display_props : displays) {
|
for (auto const &display_props : displays) {
|
||||||
|
m_logger.info(" Checking display: {}",
|
||||||
|
display_props.displayName
|
||||||
|
? std::string(display_props.displayName)
|
||||||
|
: "(unnamed)");
|
||||||
|
|
||||||
auto const modes
|
auto const modes
|
||||||
= device.getDisplayModePropertiesKHR(display_props.display);
|
= device.getDisplayModePropertiesKHR(display_props.display);
|
||||||
if (modes.empty()) {
|
if (modes.empty()) {
|
||||||
|
m_logger.info(" Display has no modes");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_logger.info(" Display has {} mode(s)", modes.size());
|
||||||
|
|
||||||
auto const best_mode_it = std::max_element(modes.begin(),
|
auto const best_mode_it = std::max_element(modes.begin(),
|
||||||
modes.end(), [](auto const &lhs, auto const &rhs) {
|
modes.end(), [](auto const &lhs, auto const &rhs) {
|
||||||
auto const lhs_extent = lhs.parameters.visibleRegion;
|
auto const lhs_extent = lhs.parameters.visibleRegion;
|
||||||
@@ -955,9 +1000,15 @@ auto VulkanRenderer::setup_kms_surface() -> void
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!plane_index) {
|
if (!plane_index) {
|
||||||
|
m_logger.info(" No display plane supports this display ({} "
|
||||||
|
"plane(s) checked)",
|
||||||
|
planes.size());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_logger.info(
|
||||||
|
" Found suitable display on plane {}", *plane_index);
|
||||||
|
|
||||||
auto const extent = best_mode_it->parameters.visibleRegion;
|
auto const extent = best_mode_it->parameters.visibleRegion;
|
||||||
KmsState state {};
|
KmsState state {};
|
||||||
state.display = display_props.display;
|
state.display = display_props.display;
|
||||||
@@ -1097,13 +1148,17 @@ auto VulkanRenderer::vk_init() -> void
|
|||||||
VK_KHR_COPY_COMMANDS_2_EXTENSION_NAME,
|
VK_KHR_COPY_COMMANDS_2_EXTENSION_NAME,
|
||||||
VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME,
|
VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME,
|
||||||
};
|
};
|
||||||
|
std::vector<char const *> required_extensions {};
|
||||||
for (auto const &extension : m_extra_device_extensions) {
|
for (auto const &extension : m_extra_device_extensions) {
|
||||||
desired_extensions.push_back(extension.c_str());
|
required_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(desired_extensions)
|
.add_desired_extensions(desired_extensions)
|
||||||
.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);
|
||||||
|
if (!required_extensions.empty()) {
|
||||||
|
phys_device_selector.add_required_extensions(required_extensions);
|
||||||
|
}
|
||||||
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) {
|
||||||
std::println(std::cerr,
|
std::println(std::cerr,
|
||||||
|
|||||||
Reference in New Issue
Block a user