| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784 |
- /*
- * 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
- *
- */
- #include <Tests/Game/SampleGameFixture.h>
- #include <AzCore/Debug/Timer.h>
- #include <AzCore/Math/Random.h>
- #include <AzCore/Asset/AssetManager.h>
- #include <EMotionFX/Source/Actor.h>
- #include <EMotionFX/Source/ActorManager.h>
- #include <EMotionFX/Source/AnimGraph.h>
- #include <EMotionFX/Source/AnimGraphMotionNode.h>
- #include <EMotionFX/Source/AnimGraphStateMachine.h>
- #include <EMotionFX/Source/AttachmentSkin.h>
- #include <EMotionFX/Source/EMotionFXManager.h>
- #include <EMotionFX/Source/MultiThreadScheduler.h>
- #include <EMotionFX/Source/MotionSet.h>
- #include <EMotionFX/Source/MotionInstance.h>
- #include <EMotionFX/Source/MotionInstancePool.h>
- #include <EMotionFX/Source/Importer/Importer.h>
- #include <EMotionFX/Source/SingleThreadScheduler.h>
- #include <EMotionFX/Source/Motion.h>
- #include <EMotionFX/Source/Parameter/BoolParameter.h>
- #include <EMotionFX/Source/Parameter/IntParameter.h>
- #include <EMotionFX/Source/Parameter/FloatParameter.h>
- #include <EMotionFX/Source/Parameter/Vector2Parameter.h>
- #include <EMotionFX/Source/Parameter/Vector3Parameter.h>
- #include <AzFramework/Physics/Utils.h>
- #include <AzFramework/IO/LocalFileIO.h>
- namespace EMotionFX
- {
- struct SampleParameterSet
- {
- std::vector<std::tuple<std::string, AZ::Vector2>> m_vec2Params;
- std::vector<std::pair<std::string, bool>> m_boolParams;
- std::vector<std::pair<std::string, float>> m_floatParams;
- };
- struct PerformanceTestParameters
- {
- const char* m_description;
- float m_fps;
- float m_motionSamplingRate;
- float m_totalTestTimeInSeconds;
- size_t m_numInstances;
- size_t m_numSkinAttachmentsPerInstance;
- AZ::u32 m_lodLevel;
- bool m_includeSoftwareSkinning;
- bool m_useMultiThreading;
- void Print() const
- {
- printf("-------------------------------\n");
- printf("- Performance Test Parameters\n");
- printf("- Description: %s\n", m_description);
- printf("- FPS: %f\n", m_fps);
- printf("- Motion Sampling Rate: %f\n", m_motionSamplingRate);
- printf("- Total Time (s): %f\n", m_totalTestTimeInSeconds);
- printf("- Frames: %d\n", static_cast<int>(m_totalTestTimeInSeconds * m_fps));
- printf("- Num Instances: %zd\n", m_numInstances);
- printf("- Num Skin Attachents per Instance: %zd\n", m_numSkinAttachmentsPerInstance);
- printf("- LOD Level: %d\n", m_lodLevel);
- printf("- Software Skin: %s\n", m_includeSoftwareSkinning ? "True" : "False");
- printf("- Multi-threading:%s\n", m_useMultiThreading ? "True" : "False");
- }
- };
- class PerformanceTestFixture
- : public SampleGameFixture
- , public ::testing::WithParamInterface<PerformanceTestParameters>
- {
- public:
- void SetUp() override
- {
- SampleGameFixture::SetUp();
- m_random = new AZ::SimpleLcgRandom();
- m_random->SetSeed(875960);
- SampleParameterSet params;
- params.m_floatParams.push_back({ "movement_speed", 0.0f });
- params.m_vec2Params.push_back({ "movement_direction", AZ::Vector2(0.0f, 0.0f) });
- params.m_boolParams.push_back({ "jumping", false });
- params.m_boolParams.push_back({ "attacking", true });
- m_pyroParameterSet.emplace_back(params);
- params.m_floatParams.push_back({ "movement_speed", 1.0f });
- params.m_vec2Params.push_back({ "movement_direction", AZ::Vector2(1.0f, 0.0f) });
- params.m_boolParams.push_back({ "jumping", false });
- params.m_boolParams.push_back({ "attacking", false });
- m_pyroParameterSet.emplace_back(params);
- params.m_floatParams.push_back({ "movement_speed", 0.5f });
- params.m_vec2Params.push_back({ "movement_direction", AZ::Vector2(0.5f, 0.5f) });
- params.m_boolParams.push_back({ "jumping", false });
- params.m_boolParams.push_back({ "attacking", false });
- m_pyroParameterSet.emplace_back(params);
- params.m_floatParams.push_back({ "movement_speed", 0.0f });
- params.m_vec2Params.push_back({ "movement_direction", AZ::Vector2(0.0f, 0.0f) });
- params.m_boolParams.push_back({ "jumping", true });
- params.m_boolParams.push_back({ "attacking", false });
- m_pyroParameterSet.emplace_back(params);
- }
- void TearDown() override
- {
- delete m_random;
- SampleGameFixture::TearDown();
- }
- float RandomRange(float min, float max) const
- {
- return min + m_random->GetRandomFloat() * (max - min);
- }
- AZ::Vector3 RandomRangeVec3(float min, float max) const
- {
- return AZ::Vector3(
- RandomRange(min, max),
- RandomRange(min, max),
- RandomRange(min, max));
- }
- void RandomizeParameters(const AZStd::vector<ActorInstance*>& actorInstances)
- {
- for (ActorInstance* actorInstance : actorInstances)
- {
- AnimGraphInstance* animGraphInstance = actorInstance->GetAnimGraphInstance();
- AZ_Assert(animGraphInstance, "Actor instance should have an anim graph instance playing.");
- const AnimGraph* animGraph = animGraphInstance->GetAnimGraph();
- const size_t parameterSetIndex = static_cast<size_t>(RandomRange(0.0f, static_cast<float>(m_pyroParameterSet.size())-0.0001f));
- const SampleParameterSet& params = m_pyroParameterSet[parameterSetIndex];
- // Set parameters to default values.
- const size_t numParameters = animGraph->GetNumValueParameters();
- for (size_t i = 0; i < numParameters; ++i)
- {
- const ValueParameter* parameter = animGraph->FindValueParameter(i);
- MCore::Attribute* attribute = animGraphInstance->GetParameterValue(static_cast<AZ::u32>(i));
- if (parameter->RTTI_GetType() == azrtti_typeid<BoolParameter>())
- {
- const BoolParameter* boolParameter = static_cast<const BoolParameter*>(parameter);
- MCore::AttributeBool* boolAttribute = static_cast<MCore::AttributeBool*>(attribute);
- boolAttribute->SetValue(boolParameter->GetDefaultValue());
- }
- if (parameter->RTTI_GetType() == azrtti_typeid<FloatParameter>())
- {
- const FloatParameter* floatParameter = static_cast<const FloatParameter*>(parameter);
- MCore::AttributeFloat* floatAttribute = static_cast<MCore::AttributeFloat*>(attribute);
- floatAttribute->SetValue(floatParameter->GetDefaultValue());
- }
- if (parameter->RTTI_GetType() == azrtti_typeid<Vector2Parameter>())
- {
- const Vector2Parameter* vec2Parameter = static_cast<const Vector2Parameter*>(parameter);
- MCore::AttributeVector2* vec2Attribute = static_cast<MCore::AttributeVector2*>(attribute);
- vec2Attribute->SetValue(vec2Parameter->GetDefaultValue());
- }
- }
- // Bool parameters
- for (const auto& boolParamPair : params.m_boolParams)
- {
- const AZ::Outcome<size_t> parameterIndex = animGraph->FindValueParameterIndexByName(boolParamPair.first.c_str());
- ASSERT_TRUE(parameterIndex.IsSuccess());
- const ValueParameter* parameter = animGraph->FindValueParameter(parameterIndex.GetValue());
- ASSERT_NE(parameter, nullptr);
- ASSERT_EQ(parameter->GetName(), boolParamPair.first.c_str());
- MCore::Attribute* attribute = animGraphInstance->GetParameterValue(static_cast<AZ::u32>(parameterIndex.GetValue()));
- MCore::AttributeBool* boolAttribute = static_cast<MCore::AttributeBool*>(attribute);
- boolAttribute->SetValue(boolParamPair.second);
- }
- // Vec2 parameters
- for (const auto& vec2ParamTuple : params.m_vec2Params)
- {
- const AZ::Outcome<size_t> parameterIndex = animGraph->FindValueParameterIndexByName(std::get<0>(vec2ParamTuple).c_str());
- ASSERT_TRUE(parameterIndex.IsSuccess());
- const ValueParameter* parameter = animGraph->FindValueParameter(parameterIndex.GetValue());
- ASSERT_NE(parameter, nullptr);
- ASSERT_EQ(parameter->GetName(), std::get<0>(vec2ParamTuple).c_str());
- MCore::Attribute* attribute = animGraphInstance->GetParameterValue(static_cast<AZ::u32>(parameterIndex.GetValue()));
- MCore::AttributeVector2* vec2Attribute = static_cast<MCore::AttributeVector2*>(attribute);
- vec2Attribute->SetValue(std::get<1>(vec2ParamTuple));
- }
- // Float parameters
- for (const auto& floatParamPair : params.m_floatParams)
- {
- const AZ::Outcome<size_t> parameterIndex = animGraph->FindValueParameterIndexByName(floatParamPair.first.c_str());
- ASSERT_TRUE(parameterIndex.IsSuccess());
- const ValueParameter* parameter = animGraph->FindValueParameter(parameterIndex.GetValue());
- ASSERT_NE(parameter, nullptr);
- ASSERT_EQ(parameter->GetName(), floatParamPair.first.c_str());
- MCore::Attribute* attribute = animGraphInstance->GetParameterValue(static_cast<AZ::u32>(parameterIndex.GetValue()));
- MCore::AttributeFloat* floatAttribute = static_cast<MCore::AttributeFloat*>(attribute);
- floatAttribute->SetValue(floatParamPair.second);
- }
- }
- }
- static AZStd::tuple<float, float, float, float> CalculateStats(const AZStd::vector<float>& samples)
- {
- const size_t numSamples = samples.size();
- if (numSamples == 0)
- {
- return { 0.0f, 0.0f, 0.0f, 0.0f };
- }
- float best = samples[0];
- float worst = samples[0];
- float accumulated = 0.0f;
- for (const float sample : samples)
- {
- best = AZ::GetMin<float>(best, sample);
- worst = AZ::GetMax<float>(worst, sample);
- accumulated += sample;
- }
- const float mean = accumulated / static_cast<float>(numSamples);
- float variance = 0.0f;
- for (const float sample : samples)
- {
- variance += powf(sample - mean, 2.0f);
- }
- variance = variance / static_cast<float>(numSamples);
- const float stdDeviation = sqrtf(variance);
- return { best, mean, worst, stdDeviation };
- }
- void PrintReport(const AZStd::vector<float>& transformUpdateFrameTimes,
- const AZStd::vector<float>& meshDeformFrameTimes,
- float totalTransformUpdateTime,
- float totalMeshDeformTime)
- {
- const PerformanceTestParameters& param = GetParam();
- // Totals
- printf("----------------------------------------------------\n");
- printf("- Performance Test Report -\n");
- if (param.m_includeSoftwareSkinning)
- {
- printf("- Totals:\n");
- printf(" Total Time (s): %.4f s\n", totalTransformUpdateTime + totalMeshDeformTime);
- printf(" Total Transform Update Time (s): %.4f s\n", totalTransformUpdateTime);
- printf(" Total Mesh Deform Time (s): %.4f s\n", totalMeshDeformTime);
- printf(" Transform Mesh Ratio: %.4f %%\n", totalTransformUpdateTime / totalMeshDeformTime);
- }
- else
- {
- printf("- Total Time (s): %.4f s\n", totalTransformUpdateTime + totalMeshDeformTime);
- }
- // Transform update
- float transformBest;
- float transformMean;
- float transformWorst;
- float transformStdDeviation;
- AZStd::tie(transformBest, transformMean, transformWorst, transformStdDeviation) = CalculateStats(transformUpdateFrameTimes);
- printf("- Transform update:\n");
- printf(" Best Frame: %.4f ms (%.1f FPS)\n", transformBest * 1000.0f, transformBest > 0.0f ? 1.0f / transformBest : 0.0f);
- printf(" Mean Frame: %.4f ms (%.1f FPS)\n", transformMean * 1000.0f, transformMean > 0.0f ? 1.0f / transformMean : 0.0f);
- printf(" Worst Frame: %.4f ms (%.1f FPS)\n", transformWorst * 1000.0f, transformWorst > 0.0f ? 1.0f / transformWorst : 0.0f);
- printf(" Std Deviation: %.4f ms\n", transformStdDeviation * 1000.0f);
- // Mesh deforms
- if (param.m_includeSoftwareSkinning)
- {
- float meshDeformBest;
- float meshDeformMean;
- float meshDeformWorst;
- float meshDeformStdDeviation;
- AZStd::tie(meshDeformBest, meshDeformMean, meshDeformWorst, meshDeformStdDeviation) = CalculateStats(meshDeformFrameTimes);
- printf("- Mesh deforms:\n");
- printf(" Best Frame: %.4f ms\n", meshDeformBest * 1000.0f);
- printf(" Mean Frame: %.4f ms\n", meshDeformMean * 1000.0f);
- printf(" Worst Frame: %.4f ms\n", meshDeformWorst * 1000.0f);
- printf(" Std Deviation: %.4f ms\n", meshDeformStdDeviation * 1000.0f);
- }
- printf("----------------------------------------------------\n");
- }
- void TestMotionSamplingPerformance(const char* motionFilename)
- {
- const AZStd::string assetFolder = GetAssetFolder();
- GetEMotionFX().SetMediaRootFolder(assetFolder.c_str());
- GetEMotionFX().InitAssetFolderPaths();
- const char* actorFilename = "@products@\\animationsamples\\advanced_rinlocomotion\\actor\\rinactor.actor";
- Importer* importer = GetEMotionFX().GetImporter();
- importer->SetLoggingEnabled(false);
- const AZStd::string resolvedActorFilename = ResolvePath(actorFilename);
- EXPECT_TRUE(AZ::IO::LocalFileIO::GetInstance()->Exists(resolvedActorFilename.c_str()))
- << AZStd::string::format("Actor file '%s' does not exist on local hard drive.", resolvedActorFilename.c_str()).c_str();
- AZStd::unique_ptr<Actor> actor = importer->LoadActor(resolvedActorFilename);
- ASSERT_NE(actor, nullptr) << "Actor failed to load.";
- Motion* motion = importer->LoadMotion(ResolvePath(motionFilename));
- ASSERT_NE(motion, nullptr) << "Motion failed to load.";
- ActorInstance* actorInstance = ActorInstance::Create(actor.get());
- const Pose* bindPose = actor->GetBindPose();
- Pose outPose;
- outPose.InitFromBindPose(actorInstance);
- MotionInstance* motionInstance = GetMotionInstancePool().RequestNew(motion, actorInstance);
- const size_t numSamples = 100000;
- AZ::Debug::Timer timer;
- // Sample the same time value.
- timer.Stamp();
- for (size_t i = 0; i < numSamples; ++i)
- {
- motionInstance->SetCurrentTimeNormalized(0.33f);
- motion->Update(bindPose, &outPose, motionInstance);
- }
- float activationTime = timer.GetDeltaTimeInSeconds();
- printf("Sampling same frame = %.2f ms\n", activationTime * 1000.0f);
- // Sample random time values.
- timer.Stamp();
- for (size_t i = 0; i < numSamples; ++i)
- {
- motionInstance->SetCurrentTimeNormalized(rand() / static_cast<float>(RAND_MAX));
- motion->Update(bindPose, &outPose, motionInstance);
- }
- activationTime = timer.GetDeltaTimeInSeconds();
- printf("Sampling random frame = %.2f ms\n", activationTime * 1000.0f);
- // Sample forward.
- timer.Stamp();
- for (size_t i = 0; i < numSamples; ++i)
- {
- motionInstance->SetCurrentTimeNormalized(i / static_cast<float>(numSamples));
- motion->Update(bindPose, &outPose, motionInstance);
- }
- activationTime = timer.GetDeltaTimeInSeconds();
- printf("Sampling forward sequential = %.2f ms\n", activationTime * 1000.0f);
- // Sample backward.
- timer.Stamp();
- for (size_t i = 0; i < numSamples; ++i)
- {
- motionInstance->SetCurrentTimeNormalized(1.0f - (i / static_cast<float>(numSamples)));
- motion->Update(bindPose, &outPose, motionInstance);
- }
- activationTime = timer.GetDeltaTimeInSeconds();
- printf("Sampling backward sequential = %.2f ms\n", activationTime * 1000.0f);
- GetMotionInstancePool().Free(motionInstance);
- actorInstance->Destroy();
- motion->Destroy();
- }
- private:
- AZ::SimpleLcgRandom* m_random;
- std::vector<SampleParameterSet> m_pyroParameterSet;
- };
- TEST_P(PerformanceTestFixture, DISABLED_PerformanceTest)
- {
- const PerformanceTestParameters& param = GetParam();
- const size_t numIterations = static_cast<size_t>(param.m_totalTestTimeInSeconds * param.m_fps);
- const float frameTimeDelta = 1.0f / param.m_fps;
- param.Print();
- ActorManager* actorManager = GetEMotionFX().GetActorManager();
- ActorUpdateScheduler* scheduler = nullptr;
- if (param.m_useMultiThreading)
- {
- scheduler = MultiThreadScheduler::Create();
- }
- else
- {
- scheduler = SingleThreadScheduler::Create();
- }
- actorManager->SetScheduler(scheduler);
- const AZStd::string assetFolder = GetAssetFolder();
- GetEMotionFX().SetMediaRootFolder(assetFolder.c_str());
- GetEMotionFX().InitAssetFolderPaths();
- // This path points to assets in the advance rin demo.
- // To test different assets, change the path here.
- const char* actorFilename = "@products@\\AnimationSamples\\Advanced_RinLocomotion\\Actor\\rinActor.actor";
- const char* motionSetFilename = "@products@\\AnimationSamples\\Advanced_RinLocomotion\\AnimationEditorFiles\\Advanced_RinLocomotion.motionset";
- const char* animGraphFilename = "@products@\\AnimationSamples\\Advanced_RinLocomotion\\AnimationEditorFiles\\Advanced_RinLocomotion.animgraph";
- Importer* importer = GetEMotionFX().GetImporter();
- importer->SetLoggingEnabled(false);
- AZStd::unique_ptr<Actor> actor = importer->LoadActor(ResolvePath(actorFilename));
- ASSERT_NE(actor, nullptr) << "Actor failed to load.";
- MotionSet* motionSet = importer->LoadMotionSet(ResolvePath(motionSetFilename));
- ASSERT_NE(motionSet, nullptr) << "Motion set failed to load.";
- AnimGraph* animGraph = importer->LoadAnimGraph(ResolvePath(animGraphFilename));
- ASSERT_NE(animGraph, nullptr) << "Anim graph failed to load.";
- // Create instances and start running the anim graphs.
- AZStd::vector<ActorInstance*> actorInstances;
- AZStd::vector<ActorInstance*> actorInstancesIncludingAttachments;
- actorInstances.reserve(param.m_numInstances);
- for (size_t i = 0; i < param.m_numInstances; ++i)
- {
- ActorInstance* actorInstance = ActorInstance::Create(actor.get());
- if (!AZ::IsClose(param.m_motionSamplingRate, 0.0f, AZ::Constants::FloatEpsilon))
- {
- actorInstance->SetMotionSamplingRate(1.0f / param.m_motionSamplingRate);
- }
- actorInstance->SetLocalSpacePosition(RandomRangeVec3(-100.0f, 100.0f));
- actorInstances.emplace_back(actorInstance);
- actorInstancesIncludingAttachments.emplace_back(actorInstance);
- AnimGraphInstance* animGraphInstance = AnimGraphInstance::Create(animGraph, actorInstance, motionSet);
- actorInstance->SetAnimGraphInstance(animGraphInstance);
- actorInstance->SetLODLevel(param.m_lodLevel);
- actorInstance->UpdateTransformations(0.0f);
- // Add skin attachments.
- for (size_t attachmentNr = 0; attachmentNr < param.m_numSkinAttachmentsPerInstance; ++attachmentNr)
- {
- ActorInstance* attachmentActorInstance = ActorInstance::Create(actor.get());
- EMotionFX::Attachment* attachment = EMotionFX::AttachmentSkin::Create(/*attachmentTarget*/actorInstance, attachmentActorInstance);
- actorInstance->AddAttachment(attachment);
- actorInstancesIncludingAttachments.emplace_back(attachmentActorInstance);
- }
- }
- // Preload motions and make sure they got loaded successfully.
- motionSet->Preload();
- const auto& motionEntries = motionSet->GetMotionEntries();
- for (const auto& motionEntryPair : motionEntries)
- {
- const MotionSet::MotionEntry* motionEntry = motionEntryPair.second;
- ASSERT_NE(motionEntry->GetMotion(), nullptr);
- }
- AZ::Debug::Timer timer;
- AZStd::vector<float> transformUpdateFrameTimes;
- AZStd::vector<float> meshDeformFrameTimes;
- transformUpdateFrameTimes.reserve(numIterations);
- meshDeformFrameTimes.reserve(numIterations);
- float totalTransformUpdateTime = 0.0f;
- float totalMeshDeformTime = 0.0f;
- const float randomizeParametersEvery = 1.0; // Change parameters every second
- float randomizeParameterTimer = 0.0f;
- for (size_t i = 0; i < numIterations; ++i)
- {
- randomizeParameterTimer += frameTimeDelta;
- if (randomizeParameterTimer >= randomizeParametersEvery)
- {
- RandomizeParameters(actorInstances);
- randomizeParameterTimer = 0.0;
- }
- // Output skeletal poses.
- timer.Stamp();
- GetEMotionFX().Update(frameTimeDelta);
- const float transformUpdateTime = timer.GetDeltaTimeInSeconds();
- totalTransformUpdateTime += transformUpdateTime;
- transformUpdateFrameTimes.emplace_back(transformUpdateTime);
- // Update mesh deformers (software skinning).
- if (param.m_includeSoftwareSkinning)
- {
- timer.Stamp();
- for (ActorInstance* actorInstance : actorInstancesIncludingAttachments)
- {
- actorInstance->UpdateMeshDeformers(frameTimeDelta);
- }
- const float meshDeformTime = timer.GetDeltaTimeInSeconds();
- totalMeshDeformTime += meshDeformTime;
- meshDeformFrameTimes.emplace_back(meshDeformTime);
- }
- }
- PrintReport(transformUpdateFrameTimes, meshDeformFrameTimes, totalTransformUpdateTime, totalMeshDeformTime);
- for (ActorInstance* actorInstance : actorInstancesIncludingAttachments)
- {
- actorInstance->Destroy();
- }
- delete animGraph;
- delete motionSet;
- }
- const float g_updatesPerSec = 60.0f;
- const float g_totalTestTime = 60.0f; // 1 minute
- const size_t g_numInstances = 100;
- std::vector<PerformanceTestParameters> performanceTestData
- {
- // Baseline
- {
- "Baseline",
- g_updatesPerSec, // fps
- 0.0f, // motion sampling rate
- g_totalTestTime, // total test time
- g_numInstances, // instances
- 0, // num skin attachments per instance
- 0, // lod level
- false, // software skinning
- false // multi-threading
- },
- // Multi-threading
- {
- "Multi-threading",
- g_updatesPerSec, // fps
- 0.0f, // motion sampling rate
- g_totalTestTime, // total test time
- g_numInstances, // instances
- 0, // num skin attachments per instance
- 0, // lod level
- false, // software skinning
- true // multi-threading
- },
- // Multi-threading with 1 skin attachments
- {
- "Multi-threading with 1 skin attachments",
- g_updatesPerSec, // fps
- 0.0f, // motion sampling rate
- g_totalTestTime, // total test time
- g_numInstances, // instances
- 1, // num skin attachments per instance
- 0, // lod level
- false, // software skinning
- true // multi-threading
- },
- // Multi-threading and restricted motion sampling rate
- {
- "Multi-threading and restricted motion sampling rate",
- g_updatesPerSec, // fps
- 60.0f, // motion sampling rate
- g_totalTestTime, // total test time
- g_numInstances, // instances
- 0, // num skin attachments per instance
- 0, // lod level
- false, // software skinning
- true // multi-threading
- },
- // Multi-threading and lower motion sampling rate
- {
- "Multi-threading and lower motion sampling rate",
- g_updatesPerSec, // fps
- 30.0f, // motion sampling rate
- g_totalTestTime, // total test time
- g_numInstances, // instances
- 0, // num skin attachments per instance
- 0, // lod level
- false, // software skinning
- true // multi-threading
- },
- // Multi-threading and lower motion sampling rate
- {
- "Multi-threading and lower motion sampling rate",
- g_updatesPerSec, // fps
- 10.0f, // motion sampling rate
- g_totalTestTime, // total test time
- g_numInstances, // instances
- 0, // num skin attachments per instance
- 0, // lod level
- false, // software skinning
- true // multi-threading
- },
- // Multi-threading at LOD level = 1
- {
- "Multi-threading at LOD level = 1",
- g_updatesPerSec, // fps
- 0.0f, // motion sampling rate
- g_totalTestTime, // total test time
- g_numInstances, // instances
- 0, // num skin attachments per instance
- 1, // lod level
- false, // software skinning
- true // multi-threading
- },
- // Multi-threading at LOD level = 2
- {
- "Multi-threading at LOD level = 2",
- g_updatesPerSec, // fps
- 0.0f, // motion sampling rate
- g_totalTestTime, // total test time
- g_numInstances, // instances
- 0, // num skin attachments per instance
- 2, // lod level
- false, // software skinning
- true // multi-threading
- },
- // Multi-threading at LOD level = 3
- {
- "Multi-threading at LOD level = 3",
- g_updatesPerSec, // fps
- 0.0f, // motion sampling rate
- g_totalTestTime, // total test time
- g_numInstances, // instances
- 0, // num skin attachments per instance
- 3, // lod level
- false, // software skinning
- true // multi-threading
- },
- // Multi-threading at LOD level = 4
- {
- "Multi-threading at LOD level = 4",
- g_updatesPerSec, // fps
- 0.0f, // motion sampling rate
- g_totalTestTime, // total test time
- g_numInstances, // instances
- 0, // num skin attachments per instance
- 4, // lod level
- false, // software skinning
- true // multi-threading
- },
- // Server test: LOD0
- {
- "Server test: LOD0",
- 30.0f, // fps
- 0.0f, // motion sampling rate
- g_totalTestTime, // total test time
- g_numInstances, // instances
- 0, // num skin attachments per instance
- 0, // lod level
- false, // software skinning
- false // multi-threading
- },
- // Server test: LOD4
- {
- "Server test: LOD4",
- 30.0f, // fps
- 0.0f, // motion sampling rate
- g_totalTestTime, // total test time
- g_numInstances, // instances
- 0, // num skin attachments per instance
- 4, // lod level
- false, // software skinning
- false // multi-threading
- },
- // Server test: Server actor optimization (bone removal).
- {
- "Server test: Server actor optimization (bone removal)",
- 30.0f, // fps
- 0.0f, // motion sampling rate
- g_totalTestTime, // total test time
- g_numInstances, // instances
- 0, // num skin attachments per instance
- 0, // lod level
- false, // software skinning
- false // multi-threading
- }/*,
- // Software skinning (this is extremely slow and will take a long time to run)
- {
- "Software skinning",
- g_updatesPerSec, // fps
- 0.0f, // motion sampling rate
- g_totalTestTime, // total test time
- g_numInstances, // instances
- 0, // num skin attachments per instance
- 0, // lod level
- true, // software skinning
- false // multi-threading
- }*/
- };
- std::vector<PerformanceTestParameters> debugTestData
- {
- {
- "debug",
- g_updatesPerSec, // fps
- 60.0f, // motion sampling rate
- g_totalTestTime, // total test time
- 1, // instances
- 0, // num skin attachments per instance
- 0, // lod level
- false, // software skinning
- true // multi-threading
- }
- };
- INSTANTIATE_TEST_CASE_P(PerformanceTests,
- PerformanceTestFixture,
- ::testing::ValuesIn(performanceTestData));
- //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- TEST_F(PerformanceTestFixture, DISABLED_DeferredInitPerformanceTest)
- {
- const AZStd::string assetFolder = GetAssetFolder();
- GetEMotionFX().SetMediaRootFolder(assetFolder.c_str());
- GetEMotionFX().InitAssetFolderPaths();
- // This path points to assets in the advance rin demo.
- // To test different assets, change the path here.
- const char* actorFilename = "@products@\\AnimationSamples\\Advanced_RinLocomotion\\Actor\\rinActor.actor";
- const char* motionSetFilename = "@products@\\AnimationSamples\\Advanced_RinLocomotion\\AnimationEditorFiles\\Advanced_RinLocomotion.motionset";
- const char* animGraphFilename = "@products@\\AnimationSamples\\Advanced_RinLocomotion\\AnimationEditorFiles\\Advanced_RinLocomotion.animgraph";
- Importer* importer = GetEMotionFX().GetImporter();
- importer->SetLoggingEnabled(false);
- const AZStd::string resolvedActorFilename = ResolvePath(actorFilename);
- EXPECT_TRUE(AZ::IO::LocalFileIO::GetInstance()->Exists(resolvedActorFilename.c_str()))
- << AZStd::string::format("Actor file '%s' does not exist on local hard drive.", resolvedActorFilename.c_str()).c_str();
- AZStd::unique_ptr<Actor> actor = importer->LoadActor(resolvedActorFilename);
- ASSERT_NE(actor, nullptr) << "Actor failed to load.";
- MotionSet* motionSet = importer->LoadMotionSet(ResolvePath(motionSetFilename));
- ASSERT_NE(motionSet, nullptr) << "Motion set failed to load.";
- AnimGraph* animGraph = importer->LoadAnimGraph(ResolvePath(animGraphFilename));
- ASSERT_NE(animGraph, nullptr) << "Anim graph failed to load.";
- // Create instances.
- const size_t numInstances = 1000;
- AZStd::vector<ActorInstance*> actorInstances;
- for (size_t i = 0; i < numInstances; ++i)
- {
- ActorInstance* actorInstance = ActorInstance::Create(actor.get());
- actorInstances.emplace_back(actorInstance);
- }
- // Preload motions and make sure they got loaded successfully.
- motionSet->Preload();
- const auto& motionEntries = motionSet->GetMotionEntries();
- for (const auto& motionEntryPair : motionEntries)
- {
- const MotionSet::MotionEntry* motionEntry = motionEntryPair.second;
- ASSERT_NE(motionEntry->GetMotion(), nullptr);
- }
- AZ::Debug::Timer timer;
- timer.Stamp();
- for (ActorInstance* actorInstance : actorInstances)
- {
- AnimGraphInstance* animGraphInstance = AnimGraphInstance::Create(animGraph, actorInstance, motionSet);
- actorInstance->SetAnimGraphInstance(animGraphInstance);
- }
- const float activationTime = timer.GetDeltaTimeInSeconds();
- printf("Instantiating took = %.2f ms\n", activationTime * 1000.0f);
- printf("Activation Time = %.2f ms\n", activationTime * 1000.0f);
- for (ActorInstance* actorInstance : actorInstances)
- {
- actorInstance->Destroy();
- }
- delete animGraph;
- delete motionSet;
- }
- TEST_F(PerformanceTestFixture, DISABLED_MotionSamplingPerformanceNonUniform)
- {
- // Make sure that the motion is set to use NonUniform sampling! Change this in the scene settings! Otherwise you get wrong results.
- TestMotionSamplingPerformance("@products@\\animationsamples\\advanced_rinlocomotion\\motions\\rin_idle.motion");
- }
- TEST_F(PerformanceTestFixture, DISABLED_MotionSamplingPerformanceUniform)
- {
- // Make sure that the motion is set to use Uniform sampling! Change this in the scene settings! Otherwise you get wrong results.
- TestMotionSamplingPerformance("@products@\\animationsamples\\advanced_rinlocomotion\\motions\\rin_walk_kick_01.motion");
- }
- } // namespace EMotionFX
|