fix critical deadlock between render and game threads in UE 5.6 when invoking IHeadMountedDisplay::GetHMDMonitorInfo()
This commit is contained in:
@@ -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();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user