From ab6041edd77750a0d162b22759a5733d1568d3d5 Mon Sep 17 00:00:00 2001 From: Mamadou Babaei Date: Wed, 30 Apr 2025 19:47:49 +0200 Subject: [PATCH] fix a critical deadlock issue (UE-212224) in UE 5.5/5.6 during PipelinedFrameState acquisition --- Handbook/src/appendix/changelog.md | 1 + .../Private/SGTracking/SGXRTracker.cpp | 72 +++++++++++++++++++ 2 files changed, 73 insertions(+) diff --git a/Handbook/src/appendix/changelog.md b/Handbook/src/appendix/changelog.md index 21d1bfb8..465970f6 100644 --- a/Handbook/src/appendix/changelog.md +++ b/Handbook/src/appendix/changelog.md @@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed - Backend initialization error handling on Android. +- Fix [a critical issue introduced by UE `5.5`](https://github.com/EpicGames/UnrealEngine/blob/ef1397773d160d39423feb90cb2196ddfaa1e2ae/Engine/Plugins/Runtime/OpenXR/Source/OpenXRHMD/Private/OpenXRHMD.cpp#L1740) that [also affects the upcoming UE `5.6`](https://github.com/EpicGames/UnrealEngine/blob/bedc5631b81cd39aaac8d61f303eacc86d4220f0/Engine/Plugins/Runtime/OpenXR/Source/OpenXRHMD/Private/OpenXRHMD.cpp#L1772). This is known as issue `UE-212224`, which leads to a deadlock during `PipelinedFrameState` acquisition between the game and rendering threads. ### Changed diff --git a/Source/SenseGloveTracking/Private/SGTracking/SGXRTracker.cpp b/Source/SenseGloveTracking/Private/SGTracking/SGXRTracker.cpp index ccbd07f7..65cbca24 100644 --- a/Source/SenseGloveTracking/Private/SGTracking/SGXRTracker.cpp +++ b/Source/SenseGloveTracking/Private/SGTracking/SGXRTracker.cpp @@ -35,6 +35,11 @@ #include "SGTracking/SGXRTracker.h" +#if ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 5 +#include "Async/Async.h" +#include "Async/Future.h" +#include "Async/TaskGraphInterfaces.h" +#endif /* ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 5 */ #include "Containers/Array.h" #include "Containers/Map.h" #include "Engine/Engine.h" @@ -46,6 +51,10 @@ #endif /* ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 4 */ #include "IOpenXRHMDModule.h" #include "IXRTrackingSystem.h" +#if ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 5 +#include "Misc/Optional.h" +#include "Misc/Timespan.h" +#endif /* ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 5 */ #include "OpenXRCore.h" #if ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION <= 3 #include "OpenXRHMD.h" @@ -2204,6 +2213,7 @@ bool FSGXRTracker::FImpl::GetControllerTransform( IMotionController::GetModularFeatureName()) }; +#if ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION <= 4 for (const IMotionController* MotionController: MotionControllers) { if (!MotionController) @@ -2237,6 +2247,68 @@ bool FSGXRTracker::FImpl::GetControllerTransform( break; } } +#endif /* ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION <= 4 */ + +#if ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 5 + TPromise> Promise; + const TFuture> Future{Promise.GetFuture()}; + + AsyncTask(ENamedThreads::ActualRenderingThread, + [ + this, + WorldToMetersScale, + &PositionalTrackingHardwareMotionSource, + &TargetPositionalTrackingProviderName, + MotionControllers, + Promise = MoveTemp(Promise)]() mutable + { + for (const IMotionController* MotionController: MotionControllers) + { + if (!MotionController) + { + continue; + } + + const ETrackingStatus TrackingStatus = MotionController->GetControllerTrackingStatus( + DeviceIndex, PositionalTrackingHardwareMotionSource); + if (TrackingStatus == ETrackingStatus::NotTracked) + { + continue; + } + + const FName DeviceTypeName{MotionController->GetMotionControllerDeviceTypeName()}; + if (DeviceTypeName != TargetPositionalTrackingProviderName) + { + continue; + } + + FRotator Orientation; + FVector Position; + const bool bGotTransform = MotionController->GetControllerOrientationAndPosition( + DeviceIndex, PositionalTrackingHardwareMotionSource, + Orientation, Position, WorldToMetersScale); + if (bGotTransform) + { + FTransform Transform{Orientation, Position}; + Promise.SetValue(MoveTemp(Transform)); + return; + } + } + + Promise.SetValue(TOptional{}); + }); + + if (Future.WaitFor(FTimespan::FromMilliseconds(100))) + { + TOptional Result{Future.Get()}; + if (Result.IsSet()) + { + OutTransform = Result.GetValue(); + bOutMotionSourceHandTracking = false; + bTracked = true; + } + } +#endif /* ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 5 */ } if (!bTracked && bFallbackToHandTrackingIfNoGloveDetected)