You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
540 lines
25 KiB
C++
540 lines
25 KiB
C++
/*
|
|
* Copyright (c) Contributors to the Open 3D Engine Project.
|
|
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
|
*
|
|
*/
|
|
|
|
#ifdef HAVE_BENCHMARK
|
|
#include <benchmark/benchmark.h>
|
|
|
|
#include <AzTest/AzTest.h>
|
|
#include <AzFramework/Physics/Collision/CollisionEvents.h>
|
|
#include <AzFramework/Physics/Common/PhysicsEvents.h>
|
|
|
|
#include <Benchmarks/PhysXBenchmarksUtilities.h>
|
|
#include <Benchmarks/PhysXBenchmarksCommon.h>
|
|
#include <Benchmarks/PhysXBenchmarkWashingMachine.h>
|
|
|
|
#include <PhysXTestCommon.h>
|
|
#include <PhysXTestUtil.h>
|
|
|
|
namespace PhysX::Benchmarks
|
|
{
|
|
namespace RigidBodyConstants
|
|
{
|
|
//! Controls the simulation length of the test. 30secs at 60fps
|
|
static const int GameFramesToSimulate = 1800;
|
|
|
|
//! The size of safe the test region, used for spawning Rigid bodies
|
|
static const float TestRadius = 250.0f;
|
|
|
|
//! The size of the test terrain
|
|
static const float TerrainSize = 1000.0f;
|
|
|
|
//! Decide if CCD should be on/off for the following tests
|
|
static const bool CCDEnabled = true;
|
|
|
|
//! Constant seed to use with random number generation
|
|
static const long long RandGenSeed = 8010412111588; //(Number generated by concatenating 'PhysX' ascii character codes (80 104 121 115 88).
|
|
|
|
//! Constants for setting up the washing machine
|
|
namespace WashingMachine
|
|
{
|
|
static const float CylinderHeight = 500.0f;
|
|
static const float BladeRPM = 10.0f;
|
|
} // namespace WashingMachine
|
|
|
|
//! Constants for setting up the Rigid Bodies
|
|
namespace RigidBodys
|
|
{
|
|
static const float BoxSize = 5.0f;
|
|
|
|
//! Default starting value of Entity Ids for rigid bodies
|
|
static const AZ::u64 RigidBodyEntityIdStart = 2000u;
|
|
}
|
|
|
|
//! Settings used to setup each benchmark
|
|
namespace BenchmarkSettings
|
|
{
|
|
//! Values passed to benchmark to select the number of rigid bodies to spawn during each test
|
|
//! Current values will run tests between StartRange to EndRange (inclusive), multiplying by RangeMultiplier each step.
|
|
static const int StartRange = 128;
|
|
static const int EndRange = 8192;
|
|
static const int RangeMultipler = 2;
|
|
|
|
//!Flags to adjust how the collision handlers benchmark runs
|
|
static const int AllCollisionHanders = 0; // create the same number of handlers as rigid bodies
|
|
static const int HalfCollisionHandlers = 1; // create half the number of handlers as rigid bodies
|
|
static const int NoCollisionHandlers = 2; // create the no handlers
|
|
|
|
//! Number of iterations for each test
|
|
static const int NumIterations = 3;
|
|
} // namespace BenchmarkRange
|
|
} // namespace RigidBodyConstants
|
|
|
|
namespace Utils
|
|
{
|
|
//! Object that will connect to the collision notification bus of the provided entity id
|
|
struct SimulatedBodyCollisionHandler
|
|
{
|
|
SimulatedBodyCollisionHandler(AzPhysics::SceneHandle sceneHandle, AzPhysics::SimulatedBodyHandle bodyHandle)
|
|
: m_onCollisionBeginHandler(
|
|
[this]([[maybe_unused]] AzPhysics::SimulatedBodyHandle bodyHandle,
|
|
[[maybe_unused]] const AzPhysics::CollisionEvent& event)
|
|
{
|
|
m_beginCount++;
|
|
})
|
|
, m_onCollisionPersistHandler(
|
|
[this]([[maybe_unused]] AzPhysics::SimulatedBodyHandle bodyHandle,
|
|
[[maybe_unused]] const AzPhysics::CollisionEvent& event)
|
|
{
|
|
m_persistCount++;
|
|
})
|
|
, m_onCollisionEndHandler(
|
|
[this]([[maybe_unused]] AzPhysics::SimulatedBodyHandle bodyHandle,
|
|
[[maybe_unused]] const AzPhysics::CollisionEvent& event)
|
|
{
|
|
m_endCount++;
|
|
})
|
|
{
|
|
AzPhysics::SimulatedBodyEvents::RegisterOnCollisionBeginHandler(sceneHandle, bodyHandle, m_onCollisionBeginHandler);
|
|
AzPhysics::SimulatedBodyEvents::RegisterOnCollisionBeginHandler(sceneHandle, bodyHandle, m_onCollisionPersistHandler);
|
|
AzPhysics::SimulatedBodyEvents::RegisterOnCollisionBeginHandler(sceneHandle, bodyHandle, m_onCollisionEndHandler);
|
|
}
|
|
|
|
SimulatedBodyCollisionHandler(SimulatedBodyCollisionHandler&& other)
|
|
{
|
|
m_onCollisionBeginHandler = AZStd::move(other.m_onCollisionBeginHandler);
|
|
m_onCollisionPersistHandler = AZStd::move(other.m_onCollisionPersistHandler);
|
|
m_onCollisionEndHandler = AZStd::move(other.m_onCollisionEndHandler);
|
|
m_beginCount = other.m_beginCount;
|
|
m_persistCount = other.m_persistCount;
|
|
m_endCount = other.m_endCount;
|
|
}
|
|
|
|
~SimulatedBodyCollisionHandler()
|
|
{
|
|
m_onCollisionBeginHandler.Disconnect();
|
|
m_onCollisionPersistHandler.Disconnect();
|
|
m_onCollisionEndHandler.Disconnect();
|
|
}
|
|
|
|
int m_beginCount = 0;
|
|
int m_persistCount = 0;
|
|
int m_endCount = 0;
|
|
private:
|
|
AzPhysics::SimulatedBodyEvents::OnCollisionBegin::Handler m_onCollisionBeginHandler;
|
|
AzPhysics::SimulatedBodyEvents::OnCollisionPersist::Handler m_onCollisionPersistHandler;
|
|
AzPhysics::SimulatedBodyEvents::OnCollisionEnd::Handler m_onCollisionEndHandler;
|
|
};
|
|
} // namespace Utils
|
|
|
|
//! Rigid body performance fixture.
|
|
//! Will create a world, and terrain.
|
|
class PhysXRigidbodyBenchmarkFixture
|
|
: public PhysXBaseBenchmarkFixture
|
|
{
|
|
protected:
|
|
virtual void internalSetUp()
|
|
{
|
|
PhysXBaseBenchmarkFixture::SetUpInternal();
|
|
//need to get the Physics::System to be able to spawn the rigid bodies
|
|
m_system = AZ::Interface<Physics::System>::Get();
|
|
|
|
m_terrainEntity = PhysX::TestUtils::CreateFlatTestTerrain(m_testSceneHandle, RigidBodyConstants::TerrainSize, RigidBodyConstants::TerrainSize);
|
|
}
|
|
|
|
virtual void internalTearDown()
|
|
{
|
|
m_terrainEntity = nullptr;
|
|
PhysXBaseBenchmarkFixture::TearDownInternal();
|
|
}
|
|
public:
|
|
void SetUp(const benchmark::State&) override
|
|
{
|
|
internalSetUp();
|
|
}
|
|
void SetUp(benchmark::State&) override
|
|
{
|
|
internalSetUp();
|
|
}
|
|
|
|
void TearDown(const benchmark::State&) override
|
|
{
|
|
internalTearDown();
|
|
}
|
|
void TearDown(benchmark::State&) override
|
|
{
|
|
internalTearDown();
|
|
}
|
|
|
|
protected:
|
|
// PhysXBaseBenchmarkFixture Interface ---------
|
|
AzPhysics::SceneConfiguration GetDefaultSceneConfiguration() override
|
|
{
|
|
AzPhysics::SceneConfiguration sceneConfig = AzPhysics::SceneConfiguration::CreateDefault();
|
|
sceneConfig.m_enableCcd = RigidBodyConstants::CCDEnabled;
|
|
return sceneConfig;
|
|
}
|
|
// PhysXBaseBenchmarkFixture Interface ---------
|
|
|
|
Physics::System *m_system;
|
|
EntityPtr m_terrainEntity;
|
|
};
|
|
|
|
//! BM_RigidBody_AtRest - This test will spawn the requested number of rigid bodies and place them near the ground
|
|
//! and the rigid bodies will go 'asleep'
|
|
//! The test will run the simulation for ~1800 game frames at 60fps.
|
|
BENCHMARK_DEFINE_F(PhysXRigidbodyBenchmarkFixture, BM_RigidBody_AtRest)(benchmark::State& state)
|
|
{
|
|
//get the request number of rigid bodies and prepare to spawn them
|
|
const int numRigidBodies = static_cast<int>(state.range(0));
|
|
|
|
//common settings for each rigid body
|
|
const float boxSizeWithSpacing = RigidBodyConstants::RigidBodys::BoxSize + 2.0f;
|
|
const int boxesPerCol = static_cast<const int>(RigidBodyConstants::TerrainSize / boxSizeWithSpacing) - 1;
|
|
int spawnColIdx = 0;
|
|
int spawnRowIdx = 0;
|
|
|
|
//function to generate the rigid bodies position / orientation / mass
|
|
Utils::GenerateSpawnPositionFuncPtr posGenerator = [boxSizeWithSpacing, boxesPerCol, &spawnColIdx, &spawnRowIdx]([[maybe_unused]] int idx) -> const AZ::Vector3 {
|
|
const float x = boxSizeWithSpacing + (boxSizeWithSpacing * spawnColIdx);
|
|
const float y = boxSizeWithSpacing + (boxSizeWithSpacing * spawnRowIdx);
|
|
const float z = RigidBodyConstants::RigidBodys::BoxSize / 2.0f;
|
|
|
|
//advance to the next position to spawn the next rigid body
|
|
spawnColIdx++;
|
|
if (spawnColIdx >= boxesPerCol)
|
|
{
|
|
spawnColIdx = 0;
|
|
spawnRowIdx++;
|
|
}
|
|
return AZ::Vector3(x, y, z);
|
|
};
|
|
|
|
auto boxShapeConfiguration = AZStd::make_shared<Physics::BoxShapeConfiguration>(AZ::Vector3(RigidBodyConstants::RigidBodys::BoxSize));
|
|
Utils::GenerateColliderFuncPtr colliderGenerator = [&boxShapeConfiguration]([[maybe_unused]] int idx)
|
|
{
|
|
return boxShapeConfiguration;
|
|
};
|
|
//spawn the rigid bodies
|
|
AzPhysics::SimulatedBodyHandleList rigidBodies = Utils::CreateRigidBodies(numRigidBodies, m_defaultScene,
|
|
RigidBodyConstants::CCDEnabled, &colliderGenerator, &posGenerator);
|
|
|
|
//setup the sub tick tracker
|
|
Utils::PrePostSimulationEventHandler subTickTracker;
|
|
subTickTracker.Start(m_defaultScene);
|
|
|
|
//setup the frame timer tracker
|
|
Types::TimeList tickTimes;
|
|
for ([[maybe_unused]] auto _ : state)
|
|
{
|
|
for (AZ::u32 i = 0; i < RigidBodyConstants::GameFramesToSimulate; i++)
|
|
{
|
|
auto start = AZStd::chrono::system_clock::now();
|
|
StepScene1Tick(DefaultTimeStep);
|
|
|
|
//time each physics tick and store it to analyze
|
|
auto tickElapsedMilliseconds = Types::double_milliseconds(AZStd::chrono::system_clock::now() - start);
|
|
tickTimes.emplace_back(tickElapsedMilliseconds.count());
|
|
}
|
|
}
|
|
subTickTracker.Stop();
|
|
|
|
//object clean up
|
|
m_defaultScene->RemoveSimulatedBodies(rigidBodies);
|
|
rigidBodies.clear();
|
|
|
|
//sort the frame times and get the P50, P90, P99 percentiles
|
|
Utils::ReportFramePercentileCounters(state, tickTimes, subTickTracker.GetSubTickTimes());
|
|
Utils::ReportFrameStandardDeviationAndMeanCounters(state, tickTimes, subTickTracker.GetSubTickTimes());
|
|
}
|
|
|
|
//! BM_RigidBody_MovingAndColliding - This test will create the physics washing machine, a cylinder with a spinning blade where
|
|
//! it will spawn the requested number of rigid bodies above the machine and let them fall into a spinning blade.
|
|
//! The test will run the simulation for ~1800 game frames at 60fps.
|
|
BENCHMARK_DEFINE_F(PhysXRigidbodyBenchmarkFixture, BM_RigidBody_MovingAndColliding)(benchmark::State &state)
|
|
{
|
|
//setup some pieces for the test
|
|
AZ::SimpleLcgRandom rand;
|
|
rand.SetSeed(RigidBodyConstants::RandGenSeed);
|
|
|
|
//Create a washing machine of physx objects. This is a cylinder with a spinning blade that rigid bodies are placed inside
|
|
const AZ::Vector3 washingMachineCentre(500.0f, 500.0f, 1.0f);
|
|
WashingMachine washingMachine;
|
|
washingMachine.SetupWashingMachine(
|
|
m_testSceneHandle, RigidBodyConstants::TestRadius, RigidBodyConstants::WashingMachine::CylinderHeight,
|
|
washingMachineCentre, RigidBodyConstants::WashingMachine::BladeRPM);
|
|
|
|
//get the request number of rigid bodies and prepare to spawn them
|
|
const int numRigidBodies = static_cast<int>(state.range(0));
|
|
|
|
//add the rigid bodies
|
|
//function to generate the rigid bodies position / orientation / mass
|
|
Utils::GenerateSpawnPositionFuncPtr posGenerator = [washingMachineCentre, &rand](int idx) -> const AZ::Vector3 {
|
|
const float spawnArea = (RigidBodyConstants::TestRadius * 1.5f);
|
|
const float x = washingMachineCentre.GetX() + (rand.GetRandomFloat() - 0.5f) * spawnArea;
|
|
const float y = washingMachineCentre.GetY() + (rand.GetRandomFloat() - 0.5f) * spawnArea;
|
|
const float z = washingMachineCentre.GetZ() + RigidBodyConstants::WashingMachine::CylinderHeight + ((RigidBodyConstants::RigidBodys::BoxSize / 2.0f) * idx);
|
|
return AZ::Vector3(x, y, z);
|
|
};
|
|
Utils::GenerateSpawnOrientationFuncPtr oriGenerator = [&rand]([[maybe_unused]] int idx) -> AZ::Quaternion {
|
|
return AZ::CreateRandomQuaternion(rand);
|
|
};
|
|
Utils::GenerateMassFuncPtr massGenerator = [&rand]([[maybe_unused]] int idx) -> float {
|
|
return rand.GetRandomFloat() * 25.0f + 5.0f;
|
|
};
|
|
auto boxShapeConfiguration = AZStd::make_shared<Physics::BoxShapeConfiguration>(AZ::Vector3(RigidBodyConstants::RigidBodys::BoxSize));
|
|
Utils::GenerateColliderFuncPtr colliderGenerator = [&boxShapeConfiguration]([[maybe_unused]] int idx)
|
|
{
|
|
return boxShapeConfiguration;
|
|
};
|
|
//spawn the rigid bodies
|
|
AzPhysics::SimulatedBodyHandleList rigidBodies = Utils::CreateRigidBodies(numRigidBodies, m_defaultScene,
|
|
RigidBodyConstants::CCDEnabled, &colliderGenerator, &posGenerator, &oriGenerator, &massGenerator);
|
|
|
|
//setup the sub tick tracker
|
|
Utils::PrePostSimulationEventHandler subTickTracker;
|
|
subTickTracker.Start(m_defaultScene);
|
|
|
|
//setup the frame timer tracker
|
|
AZStd::vector<double> tickTimes;
|
|
tickTimes.reserve(RigidBodyConstants::GameFramesToSimulate);
|
|
for ([[maybe_unused]] auto _ : state)
|
|
{
|
|
for (AZ::u32 i = 0; i < RigidBodyConstants::GameFramesToSimulate; i++)
|
|
{
|
|
auto start = AZStd::chrono::system_clock::now();
|
|
StepScene1Tick(DefaultTimeStep);
|
|
|
|
//time each physics tick and store it to analyze
|
|
auto tickElapsedMilliseconds = Types::double_milliseconds(AZStd::chrono::system_clock::now() - start);
|
|
tickTimes.emplace_back(tickElapsedMilliseconds.count());
|
|
}
|
|
}
|
|
subTickTracker.Stop();
|
|
|
|
//object clean up
|
|
washingMachine.TearDownWashingMachine();
|
|
m_defaultScene->RemoveSimulatedBodies(rigidBodies);
|
|
rigidBodies.clear();
|
|
|
|
//sort the frame times and get the P50, P90, P99 percentiles
|
|
Utils::ReportFramePercentileCounters(state, tickTimes, subTickTracker.GetSubTickTimes());
|
|
Utils::ReportFrameStandardDeviationAndMeanCounters(state, tickTimes, subTickTracker.GetSubTickTimes());
|
|
}
|
|
|
|
//! Same as the PhysXRigidbodyBenchmarkFixture, adds a world event handler to receive collision events
|
|
class PhysXRigidbodyCollisionsBenchmarkFixture
|
|
: public PhysXRigidbodyBenchmarkFixture
|
|
{
|
|
void internalSetUp() override
|
|
{
|
|
PhysXRigidbodyBenchmarkFixture::internalSetUp();
|
|
|
|
m_collisionBeginCount = 0;
|
|
m_collisionPersistCount = 0;
|
|
m_collisionEndCount = 0;
|
|
|
|
m_onSceneCollisionHandler = AzPhysics::SceneEvents::OnSceneCollisionsEvent::Handler(
|
|
[this]([[maybe_unused]] AzPhysics::SceneHandle sceneHandle,
|
|
const AzPhysics::CollisionEventList& collisionData)
|
|
{
|
|
//count the events
|
|
for (const auto& collisionEvent : collisionData)
|
|
{
|
|
switch (collisionEvent.m_type)
|
|
{
|
|
case AzPhysics::CollisionEvent::Type::Begin:
|
|
m_collisionBeginCount++;
|
|
break;
|
|
case AzPhysics::CollisionEvent::Type::Persist:
|
|
m_collisionPersistCount++;
|
|
break;
|
|
case AzPhysics::CollisionEvent::Type::End:
|
|
m_collisionEndCount++;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
);
|
|
m_defaultScene->RegisterSceneCollisionEventHandler(m_onSceneCollisionHandler);
|
|
}
|
|
|
|
void internalTearDown() override
|
|
{
|
|
m_onSceneCollisionHandler.Disconnect();
|
|
|
|
PhysXRigidbodyBenchmarkFixture::internalTearDown();
|
|
}
|
|
|
|
public:
|
|
void SetUp(const benchmark::State&) override
|
|
{
|
|
internalSetUp();
|
|
}
|
|
void SetUp(benchmark::State&) override
|
|
{
|
|
internalSetUp();
|
|
}
|
|
|
|
void TearDown(const benchmark::State&) override
|
|
{
|
|
internalTearDown();
|
|
}
|
|
void TearDown(benchmark::State&) override
|
|
{
|
|
internalTearDown();
|
|
}
|
|
|
|
protected:
|
|
// Collision counters to track and report the number of events
|
|
int m_collisionBeginCount;
|
|
int m_collisionPersistCount;
|
|
int m_collisionEndCount;
|
|
|
|
AzPhysics::SceneEvents::OnSceneCollisionsEvent::Handler m_onSceneCollisionHandler;
|
|
};
|
|
|
|
//! BM_RigidBody_MovingAndColliding_CollisionHandlers - Runs that same benchmark as BM_RigidBody_MovingAndColliding, under a different fixture that adds world event handler for collisions
|
|
//! Will have an equal number of Collision Handlers and rigid bodies. Not all rigid bodies will get a handler, some will have multiple.
|
|
//! The test will run the simulation for ~1800 game frames at 60fps.
|
|
BENCHMARK_DEFINE_F(PhysXRigidbodyCollisionsBenchmarkFixture, BM_RigidBody_MovingAndColliding_CollisionHandlers)(benchmark::State& state)
|
|
{
|
|
//setup some pieces for the test
|
|
AZ::SimpleLcgRandom rand;
|
|
rand.SetSeed(RigidBodyConstants::RandGenSeed);
|
|
|
|
//Create a washing machine of physx objects. This is a cylinder with a spinning blade that rigid bodies are placed inside
|
|
const AZ::Vector3 washingMachineCentre(500.0f, 500.0f, 1.0f);
|
|
WashingMachine washingMachine;
|
|
washingMachine.SetupWashingMachine(
|
|
m_testSceneHandle, RigidBodyConstants::TestRadius, RigidBodyConstants::WashingMachine::CylinderHeight,
|
|
washingMachineCentre, RigidBodyConstants::WashingMachine::BladeRPM);
|
|
|
|
//get the request number of rigid bodies and prepare to spawn them
|
|
const int numRigidBodies = static_cast<int>(state.range(0));
|
|
|
|
//add the rigid bodies
|
|
//function to generate the rigid bodies position / orientation / mass
|
|
Utils::GenerateSpawnPositionFuncPtr posGenerator = [washingMachineCentre, &rand](int idx) -> const AZ::Vector3 {
|
|
const float u = std::sqrt(rand.GetRandomFloat());
|
|
const float theta = AZ::Constants::TwoPi * rand.GetRandomFloat();
|
|
const float x = washingMachineCentre.GetX() + RigidBodyConstants::TestRadius * u * std::sin(theta);
|
|
const float y = washingMachineCentre.GetY() + RigidBodyConstants::TestRadius * u * std::cos(theta);
|
|
const float z = washingMachineCentre.GetZ() + RigidBodyConstants::WashingMachine::CylinderHeight + ((RigidBodyConstants::RigidBodys::BoxSize / 2.0f) * idx);
|
|
return AZ::Vector3(x, y, z);
|
|
};
|
|
Utils::GenerateSpawnOrientationFuncPtr oriGenerator = [&rand]([[maybe_unused]] int idx) -> AZ::Quaternion {
|
|
return AZ::CreateRandomQuaternion(rand);
|
|
};
|
|
Utils::GenerateMassFuncPtr massGenerator = [&rand]([[maybe_unused]] int idx) -> float {
|
|
return rand.GetRandomFloat() * 25.0f + 5.0f;
|
|
};
|
|
|
|
Utils::GenerateEntityIdFuncPtr entityIdGenerator = [](int idx) -> AZ::EntityId {
|
|
return AZ::EntityId(static_cast<AZ::u64>(idx) + RigidBodyConstants::RigidBodys::RigidBodyEntityIdStart);
|
|
};
|
|
auto boxShapeConfiguration = AZStd::make_shared<Physics::BoxShapeConfiguration>(AZ::Vector3(RigidBodyConstants::RigidBodys::BoxSize));
|
|
Utils::GenerateColliderFuncPtr colliderGenerator = [&boxShapeConfiguration]([[maybe_unused]] int idx)
|
|
{
|
|
return boxShapeConfiguration;
|
|
};
|
|
//spawn the rigid bodies
|
|
AzPhysics::SimulatedBodyHandleList rigidBodies = Utils::CreateRigidBodies(numRigidBodies, m_defaultScene,
|
|
RigidBodyConstants::CCDEnabled, &colliderGenerator, &posGenerator, &oriGenerator, &massGenerator);
|
|
|
|
//create the collision handlers
|
|
AZStd::vector<Utils::SimulatedBodyCollisionHandler> collisionHandlers;
|
|
int numberCollisionHandlers = 0;
|
|
if (static_cast<int>(state.range(1)) == RigidBodyConstants::BenchmarkSettings::AllCollisionHanders)
|
|
{
|
|
numberCollisionHandlers = numRigidBodies;
|
|
}
|
|
else if (static_cast<int>(state.range(1)) == RigidBodyConstants::BenchmarkSettings::HalfCollisionHandlers)
|
|
{
|
|
numberCollisionHandlers = numRigidBodies / 2;
|
|
}
|
|
collisionHandlers.reserve(numberCollisionHandlers);
|
|
for (int i = 0; i < numberCollisionHandlers; i++)
|
|
{
|
|
const AZ::u64 randIndex = rand.Getu64Random() % numRigidBodies; //randomly select the offset.
|
|
collisionHandlers.emplace_back(m_testSceneHandle, rigidBodies[randIndex]);
|
|
}
|
|
|
|
//setup the sub tick tracker
|
|
Utils::PrePostSimulationEventHandler subTickTracker;
|
|
subTickTracker.Start(m_defaultScene);
|
|
|
|
//setup the frame timer tracker
|
|
AZStd::vector<double> tickTimes;
|
|
tickTimes.reserve(RigidBodyConstants::GameFramesToSimulate);
|
|
for ([[maybe_unused]] auto _ : state)
|
|
{
|
|
for (AZ::u32 i = 0; i < RigidBodyConstants::GameFramesToSimulate; i++)
|
|
{
|
|
auto start = AZStd::chrono::system_clock::now();
|
|
StepScene1Tick(DefaultTimeStep);
|
|
|
|
//time each physics tick and store it to analyze
|
|
auto tickElapsedMilliseconds = Types::double_milliseconds(AZStd::chrono::system_clock::now() - start);
|
|
tickTimes.emplace_back(tickElapsedMilliseconds.count());
|
|
}
|
|
}
|
|
subTickTracker.Stop();
|
|
|
|
//object clean up
|
|
collisionHandlers.clear();
|
|
washingMachine.TearDownWashingMachine();
|
|
m_defaultScene->RemoveSimulatedBodies(rigidBodies);
|
|
rigidBodies.clear();
|
|
|
|
//sort the frame times and get the P50, P90, P99 percentiles
|
|
Utils::ReportFramePercentileCounters(state, tickTimes, subTickTracker.GetSubTickTimes());
|
|
Utils::ReportFrameStandardDeviationAndMeanCounters(state, tickTimes, subTickTracker.GetSubTickTimes());
|
|
|
|
//add the collision counts
|
|
state.counters["Collisions-Begin"] = static_cast<double>(m_collisionBeginCount);
|
|
state.counters["Collisions-Persist"] = static_cast<double>(m_collisionPersistCount);
|
|
state.counters["Collisions-End"] = static_cast<double>(m_collisionEndCount);
|
|
}
|
|
|
|
BENCHMARK_REGISTER_F(PhysXRigidbodyBenchmarkFixture, BM_RigidBody_AtRest)
|
|
->RangeMultiplier(RigidBodyConstants::BenchmarkSettings::RangeMultipler)
|
|
->Range(RigidBodyConstants::BenchmarkSettings::StartRange, RigidBodyConstants::BenchmarkSettings::EndRange)
|
|
->Unit(benchmark::kMillisecond)
|
|
->Iterations(RigidBodyConstants::BenchmarkSettings::NumIterations)
|
|
;
|
|
|
|
BENCHMARK_REGISTER_F(PhysXRigidbodyBenchmarkFixture, BM_RigidBody_MovingAndColliding)
|
|
->RangeMultiplier(RigidBodyConstants::BenchmarkSettings::RangeMultipler)
|
|
->Range(RigidBodyConstants::BenchmarkSettings::StartRange, RigidBodyConstants::BenchmarkSettings::EndRange)
|
|
->Unit(benchmark::kMillisecond)
|
|
->Iterations(RigidBodyConstants::BenchmarkSettings::NumIterations)
|
|
;
|
|
|
|
BENCHMARK_REGISTER_F(PhysXRigidbodyCollisionsBenchmarkFixture, BM_RigidBody_MovingAndColliding_CollisionHandlers)
|
|
->RangeMultiplier(RigidBodyConstants::BenchmarkSettings::RangeMultipler)
|
|
->Ranges({ {RigidBodyConstants::BenchmarkSettings::StartRange, RigidBodyConstants::BenchmarkSettings::EndRange}, {RigidBodyConstants::BenchmarkSettings::AllCollisionHanders, RigidBodyConstants::BenchmarkSettings::AllCollisionHanders} })
|
|
->Unit(benchmark::kMillisecond)
|
|
->Iterations(RigidBodyConstants::BenchmarkSettings::NumIterations)
|
|
;
|
|
|
|
BENCHMARK_REGISTER_F(PhysXRigidbodyCollisionsBenchmarkFixture, BM_RigidBody_MovingAndColliding_CollisionHandlers)
|
|
->RangeMultiplier(RigidBodyConstants::BenchmarkSettings::RangeMultipler)
|
|
->Ranges({ {RigidBodyConstants::BenchmarkSettings::StartRange, RigidBodyConstants::BenchmarkSettings::EndRange}, {RigidBodyConstants::BenchmarkSettings::HalfCollisionHandlers, RigidBodyConstants::BenchmarkSettings::HalfCollisionHandlers} })
|
|
->Unit(benchmark::kMillisecond)
|
|
->Iterations(RigidBodyConstants::BenchmarkSettings::NumIterations)
|
|
;
|
|
|
|
BENCHMARK_REGISTER_F(PhysXRigidbodyCollisionsBenchmarkFixture, BM_RigidBody_MovingAndColliding_CollisionHandlers)
|
|
->RangeMultiplier(RigidBodyConstants::BenchmarkSettings::RangeMultipler)
|
|
->Ranges({ {RigidBodyConstants::BenchmarkSettings::StartRange, RigidBodyConstants::BenchmarkSettings::EndRange}, {RigidBodyConstants::BenchmarkSettings::NoCollisionHandlers, RigidBodyConstants::BenchmarkSettings::NoCollisionHandlers} })
|
|
->Unit(benchmark::kMillisecond)
|
|
->Iterations(RigidBodyConstants::BenchmarkSettings::NumIterations)
|
|
;
|
|
} // namespace PhysX::Benchmarks
|
|
#endif
|