diff --git a/Source/Editor/Windows/Profiler/Physics.cs b/Source/Editor/Windows/Profiler/Physics.cs new file mode 100644 index 000000000..b2f52462d --- /dev/null +++ b/Source/Editor/Windows/Profiler/Physics.cs @@ -0,0 +1,113 @@ +// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved. + +using FlaxEngine; +using FlaxEngine.GUI; + +namespace FlaxEditor.Windows.Profiler +{ + /// + /// The physics simulation profiling mode. + /// + /// + internal sealed class Physics : ProfilerMode + { + private readonly SingleChart _activeBodiesChart; + private readonly SingleChart _activeJointsChart; + private readonly SingleChart _dynamicBodiesChart; + private readonly SingleChart _staticBodiesChart; + private readonly SingleChart _newPairsChart; + private readonly SingleChart _newTouchesChart; + + public Physics() + : base("Physics") + { + // Layout + var panel = new Panel(ScrollBars.Vertical) + { + AnchorPreset = AnchorPresets.StretchAll, + Offsets = Margin.Zero, + Parent = this, + }; + var layout = new VerticalPanel + { + AnchorPreset = AnchorPresets.HorizontalStretchTop, + Offsets = Margin.Zero, + IsScrollable = true, + Parent = panel, + }; + + // Charts + _activeBodiesChart = new SingleChart + { + Title = "Active Bodies", + Parent = layout, + }; + _activeBodiesChart.SelectedSampleChanged += OnSelectedSampleChanged; + _activeJointsChart = new SingleChart + { + Title = "Active Joints", + Parent = layout, + }; + _activeJointsChart.SelectedSampleChanged += OnSelectedSampleChanged; + _dynamicBodiesChart = new SingleChart + { + Title = "Dynamic Bodies", + Parent = layout, + }; + _dynamicBodiesChart.SelectedSampleChanged += OnSelectedSampleChanged; + _staticBodiesChart = new SingleChart + { + Title = "Static Bodies", + Parent = layout, + }; + _staticBodiesChart.SelectedSampleChanged += OnSelectedSampleChanged; + _newPairsChart = new SingleChart + { + Title = "New Pairs", + Parent = layout, + }; + _newPairsChart.SelectedSampleChanged += OnSelectedSampleChanged; + _newTouchesChart = new SingleChart + { + Title = "New Touches", + Parent = layout, + }; + _newTouchesChart.SelectedSampleChanged += OnSelectedSampleChanged; + } + + /// + public override void Clear() + { + _activeBodiesChart.Clear(); + _activeJointsChart.Clear(); + _dynamicBodiesChart.Clear(); + _staticBodiesChart.Clear(); + _newPairsChart.Clear(); + _newTouchesChart.Clear(); + } + + /// + public override void Update(ref SharedUpdateData sharedData) + { + PhysicsStatistics statistics = FlaxEngine.Physics.DefaultScene.Statistics; + + _activeBodiesChart.AddSample(statistics.ActiveDynamicBodies + statistics.ActiveKinematicBodies); + _activeJointsChart.AddSample(statistics.ActiveJoints); + _dynamicBodiesChart.AddSample(statistics.DynamicBodies + statistics.KinematicBodies); + _staticBodiesChart.AddSample(statistics.StaticBodies); + _newPairsChart.AddSample(statistics.NewPairs); + _newTouchesChart.AddSample(statistics.NewTouches); + } + + /// + public override void UpdateView(int selectedFrame, bool showOnlyLastUpdateEvents) + { + _activeBodiesChart.SelectedSampleIndex = selectedFrame; + _activeJointsChart.SelectedSampleIndex = selectedFrame; + _dynamicBodiesChart.SelectedSampleIndex = selectedFrame; + _staticBodiesChart.SelectedSampleIndex = selectedFrame; + _newPairsChart.SelectedSampleIndex = selectedFrame; + _newTouchesChart.SelectedSampleIndex = selectedFrame; + } + } +} diff --git a/Source/Editor/Windows/Profiler/ProfilerWindow.cs b/Source/Editor/Windows/Profiler/ProfilerWindow.cs index b97e3a988..a723d64f2 100644 --- a/Source/Editor/Windows/Profiler/ProfilerWindow.cs +++ b/Source/Editor/Windows/Profiler/ProfilerWindow.cs @@ -200,6 +200,7 @@ namespace FlaxEditor.Windows.Profiler AddMode(new Memory()); AddMode(new Assets()); AddMode(new Network()); + AddMode(new Physics()); // Init view _frameIndex = -1; diff --git a/Source/Engine/Physics/PhysX/PhysicsBackendPhysX.cpp b/Source/Engine/Physics/PhysX/PhysicsBackendPhysX.cpp index 91e795a83..a0fbeefcc 100644 --- a/Source/Engine/Physics/PhysX/PhysicsBackendPhysX.cpp +++ b/Source/Engine/Physics/PhysX/PhysicsBackendPhysX.cpp @@ -10,6 +10,7 @@ #include "Engine/Physics/CollisionData.h" #include "Engine/Physics/PhysicalMaterial.h" #include "Engine/Physics/PhysicsScene.h" +#include "Engine/Physics/PhysicsStatistics.h" #include "Engine/Physics/CollisionCooking.h" #include "Engine/Physics/Actors/IPhysicsActor.h" #include "Engine/Physics/Joints/Limits.h" @@ -1340,6 +1341,30 @@ void PhysicsBackend::AddSceneActorAction(void* scene, void* actor, ActionType ac FlushLocker.Unlock(); } +#if COMPILE_WITH_PROFILER + +void PhysicsBackend::GetSceneStatistics(void* scene, PhysicsStatistics& result) +{ + PROFILE_CPU_NAMED("Physics.Statistics"); + auto scenePhysX = (ScenePhysX*)scene; + + PxSimulationStatistics px; + scenePhysX->Scene->getSimulationStatistics(px); + + result.ActiveDynamicBodies = px.nbActiveDynamicBodies; + result.ActiveKinematicBodies = px.nbActiveKinematicBodies; + result.ActiveJoints = px.nbActiveConstraints; + result.StaticBodies = px.nbStaticBodies; + result.DynamicBodies = px.nbDynamicBodies; + result.KinematicBodies = px.nbKinematicBodies; + result.NewPairs = px.nbNewPairs; + result.LostPairs = px.nbLostPairs; + result.NewTouches = px.nbNewTouches; + result.LostTouches = px.nbLostTouches; +} + +#endif + bool PhysicsBackend::RayCast(void* scene, const Vector3& origin, const Vector3& direction, const float maxDistance, uint32 layerMask, bool hitTriggers) { SCENE_QUERY_SETUP(true); diff --git a/Source/Engine/Physics/Physics.cpp b/Source/Engine/Physics/Physics.cpp index 30d5cbe0c..007bfb6fd 100644 --- a/Source/Engine/Physics/Physics.cpp +++ b/Source/Engine/Physics/Physics.cpp @@ -5,6 +5,7 @@ #include "PhysicsBackend.h" #include "PhysicalMaterial.h" #include "PhysicsSettings.h" +#include "PhysicsStatistics.h" #include "Engine/Engine/Time.h" #include "Engine/Engine/EngineService.h" #include "Engine/Profiler/ProfilerCPU.h" @@ -417,6 +418,17 @@ void PhysicsScene::SetOrigin(const Vector3& value) } } +#if COMPILE_WITH_PROFILER + +PhysicsStatistics PhysicsScene::GetStatistics() const +{ + PhysicsStatistics result; + PhysicsBackend::GetSceneStatistics(_scene, result); + return result; +} + +#endif + bool PhysicsScene::Init(const StringView& name, const PhysicsSettings& settings) { if (_scene) diff --git a/Source/Engine/Physics/PhysicsBackend.h b/Source/Engine/Physics/PhysicsBackend.h index fda15a079..f72c7f679 100644 --- a/Source/Engine/Physics/PhysicsBackend.h +++ b/Source/Engine/Physics/PhysicsBackend.h @@ -98,6 +98,9 @@ public: static void AddSceneActor(void* scene, void* actor); static void RemoveSceneActor(void* scene, void* actor); static void AddSceneActorAction(void* scene, void* actor, ActionType action); +#if COMPILE_WITH_PROFILER + static void GetSceneStatistics(void* scene, PhysicsStatistics& result); +#endif // Scene Queries static bool RayCast(void* scene, const Vector3& origin, const Vector3& direction, float maxDistance, uint32 layerMask, bool hitTriggers); diff --git a/Source/Engine/Physics/PhysicsBackendEmpty.cpp b/Source/Engine/Physics/PhysicsBackendEmpty.cpp index 49861f0df..516562e28 100644 --- a/Source/Engine/Physics/PhysicsBackendEmpty.cpp +++ b/Source/Engine/Physics/PhysicsBackendEmpty.cpp @@ -123,6 +123,14 @@ void PhysicsBackend::AddSceneActorAction(void* scene, void* actor, ActionType ac { } +#if COMPILE_WITH_PROFILER + +void PhysicsBackend::GetSceneStatistics(void* scene, PhysicsStatistics& result) +{ +} + +#endif + bool PhysicsBackend::RayCast(void* scene, const Vector3& origin, const Vector3& direction, const float maxDistance, uint32 layerMask, bool hitTriggers) { return false; diff --git a/Source/Engine/Physics/PhysicsScene.h b/Source/Engine/Physics/PhysicsScene.h index 81fab3507..bc6da6618 100644 --- a/Source/Engine/Physics/PhysicsScene.h +++ b/Source/Engine/Physics/PhysicsScene.h @@ -100,6 +100,13 @@ public: /// API_PROPERTY() void SetOrigin(const Vector3& value); +#if COMPILE_WITH_PROFILER + /// + /// Gets the physics simulation statistics for the scene. + /// + API_PROPERTY() PhysicsStatistics GetStatistics() const; +#endif + public: /// /// Initializes the scene. diff --git a/Source/Engine/Physics/PhysicsStatistics.h b/Source/Engine/Physics/PhysicsStatistics.h new file mode 100644 index 000000000..acb4393e9 --- /dev/null +++ b/Source/Engine/Physics/PhysicsStatistics.h @@ -0,0 +1,40 @@ +// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved. + +#pragma once + +#include "Types.h" +#include "Engine/Scripting/ScriptingType.h" + +/// +/// Physics simulation statistics container for profiler. +/// +API_STRUCT(NoDefault) struct FLAXENGINE_API PhysicsStatistics +{ + DECLARE_SCRIPTING_TYPE_MINIMAL(PhysicsStatistics); + + // Number of active dynamic bodies for the current simulation step. Does not include active kinematic bodies. + API_FIELD() uint32 ActiveDynamicBodies; + // Number of active kinematic bodies for the current simulation step. + API_FIELD() uint32 ActiveKinematicBodies; + // Number of active joints object for the current simulation step. + API_FIELD() uint32 ActiveJoints; + // Number of static bodies for the current simulation step. + API_FIELD() uint32 StaticBodies; + // Number of dynamic bodies for the current simulation step. + API_FIELD() uint32 DynamicBodies; + // Number of kinematic bodies for the current simulation step. + API_FIELD() uint32 KinematicBodies; + // Number of new pairs found during this frame. + API_FIELD() uint32 NewPairs; + // Number of lost pairs during this frame. + API_FIELD() uint32 LostPairs; + // Number of new touches found during this frame. + API_FIELD() uint32 NewTouches; + // Number of lost touches during this frame. + API_FIELD() uint32 LostTouches; + + PhysicsStatistics() + { + Platform::MemoryClear(this, sizeof(PhysicsStatistics)); + } +}; diff --git a/Source/Engine/Physics/Types.h b/Source/Engine/Physics/Types.h index b5b34ceec..ed12f8611 100644 --- a/Source/Engine/Physics/Types.h +++ b/Source/Engine/Physics/Types.h @@ -7,6 +7,7 @@ #include "Engine/Core/Math/Vector3.h" #include "Engine/Scripting/ScriptingType.h" +struct PhysicsStatistics; class PhysicsColliderActor; class PhysicsScene; class Joint;