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:36:20 +02:00
parent 7a553a0621
commit 15bb6d9f1f
3 changed files with 69 additions and 4 deletions
@@ -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();