diff options
author | Bastiaan Olij <mux213@gmail.com> | 2024-03-21 18:58:24 +1100 |
---|---|---|
committer | Bastiaan Olij <mux213@gmail.com> | 2024-05-01 14:24:41 +1000 |
commit | cbab7dc04942ccb07a2ca0bc942498a319e57e35 (patch) | |
tree | cbdea1856b04a1e1b6f0c9eb388dd73246306490 /modules/openxr/openxr_api.h | |
parent | d282e4f0e6b6ebcf3bd6e05cd62f2a8fe1f9a238 (diff) | |
download | redot-engine-cbab7dc04942ccb07a2ca0bc942498a319e57e35.tar.gz |
OpenXR: Change timing of xrWaitFrame and add thread safety features to OpenXR
Diffstat (limited to 'modules/openxr/openxr_api.h')
-rw-r--r-- | modules/openxr/openxr_api.h | 90 |
1 files changed, 76 insertions, 14 deletions
diff --git a/modules/openxr/openxr_api.h b/modules/openxr/openxr_api.h index e835366200..c95867810c 100644 --- a/modules/openxr/openxr_api.h +++ b/modules/openxr/openxr_api.h @@ -46,13 +46,11 @@ #include "core/templates/rb_map.h" #include "core/templates/rid_owner.h" #include "core/templates/vector.h" +#include "servers/rendering_server.h" #include "servers/xr/xr_pose.h" #include <openxr/openxr.h> -// Note, OpenXR code that we wrote for our plugin makes use of C++20 notation for initializing structs which ensures zeroing out unspecified members. -// Godot is currently restricted to C++17 which doesn't allow this notation. Make sure critical fields are set. - // forward declarations, we don't want to include these fully class OpenXRInterface; @@ -77,7 +75,7 @@ public: static void free_queued(); void free(); - bool acquire(XrBool32 &p_should_render); + bool acquire(bool &p_should_render); bool release(); RID get_image(); }; @@ -151,9 +149,6 @@ private: uint32_t view_count = 0; XrViewConfigurationView *view_configuration_views = nullptr; - XrView *views = nullptr; - XrCompositionLayerProjectionView *projection_views = nullptr; - XrCompositionLayerDepthInfoKHR *depth_views = nullptr; // Only used by Composition Layer Depth Extension if available enum OpenXRSwapChainTypes { OPENXR_SWAPCHAIN_COLOR, @@ -164,14 +159,11 @@ private: int64_t color_swapchain_format = 0; int64_t depth_swapchain_format = 0; - Size2i main_swapchain_size = { 0, 0 }; - OpenXRSwapChainInfo main_swapchains[OPENXR_SWAPCHAIN_MAX]; + bool play_space_is_dirty = true; XrSpace play_space = XR_NULL_HANDLE; XrSpace view_space = XR_NULL_HANDLE; - bool view_pose_valid = false; XRPose::TrackingConfidence head_pose_confidence = XRPose::XR_TRACKING_CONFIDENCE_NONE; - bool has_xr_viewport = false; bool emulating_local_floor = false; bool should_reset_emulated_floor_height = false; @@ -328,6 +320,72 @@ private: // convenience void copy_string_to_char_buffer(const String p_string, char *p_buffer, int p_buffer_len); + // Render state, Only accessible in rendering thread + struct RenderState { + bool running = false; + bool should_render = false; + bool has_xr_viewport = false; + XrTime predicted_display_time = 0; + XrSpace play_space = XR_NULL_HANDLE; + double render_target_size_multiplier = 1.0; + + uint32_t view_count = 0; + XrView *views = nullptr; + XrCompositionLayerProjectionView *projection_views = nullptr; + XrCompositionLayerDepthInfoKHR *depth_views = nullptr; // Only used by Composition Layer Depth Extension if available + bool submit_depth_buffer = false; // if set to true we submit depth buffers to OpenXR if a suitable extension is enabled. + bool view_pose_valid = false; + + Size2i main_swapchain_size; + OpenXRSwapChainInfo main_swapchains[OPENXR_SWAPCHAIN_MAX]; + } render_state; + + static void _allocate_view_buffers(uint32_t p_view_count, bool p_submit_depth_buffer); + static void _set_render_session_running(bool p_is_running); + static void _set_render_display_info(XrTime p_predicted_display_time, bool p_should_render); + static void _set_render_play_space(uint64_t p_play_space); + static void _set_render_state_multiplier(double p_render_target_size_multiplier); + + _FORCE_INLINE_ void allocate_view_buffers(uint32_t p_view_count, bool p_submit_depth_buffer) { + // If we're rendering on a separate thread, we may still be processing the last frame, don't communicate this till we're ready... + RenderingServer *rendering_server = RenderingServer::get_singleton(); + ERR_FAIL_NULL(rendering_server); + + rendering_server->call_on_render_thread(callable_mp_static(&OpenXRAPI::_allocate_view_buffers).bind(p_view_count, p_submit_depth_buffer)); + } + + _FORCE_INLINE_ void set_render_session_running(bool p_is_running) { + // If we're rendering on a separate thread, we may still be processing the last frame, don't communicate this till we're ready... + RenderingServer *rendering_server = RenderingServer::get_singleton(); + ERR_FAIL_NULL(rendering_server); + + rendering_server->call_on_render_thread(callable_mp_static(&OpenXRAPI::_set_render_session_running).bind(p_is_running)); + } + + _FORCE_INLINE_ void set_render_display_info(XrTime p_predicted_display_time, bool p_should_render) { + // If we're rendering on a separate thread, we may still be processing the last frame, don't communicate this till we're ready... + RenderingServer *rendering_server = RenderingServer::get_singleton(); + ERR_FAIL_NULL(rendering_server); + + rendering_server->call_on_render_thread(callable_mp_static(&OpenXRAPI::_set_render_display_info).bind(p_predicted_display_time, p_should_render)); + } + + _FORCE_INLINE_ void set_render_play_space(XrSpace p_play_space) { + // If we're rendering on a separate thread, we may still be processing the last frame, don't communicate this till we're ready... + RenderingServer *rendering_server = RenderingServer::get_singleton(); + ERR_FAIL_NULL(rendering_server); + + rendering_server->call_on_render_thread(callable_mp_static(&OpenXRAPI::_set_render_play_space).bind(uint64_t(p_play_space))); + } + + _FORCE_INLINE_ void set_render_state_multiplier(double p_render_target_size_multiplier) { + // If we're rendering on a separate thread, we may still be processing the last frame, don't communicate this till we're ready... + RenderingServer *rendering_server = RenderingServer::get_singleton(); + ERR_FAIL_NULL(rendering_server); + + rendering_server->call_on_render_thread(callable_mp_static(&OpenXRAPI::_set_render_state_multiplier).bind(p_render_target_size_multiplier)); + } + public: XrInstance get_instance() const { return instance; }; XrSystemId get_system_id() const { return system_id; }; @@ -384,9 +442,13 @@ public: bool initialize_session(); void finish(); - XrSpace get_play_space() const { return play_space; } - XrTime get_next_frame_time() { return frame_state.predictedDisplayTime + frame_state.predictedDisplayPeriod; } - bool can_render() { return instance != XR_NULL_HANDLE && session != XR_NULL_HANDLE && running && view_pose_valid && frame_state.shouldRender; } + _FORCE_INLINE_ XrSpace get_play_space() const { return play_space; } + _FORCE_INLINE_ XrTime get_predicted_display_time() { return frame_state.predictedDisplayTime; } + _FORCE_INLINE_ XrTime get_next_frame_time() { return frame_state.predictedDisplayTime + frame_state.predictedDisplayPeriod; } + _FORCE_INLINE_ bool can_render() { + ERR_ON_RENDER_THREAD_V(false); + return instance != XR_NULL_HANDLE && session != XR_NULL_HANDLE && running && frame_state.shouldRender; + } XrHandTrackerEXT get_hand_tracker(int p_hand_index); |