234 lines
8.4 KiB
C
234 lines
8.4 KiB
C
|
// @lint-ignore-every LICENSELINT
|
||
|
// Copyright Epic Games, Inc. All Rights Reserved.
|
||
|
|
||
|
#pragma once
|
||
|
#include "OculusXRHMDPrivate.h"
|
||
|
#include "ProceduralMeshComponent.h"
|
||
|
|
||
|
#if OCULUS_HMD_SUPPORTED_PLATFORMS
|
||
|
#include "OculusXRHMD_CustomPresent.h"
|
||
|
#include "XRSwapChain.h"
|
||
|
#include "OculusXRPassthroughLayerShapes.h"
|
||
|
|
||
|
namespace OculusXRHMD
|
||
|
{
|
||
|
|
||
|
//-------------------------------------------------------------------------------------------------
|
||
|
// FOvrpLayer
|
||
|
//-------------------------------------------------------------------------------------------------
|
||
|
class FDeferredDeletionQueue;
|
||
|
|
||
|
class FOvrpLayer : public TSharedFromThis<FOvrpLayer, ESPMode::ThreadSafe>
|
||
|
{
|
||
|
public:
|
||
|
FOvrpLayer(uint32 InOvrpLayerId, FDeferredDeletionQueue* InDeferredDeletion);
|
||
|
~FOvrpLayer();
|
||
|
|
||
|
protected:
|
||
|
uint32 OvrpLayerId;
|
||
|
|
||
|
private:
|
||
|
FDeferredDeletionQueue* DeferredDeletion; // necessary for deferred deletion queue of the actual OvrpLayer
|
||
|
};
|
||
|
|
||
|
typedef TSharedPtr<FOvrpLayer, ESPMode::ThreadSafe> FOvrpLayerPtr;
|
||
|
|
||
|
//-------------------------------------------------------------------------------------------------
|
||
|
// FLayer
|
||
|
//-------------------------------------------------------------------------------------------------
|
||
|
|
||
|
class FLayer : public TSharedFromThis<FLayer, ESPMode::ThreadSafe>
|
||
|
{
|
||
|
public:
|
||
|
FLayer(uint32 InId);
|
||
|
FLayer(const FLayer& InLayer);
|
||
|
~FLayer();
|
||
|
|
||
|
uint32 GetId() const { return Id; }
|
||
|
int GetOvrpId() const { return OvrpLayerId; }
|
||
|
void SetDesc(const IStereoLayers::FLayerDesc& InDesc);
|
||
|
void SetDesc(const FSettings* Settings, const IStereoLayers::FLayerDesc& InDesc);
|
||
|
const IStereoLayers::FLayerDesc& GetDesc() const { return Desc; }
|
||
|
void SetEyeLayerDesc(const ovrpLayerDesc_EyeFov& InEyeLayerDesc);
|
||
|
const FXRSwapChainPtr& GetSwapChain() const { return SwapChain; }
|
||
|
const FXRSwapChainPtr& GetRightSwapChain() const { return RightSwapChain; }
|
||
|
const FXRSwapChainPtr& GetDepthSwapChain() const { return DepthSwapChain; }
|
||
|
const FXRSwapChainPtr& GetFoveationSwapChain() const { return FoveationSwapChain; }
|
||
|
const FXRSwapChainPtr& GetMotionVectorSwapChain() const { return MotionVectorSwapChain; }
|
||
|
const FXRSwapChainPtr& GetMotionVectorDepthSwapChain() const { return MotionVectorDepthSwapChain; }
|
||
|
void MarkTextureForUpdate() { bUpdateTexture = true; }
|
||
|
bool NeedsPokeAHole();
|
||
|
void HandlePokeAHoleComponent();
|
||
|
void BuildPokeAHoleMesh(TArray<FVector>& Vertices, TArray<int32>& Triangles, TArray<FVector2D>& UV0);
|
||
|
bool NeedsPassthroughPokeAHole();
|
||
|
|
||
|
bool ShapeNeedsTextures(ovrpShape shape);
|
||
|
|
||
|
FTextureRHIRef GetTexture() { return Desc.Texture; }
|
||
|
|
||
|
TSharedPtr<FLayer, ESPMode::ThreadSafe> Clone() const;
|
||
|
|
||
|
bool CanReuseResources(const FLayer* InLayer) const;
|
||
|
bool Initialize_RenderThread(const FSettings* Settings, FCustomPresent* CustomPresent, FDeferredDeletionQueue* DeferredDeletion, FRHICommandListImmediate& RHICmdList, const FLayer* InLayer = nullptr);
|
||
|
void UpdateTexture_RenderThread(const FSettings* Settings, FCustomPresent* CustomPresent, FRHICommandListImmediate& RHICmdList);
|
||
|
void UpdatePassthrough_RenderThread(FCustomPresent* CustomPresent, FRHICommandListImmediate& RHICmdList, const FGameFrame* Frame);
|
||
|
|
||
|
const ovrpLayerSubmit* UpdateLayer_RHIThread(const FSettings* Settings, const FGameFrame* Frame, const int LayerIndex);
|
||
|
void IncrementSwapChainIndex_RHIThread(FCustomPresent* CustomPresent);
|
||
|
void ReleaseResources_RHIThread();
|
||
|
bool IsVisible() { return (Desc.Flags & IStereoLayers::LAYER_FLAG_HIDDEN) == 0; }
|
||
|
|
||
|
bool bNeedsTexSrgbCreate;
|
||
|
|
||
|
void AddPassthroughMesh_RenderThread(const TArray<FVector>& Vertices, const TArray<int32>& Triangles, FMatrix Transformation, uint64_t& OutMeshHandle, uint64_t& OutInstanceHandle);
|
||
|
void UpdatePassthroughMeshTransform_RenderThread(uint64_t InstanceHandle, FMatrix Transformation);
|
||
|
void RemovePassthroughMesh_RenderThread(uint64_t MeshHandle, uint64_t InstanceHandle);
|
||
|
|
||
|
void DestroyLayer();
|
||
|
|
||
|
protected:
|
||
|
struct FPassthroughMesh
|
||
|
{
|
||
|
FPassthroughMesh(uint64_t MeshHandle, uint64_t InstanceHandle)
|
||
|
: MeshHandle(MeshHandle)
|
||
|
, InstanceHandle(InstanceHandle)
|
||
|
{
|
||
|
}
|
||
|
uint64_t MeshHandle;
|
||
|
uint64_t InstanceHandle;
|
||
|
};
|
||
|
|
||
|
typedef TSharedPtr<TMap<FString, FPassthroughMesh>, ESPMode::ThreadSafe> FUserDefinedGeometryMapPtr;
|
||
|
|
||
|
void UpdatePassthroughStyle_RenderThread(const FEdgeStyleParameters& EdgeStyleParameters);
|
||
|
|
||
|
struct FPassthroughPokeActor
|
||
|
{
|
||
|
FPassthroughPokeActor(){};
|
||
|
FPassthroughPokeActor(UProceduralMeshComponent* PokeAHoleComponentPtr, AActor* PokeAHoleActor)
|
||
|
: PokeAHoleComponentPtr(PokeAHoleComponentPtr)
|
||
|
, PokeAHoleActor(PokeAHoleActor){};
|
||
|
UProceduralMeshComponent* PokeAHoleComponentPtr;
|
||
|
AActor* PokeAHoleActor;
|
||
|
};
|
||
|
|
||
|
typedef TSharedPtr<TMap<FString, FPassthroughPokeActor>, ESPMode::ThreadSafe> FPassthroughPokeActorMapPtr;
|
||
|
|
||
|
bool BuildPassthroughPokeActor(FOculusPassthroughMeshRef PassthroughMesh, FPassthroughPokeActor& OutPassthroughPokeActor);
|
||
|
void UpdatePassthroughPokeActors_GameThread();
|
||
|
|
||
|
uint32 Id;
|
||
|
IStereoLayers::FLayerDesc Desc;
|
||
|
int OvrpLayerId;
|
||
|
ovrpLayerDescUnion OvrpLayerDesc;
|
||
|
ovrpLayerSubmitUnion OvrpLayerSubmit;
|
||
|
FOvrpLayerPtr OvrpLayer;
|
||
|
FXRSwapChainPtr SwapChain;
|
||
|
FXRSwapChainPtr DepthSwapChain;
|
||
|
FXRSwapChainPtr FoveationSwapChain;
|
||
|
FXRSwapChainPtr RightSwapChain;
|
||
|
FXRSwapChainPtr RightDepthSwapChain;
|
||
|
FXRSwapChainPtr MotionVectorSwapChain;
|
||
|
FXRSwapChainPtr MotionVectorDepthSwapChain;
|
||
|
FTextureRHIRef InvAlphaTexture;
|
||
|
bool bUpdateTexture;
|
||
|
bool bInvertY;
|
||
|
bool bHasDepth;
|
||
|
bool bSupportDepthComposite;
|
||
|
|
||
|
UProceduralMeshComponent* PokeAHoleComponentPtr;
|
||
|
AActor* PokeAHoleActor;
|
||
|
|
||
|
FUserDefinedGeometryMapPtr UserDefinedGeometryMap;
|
||
|
FPassthroughPokeActorMapPtr PassthroughPokeActorMap;
|
||
|
};
|
||
|
|
||
|
typedef TSharedPtr<FLayer, ESPMode::ThreadSafe> FLayerPtr;
|
||
|
|
||
|
//-------------------------------------------------------------------------------------------------
|
||
|
// FLayerPtr_CompareId
|
||
|
//-------------------------------------------------------------------------------------------------
|
||
|
|
||
|
struct FLayerPtr_CompareId
|
||
|
{
|
||
|
FORCEINLINE bool operator()(const FLayerPtr& A, const FLayerPtr& B) const
|
||
|
{
|
||
|
return A->GetId() < B->GetId();
|
||
|
}
|
||
|
};
|
||
|
|
||
|
//-------------------------------------------------------------------------------------------------
|
||
|
// FLayerPtr_ComparePriority
|
||
|
//-------------------------------------------------------------------------------------------------
|
||
|
|
||
|
struct FLayerPtr_ComparePriority
|
||
|
{
|
||
|
FORCEINLINE bool operator()(const FLayerPtr& A, const FLayerPtr& B) const
|
||
|
{
|
||
|
if (A->GetDesc().Priority < B->GetDesc().Priority)
|
||
|
return true;
|
||
|
if (A->GetDesc().Priority > B->GetDesc().Priority)
|
||
|
return false;
|
||
|
|
||
|
return A->GetId() < B->GetId();
|
||
|
}
|
||
|
};
|
||
|
|
||
|
struct FLayerPtr_CompareTotal
|
||
|
{
|
||
|
FORCEINLINE int32 GetLayerTypePriority(const FLayerPtr& A) const
|
||
|
{
|
||
|
// Draw FReconstructedLayer, PoleAHole layers (Android only), EyeFov layer, followed by other layers
|
||
|
const bool IsEyeFov = (A->GetId() == 0);
|
||
|
const bool IsPokeAHole = A->NeedsPokeAHole() || A->NeedsPassthroughPokeAHole();
|
||
|
bool IsUnderlay = false;
|
||
|
|
||
|
if (A->GetDesc().HasShape<FReconstructedLayer>())
|
||
|
{
|
||
|
const FReconstructedLayer& ReconstructedLayerProps = A->GetDesc().GetShape<FReconstructedLayer>();
|
||
|
IsUnderlay = (ReconstructedLayerProps.PassthroughLayerOrder == PassthroughLayerOrder_Underlay);
|
||
|
}
|
||
|
else if (A->GetDesc().HasShape<FUserDefinedLayer>())
|
||
|
{
|
||
|
const FUserDefinedLayer& UserDefinedLayerProps = A->GetDesc().GetShape<FUserDefinedLayer>();
|
||
|
IsUnderlay = (UserDefinedLayerProps.PassthroughLayerOrder == PassthroughLayerOrder_Underlay);
|
||
|
}
|
||
|
|
||
|
const int32 Priority = IsUnderlay ? -2 : IsPokeAHole ? -1
|
||
|
: IsEyeFov ? 0
|
||
|
: 1;
|
||
|
return Priority;
|
||
|
}
|
||
|
|
||
|
FORCEINLINE bool operator()(const FLayerPtr& A, const FLayerPtr& B) const
|
||
|
{
|
||
|
// First order layers by type
|
||
|
int32 PassA = GetLayerTypePriority(A);
|
||
|
int32 PassB = GetLayerTypePriority(B);
|
||
|
|
||
|
if (PassA != PassB)
|
||
|
return PassA < PassB;
|
||
|
|
||
|
// Draw non-FaceLocked layers first
|
||
|
const IStereoLayers::FLayerDesc& DescA = A->GetDesc();
|
||
|
const IStereoLayers::FLayerDesc& DescB = B->GetDesc();
|
||
|
|
||
|
bool bFaceLockedA = (DescA.PositionType == IStereoLayers::ELayerType::FaceLocked);
|
||
|
bool bFaceLockedB = (DescB.PositionType == IStereoLayers::ELayerType::FaceLocked);
|
||
|
|
||
|
if (bFaceLockedA != bFaceLockedB)
|
||
|
return !bFaceLockedA;
|
||
|
|
||
|
// Draw layers by ascending priority
|
||
|
if (DescA.Priority != DescB.Priority)
|
||
|
return DescA.Priority < DescB.Priority;
|
||
|
|
||
|
// Draw layers by ascending id
|
||
|
return A->GetId() < B->GetId();
|
||
|
}
|
||
|
};
|
||
|
|
||
|
} // namespace OculusXRHMD
|
||
|
|
||
|
#endif //OCULUS_HMD_SUPPORTED_PLATFORMS
|