fix the MarkRenderStateDirty data race condition by gathering as much as data only on the game thread
This commit is contained in:
@@ -51,6 +51,13 @@
|
||||
FSGVirtualHandAnimInstanceProxy::FSGVirtualHandAnimInstanceProxy()
|
||||
: FAnimInstanceProxy()
|
||||
{
|
||||
bIsVirtualHandVisible = false;
|
||||
VirtualHand = nullptr;
|
||||
HandMeshAsset = nullptr;
|
||||
HandSkeleton = nullptr;
|
||||
bMarkRenderStateDirty = false;
|
||||
|
||||
bShouldAnimationApplyBoneLocation = false;
|
||||
}
|
||||
|
||||
FSGVirtualHandAnimInstanceProxy::FSGVirtualHandAnimInstanceProxy(UAnimInstance* Instance)
|
||||
@@ -67,41 +74,54 @@ void FSGVirtualHandAnimInstanceProxy::PreEvaluateAnimation(UAnimInstance* InAnim
|
||||
return;
|
||||
}
|
||||
|
||||
USGVirtualHandComponent* VirtualHand{Cast<USGVirtualHandComponent>(GetSkelMeshComponent())};
|
||||
VirtualHand = Cast<USGVirtualHandComponent>(GetSkelMeshComponent());
|
||||
if (!IsValid(VirtualHand))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
HandMeshAsset = VirtualHand->GetSkeletalMeshAsset();
|
||||
if (!IsValid(HandMeshAsset))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
HandSkeleton = HandMeshAsset->GetSkeleton();
|
||||
if (!IsValid(HandSkeleton))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
bIsVirtualHandVisible = VirtualHand->IsVisible() && VirtualHand->GetVisibleFlag();
|
||||
if (!bIsVirtualHandVisible)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const bool bGotMotionControllerData = VirtualHand->GetMotionControllerData(MotionControllerData);
|
||||
if (!bGotMotionControllerData || !MotionControllerData.bValid)
|
||||
{
|
||||
return;
|
||||
}
|
||||
ensureAlwaysMsgf(MotionControllerData.HandKeyPositions.Num() == MotionControllerData.HandKeyRotations.Num(),
|
||||
TEXT("Mismatched motion controller data positions and rotations!"));
|
||||
|
||||
BoneNamesMap.Empty();
|
||||
for (TArray<FQuat>::SizeType HandKeyIndex = 0;
|
||||
HandKeyIndex < MotionControllerData.HandKeyRotations.Num(); ++HandKeyIndex)
|
||||
{
|
||||
const FName& BoneName{VirtualHand->GetHandBoneName(HandKeyIndex)};
|
||||
BoneNamesMap.Add(HandKeyIndex, BoneName);
|
||||
}
|
||||
|
||||
const FRotator& AnimationBoneRotationCorrectionOffset{VirtualHand->GetAnimationBoneRotationCorrectionOffset()};
|
||||
AnimationBoneCorrectionOffsetTransform = FTransform{AnimationBoneRotationCorrectionOffset};
|
||||
bShouldAnimationApplyBoneLocation = VirtualHand->ShouldAnimationApplyBoneLocation();
|
||||
}
|
||||
|
||||
bool FSGVirtualHandAnimInstanceProxy::Evaluate(FPoseContext& Output)
|
||||
{
|
||||
USGVirtualHandComponent* VirtualHand{Cast<USGVirtualHandComponent>(GetSkelMeshComponent())};
|
||||
if (!IsValid(VirtualHand))
|
||||
{
|
||||
return FAnimInstanceProxy::Evaluate(Output);
|
||||
}
|
||||
|
||||
const bool bIsVisible = VirtualHand->IsVisible() && VirtualHand->GetVisibleFlag();
|
||||
if (!bIsVisible)
|
||||
{
|
||||
return FAnimInstanceProxy::Evaluate(Output);
|
||||
}
|
||||
|
||||
const USkeletalMesh* HandMesh{VirtualHand->GetSkeletalMeshAsset()};
|
||||
if (!IsValid(HandMesh))
|
||||
{
|
||||
return FAnimInstanceProxy::Evaluate(Output);
|
||||
}
|
||||
|
||||
const USkeleton* HandSkeleton{HandMesh->GetSkeleton()};
|
||||
if (!IsValid(HandSkeleton))
|
||||
if (!bIsVirtualHandVisible)
|
||||
{
|
||||
return FAnimInstanceProxy::Evaluate(Output);
|
||||
}
|
||||
@@ -111,20 +131,13 @@ bool FSGVirtualHandAnimInstanceProxy::Evaluate(FPoseContext& Output)
|
||||
return FAnimInstanceProxy::Evaluate(Output);
|
||||
}
|
||||
|
||||
ensureAlwaysMsgf(MotionControllerData.HandKeyPositions.Num() == MotionControllerData.HandKeyRotations.Num(),
|
||||
TEXT("Mismatched motion controller data positions and rotations!"));
|
||||
|
||||
const FRotator& AnimationBoneRotationCorrectionOffset{VirtualHand->GetAnimationBoneRotationCorrectionOffset()};
|
||||
const FTransform AnimationBoneCorrectionOffsetTransform{AnimationBoneRotationCorrectionOffset};
|
||||
const bool bAnimationShouldApplyBoneLocation = VirtualHand->AnimationShouldApplyBoneLocation();
|
||||
|
||||
FComponentSpacePoseContext PoseContext{Output.AnimInstanceProxy};
|
||||
PoseContext.Pose.InitPose(Output.Pose);
|
||||
|
||||
for (TArray<FQuat>::SizeType HandKeyIndex = 0;
|
||||
HandKeyIndex < MotionControllerData.HandKeyRotations.Num(); ++HandKeyIndex)
|
||||
for (const TTuple<TArray<FQuat>::SizeType, FName>& Bone: BoneNamesMap)
|
||||
{
|
||||
FName BoneName{VirtualHand->GetHandBoneName(HandKeyIndex)};
|
||||
const TArray<FQuat>::SizeType HandKeyIndex = Bone.Key;
|
||||
const FName& BoneName{Bone.Value};
|
||||
if (BoneName == NAME_None)
|
||||
{
|
||||
continue;
|
||||
@@ -137,7 +150,7 @@ bool FSGVirtualHandAnimInstanceProxy::Evaluate(FPoseContext& Output)
|
||||
}
|
||||
|
||||
FBoneReference BoneReference;
|
||||
BoneReference.BoneName = MoveTemp(BoneName);
|
||||
BoneReference.BoneName = BoneName;
|
||||
BoneReference.BoneIndex = BoneIndex;
|
||||
BoneReference.bUseSkeletonIndex = true;
|
||||
|
||||
@@ -154,7 +167,7 @@ bool FSGVirtualHandAnimInstanceProxy::Evaluate(FPoseContext& Output)
|
||||
BoneController.RotationSpace = EBoneControlSpace::BCS_WorldSpace;
|
||||
BoneController.ScaleMode = EBoneModificationMode::BMM_Ignore;
|
||||
|
||||
if (bAnimationShouldApplyBoneLocation)
|
||||
if (bShouldAnimationApplyBoneLocation)
|
||||
{
|
||||
FVector BoneTranslation{BoneTransform.GetLocation()};
|
||||
BoneController.TranslationMode = EBoneModificationMode::BMM_Replace;
|
||||
@@ -182,11 +195,27 @@ bool FSGVirtualHandAnimInstanceProxy::Evaluate(FPoseContext& Output)
|
||||
PoseContext.Pose.LocalBlendCSBoneTransforms(BoneTransforms, 1.0f);
|
||||
PoseContext.Pose.ConvertComponentPosesToLocalPoses(PoseContext.Pose, Output.Pose);
|
||||
|
||||
/// FIXME
|
||||
// This causes a data race in the refactored code!
|
||||
//VirtualHand->MarkRenderStateDirty();
|
||||
bMarkRenderStateDirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void FSGVirtualHandAnimInstanceProxy::PostEvaluate(UAnimInstance* InAnimInstance)
|
||||
{
|
||||
FAnimInstanceProxy::PostEvaluate(InAnimInstance);
|
||||
|
||||
if (!bMarkRenderStateDirty)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!IsValid(VirtualHand))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
VirtualHand->MarkRenderStateDirty();
|
||||
}
|
||||
@@ -215,7 +215,7 @@ USGVirtualHandComponent::USGVirtualHandComponent(const FObjectInitializer& Objec
|
||||
bVisibleWhenHandDataUnavailable = false;
|
||||
|
||||
AnimationBoneRotationCorrectionOffset = FRotator{0.0f, 90.0f, 90.0f};
|
||||
bAnimationShouldApplyBoneLocation = true;
|
||||
bShouldAnimationApplyBoneLocation = true;
|
||||
|
||||
bAutoStopAllHapticsOnEndPlay = true;
|
||||
|
||||
|
||||
@@ -36,7 +36,10 @@
|
||||
#pragma once
|
||||
|
||||
#include "Animation/AnimInstanceProxy.h"
|
||||
#include "Containers/Array.h"
|
||||
#include "HeadMountedDisplayTypes.h"
|
||||
#include "Math/Quat.h"
|
||||
#include "Math/Transform.h"
|
||||
#include "Templates/UniquePtr.h"
|
||||
#include "UObject/NameTypes.h"
|
||||
|
||||
@@ -48,20 +51,72 @@ struct SENSEGLOVE_API FSGVirtualHandAnimInstanceProxy : public FAnimInstanceProx
|
||||
GENERATED_USTRUCT_BODY()
|
||||
|
||||
private:
|
||||
bool bIsVirtualHandVisible;
|
||||
USGVirtualHandComponent* VirtualHand;
|
||||
USkeletalMesh* HandMeshAsset;
|
||||
USkeleton* HandSkeleton;
|
||||
bool bMarkRenderStateDirty;
|
||||
|
||||
FXRMotionControllerData MotionControllerData;
|
||||
TMap<TArray<FQuat>::SizeType, FName> BoneNamesMap;
|
||||
|
||||
FTransform AnimationBoneCorrectionOffsetTransform;
|
||||
bool bShouldAnimationApplyBoneLocation;
|
||||
|
||||
public:
|
||||
FSGVirtualHandAnimInstanceProxy();
|
||||
FSGVirtualHandAnimInstanceProxy(UAnimInstance* Instance);
|
||||
|
||||
protected:
|
||||
FORCEINLINE bool IsVirtualHandVisible() const
|
||||
{
|
||||
return bIsVirtualHandVisible;
|
||||
}
|
||||
|
||||
FORCEINLINE USGVirtualHandComponent* GetVirtualHand() const
|
||||
{
|
||||
return VirtualHand;
|
||||
}
|
||||
|
||||
FORCEINLINE USkeletalMesh* GetHandMeshAsset() const
|
||||
{
|
||||
return HandMeshAsset;
|
||||
}
|
||||
|
||||
FORCEINLINE USkeleton* GetHandSkeleton() const
|
||||
{
|
||||
return HandSkeleton;
|
||||
}
|
||||
|
||||
FORCEINLINE bool IsRenderStateDirty() const
|
||||
{
|
||||
return bMarkRenderStateDirty;
|
||||
}
|
||||
|
||||
FORCEINLINE const FXRMotionControllerData& GetMotionControllerData() const
|
||||
{
|
||||
return MotionControllerData;
|
||||
}
|
||||
|
||||
FORCEINLINE const TMap<TArray<FQuat>::SizeType, FName>& GetBoneNamesMap() const
|
||||
{
|
||||
return BoneNamesMap;
|
||||
}
|
||||
|
||||
FORCEINLINE const FTransform& GetAnimationBoneCorrectionOffsetTransform() const
|
||||
{
|
||||
return AnimationBoneCorrectionOffsetTransform;
|
||||
}
|
||||
|
||||
FORCEINLINE bool ShouldAnimationApplyBoneLocation() const
|
||||
{
|
||||
return bShouldAnimationApplyBoneLocation;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void PreEvaluateAnimation(UAnimInstance* InAnimInstance) override;
|
||||
|
||||
virtual bool Evaluate(FPoseContext& Output) override;
|
||||
|
||||
virtual void PostEvaluate(UAnimInstance* InAnimInstance) override;
|
||||
};
|
||||
@@ -102,7 +102,7 @@ private:
|
||||
FRotator AnimationBoneRotationCorrectionOffset;
|
||||
|
||||
UPROPERTY(EditAnywhere, Category="SenseGlove | Animation", meta=(AllowPrivateAccess="false"))
|
||||
uint8 bAnimationShouldApplyBoneLocation : 1;
|
||||
uint8 bShouldAnimationApplyBoneLocation : 1;
|
||||
|
||||
UPROPERTY(EditAnywhere, Category="SenseGlove | Haptics", meta=(AllowPrivateAccess="false"))
|
||||
uint8 bAutoStopAllHapticsOnEndPlay : 1;
|
||||
@@ -185,14 +185,14 @@ public:
|
||||
AnimationBoneRotationCorrectionOffset = InAnimationBoneRotationCorrectionOffset;
|
||||
}
|
||||
|
||||
FORCEINLINE bool AnimationShouldApplyBoneLocation() const
|
||||
FORCEINLINE bool ShouldAnimationApplyBoneLocation() const
|
||||
{
|
||||
return !!bAnimationShouldApplyBoneLocation;
|
||||
return !!bShouldAnimationApplyBoneLocation;
|
||||
}
|
||||
|
||||
FORCEINLINE void SetAnimationShouldApplyBoneLocation(const bool bInAnimationShouldApplyBoneLocation)
|
||||
FORCEINLINE void SetShouldAnimationApplyBoneLocation(const bool bInShouldAnimationApplyBoneLocation)
|
||||
{
|
||||
bAnimationShouldApplyBoneLocation = bInAnimationShouldApplyBoneLocation;
|
||||
bShouldAnimationApplyBoneLocation = bInShouldAnimationApplyBoneLocation;
|
||||
}
|
||||
|
||||
FORCEINLINE bool AutoStopsAllHapticsOnEndPlay() const
|
||||
|
||||
@@ -98,16 +98,16 @@ void UVirtualHandComponentKismetLibrary::SetAnimationBoneRotationCorrectionOffse
|
||||
VirtualHandComponent->SetAnimationBoneRotationCorrectionOffset(InAnimationBoneRotationCorrectionOffset);
|
||||
}
|
||||
|
||||
bool UVirtualHandComponentKismetLibrary::AnimationShouldApplyBoneLocation(
|
||||
bool UVirtualHandComponentKismetLibrary::ShouldAnimationApplyBoneLocation(
|
||||
const USGVirtualHandComponent* VirtualHandComponent)
|
||||
{
|
||||
return VirtualHandComponent->AnimationShouldApplyBoneLocation();
|
||||
return VirtualHandComponent->ShouldAnimationApplyBoneLocation();
|
||||
}
|
||||
|
||||
void UVirtualHandComponentKismetLibrary::SetAnimationShouldApplyBoneLocation(
|
||||
USGVirtualHandComponent* VirtualHandComponent, const bool bInAnimationShouldApplyBoneLocation)
|
||||
void UVirtualHandComponentKismetLibrary::SetShouldAnimationApplyBoneLocation(
|
||||
USGVirtualHandComponent* VirtualHandComponent, const bool bInShouldAnimationApplyBoneLocation)
|
||||
{
|
||||
VirtualHandComponent->SetAnimationShouldApplyBoneLocation(bInAnimationShouldApplyBoneLocation);
|
||||
VirtualHandComponent->SetShouldAnimationApplyBoneLocation(bInShouldAnimationApplyBoneLocation);
|
||||
}
|
||||
|
||||
bool UVirtualHandComponentKismetLibrary::AutoStopsAllHapticsOnEndPlay(
|
||||
|
||||
@@ -97,13 +97,13 @@ public:
|
||||
const FRotator& InAnimationBoneRotationCorrectionOffset);
|
||||
|
||||
UFUNCTION(BlueprintPure, Category="SenseGlove | Components | Virtual Hand Component")
|
||||
static bool AnimationShouldApplyBoneLocation(
|
||||
static bool ShouldAnimationApplyBoneLocation(
|
||||
const USGVirtualHandComponent* VirtualHandComponent);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category="SenseGlove | Components | Virtual Hand Component")
|
||||
static void SetAnimationShouldApplyBoneLocation(
|
||||
static void SetShouldAnimationApplyBoneLocation(
|
||||
UPARAM(ref) USGVirtualHandComponent* VirtualHandComponent,
|
||||
bool bInAnimationShouldApplyBoneLocation);
|
||||
bool bInShouldAnimationApplyBoneLocation);
|
||||
|
||||
UFUNCTION(BlueprintPure, Category="SenseGlove | Components | Virtual Hand Component")
|
||||
static bool AutoStopsAllHapticsOnEndPlay(const USGVirtualHandComponent* VirtualHandComponent);
|
||||
|
||||
Reference in New Issue
Block a user