From 4ac870f7012964f699daa94b2f66e075ab371d8c Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Thu, 19 Jun 2025 13:57:50 +0200 Subject: [PATCH] Optimize physics transformation updates propagation in async via Job System --- Source/Engine/Physics/Actors/RigidBody.cpp | 8 +++++ .../Physics/PhysX/PhysicsBackendPhysX.cpp | 31 +++++++++++++++++-- 2 files changed, 36 insertions(+), 3 deletions(-) diff --git a/Source/Engine/Physics/Actors/RigidBody.cpp b/Source/Engine/Physics/Actors/RigidBody.cpp index a58911dfb..565bd9fbd 100644 --- a/Source/Engine/Physics/Actors/RigidBody.cpp +++ b/Source/Engine/Physics/Actors/RigidBody.cpp @@ -468,6 +468,14 @@ void RigidBody::OnActiveTransformChanged() void RigidBody::BeginPlay(SceneBeginData* data) { +#if USE_EDITOR || !BUILD_RELEASE + // FlushActiveTransforms runs in async for each separate actor thus we don't support two rigidbodies that transformations depend on each other + if (Cast(GetParent())) + { + LOG(Warning, "Rigid Body '{0}' is attached to other Rigid Body which is not unsupported and might cause physical simulation instability.", GetNamePath()); + } +#endif + // Create rigid body ASSERT(_actor == nullptr); void* scene = GetPhysicsScene()->GetPhysicsScene(); diff --git a/Source/Engine/Physics/PhysX/PhysicsBackendPhysX.cpp b/Source/Engine/Physics/PhysX/PhysicsBackendPhysX.cpp index 673b1e96d..99b54e8fc 100644 --- a/Source/Engine/Physics/PhysX/PhysicsBackendPhysX.cpp +++ b/Source/Engine/Physics/PhysX/PhysicsBackendPhysX.cpp @@ -1901,6 +1901,23 @@ void PhysicsBackend::StartSimulateScene(void* scene, float dt) scenePhysX->Stepper.renderDone(); } +PxActor** CachedActiveActors; +int64 CachedActiveActorsCount; +volatile int64 CachedActiveActorIndex; + +void FlushActiveTransforms(int32 i) +{ + PROFILE_CPU(); + int64 index; + while ((index = Platform::InterlockedIncrement(&CachedActiveActorIndex)) < CachedActiveActorsCount) + { + const auto pxActor = (PxRigidActor*)CachedActiveActors[index]; + auto actor = static_cast(pxActor->userData); + if (actor) + actor->OnActiveTransformChanged(); + } +} + void PhysicsBackend::EndSimulateScene(void* scene) { PROFILE_MEM(Physics); @@ -1919,10 +1936,18 @@ void PhysicsBackend::EndSimulateScene(void* scene) // Gather change info PxU32 activeActorsCount; PxActor** activeActors = scenePhysX->Scene->getActiveActors(activeActorsCount); - if (activeActorsCount > 0) + + // Update changed transformations + if (activeActorsCount > 50 && JobSystem::GetThreadsCount() > 1) + { + // Run in async via job system + CachedActiveActors = activeActors; + CachedActiveActorsCount = activeActorsCount; + CachedActiveActorIndex = -1; + JobSystem::Execute(FlushActiveTransforms, JobSystem::GetThreadsCount()); + } + else { - // Update changed transformations - // TODO: use jobs system if amount if huge for (uint32 i = 0; i < activeActorsCount; i++) { const auto pxActor = (PxRigidActor*)*activeActors++;