diff --git a/drivers/gles3/storage/texture_storage.cpp b/drivers/gles3/storage/texture_storage.cpp index 14bbe635a4f0..28eeb2ebb3c7 100644 --- a/drivers/gles3/storage/texture_storage.cpp +++ b/drivers/gles3/storage/texture_storage.cpp @@ -2481,7 +2481,7 @@ Size2i TextureStorage::render_target_get_size(RID p_render_target) const { return rt->size; } -void TextureStorage::render_target_set_override(RID p_render_target, RID p_color_texture, RID p_depth_texture, RID p_velocity_texture) { +void TextureStorage::render_target_set_override(RID p_render_target, RID p_color_texture, RID p_depth_texture, RID p_velocity_texture, RID p_velocity_depth_texture) { RenderTarget *rt = render_target_owner.get_or_null(p_render_target); ERR_FAIL_NULL(rt); ERR_FAIL_COND(rt->direct_to_screen); diff --git a/drivers/gles3/storage/texture_storage.h b/drivers/gles3/storage/texture_storage.h index 916662dcd66f..1fecb2e5bb39 100644 --- a/drivers/gles3/storage/texture_storage.h +++ b/drivers/gles3/storage/texture_storage.h @@ -685,13 +685,17 @@ class TextureStorage : public RendererTextureStorage { virtual void render_target_set_vrs_texture(RID p_render_target, RID p_texture) override {} virtual RID render_target_get_vrs_texture(RID p_render_target) const override { return RID(); } - virtual void render_target_set_override(RID p_render_target, RID p_color_texture, RID p_depth_texture, RID p_velocity_texture) override; + virtual void render_target_set_override(RID p_render_target, RID p_color_texture, RID p_depth_texture, RID p_velocity_texture, RID p_velocity_depth_texture) override; virtual RID render_target_get_override_color(RID p_render_target) const override; virtual RID render_target_get_override_depth(RID p_render_target) const override; virtual RID render_target_get_override_velocity(RID p_render_target) const override; + virtual RID render_target_get_override_velocity_depth(RID p_render_target) const override { return RID(); } virtual RID render_target_get_texture(RID p_render_target) override; + virtual void render_target_set_velocity_target_size(RID p_render_target, const Size2i &p_target_size) override {} + virtual Size2i render_target_get_velocity_target_size(RID p_render_target) const override { return Size2i(); } + void bind_framebuffer(GLuint framebuffer) { glBindFramebuffer(GL_FRAMEBUFFER, framebuffer); } diff --git a/modules/openxr/doc_classes/OpenXRAPIExtension.xml b/modules/openxr/doc_classes/OpenXRAPIExtension.xml index 432b331eecd2..d244b4219d10 100644 --- a/modules/openxr/doc_classes/OpenXRAPIExtension.xml +++ b/modules/openxr/doc_classes/OpenXRAPIExtension.xml @@ -82,12 +82,32 @@ Returns the predicted display timing for the current frame. + + + + Returns the far boundary value of the camera frustum. + [b]Note:[/b] This is only accessible in the render thread. + + + + + + Returns the near boundary value of the camera frustum. + [b]Note:[/b] This is only accessible in the render thread. + + Returns the OpenXR session, which is an [url=https://registry.khronos.org/OpenXR/specs/1.0/man/html/XrSession.html]XrSession[/url] cast to an integer. + + + + Returns an array of supported swapchain formats. + + @@ -133,6 +153,54 @@ Returns [code]true[/code] if OpenXR is enabled. + + + + + Acquires the image of the provided swapchain. + + + + + + + + + + + + + Returns a pointer to a new swapchain created using the provided parameters. + + + + + + + Destroys the provided swapchain and frees it from memory. + + + + + + + Returns the RID of the provided swapchain's image. + + + + + + + Returns the [code]XrSwapchain[/code] handle of the provided swapchain. + + + + + + + Releases the image of the provided swapchain. + + @@ -140,6 +208,13 @@ Registers the given extension as a composition layer provider. + + + + + Registers the given extension as a provider of additional data structures to projections views. + + @@ -156,6 +231,27 @@ Set the object name of an OpenXR object, used for debug output. [param object_type] must be a valid OpenXR [code]XrObjectType[/code] enum and [param object_handle] must be a valid OpenXR object handle. + + + + + Sets the render target of the velocity depth texture. + + + + + + + Sets the target size of the velocity and velocity depth textures. + + + + + + + Sets the render target of the velocity texture. + + @@ -170,6 +266,13 @@ Unregisters the given extension as a composition layer provider. + + + + + Unregisters the given extension as a provider of additional data structures to projections views. + + diff --git a/modules/openxr/doc_classes/OpenXRExtensionWrapperExtension.xml b/modules/openxr/doc_classes/OpenXRExtensionWrapperExtension.xml index c174ee4d69cc..cf6cd37c3084 100644 --- a/modules/openxr/doc_classes/OpenXRExtensionWrapperExtension.xml +++ b/modules/openxr/doc_classes/OpenXRExtensionWrapperExtension.xml @@ -217,6 +217,14 @@ Adds additional data structures when the OpenXR instance is created. + + + + + + Adds additional data structures to the projection view of the given [param view_index]. + + diff --git a/modules/openxr/extensions/openxr_composition_layer_extension.cpp b/modules/openxr/extensions/openxr_composition_layer_extension.cpp index 1e3490d1ed9c..f6270288913a 100644 --- a/modules/openxr/extensions/openxr_composition_layer_extension.cpp +++ b/modules/openxr/extensions/openxr_composition_layer_extension.cpp @@ -210,7 +210,7 @@ void OpenXRViewportCompositionLayerProvider::set_viewport(RID p_viewport, Size2i if (subviewport.viewport != p_viewport) { if (subviewport.viewport.is_valid()) { RID rt = rs->viewport_get_render_target(subviewport.viewport); - RSG::texture_storage->render_target_set_override(rt, RID(), RID(), RID()); + RSG::texture_storage->render_target_set_override(rt, RID(), RID(), RID(), RID()); } subviewport.viewport = p_viewport; @@ -323,7 +323,7 @@ void OpenXRViewportCompositionLayerProvider::on_pre_render() { if (update_and_acquire_swapchain(update_mode == RS::VIEWPORT_UPDATE_ONCE)) { // Render to our XR swapchain image. RID rt = rs->viewport_get_render_target(subviewport.viewport); - RSG::texture_storage->render_target_set_override(rt, get_current_swapchain_texture(), RID(), RID()); + RSG::texture_storage->render_target_set_override(rt, get_current_swapchain_texture(), RID(), RID(), RID()); } } } diff --git a/modules/openxr/extensions/openxr_extension_wrapper.h b/modules/openxr/extensions/openxr_extension_wrapper.h index 95b537d1b453..9e3a7136f56b 100644 --- a/modules/openxr/extensions/openxr_extension_wrapper.h +++ b/modules/openxr/extensions/openxr_extension_wrapper.h @@ -62,6 +62,7 @@ class OpenXRExtensionWrapper { virtual void *set_session_create_and_get_next_pointer(void *p_next_pointer) { return p_next_pointer; } // Add additional data structures when we create our OpenXR session. virtual void *set_swapchain_create_info_and_get_next_pointer(void *p_next_pointer) { return p_next_pointer; } // Add additional data structures when creating OpenXR swap chains. virtual void *set_hand_joint_locations_and_get_next_pointer(int p_hand_index, void *p_next_pointer) { return p_next_pointer; } + virtual void *set_projection_views_and_get_next_pointer(int p_view_index, void *p_next_pointer) { return p_next_pointer; } virtual PackedStringArray get_suggested_tracker_names() { return PackedStringArray(); } diff --git a/modules/openxr/extensions/openxr_extension_wrapper_extension.cpp b/modules/openxr/extensions/openxr_extension_wrapper_extension.cpp index fb8d1b9d69e0..e6a4c2618c68 100644 --- a/modules/openxr/extensions/openxr_extension_wrapper_extension.cpp +++ b/modules/openxr/extensions/openxr_extension_wrapper_extension.cpp @@ -39,6 +39,7 @@ void OpenXRExtensionWrapperExtension::_bind_methods() { GDVIRTUAL_BIND(_set_session_create_and_get_next_pointer, "next_pointer"); GDVIRTUAL_BIND(_set_swapchain_create_info_and_get_next_pointer, "next_pointer"); GDVIRTUAL_BIND(_set_hand_joint_locations_and_get_next_pointer, "hand_index", "next_pointer"); + GDVIRTUAL_BIND(_set_projection_views_and_get_next_pointer, "view_index", "next_pointer"); GDVIRTUAL_BIND(_get_composition_layer_count); GDVIRTUAL_BIND(_get_composition_layer, "index"); GDVIRTUAL_BIND(_get_composition_layer_order, "index"); @@ -140,6 +141,16 @@ void *OpenXRExtensionWrapperExtension::set_hand_joint_locations_and_get_next_poi return nullptr; } +void *OpenXRExtensionWrapperExtension::set_projection_views_and_get_next_pointer(int p_view_index, void *p_next_pointer) { + uint64_t pointer = 0; + + if (GDVIRTUAL_CALL(_set_projection_views_and_get_next_pointer, p_view_index, GDExtensionPtr(p_next_pointer), pointer)) { + return reinterpret_cast(pointer); + } + + return nullptr; +} + PackedStringArray OpenXRExtensionWrapperExtension::get_suggested_tracker_names() { PackedStringArray ret; diff --git a/modules/openxr/extensions/openxr_extension_wrapper_extension.h b/modules/openxr/extensions/openxr_extension_wrapper_extension.h index 8fc6511277ba..350bcb98307e 100644 --- a/modules/openxr/extensions/openxr_extension_wrapper_extension.h +++ b/modules/openxr/extensions/openxr_extension_wrapper_extension.h @@ -60,6 +60,7 @@ class OpenXRExtensionWrapperExtension : public Object, public OpenXRExtensionWra virtual void *set_session_create_and_get_next_pointer(void *p_next_pointer) override; virtual void *set_swapchain_create_info_and_get_next_pointer(void *p_next_pointer) override; virtual void *set_hand_joint_locations_and_get_next_pointer(int p_hand_index, void *p_next_pointer) override; + virtual void *set_projection_views_and_get_next_pointer(int p_view_index, void *p_next_pointer) override; virtual int get_composition_layer_count() override; virtual XrCompositionLayerBaseHeader *get_composition_layer(int p_index) override; @@ -71,6 +72,7 @@ class OpenXRExtensionWrapperExtension : public Object, public OpenXRExtensionWra GDVIRTUAL1R(uint64_t, _set_session_create_and_get_next_pointer, GDExtensionPtr); GDVIRTUAL1R(uint64_t, _set_swapchain_create_info_and_get_next_pointer, GDExtensionPtr); GDVIRTUAL2R(uint64_t, _set_hand_joint_locations_and_get_next_pointer, int, GDExtensionPtr); + GDVIRTUAL2R(uint64_t, _set_projection_views_and_get_next_pointer, int, GDExtensionPtr); GDVIRTUAL0R(int, _get_composition_layer_count); GDVIRTUAL1R(uint64_t, _get_composition_layer, int); GDVIRTUAL1R(int, _get_composition_layer_order, int); diff --git a/modules/openxr/openxr_api.cpp b/modules/openxr/openxr_api.cpp index 17755417578a..ae2632564e8b 100644 --- a/modules/openxr/openxr_api.cpp +++ b/modules/openxr/openxr_api.cpp @@ -1916,6 +1916,9 @@ bool OpenXRAPI::get_view_projection(uint32_t p_view, double p_z_near, double p_z } } + render_state.z_near = p_z_near; + render_state.z_far = p_z_far; + // now update our projection return graphics_extension->create_projection_fov(render_state.views[p_view].fov, p_z_near, p_z_far, p_camera_matrix); } @@ -2343,6 +2346,30 @@ RID OpenXRAPI::get_depth_texture() { } } +void OpenXRAPI::set_velocity_texture(RID p_render_target) { + velocity_texture = p_render_target; +} + +RID OpenXRAPI::get_velocity_texture() { + return velocity_texture; +} + +void OpenXRAPI::set_velocity_depth_texture(RID p_render_target) { + velocity_depth_texture = p_render_target; +} + +RID OpenXRAPI::get_velocity_depth_texture() { + return velocity_depth_texture; +} + +void OpenXRAPI::set_velocity_target_size(const Size2i &p_target_size) { + velocity_target_size = p_target_size; +} + +Size2i OpenXRAPI::get_velocity_target_size() { + return velocity_target_size; +} + void OpenXRAPI::post_draw_viewport(RID p_render_target) { // Must be called from rendering thread! ERR_NOT_ON_RENDER_THREAD; @@ -2448,6 +2475,20 @@ void OpenXRAPI::end_frame() { render_state.view_count, // viewCount render_state.projection_views, // views }; + + if (projection_views_extensions.size() > 0) { + for (uint32_t v = 0; v < render_state.view_count; v++) { + void *next_pointer = nullptr; + for (OpenXRExtensionWrapper *wrapper : projection_views_extensions) { + void *np = wrapper->set_projection_views_and_get_next_pointer(v, next_pointer); + if (np != nullptr) { + next_pointer = np; + } + } + render_state.projection_views[v].next = next_pointer; + } + } + ordered_layers_list.push_back({ (const XrCompositionLayerBaseHeader *)&projection_layer, 0 }); // Sort our layers. @@ -2578,6 +2619,14 @@ Size2 OpenXRAPI::get_play_space_bounds() const { return ret; } +PackedInt64Array OpenXRAPI::get_supported_swapchain_formats() { + PackedInt64Array supported_swapchain_list; + for (uint32_t i = 0; i < num_swapchain_formats; i++) { + supported_swapchain_list.push_back(supported_swapchain_formats[i]); + } + return supported_swapchain_list; +} + OpenXRAPI::OpenXRAPI() { // OpenXRAPI is only constructed if OpenXR is enabled. singleton = this; @@ -3499,6 +3548,14 @@ void OpenXRAPI::unregister_composition_layer_provider(OpenXRCompositionLayerProv composition_layer_providers.erase(provider); } +void OpenXRAPI::register_projection_views_extension(OpenXRExtensionWrapper *p_extension) { + projection_views_extensions.append(p_extension); +} + +void OpenXRAPI::unregister_projection_views_extension(OpenXRExtensionWrapper *p_extension) { + projection_views_extensions.erase(p_extension); +} + const XrEnvironmentBlendMode *OpenXRAPI::get_supported_environment_blend_modes(uint32_t &count) { count = num_supported_environment_blend_modes; return supported_environment_blend_modes; diff --git a/modules/openxr/openxr_api.h b/modules/openxr/openxr_api.h index ecffce181620..21e18fc5f813 100644 --- a/modules/openxr/openxr_api.h +++ b/modules/openxr/openxr_api.h @@ -102,6 +102,9 @@ class OpenXRAPI { // composition layer providers Vector composition_layer_providers; + // projection views extensions + Vector projection_views_extensions; + // view configuration uint32_t num_view_configuration_types = 0; XrViewConfigurationType *supported_view_configuration_types = nullptr; @@ -153,7 +156,6 @@ class OpenXRAPI { enum OpenXRSwapChainTypes { OPENXR_SWAPCHAIN_COLOR, OPENXR_SWAPCHAIN_DEPTH, - // OPENXR_SWAPCHAIN_VELOCITY, OPENXR_SWAPCHAIN_MAX }; @@ -165,6 +167,10 @@ class OpenXRAPI { XrSpace view_space = XR_NULL_HANDLE; XRPose::TrackingConfidence head_pose_confidence = XRPose::XR_TRACKING_CONFIDENCE_NONE; + RID velocity_texture; + RID velocity_depth_texture; + Size2i velocity_target_size; + // When LOCAL_FLOOR isn't supported, we use an approach based on the example code in the // OpenXR spec in order to emulate it. // See: https://registry.khronos.org/OpenXR/specs/1.0/html/xrspec.html#XR_EXT_local_floor @@ -345,6 +351,9 @@ class OpenXRAPI { 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; + double z_near = 0.0; + double z_far = 0.0; + Size2i main_swapchain_size; OpenXRSwapChainInfo main_swapchains[OPENXR_SWAPCHAIN_MAX]; } render_state; @@ -477,6 +486,12 @@ class OpenXRAPI { XrSwapchain get_color_swapchain(); RID get_color_texture(); RID get_depth_texture(); + void set_velocity_texture(RID p_render_target); + RID get_velocity_texture(); + void set_velocity_depth_texture(RID p_render_target); + RID get_velocity_depth_texture(); + void set_velocity_target_size(const Size2i &p_target_size); + Size2i get_velocity_target_size(); void post_draw_viewport(RID p_render_target); void end_frame(); @@ -502,9 +517,13 @@ class OpenXRAPI { Size2 get_play_space_bounds() const; // swapchains + PackedInt64Array get_supported_swapchain_formats(); int64_t get_color_swapchain_format() const { return color_swapchain_format; } int64_t get_depth_swapchain_format() const { return depth_swapchain_format; } + double get_render_state_z_near() const { return render_state.z_near; } + double get_render_state_z_far() const { return render_state.z_far; } + // action map String get_default_action_map_resource_name(); @@ -542,6 +561,9 @@ class OpenXRAPI { void register_composition_layer_provider(OpenXRCompositionLayerProvider *provider); void unregister_composition_layer_provider(OpenXRCompositionLayerProvider *provider); + void register_projection_views_extension(OpenXRExtensionWrapper *p_extension); + void unregister_projection_views_extension(OpenXRExtensionWrapper *p_extension); + const XrEnvironmentBlendMode *get_supported_environment_blend_modes(uint32_t &count); bool is_environment_blend_mode_supported(XrEnvironmentBlendMode p_blend_mode) const; bool set_environment_blend_mode(XrEnvironmentBlendMode p_blend_mode); diff --git a/modules/openxr/openxr_api_extension.cpp b/modules/openxr/openxr_api_extension.cpp index f3bc178d3a25..506e1fc64d35 100644 --- a/modules/openxr/openxr_api_extension.cpp +++ b/modules/openxr/openxr_api_extension.cpp @@ -61,6 +61,25 @@ void OpenXRAPIExtension::_bind_methods() { ClassDB::bind_method(D_METHOD("register_composition_layer_provider", "extension"), &OpenXRAPIExtension::register_composition_layer_provider); ClassDB::bind_method(D_METHOD("unregister_composition_layer_provider", "extension"), &OpenXRAPIExtension::unregister_composition_layer_provider); + ClassDB::bind_method(D_METHOD("register_projection_views_extension", "extension"), &OpenXRAPIExtension::register_projection_views_extension); + ClassDB::bind_method(D_METHOD("unregister_projection_views_extension", "extension"), &OpenXRAPIExtension::unregister_projection_views_extension); + + ClassDB::bind_method(D_METHOD("get_render_state_z_near"), &OpenXRAPIExtension::get_render_state_z_near); + ClassDB::bind_method(D_METHOD("get_render_state_z_far"), &OpenXRAPIExtension::get_render_state_z_far); + + ClassDB::bind_method(D_METHOD("set_velocity_texture", "render_target"), &OpenXRAPIExtension::set_velocity_texture); + ClassDB::bind_method(D_METHOD("set_velocity_depth_texture", "render_target"), &OpenXRAPIExtension::set_velocity_depth_texture); + ClassDB::bind_method(D_METHOD("set_velocity_target_size", "target_size"), &OpenXRAPIExtension::set_velocity_target_size); + + ClassDB::bind_method(D_METHOD("get_supported_swapchain_formats"), &OpenXRAPIExtension::get_supported_swapchain_formats); + + ClassDB::bind_method(D_METHOD("openxr_swapchain_create", "create_flags", "usage_flags", "swapchain_format", "width", "height", "sample_count", "array_size"), &OpenXRAPIExtension::openxr_swapchain_create); + ClassDB::bind_method(D_METHOD("openxr_swapchain_free", "swapchain"), &OpenXRAPIExtension::openxr_swapchain_free); + ClassDB::bind_method(D_METHOD("openxr_swapchain_get_swapchain", "swapchain"), &OpenXRAPIExtension::openxr_swapchain_get_swapchain); + ClassDB::bind_method(D_METHOD("openxr_swapchain_acquire", "swapchain"), &OpenXRAPIExtension::openxr_swapchain_acquire); + ClassDB::bind_method(D_METHOD("openxr_swapchain_get_image", "swapchain"), &OpenXRAPIExtension::openxr_swapchain_get_image); + ClassDB::bind_method(D_METHOD("openxr_swapchain_release", "swapchain"), &OpenXRAPIExtension::openxr_swapchain_release); + ClassDB::bind_method(D_METHOD("set_emulate_environment_blend_mode_alpha_blend", "enabled"), &OpenXRAPIExtension::set_emulate_environment_blend_mode_alpha_blend); ClassDB::bind_method(D_METHOD("is_environment_blend_mode_alpha_supported"), &OpenXRAPIExtension::is_environment_blend_mode_alpha_blend_supported); @@ -193,6 +212,94 @@ void OpenXRAPIExtension::unregister_composition_layer_provider(OpenXRExtensionWr OpenXRAPI::get_singleton()->unregister_composition_layer_provider(p_extension); } +void OpenXRAPIExtension::register_projection_views_extension(OpenXRExtensionWrapperExtension *p_extension) { + ERR_FAIL_NULL(OpenXRAPI::get_singleton()); + OpenXRAPI::get_singleton()->register_projection_views_extension(p_extension); +} + +void OpenXRAPIExtension::unregister_projection_views_extension(OpenXRExtensionWrapperExtension *p_extension) { + ERR_FAIL_NULL(OpenXRAPI::get_singleton()); + OpenXRAPI::get_singleton()->unregister_projection_views_extension(p_extension); +} + +double OpenXRAPIExtension::get_render_state_z_near() { + ERR_NOT_ON_RENDER_THREAD_V(0.0); + ERR_FAIL_NULL_V(OpenXRAPI::get_singleton(), 0.0); + return OpenXRAPI::get_singleton()->get_render_state_z_near(); +} + +double OpenXRAPIExtension::get_render_state_z_far() { + ERR_NOT_ON_RENDER_THREAD_V(0.0); + ERR_FAIL_NULL_V(OpenXRAPI::get_singleton(), 0.0); + return OpenXRAPI::get_singleton()->get_render_state_z_far(); +} + +void OpenXRAPIExtension::set_velocity_texture(RID p_render_target) { + ERR_FAIL_NULL(OpenXRAPI::get_singleton()); + OpenXRAPI::get_singleton()->set_velocity_texture(p_render_target); +} + +void OpenXRAPIExtension::set_velocity_depth_texture(RID p_render_target) { + ERR_FAIL_NULL(OpenXRAPI::get_singleton()); + OpenXRAPI::get_singleton()->set_velocity_depth_texture(p_render_target); +} + +void OpenXRAPIExtension::set_velocity_target_size(const Size2i &p_target_size) { + ERR_FAIL_NULL(OpenXRAPI::get_singleton()); + OpenXRAPI::get_singleton()->set_velocity_target_size(p_target_size); +} + +PackedInt64Array OpenXRAPIExtension::get_supported_swapchain_formats() { + ERR_FAIL_NULL_V(OpenXRAPI::get_singleton(), PackedInt64Array()); + return OpenXRAPI::get_singleton()->get_supported_swapchain_formats(); +} + +uint64_t OpenXRAPIExtension::openxr_swapchain_create(XrSwapchainCreateFlags p_create_flags, XrSwapchainUsageFlags p_usage_flags, int64_t p_swapchain_format, uint32_t p_width, uint32_t p_height, uint32_t p_sample_count, uint32_t p_array_size) { + ERR_FAIL_NULL_V(OpenXRAPI::get_singleton(), 0); + + OpenXRAPI::OpenXRSwapChainInfo *new_swapchain_info = memnew(OpenXRAPI::OpenXRSwapChainInfo); + new_swapchain_info->create(p_create_flags, p_usage_flags, p_swapchain_format, p_width, p_height, p_sample_count, p_array_size); + return reinterpret_cast(new_swapchain_info); +} + +void OpenXRAPIExtension::openxr_swapchain_free(uint64_t p_swapchain_info) { + ERR_FAIL_NULL(OpenXRAPI::get_singleton()); + + OpenXRAPI::OpenXRSwapChainInfo *swapchain_info = reinterpret_cast(p_swapchain_info); + swapchain_info->free(); + memfree(swapchain_info); +} + +uint64_t OpenXRAPIExtension::openxr_swapchain_get_swapchain(uint64_t p_swapchain_info) { + ERR_FAIL_NULL_V(OpenXRAPI::get_singleton(), 0); + + OpenXRAPI::OpenXRSwapChainInfo *swapchain_info = reinterpret_cast(p_swapchain_info); + XrSwapchain swapchain = swapchain_info->get_swapchain(); + return reinterpret_cast(swapchain); +} + +void OpenXRAPIExtension::openxr_swapchain_acquire(uint64_t p_swapchain_info) { + ERR_FAIL_NULL(OpenXRAPI::get_singleton()); + + OpenXRAPI::OpenXRSwapChainInfo *swapchain_info = reinterpret_cast(p_swapchain_info); + bool should_render = true; // Can ignore should_render. + swapchain_info->acquire(should_render); +} + +RID OpenXRAPIExtension::openxr_swapchain_get_image(uint64_t p_swapchain_info) { + ERR_FAIL_NULL_V(OpenXRAPI::get_singleton(), RID()); + + OpenXRAPI::OpenXRSwapChainInfo *swapchain_info = reinterpret_cast(p_swapchain_info); + return swapchain_info->get_image(); +} + +void OpenXRAPIExtension::openxr_swapchain_release(uint64_t p_swapchain_info) { + ERR_FAIL_NULL(OpenXRAPI::get_singleton()); + + OpenXRAPI::OpenXRSwapChainInfo *swapchain_info = reinterpret_cast(p_swapchain_info); + swapchain_info->release(); +} + void OpenXRAPIExtension::set_emulate_environment_blend_mode_alpha_blend(bool p_enabled) { ERR_FAIL_NULL(OpenXRAPI::get_singleton()); OpenXRAPI::get_singleton()->set_emulate_environment_blend_mode_alpha_blend(p_enabled); diff --git a/modules/openxr/openxr_api_extension.h b/modules/openxr/openxr_api_extension.h index 1b88b418f61f..6519aea7f1a2 100644 --- a/modules/openxr/openxr_api_extension.h +++ b/modules/openxr/openxr_api_extension.h @@ -82,6 +82,25 @@ class OpenXRAPIExtension : public RefCounted { void register_composition_layer_provider(OpenXRExtensionWrapperExtension *p_extension); void unregister_composition_layer_provider(OpenXRExtensionWrapperExtension *p_extension); + void register_projection_views_extension(OpenXRExtensionWrapperExtension *p_extension); + void unregister_projection_views_extension(OpenXRExtensionWrapperExtension *p_extension); + + double get_render_state_z_near(); + double get_render_state_z_far(); + + void set_velocity_texture(RID p_render_target); + void set_velocity_depth_texture(RID p_render_target); + void set_velocity_target_size(const Size2i &p_target_size); + + PackedInt64Array get_supported_swapchain_formats(); + + uint64_t openxr_swapchain_create(XrSwapchainCreateFlags p_create_flags, XrSwapchainUsageFlags p_usage_flags, int64_t p_swapchain_format, uint32_t p_width, uint32_t p_height, uint32_t p_sample_count, uint32_t p_array_size); + void openxr_swapchain_free(uint64_t p_swapchain_info); + uint64_t openxr_swapchain_get_swapchain(uint64_t p_swapchain_info); + void openxr_swapchain_acquire(uint64_t p_swapchain_info); + RID openxr_swapchain_get_image(uint64_t p_swapchain_info); + void openxr_swapchain_release(uint64_t p_swapchain_info); + enum OpenXRAlphaBlendModeSupport { OPENXR_ALPHA_BLEND_MODE_SUPPORT_NONE = 0, OPENXR_ALPHA_BLEND_MODE_SUPPORT_REAL = 1, diff --git a/modules/openxr/openxr_interface.cpp b/modules/openxr/openxr_interface.cpp index 68e04694e3d0..f7f47f36e86a 100644 --- a/modules/openxr/openxr_interface.cpp +++ b/modules/openxr/openxr_interface.cpp @@ -1053,6 +1053,30 @@ RID OpenXRInterface::get_depth_texture() { } } +RID OpenXRInterface::get_velocity_texture() { + if (openxr_api) { + return openxr_api->get_velocity_texture(); + } else { + return RID(); + } +} + +RID OpenXRInterface::get_velocity_depth_texture() { + if (openxr_api) { + return openxr_api->get_velocity_depth_texture(); + } else { + return RID(); + } +} + +Size2i OpenXRInterface::get_velocity_target_size() { + if (openxr_api) { + return openxr_api->get_velocity_target_size(); + } else { + return Size2i(); + } +} + void OpenXRInterface::handle_hand_tracking(const String &p_path, OpenXRHandTrackingExtension::HandTrackedHands p_hand) { OpenXRHandTrackingExtension *hand_tracking_ext = OpenXRHandTrackingExtension::get_singleton(); if (hand_tracking_ext && hand_tracking_ext->get_active()) { diff --git a/modules/openxr/openxr_interface.h b/modules/openxr/openxr_interface.h index d1bf2aaf7878..b37c2eda2901 100644 --- a/modules/openxr/openxr_interface.h +++ b/modules/openxr/openxr_interface.h @@ -185,6 +185,9 @@ class OpenXRInterface : public XRInterface { virtual RID get_color_texture() override; virtual RID get_depth_texture() override; + virtual RID get_velocity_texture() override; + virtual RID get_velocity_depth_texture() override; + virtual Size2i get_velocity_target_size() override; virtual void process() override; virtual void pre_render() override; diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index 1a047dfa2765..68085edbb19c 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -4527,7 +4527,7 @@ void Viewport::set_use_xr(bool p_use_xr) { // Reset render target override textures. RID rt = RS::get_singleton()->viewport_get_render_target(viewport); - RSG::texture_storage->render_target_set_override(rt, RID(), RID(), RID()); + RSG::texture_storage->render_target_set_override(rt, RID(), RID(), RID(), RID()); } } } diff --git a/servers/rendering/dummy/storage/texture_storage.h b/servers/rendering/dummy/storage/texture_storage.h index 63eb441915ee..35135ce860e0 100644 --- a/servers/rendering/dummy/storage/texture_storage.h +++ b/servers/rendering/dummy/storage/texture_storage.h @@ -200,12 +200,16 @@ class TextureStorage : public RendererTextureStorage { virtual void render_target_set_vrs_texture(RID p_render_target, RID p_texture) override {} virtual RID render_target_get_vrs_texture(RID p_render_target) const override { return RID(); } - virtual void render_target_set_override(RID p_render_target, RID p_color_texture, RID p_depth_texture, RID p_velocity_texture) override {} + virtual void render_target_set_override(RID p_render_target, RID p_color_texture, RID p_depth_texture, RID p_velocity_texture, RID p_velocity_depth_texture) override {} virtual RID render_target_get_override_color(RID p_render_target) const override { return RID(); } virtual RID render_target_get_override_depth(RID p_render_target) const override { return RID(); } virtual RID render_target_get_override_velocity(RID p_render_target) const override { return RID(); } + virtual RID render_target_get_override_velocity_depth(RID p_render_target) const override { return RID(); } virtual RID render_target_get_texture(RID p_render_target) override { return RID(); } + + virtual void render_target_set_velocity_target_size(RID p_render_target, const Size2i &p_target_size) override {} + virtual Size2i render_target_get_velocity_target_size(RID p_render_target) const override { return Size2i(0, 0); } }; } // namespace RendererDummy diff --git a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp index 697d9490158e..52eacb160937 100644 --- a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp @@ -3436,7 +3436,7 @@ RID TextureStorage::render_target_get_texture(RID p_render_target) { return rt->texture; } -void TextureStorage::render_target_set_override(RID p_render_target, RID p_color_texture, RID p_depth_texture, RID p_velocity_texture) { +void TextureStorage::render_target_set_override(RID p_render_target, RID p_color_texture, RID p_depth_texture, RID p_velocity_texture, RID p_velocity_depth_texture) { RenderTarget *rt = render_target_owner.get_or_null(p_render_target); ERR_FAIL_NULL(rt); diff --git a/servers/rendering/renderer_rd/storage_rd/texture_storage.h b/servers/rendering/renderer_rd/storage_rd/texture_storage.h index 3d281cf98a23..cfd85b28167f 100644 --- a/servers/rendering/renderer_rd/storage_rd/texture_storage.h +++ b/servers/rendering/renderer_rd/storage_rd/texture_storage.h @@ -779,15 +779,19 @@ class TextureStorage : public RendererTextureStorage { virtual void render_target_set_vrs_texture(RID p_render_target, RID p_texture) override; virtual RID render_target_get_vrs_texture(RID p_render_target) const override; - virtual void render_target_set_override(RID p_render_target, RID p_color_texture, RID p_depth_texture, RID p_velocity_texture) override; + virtual void render_target_set_override(RID p_render_target, RID p_color_texture, RID p_depth_texture, RID p_velocity_texture, RID p_velocity_depth_texture) override; virtual RID render_target_get_override_color(RID p_render_target) const override; virtual RID render_target_get_override_depth(RID p_render_target) const override; RID render_target_get_override_depth_slice(RID p_render_target, const uint32_t p_layer) const; virtual RID render_target_get_override_velocity(RID p_render_target) const override; RID render_target_get_override_velocity_slice(RID p_render_target, const uint32_t p_layer) const; + virtual RID render_target_get_override_velocity_depth(RID p_render_target) const override { return RID(); } virtual RID render_target_get_texture(RID p_render_target) override; + virtual void render_target_set_velocity_target_size(RID p_render_target, const Size2i &p_target_size) override {} + virtual Size2i render_target_get_velocity_target_size(RID p_render_target) const override { return Size2i(0, 0); } + RID render_target_get_rd_framebuffer(RID p_render_target); RID render_target_get_rd_texture(RID p_render_target); RID render_target_get_rd_texture_slice(RID p_render_target, uint32_t p_layer); diff --git a/servers/rendering/renderer_viewport.cpp b/servers/rendering/renderer_viewport.cpp index 4d6435f48a53..cdb055f1f0c0 100644 --- a/servers/rendering/renderer_viewport.cpp +++ b/servers/rendering/renderer_viewport.cpp @@ -789,7 +789,16 @@ void RendererViewport::draw_viewports(bool p_swap_buffers) { RSG::texture_storage->render_target_set_override(vp->render_target, xr_interface->get_color_texture(), xr_interface->get_depth_texture(), - xr_interface->get_velocity_texture()); + xr_interface->get_velocity_texture(), + xr_interface->get_velocity_depth_texture()); + + RSG::texture_storage->render_target_set_velocity_target_size(vp->render_target, xr_interface->get_velocity_target_size()); + + if (xr_interface->get_velocity_texture().is_valid()) { + viewport_set_force_motion_vectors(vp->self, true); + } else { + viewport_set_force_motion_vectors(vp->self, false); + } // render... RSG::scene->set_debug_draw_mode(vp->debug_draw); @@ -990,7 +999,7 @@ void RendererViewport::_viewport_set_size(Viewport *p_viewport, int p_width, int } bool RendererViewport::_viewport_requires_motion_vectors(Viewport *p_viewport) { - return p_viewport->use_taa || p_viewport->scaling_3d_mode == RenderingServer::VIEWPORT_SCALING_3D_MODE_FSR2 || p_viewport->debug_draw == RenderingServer::VIEWPORT_DEBUG_DRAW_MOTION_VECTORS; + return p_viewport->use_taa || p_viewport->scaling_3d_mode == RenderingServer::VIEWPORT_SCALING_3D_MODE_FSR2 || p_viewport->debug_draw == RenderingServer::VIEWPORT_DEBUG_DRAW_MOTION_VECTORS || p_viewport->force_motion_vectors; } void RendererViewport::viewport_set_active(RID p_viewport, bool p_active) { @@ -1338,6 +1347,25 @@ void RendererViewport::viewport_set_use_debanding(RID p_viewport, bool p_use_deb _configure_3d_render_buffers(viewport); } +void RendererViewport::viewport_set_force_motion_vectors(RID p_viewport, bool p_force_motion_vectors) { + Viewport *viewport = viewport_owner.get_or_null(p_viewport); + ERR_FAIL_NULL(viewport); + + if (viewport->force_motion_vectors == p_force_motion_vectors) { + return; + } + + bool motion_vectors_before = _viewport_requires_motion_vectors(viewport); + viewport->force_motion_vectors = p_force_motion_vectors; + + bool motion_vectors_after = _viewport_requires_motion_vectors(viewport); + if (motion_vectors_before != motion_vectors_after) { + num_viewports_with_motion_vectors += motion_vectors_after ? 1 : -1; + } + + _configure_3d_render_buffers(viewport); +} + void RendererViewport::viewport_set_use_occlusion_culling(RID p_viewport, bool p_use_occlusion_culling) { Viewport *viewport = viewport_owner.get_or_null(p_viewport); ERR_FAIL_NULL(viewport); diff --git a/servers/rendering/renderer_viewport.h b/servers/rendering/renderer_viewport.h index bf97905f8694..21cc06d6e7ab 100644 --- a/servers/rendering/renderer_viewport.h +++ b/servers/rendering/renderer_viewport.h @@ -77,6 +77,7 @@ class RendererViewport { RS::ViewportScreenSpaceAA screen_space_aa = RenderingServer::VIEWPORT_SCREEN_SPACE_AA_DISABLED; bool use_taa = false; bool use_debanding = false; + bool force_motion_vectors = false; RendererSceneRender::CameraData prev_camera_data; uint64_t prev_camera_data_frame = 0; @@ -277,6 +278,7 @@ class RendererViewport { void viewport_set_screen_space_aa(RID p_viewport, RS::ViewportScreenSpaceAA p_mode); void viewport_set_use_taa(RID p_viewport, bool p_use_taa); void viewport_set_use_debanding(RID p_viewport, bool p_use_debanding); + void viewport_set_force_motion_vectors(RID p_viewport, bool p_force_motion_vectors); void viewport_set_use_occlusion_culling(RID p_viewport, bool p_use_occlusion_culling); void viewport_set_occlusion_rays_per_thread(int p_rays_per_thread); void viewport_set_occlusion_culling_build_quality(RS::ViewportOcclusionCullingBuildQuality p_quality); diff --git a/servers/rendering/rendering_server_default.h b/servers/rendering/rendering_server_default.h index 29b1e163c78a..4cad8682e04a 100644 --- a/servers/rendering/rendering_server_default.h +++ b/servers/rendering/rendering_server_default.h @@ -724,6 +724,7 @@ class RenderingServerDefault : public RenderingServer { FUNC2(viewport_set_screen_space_aa, RID, ViewportScreenSpaceAA) FUNC2(viewport_set_use_taa, RID, bool) FUNC2(viewport_set_use_debanding, RID, bool) + FUNC2(viewport_set_force_motion_vectors, RID, bool) FUNC2(viewport_set_use_occlusion_culling, RID, bool) FUNC1(viewport_set_occlusion_rays_per_thread, int) FUNC1(viewport_set_occlusion_culling_build_quality, ViewportOcclusionCullingBuildQuality) diff --git a/servers/rendering/storage/texture_storage.h b/servers/rendering/storage/texture_storage.h index e5283848915c..45e21a70556f 100644 --- a/servers/rendering/storage/texture_storage.h +++ b/servers/rendering/storage/texture_storage.h @@ -178,13 +178,18 @@ class RendererTextureStorage { virtual RID render_target_get_vrs_texture(RID p_render_target) const = 0; // override color, depth and velocity buffers (depth and velocity only for 3D) - virtual void render_target_set_override(RID p_render_target, RID p_color_texture, RID p_depth_texture, RID p_velocity_texture) = 0; + virtual void render_target_set_override(RID p_render_target, RID p_color_texture, RID p_depth_texture, RID p_velocity_texture, RID p_velocity_depth_texture) = 0; virtual RID render_target_get_override_color(RID p_render_target) const = 0; virtual RID render_target_get_override_depth(RID p_render_target) const = 0; virtual RID render_target_get_override_velocity(RID p_render_target) const = 0; + virtual RID render_target_get_override_velocity_depth(RID p_render_target) const = 0; // get textures virtual RID render_target_get_texture(RID p_render_target) = 0; + + // Motion vectors + virtual void render_target_set_velocity_target_size(RID p_render_target, const Size2i &p_target_size) = 0; + virtual Size2i render_target_get_velocity_target_size(RID p_render_target) const = 0; }; #endif // TEXTURE_STORAGE_H diff --git a/servers/rendering_server.h b/servers/rendering_server.h index 0917af73c6a6..9a379e12d1f9 100644 --- a/servers/rendering_server.h +++ b/servers/rendering_server.h @@ -1015,6 +1015,8 @@ class RenderingServer : public Object { virtual void viewport_set_use_debanding(RID p_viewport, bool p_use_debanding) = 0; + virtual void viewport_set_force_motion_vectors(RID p_viewport, bool p_force_motion_vectors) = 0; + virtual void viewport_set_mesh_lod_threshold(RID p_viewport, float p_pixels) = 0; virtual void viewport_set_use_occlusion_culling(RID p_viewport, bool p_use_occlusion_culling) = 0; diff --git a/servers/xr/xr_interface.cpp b/servers/xr/xr_interface.cpp index e9d2fc85203b..c7fc017d7816 100644 --- a/servers/xr/xr_interface.cpp +++ b/servers/xr/xr_interface.cpp @@ -187,6 +187,14 @@ RID XRInterface::get_velocity_texture() { return RID(); } +RID XRInterface::get_velocity_depth_texture() { + return RID(); +} + +Size2i XRInterface::get_velocity_target_size() { + return Size2i(); +} + PackedStringArray XRInterface::get_suggested_tracker_names() const { PackedStringArray arr; diff --git a/servers/xr/xr_interface.h b/servers/xr/xr_interface.h index abd5476fc93b..883eb9cbc5f9 100644 --- a/servers/xr/xr_interface.h +++ b/servers/xr/xr_interface.h @@ -137,6 +137,8 @@ class XRInterface : public RefCounted { virtual RID get_color_texture(); /* obtain color output texture (if applicable) */ virtual RID get_depth_texture(); /* obtain depth output texture (if applicable, used for reprojection) */ virtual RID get_velocity_texture(); /* obtain velocity output texture (if applicable, used for spacewarp) */ + virtual RID get_velocity_depth_texture(); + virtual Size2i get_velocity_target_size(); virtual void pre_render() {} virtual bool pre_draw_viewport(RID p_render_target) { return true; } /* inform XR interface we are about to start our viewport draw process */ virtual Vector post_draw_viewport(RID p_render_target, const Rect2 &p_screen_rect) = 0; /* inform XR interface we finished our viewport draw process */