fix critical deadlock between render and game threads in UE 5.6 when invoking IHeadMountedDisplay::GetHMDMonitorInfo()

This commit is contained in:
Mamadou Babaei
2025-06-04 02:35:50 +02:00
parent 1b9d19a46b
commit 8bf62bc4d4
3 changed files with 69 additions and 4 deletions
+2
View File
@@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Changed
- Replaced Epic Native Toolchain `v24` support with Epic Native Toolchain `v25` due to the fact that now `v25` is the default Linux toolchain for UE `5.6`.
- Revamped `FSGHMDTracker` to resolve a critical deadlock between the rendering and game threads in Unreal Engine `5.6` that occurrs when `IHeadMountedDisplay::GetHMDMonitorInfo()` is invoked from `FSGXRTracker::GetControllerTransform()`. This is similar to another [critical deadlock issue (UE-212224), occurring during PipelinedFrameState acquisition, addressed in the `v2.5.0` release](#250---2025-05-09).
- Bumped the SenseGlove libraries to `v2.203.0-f3d3e676`.
- SenseGlove libraries have migrated to `C++20` from `C++17`.
- Bumped the SenseGlove Unreal Engine Marketplace Packager `v0.6.0-4108c6f`.
@@ -23,6 +24,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Resolved GNU/Linux build issues for Unreal Engine `5.5` and `5.6` caused by incorrect linkage to GNU/GCC's `libstdc++` instead of LLVM/Clang's `libc++`.
- Fix `SGLog` build issues on GNU/Linux with UE `5.6`.
- Fix type conversion safety and consistency issues across all `SGLog` formatters.
- Resolved a critical deadlock between the rendering and game threads in Unreal Engine `5.6` that occurrs when `IHeadMountedDisplay::GetHMDMonitorInfo()` is invoked from `FSGXRTracker::GetControllerTransform()`. This is similar to another [critical deadlock issue (UE-212224), occurring during PipelinedFrameState acquisition, addressed in the `v2.5.0` release](#250---2025-05-09).
- Additional minor fixes and improvements that may not be listed here.
### Removed
@@ -35,12 +35,72 @@
#include "SGTracking/SGHMDTracker.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 "Engine/Engine.h"
#include "IHeadMountedDisplay.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 "SGSettings/SGSettings.h"
struct FSGHMDTracker::FStaticImpl
{
/************************
* Static methods
************************/
static void GetHMDMonitorInfo(
IHeadMountedDisplay* Device, IHeadMountedDisplay::MonitorInfo& OutMonitorInfo);
/************************
* Constructor / Destructor
************************/
explicit FStaticImpl() = default;
virtual ~FStaticImpl() = delete;
};
void FSGHMDTracker::FStaticImpl::GetHMDMonitorInfo(
IHeadMountedDisplay* Device, IHeadMountedDisplay::MonitorInfo& OutMonitorInfo)
{
#if ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION <= 5
Device->GetHMDMonitorInfo(OutMonitorInfo);
return;
#endif /* ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION <= 5 */
#if ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 6
TPromise<TOptional<IHeadMountedDisplay::MonitorInfo>> Promise;
const TFuture<TOptional<IHeadMountedDisplay::MonitorInfo>> Future{Promise.GetFuture()};
AsyncTask(ENamedThreads::ActualRenderingThread,
[
Device,
Promise = MoveTemp(Promise)]() mutable
{
IHeadMountedDisplay::MonitorInfo MonitorInfo;
Device->GetHMDMonitorInfo(MonitorInfo);
Promise.SetValue(MoveTemp(MonitorInfo));
});
if (Future.WaitFor(FTimespan::FromMilliseconds(100)))
{
TOptional<IHeadMountedDisplay::MonitorInfo> Result{Future.Get()};
if (Result.IsSet())
{
OutMonitorInfo = Result.GetValue();
}
}
#endif /* ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION <= 5 */
}
FName FSGHMDTracker::GetDeviceName()
{
if (GEngine && GEngine->XRSystem.IsValid() && GEngine->XRSystem->IsHeadTrackingAllowed())
@@ -145,7 +205,7 @@ bool FSGHMDTracker::IsHtcVivePro()
if (Device)
{
IHeadMountedDisplay::MonitorInfo HmdMonitorInfo;
Device->GetHMDMonitorInfo(HmdMonitorInfo);
FStaticImpl::GetHMDMonitorInfo(Device, HmdMonitorInfo);
/// NOTE
// VIVE Pro:
@@ -218,7 +278,7 @@ bool FSGHMDTracker::IsHtcViveFocus3()
if (Device)
{
IHeadMountedDisplay::MonitorInfo HmdMonitorInfo;
Device->GetHMDMonitorInfo(HmdMonitorInfo);
FStaticImpl::GetHMDMonitorInfo(Device, HmdMonitorInfo);
/// NOTE
// VIVE Pro:
@@ -292,7 +352,7 @@ bool FSGHMDTracker::IsHtcViveXRElite()
if (Device)
{
IHeadMountedDisplay::MonitorInfo HmdMonitorInfo;
Device->GetHMDMonitorInfo(HmdMonitorInfo);
FStaticImpl::GetHMDMonitorInfo(Device, HmdMonitorInfo);
/// NOTE
// VIVE Pro:
@@ -366,7 +426,7 @@ bool FSGHMDTracker::IsHtcViveFocusVision()
if (Device)
{
IHeadMountedDisplay::MonitorInfo HmdMonitorInfo;
Device->GetHMDMonitorInfo(HmdMonitorInfo);
FStaticImpl::GetHMDMonitorInfo(Device, HmdMonitorInfo);
/// NOTE
// VIVE Pro:
@@ -51,6 +51,9 @@ struct SENSEGLOVETRACKING_API FSGHMDTracker
{
GENERATED_BODY()
private:
struct FStaticImpl;
public:
static FName GetDeviceName();