fix a critical deadlock issue (UE-212224) in UE 5.5/5.6 during PipelinedFrameState acquisition

This commit is contained in:
Mamadou Babaei
2025-05-09 16:32:27 +02:00
parent 263d36d040
commit ab6041edd7
2 changed files with 73 additions and 0 deletions
+1
View File
@@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Fixed ### Fixed
- Backend initialization error handling on Android. - 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 ### Changed
@@ -35,6 +35,11 @@
#include "SGTracking/SGXRTracker.h" #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/Array.h"
#include "Containers/Map.h" #include "Containers/Map.h"
#include "Engine/Engine.h" #include "Engine/Engine.h"
@@ -46,6 +51,10 @@
#endif /* ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 4 */ #endif /* ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 4 */
#include "IOpenXRHMDModule.h" #include "IOpenXRHMDModule.h"
#include "IXRTrackingSystem.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" #include "OpenXRCore.h"
#if ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION <= 3 #if ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION <= 3
#include "OpenXRHMD.h" #include "OpenXRHMD.h"
@@ -2204,6 +2213,7 @@ bool FSGXRTracker::FImpl::GetControllerTransform(
IMotionController::GetModularFeatureName()) IMotionController::GetModularFeatureName())
}; };
#if ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION <= 4
for (const IMotionController* MotionController: MotionControllers) for (const IMotionController* MotionController: MotionControllers)
{ {
if (!MotionController) if (!MotionController)
@@ -2237,6 +2247,68 @@ bool FSGXRTracker::FImpl::GetControllerTransform(
break; break;
} }
} }
#endif /* ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION <= 4 */
#if ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 5
TPromise<TOptional<FTransform>> Promise;
const TFuture<TOptional<FTransform>> 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<FTransform>{});
});
if (Future.WaitFor(FTimespan::FromMilliseconds(100)))
{
TOptional<FTransform> 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) if (!bTracked && bFallbackToHandTrackingIfNoGloveDetected)