Files
Brandyn / Techy fcc1b09210 init
2026-04-04 15:40:51 -05:00

630 lines
27 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "OpenXRHMD_Layer.h"
#include "OpenXRAssetManager.h"
#include "CoreMinimal.h"
#include "HeadMountedDisplayBase.h"
#include "XRTrackingSystemBase.h"
#include "XRRenderTargetManager.h"
#include "XRRenderBridge.h"
#include "XRSwapChain.h"
#include "SceneViewExtension.h"
#include "StereoLayerManager.h"
#include "DefaultSpectatorScreenController.h"
#include "IHeadMountedDisplayVulkanExtensions.h"
#include "IOpenXRExtensionPluginDelegates.h"
#include "IOpenXRHMD.h"
#include "Misc/EnumClassFlags.h"
#include "XRCopyTexture.h"
#include <openxr/openxr.h>
#include "DefaultStereoLayers.h"
class APlayerController;
class FSceneView;
class FSceneViewFamily;
class FFBFoveationImageGenerator;
class FOpenXRSwapchain;
class UCanvas;
class FOpenXRRenderBridge;
class IOpenXRInputModule;
struct FDefaultStereoLayers_LayerRenderParams;
union FXrCompositionLayerUnion;
/**
* Simple Head Mounted Display
*/
class FOpenXRHMD
: public FHeadMountedDisplayBase
, public FXRRenderTargetManager
, public FHMDSceneViewExtension
, public FOpenXRAssetManager
, public FSimpleLayerManager
, public IOpenXRExtensionPluginDelegates
, public IOpenXRHMD
{
private:
public:
class FDeviceSpace
{
public:
FDeviceSpace(XrAction InAction, XrPath InPath);
FDeviceSpace(XrAction InAction, XrPath InPath, XrPath InSubactionPath);
~FDeviceSpace();
bool CreateSpace(XrSession InSession);
void DestroySpace();
XrAction Action;
XrSpace Space;
XrPath Path;
XrPath SubactionPath;
};
class FTrackingSpace
{
public:
FTrackingSpace(XrReferenceSpaceType InType);
FTrackingSpace(XrReferenceSpaceType InType, XrPosef InBasePose);
~FTrackingSpace();
bool CreateSpace(XrSession InSession);
void DestroySpace();
XrReferenceSpaceType Type;
XrSpace Handle;
XrPosef BasePose;
};
// The game and render threads each have a separate copy of these structures so that they don't stomp on each other or cause tearing
// when the game thread progresses to the next frame while the render thread is still working on the previous frame.
struct FPipelinedFrameState
{
XrFrameState FrameState{XR_TYPE_FRAME_STATE};
XrViewState ViewState{XR_TYPE_VIEW_STATE};
TArray<XrView> Views;
TArray<XrViewConfigurationView> ViewConfigs;
TArray<XrSpaceLocation> DeviceLocations;
TSharedPtr<FTrackingSpace> TrackingSpace;
float WorldToMetersScale = 100.0f;
float PixelDensity = 1.0f;
int WaitCount = 0;
int BeginCount = 0;
int EndCount = 0;
bool bXrFrameStateUpdated = false;
};
struct FPipelinedFrameStateAccessorReadOnly
{
FPipelinedFrameStateAccessorReadOnly(FPipelinedFrameState const& InPipelinedFrameState, FRWLock const& InAccessGuard)
: PipelinedFrameState(InPipelinedFrameState), AccessGuard(const_cast<FRWLock&>(InAccessGuard))
{
AccessGuard.ReadLock();
}
// not virtual because we aren't going to delete via a base pointer
~FPipelinedFrameStateAccessorReadOnly()
{
AccessGuard.ReadUnlock();
}
FPipelinedFrameState const& GetFrameState() const
{
return PipelinedFrameState;
}
private:
/** The frame state we're guarding the access to. */
FPipelinedFrameState const& PipelinedFrameState;
/** Reference to the guarding lock. */
FRWLock& AccessGuard;
};
struct FPipelinedFrameStateAccessorReadWrite
{
FPipelinedFrameStateAccessorReadWrite(FPipelinedFrameState& InPipelinedFrameState, FRWLock& InAccessGuard)
: PipelinedFrameState(InPipelinedFrameState), AccessGuard(InAccessGuard)
{
AccessGuard.WriteLock();
}
// not virtual because we aren't going to delete via a base pointer
~FPipelinedFrameStateAccessorReadWrite()
{
AccessGuard.WriteUnlock();
}
FPipelinedFrameState& GetFrameState()
{
return PipelinedFrameState;
}
private:
/** The frame state we're guarding the access to. */
FPipelinedFrameState& PipelinedFrameState;
/** Reference to the guarding lock. */
FRWLock& AccessGuard;
};
struct FEmulatedLayerState
{
// These layers are used as a target to composite all the emulated face locked layers into
// and be sent to the compositor with VIEW tracking space to avoid reprojection.
TArray<XrCompositionLayerProjectionView> CompositedProjectionLayers;
TArray<XrSwapchainSubImage> EmulationImages;
// This swapchain is where the emulated face locked layers are rendered into.
FXRSwapChainPtr EmulationSwapchain;
};
struct FBasePassLayerBlendParameters
{
// Default constructor inverts the alpha for color blending to make up for the fact that UE uses
// alpha = 0 for opaque and alpha = 1 for transparent while OpenXR does the opposite.
// Alpha blending passes through the destination alpha instead.
FBasePassLayerBlendParameters()
{
srcFactorColor = XR_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA_FB;
dstFactorColor = XR_BLEND_FACTOR_SRC_ALPHA_FB;
srcFactorAlpha = XR_BLEND_FACTOR_ZERO_FB;
dstFactorAlpha = XR_BLEND_FACTOR_ONE_FB;
}
XrBlendFactorFB srcFactorColor;
XrBlendFactorFB dstFactorColor;
XrBlendFactorFB srcFactorAlpha;
XrBlendFactorFB dstFactorAlpha;
};
struct FLayerColorScaleAndBias
{
// Used by XR_KHR_composition_layer_color_scale_bias to apply a color multiplier and offset to the background layer
// and set via UHeadMountedDisplayFunctionLibrary::SetHMDColorScaleAndBias() --> OpenXRHMD::SetColorScaleAndBias()
XrColor4f ColorScale;
XrColor4f ColorBias;
};
enum class EOpenXRLayerStateFlags : uint32
{
None = 0u,
BackgroundLayerVisible = (1u << 0),
SubmitBackgroundLayer = (1u << 1),
SubmitDepthLayer = (1u << 2),
SubmitEmulatedFaceLockedLayer = (1u << 3),
SubmitMotionVectorLayer = (1u << 4),
};
FRIEND_ENUM_CLASS_FLAGS(EOpenXRLayerStateFlags);
struct FPipelinedLayerState
{
TArray<FXrCompositionLayerUnion> NativeOverlays;
TArray<XrCompositionLayerProjectionView> ProjectionLayers;
TArray<XrCompositionLayerDepthInfoKHR> DepthLayers;
TArray<XrCompositionLayerDepthTestFB> CompositionDepthTestLayers;
TArray<XrFrameSynthesisInfoEXT> FrameSynthesisLayers;
TArray<XrCompositionLayerSpaceWarpInfoFB> SpaceWarpLayers;
TArray<XrSwapchainSubImage> ColorImages;
TArray<XrSwapchainSubImage> DepthImages;
TArray<XrSwapchainSubImage> MotionVectorImages;
TArray<XrSwapchainSubImage> MotionVectorDepthImages;
FXRSwapChainPtr ColorSwapchain;
FXRSwapChainPtr DepthSwapchain;
FXRSwapChainPtr MotionVectorSwapchain;
FXRSwapChainPtr MotionVectorDepthSwapchain;
TArray<FXRSwapChainPtr> NativeOverlaySwapchains;
FEmulatedLayerState EmulatedLayerState;
EOpenXRLayerStateFlags LayerStateFlags = EOpenXRLayerStateFlags::None;
FBasePassLayerBlendParameters BasePassLayerBlendParams;
FLayerColorScaleAndBias LayerColorScaleAndBias;
};
class FVulkanExtensions : public IHeadMountedDisplayVulkanExtensions
{
public:
FVulkanExtensions(XrInstance InInstance, XrSystemId InSystem) : Instance(InInstance), System(InSystem) {}
virtual ~FVulkanExtensions() {}
/** IHeadMountedDisplayVulkanExtensions */
virtual bool GetVulkanInstanceExtensionsRequired(TArray<const ANSICHAR*>& Out) override;
virtual bool GetVulkanDeviceExtensionsRequired(VkPhysicalDevice_T *pPhysicalDevice, TArray<const ANSICHAR*>& Out) override;
private:
XrInstance Instance;
XrSystemId System;
TArray<char> Extensions;
TArray<char> DeviceExtensions;
};
/** IXRTrackingSystem interface */
virtual FName GetSystemName() const override
{
// This identifier is relied upon for plugin identification,
// see GetHMDName() to query the true XR system name.
static FName DefaultName(TEXT("OpenXR"));
return DefaultName;
}
int32 GetXRSystemFlags() const override
{
int32 flags = EXRSystemFlags::IsHeadMounted;
if (SelectedEnvironmentBlendMode != XR_ENVIRONMENT_BLEND_MODE_OPAQUE)
{
flags |= EXRSystemFlags::IsAR;
}
if (bSupportsHandTracking)
{
flags |= EXRSystemFlags::SupportsHandTracking;
}
return flags;
}
virtual bool EnumerateTrackedDevices(TArray<int32>& OutDevices, EXRTrackedDeviceType Type = EXRTrackedDeviceType::Any) override;
virtual void SetInterpupillaryDistance(float NewInterpupillaryDistance) override;
virtual float GetInterpupillaryDistance() const override;
virtual bool GetRelativeEyePose(int32 InDeviceId, int32 InViewIndex, FQuat& OutOrientation, FVector& OutPosition) override;
virtual void ResetOrientationAndPosition(float Yaw = 0.f) override;
virtual void ResetOrientation(float Yaw = 0.f) override;
virtual void ResetPosition() override;
virtual void Recenter(EOrientPositionSelector::Type Selector, float Yaw = 0.f);
virtual bool GetIsTracked(int32 DeviceId) override;
virtual bool GetCurrentPose(int32 DeviceId, FQuat& CurrentOrientation, FVector& CurrentPosition) override;
virtual bool GetPoseForTime(int32 DeviceId, FTimespan Timespan, bool& OutTimeWasUsed, FQuat& CurrentOrientation, FVector& CurrentPosition, bool& bProvidedLinearVelocity, FVector& LinearVelocity, bool& bProvidedAngularVelocity, FVector& AngularVelocityAsAxisAndLength, bool& bProvidedLinearAcceleration, FVector& LinearAcceleration, float WorldToMetersScale) override;
virtual bool GetCurrentInteractionProfile(const EControllerHand Hand, FString& InteractionProfile) override;
virtual void SetBaseRotation(const FRotator& InBaseRotation) override;
virtual FRotator GetBaseRotation() const override;
virtual void SetBaseOrientation(const FQuat& InBaseOrientation) override;
virtual FQuat GetBaseOrientation() const override;
virtual void SetBasePosition(const FVector& InBasePosition) override;
virtual FVector GetBasePosition() const override;
virtual void SetTrackingOrigin(EHMDTrackingOrigin::Type NewOrigin) override;
virtual EHMDTrackingOrigin::Type GetTrackingOrigin() const override;
virtual class IHeadMountedDisplay* GetHMDDevice() override
{
return this;
}
virtual class TSharedPtr< class IStereoRendering, ESPMode::ThreadSafe > GetStereoRenderingDevice() override
{
return SharedThis(this);
}
virtual class IStereoLayers* GetStereoLayers() override
{
return this;
}
virtual void GetMotionControllerState(UObject* WorldContext, const EXRSpaceType XRSpaceType, const EControllerHand Hand, const EXRControllerPoseType XRControllerPoseType, FXRMotionControllerState& MotionControllerState) override;
virtual void GetHandTrackingState(UObject* WorldContext, const EXRSpaceType XRSpaceType, const EControllerHand Hand, FXRHandTrackingState& HandTrackingState) override;
virtual float GetWorldToMetersScale() const override;
virtual FVector2D GetPlayAreaBounds(EHMDTrackingOrigin::Type Origin) const override;
virtual bool GetPlayAreaRect(FTransform& OutTransform, FVector2D& OutExtent) const override;
virtual bool GetTrackingOriginTransform(TEnumAsByte<EHMDTrackingOrigin::Type> Origin, FTransform& OutTransform) const override;
virtual bool HDRGetMetaDataForStereo(EDisplayOutputFormat& OutDisplayOutputFormat, EDisplayColorGamut& OutDisplayColorGamut, bool& OutbHDRSupported) override;
protected:
bool StartSession();
bool StopSession();
bool OnStereoStartup();
bool OnStereoTeardown();
bool ReadNextEvent(XrEventDataBuffer* buffer);
void DestroySession();
void RequestExitApp();
void BuildOcclusionMeshes();
bool BuildOcclusionMesh(XrVisibilityMaskTypeKHR Type, int View, FHMDViewMesh& Mesh);
FPipelinedFrameStateAccessorReadOnly GetPipelinedFrameStateForThread() const;
FPipelinedFrameStateAccessorReadWrite GetPipelinedFrameStateForThread();
void UpdateDeviceLocations(bool bUpdateOpenXRExtensionPlugins);
void EnumerateViews(FPipelinedFrameState& PipelineState);
void LocateViews(FPipelinedFrameState& PipelinedState, bool ResizeViewsArray = false);
void AllocateDepthTextureInternal(uint32 SizeX, uint32 SizeY, uint32 NumSamples, uint32 ArraySize);
void SetupFrameLayers_GameThread();
void SetupFrameLayers_RenderThread(FRDGBuilder& GraphBuilder);
void DrawEmulatedLayers_RenderThread(FRDGBuilder& GraphBuilder, const FSceneView& InView);
void DrawBackgroundCompositedEmulatedLayers_RenderThread(FRDGBuilder& GraphBuilder, const FSceneView& InView);
void DrawEmulatedFaceLockedLayers_RenderThread(FRDGBuilder& GraphBuilder, const FSceneView& InView);
/** TStereoLayerManager<FLayerDesc> */
virtual void MarkTextureForUpdate(uint32 LayerId) override;
virtual uint32 CreateLayer(const FLayerDesc& InLayerDesc) override;
virtual void DestroyLayer(uint32 LayerId) override;
virtual void SetLayerDesc(uint32 LayerId, const FLayerDesc& InLayerDesc) override;
virtual bool PopulateAnalyticsAttributes(TArray<struct FAnalyticsEventAttribute>& EventAttributes) override;
/** Populates System, SystemProperties and related fields. Can get called before OnStereoStartup. */
bool AcquireSystemIdAndProperties();
public:
/** IXRTrackingSystem interface */
virtual bool DoesSupportLateProjectionUpdate() const override { return true; }
virtual FString GetVersionString() const override;
virtual bool IsTracking(int32 DeviceId) override;
virtual bool HasValidTrackingPosition() override;
virtual IOpenXRHMD* GetIOpenXRHMD() { return this; }
/** IHeadMountedDisplay interface */
virtual bool IsHMDConnected() override;
virtual bool DoesSupportPositionalTracking() const override { return true; }
virtual bool IsHMDEnabled() const override;
virtual void EnableHMD(bool allow = true) override;
virtual FName GetHMDName() const override;
virtual bool GetHMDMonitorInfo(MonitorInfo&) override;
virtual void GetFieldOfView(float& OutHFOVInDegrees, float& OutVFOVInDegrees) const override;
virtual bool IsChromaAbCorrectionEnabled() const override;
virtual float GetPixelDenity() const override;
virtual void SetPixelDensity(const float NewDensity) override;
virtual FIntPoint GetIdealRenderTargetSize() const override;
virtual bool GetHMDDistortionEnabled(EShadingPath ShadingPath) const override { return false; }
virtual FIntRect GetFullFlatEyeRect_RenderThread(const FRHITextureDesc& EyeTexture) const override;
virtual bool HasHiddenAreaMesh() const override final;
virtual bool HasVisibleAreaMesh() const override final;
virtual void DrawHiddenAreaMesh(class FRHICommandList& RHICmdList, int32 ViewIndex) const override final;
virtual void DrawVisibleAreaMesh(class FRHICommandList& RHICmdList, int32 ViewIndex) const override final;
virtual void DrawHiddenAreaMesh(class FRHICommandList& RHICmdList, int32 ViewIndex, int32 InstanceCount) const override final;
virtual void DrawVisibleAreaMesh(class FRHICommandList& RHICmdList, int32 ViewIndex, int32 InstanceCount) const override final;
virtual void OnBeginRendering_RenderThread(FRDGBuilder& GraphBuilder, FSceneViewFamily& ViewFamily) override;
virtual void OnBeginRendering_GameThread(FSceneViewFamily& SceneViewFamily) override;
virtual void OnLateUpdateApplied_RenderThread(FRDGBuilder& GraphBuilder, const FTransform& NewRelativeTransform) override;
virtual bool OnStartGameFrame(FWorldContext& WorldContext) override;
virtual EHMDWornState::Type GetHMDWornState() override { return bIsReady ? EHMDWornState::Worn : EHMDWornState::NotWorn; }
virtual bool SetColorScaleAndBias(FLinearColor ColorScale, FLinearColor ColorBias);
/** IStereoRendering interface */
virtual bool IsStereoEnabled() const override;
virtual bool EnableStereo(bool stereo = true) override;
virtual void AdjustViewRect(int32 ViewIndex, int32& X, int32& Y, uint32& SizeX, uint32& SizeY) const override;
virtual void SetFinalViewRect(FRHICommandListImmediate& RHICmdList, const int32 StereoViewIndex, const FIntRect& FinalViewRect) override;
virtual int32 GetDesiredNumberOfViews(bool bStereoRequested) const override;
virtual EStereoscopicPass GetViewPassForIndex(bool bStereoRequested, int32 ViewIndex) const override;
virtual uint32 GetLODViewIndex() const override;
virtual bool IsStandaloneStereoOnlyDevice() const override { return bIsStandaloneStereoOnlyDevice; }
virtual FMatrix GetStereoProjectionMatrix(const int32 StereoViewIndex) const override;
virtual void GetEyeRenderParams_RenderThread(const struct FHeadMountedDisplayPassContext& Context, FVector2D& EyeToSrcUVScaleValue, FVector2D& EyeToSrcUVOffsetValue) const override;
virtual IStereoRenderTargetManager* GetRenderTargetManager() override;
virtual void RenderTexture_RenderThread(class FRDGBuilder& GraphBuilder, FRDGTextureRef BackBuffer, FRDGTextureRef SrcTexture, FVector2f WindowSize) const override;
/** ISceneViewExtension interface */
virtual void SetupViewFamily(FSceneViewFamily& InViewFamily) override;
virtual void SetupView(FSceneViewFamily& InViewFamily, FSceneView& InView) override;
virtual void BeginRenderViewFamily(FSceneViewFamily& InViewFamily) override;
virtual void PreRenderView_RenderThread(FRDGBuilder& GraphBuilder, FSceneView& InView) override;
virtual void PostRenderView_RenderThread(FRDGBuilder& GraphBuilder, FSceneView& InView) override; // for non-face locked compositing
virtual void PreRenderViewFamily_RenderThread(FRDGBuilder& GraphBuilder, FSceneViewFamily& InViewFamily) override;
virtual void PostRenderViewFamily_RenderThread(FRDGBuilder& GraphBuilder, FSceneViewFamily& InViewFamily) override;
/** FHMDSceneViewExtension interface */
virtual bool IsActiveThisFrame_Internal(const FSceneViewExtensionContext& Context) const override;
/** IStereoRenderTargetManager */
virtual bool ShouldUseSeparateRenderTarget() const override { return IsStereoEnabled() && RenderBridge.IsValid(); }
virtual void CalculateRenderTargetSize(const FViewport& Viewport, uint32& InOutSizeX, uint32& InOutSizeY) override;
virtual bool AllocateRenderTargetTextures(uint32 SizeX, uint32 SizeY, uint8 Format, uint32 NumLayers, ETextureCreateFlags Flags, ETextureCreateFlags TargetableTextureFlags, TArray<FTextureRHIRef>& OutTargetableTextures, TArray<FTextureRHIRef>& OutShaderResourceTextures, uint32 NumSamples = 1) override;
virtual int32 AcquireColorTexture() override final;
virtual int32 AcquireDepthTexture() override final;
virtual bool AllocateDepthTexture(uint32 Index, uint32 SizeX, uint32 SizeY, uint8 Format, uint32 NumMips, ETextureCreateFlags InTexFlags, ETextureCreateFlags TargetableTextureFlags, FTextureRHIRef& OutTargetableTexture, FTextureRHIRef& OutShaderResourceTexture, uint32 NumSamples = 1) override final;
virtual bool GetRecommendedMotionVectorTextureSize(FIntPoint& OutTextureSize) override;
virtual bool GetMotionVectorTexture(uint32 Index, const FIntPoint& Size, uint8 Format, uint32 NumMips, ETextureCreateFlags Flags, FTextureRHIRef& OutTexture, uint32 NumSamples = 1) override;
virtual bool GetMotionVectorDepthTexture(uint32 Index, const FIntPoint& Size, uint8 Format, uint32 NumMips, ETextureCreateFlags Flags, FTextureRHIRef& OutTexture, uint32 NumSamples = 1) override;
virtual bool ReconfigureForShaderPlatform(EShaderPlatform NewShaderPlatform) override;
virtual EPixelFormat GetActualColorSwapchainFormat() const override { return static_cast<EPixelFormat>(LastActualColorSwapchainFormat); }
/** FXRRenderTargetManager */
virtual FXRRenderBridge* GetActiveRenderBridge_GameThread(bool bUseSeparateRenderTarget) override;
/** IXRTrackingSystem */
virtual void OnBeginPlay(FWorldContext& InWorldContext) override;
/** IStereoLayers */
virtual TArray<FTextureRHIRef, TInlineAllocator<2>> GetDebugLayerTextures_RenderThread() override;
virtual void GetAllocatedTexture(uint32 LayerId, FTextureRHIRef& Texture, FTextureRHIRef& LeftTexture) override final;
/** IOpenXRExtensionPluginDelegates */
public:
virtual FApplyHapticFeedbackAddChainStructsDelegate& GetApplyHapticFeedbackAddChainStructsDelegate() override { return ApplyHapticFeedbackAddChainStructsDelegate; }
private:
FApplyHapticFeedbackAddChainStructsDelegate ApplyHapticFeedbackAddChainStructsDelegate;
public:
/** Constructor */
FOpenXRHMD(const FAutoRegister&, XrInstance InInstance, TRefCountPtr<FOpenXRRenderBridge>& InRenderBridge, TArray<const char*> InEnabledExtensions, TArray<class IOpenXRExtensionPlugin*> InExtensionPlugins, IARSystemSupport* ARSystemSupport, EOpenXRAPIVersion InOpenXRAPIVersion);
/** Destructor */
virtual ~FOpenXRHMD();
void OnBeginSimulation_GameThread();
void OnBeginRendering_RHIThread(IRHICommandContext& RHICmdContext, const FPipelinedFrameState& InFrameState, FXRSwapChainPtr ColorSwapchain, FXRSwapChainPtr DepthSwapchain, FXRSwapChainPtr MotionVectorSwapchain, FXRSwapChainPtr MotionVectorDepthSwapchain, FXRSwapChainPtr EmulationSwapchain);
void OnFinishRendering_RHIThread(IRHICommandContext& RHICmdContext);
/** IOpenXRHMD */
void SetInputModule(IOpenXRInputModule* InInputModule) override
{
InputModule = InInputModule;
}
/** @return True if the HMD was initialized OK */
bool IsInitialized() const override;
bool IsRunning() const override;
bool IsFocused() const override;
int32 AddTrackedDevice(XrAction Action, XrPath Path) override;
int32 AddTrackedDevice(XrAction Action, XrPath Path, XrPath SubActionPath) override;
void ResetTrackedDevices() override;
XrPath GetTrackedDevicePath(const int32 DeviceId) override;
XrSpace GetTrackedDeviceSpace(const int32 DeviceId) override;
bool IsExtensionEnabled(const FString& Name) const override { return EnabledExtensions.Contains(Name); }
bool IsOpenXRAPIVersionMet(EOpenXRAPIVersion RequiredVersion) const override { return OpenXRAPIVersion >= RequiredVersion; }
XrInstance GetInstance() override { return Instance; }
XrSystemId GetSystem() override { return System; }
XrSession GetSession() override { return Session; }
XrTime GetDisplayTime() const override;
XrSpace GetTrackingSpace() const override;
IOpenXRExtensionPluginDelegates& GetIOpenXRExtensionPluginDelegates() override { return *this; }
TArray<IOpenXRExtensionPlugin*>& GetExtensionPlugins() override { return ExtensionPlugins; }
void SetEnvironmentBlendMode(XrEnvironmentBlendMode NewBlendMode) override;
XrEnvironmentBlendMode GetEnvironmentBlendMode() override { return SelectedEnvironmentBlendMode; }
TArray<XrEnvironmentBlendMode> GetSupportedEnvironmentBlendModes() const override;
/** Provides the full asymmetric FOV information for the view, which allows proper centering of screen-based techniques based on forward eye gaze */
void GetFullFOVInformation(TArray<XrFovf>& FovInfos) const override;
virtual bool AllocateSwapchainTextures_RenderThread(const FOpenXRSwapchainProperties& InSwapchainProperies, FXRSwapChainPtr& InOutSwapchain, uint8& OutActualFormat) override;
/** Returns shader platform the plugin is currently configured for, in the editor it can change due to preview platforms. */
EShaderPlatform GetConfiguredShaderPlatform() const { check(ConfiguredShaderPlatform != EShaderPlatform::SP_NumPlatforms); return ConfiguredShaderPlatform; }
FOpenXRSwapchain* GetColorSwapchain_RenderThread();
bool RuntimeRequiresRHIContext() const { return bRuntimeRequiresRHIContext; }
private:
FDefaultStereoLayers_LayerRenderParams CalculateEmulatedLayerRenderParams(const FSceneView& InView);
class FEmulatedLayersPass* SetupEmulatedLayersRenderPass(FRDGBuilder& GraphBuilder, const FSceneView& InView, TArray<FDefaultStereoLayers::FStereoLayerToRender>& Layers, FRDGTextureRef RenderTarget, FDefaultStereoLayers_LayerRenderParams& OutRenderParams);
bool IsEmulatingStereoLayers();
void CopySwapchainTexture_RenderThread(FRDGBuilder& GraphBuilder, FRDGTextureRef SrcTexture, FIntRect SrcRect, const FXRSwapChainPtr& DstSwapChain, FIntRect DstRect,
bool bClearBlack, EXRCopyTextureBlendModifier SrcTextureCopyModifier, FStaticFeatureLevel FeatureLevel, FStaticShaderPlatform ShaderPlatform) const;
void UpdateLayerSwapchainTexture(FOpenXRLayer& Layer, FRDGBuilder& GraphBuilder);
void ConfigureLayerSwapchains(const struct FLayerToUpdateSwapchain& Update, FOpenXRLayer& Layer);
void AddLayersToHeaders(TArray<XrCompositionLayerBaseHeader*>& Headers);
// Gets the user path corresponding to the input EControllerHand value
static XrPath GetUserPathForControllerHand(EControllerHand Hand);
bool bStereoEnabled;
TAtomic<bool> bIsRunning;
TAtomic<bool> bIsReady;
TAtomic<bool> bIsRendering;
TAtomic<bool> bIsSynchronized;
bool bShouldWait;
bool bIsExitingSessionByxrRequestExitSession;
bool bDepthExtensionSupported;
bool bHiddenAreaMaskSupported;
bool bViewConfigurationFovSupported;
bool bNeedReBuildOcclusionMesh;
bool bIsMobileMultiViewEnabled;
bool bSupportsHandTracking;
bool bSpaceAccelerationSupported;
bool bProjectionLayerAlphaEnabled;
bool bIsStandaloneStereoOnlyDevice;
bool bRuntimeRequiresRHIContext;
bool bIsTrackingOnlySession;
bool bIsAcquireOnAnyThreadSupported;
bool bUseWaitCountToAvoidExtraXrBeginFrameCalls;
bool bEquirectLayersSupported;
bool bCylinderLayersSupported;
float WorldToMetersScale = 100.0f;
float RuntimePixelDensityMax = FHeadMountedDisplayBase::PixelDensityMax;
EShaderPlatform ConfiguredShaderPlatform = EShaderPlatform::SP_NumPlatforms;
XrSessionState CurrentSessionState;
FRWLock SessionHandleMutex;
TArray<const char*> EnabledExtensions;
IOpenXRInputModule* InputModule;
TArray<class IOpenXRExtensionPlugin*> ExtensionPlugins;
XrInstance Instance;
EOpenXRAPIVersion OpenXRAPIVersion;
XrSystemId System;
XrSession Session;
XrSpace LocalSpace;
XrSpace LocalFloorSpace;
XrSpace StageSpace;
XrSpace CustomSpace;
XrReferenceSpaceType TrackingSpaceType;
XrViewConfigurationType SelectedViewConfigurationType;
XrEnvironmentBlendMode SelectedEnvironmentBlendMode;
XrInstanceProperties InstanceProperties;
XrSystemProperties SystemProperties;
FPipelinedFrameState PipelinedFrameStateGame;
FPipelinedFrameState PipelinedFrameStateRendering;
FPipelinedFrameState PipelinedFrameStateRHI;
/** Arbitrates access to PipelinedFrameStateGame from code on task threads */
FRWLock PipelinedFrameStateGameAccessGuard;
/** Arbitrates access to PipelinedFrameStateRendering from code on task threads */
FRWLock PipelinedFrameStateRenderingAccessGuard;
// we do not expose PipelineFrameStateRHI in GetPipelinedFrameStateForThread() as of now, so no lock is provided for that one.
FPipelinedLayerState PipelinedLayerStateRendering;
FPipelinedLayerState PipelinedLayerStateRHI;
mutable FRWLock DeviceMutex;
TArray<FDeviceSpace> DeviceSpaces;
TRefCountPtr<FOpenXRRenderBridge> RenderBridge;
IRendererModule* RendererModule;
uint8 LastRequestedColorSwapchainFormat;
uint8 LastActualColorSwapchainFormat;
uint8 LastRequestedDepthSwapchainFormat;
TArray<FHMDViewMesh> HiddenAreaMeshes;
TArray<FHMDViewMesh> VisibleAreaMeshes;
bool bTrackingSpaceInvalid;
bool bUseCustomReferenceSpace;
FQuat BaseOrientation;
FVector BasePosition;
bool bLayerSupportOpenXRCompliant;
bool bOpenXRForceStereoLayersEmulationCVarCachedValue;
TArray<uint32> VisibleLayerIds;
UE_DEPRECATED(5.6, "This will no longer be needed once OnSetupLayers_RenderThread is removed")
TArray<uint32> VisibleLayerIds_RenderThread;
TArray<FDefaultStereoLayers::FStereoLayerToRender> BackgroundCompositedEmulatedLayers;
TArray<FDefaultStereoLayers::FStereoLayerToRender> EmulatedFaceLockedLayers;
TArray<FOpenXRLayer> NativeLayers;
TUniquePtr<FFBFoveationImageGenerator> FBFoveationImageGenerator;
bool bFoveationExtensionSupported;
bool bRuntimeFoveationSupported;
bool bLocalFloorSpaceSupported;
bool bUserPresenceSupported;
XrColor4f LayerColorScale;
XrColor4f LayerColorBias;
bool bCompositionLayerColorScaleBiasSupported;
bool bxrGetSystemPropertiesSuccessful;
FTransform FrameSynthesisLastTrackingToWorld;
FIntPoint RecommendedMotionVectorTextureSize;
};
ENUM_CLASS_FLAGS(FOpenXRHMD::EOpenXRLayerStateFlags);