MetaCore/tests/MetaCoreAnimationBenchmark.cpp
2026-07-27 09:50:32 +08:00

72 lines
3.2 KiB
C++

#include "MetaCoreAnimation/MetaCoreAnimation.h"
#include "MetaCoreScene/MetaCoreScene.h"
#include <algorithm>
#include <chrono>
#include <cstdlib>
#include <iostream>
#include <vector>
int main() {
using namespace MetaCore;
const auto clipGuid = MetaCoreBuildDeterministicAnimationGuid("benchmark/clip");
const auto controllerGuid = MetaCoreBuildDeterministicAnimationGuid("benchmark/controller");
MetaCoreAnimationClipDocument clip;
clip.AssetGuid = clipGuid;
clip.Duration = 1.0F;
for (int bone = 0; bone < 100; ++bone) {
MetaCoreAnimationChannelDocument channel;
channel.NodePath = "Root/Bone_" + std::to_string(bone);
channel.Target = MetaCoreAnimationChannelTarget::Translation;
channel.Vec3Keys = {{0.0F, {0, 0, 0}}, {1.0F, {static_cast<float>(bone) * 0.001F, 0, 0}}};
clip.Channels.push_back(std::move(channel));
}
MetaCoreAnimatorControllerDocument controller;
controller.AssetGuid = controllerGuid;
controller.Parameters.push_back({"Speed", MetaCoreAnimatorParameterType::Float, false, 0, 0.5F});
for (int layerIndex = 0; layerIndex < 2; ++layerIndex) {
MetaCoreAnimatorStateDocument state;
state.Id = "Move";
state.Motion.Type = MetaCoreAnimatorMotionType::BlendTree1D;
state.Motion.ParameterX = "Speed";
state.Motion.Samples = {{"slow", clipGuid, 0.0F}, {"fast", clipGuid, 1.0F}};
MetaCoreAnimatorLayerDocument layer;
layer.Id = "Layer_" + std::to_string(layerIndex);
layer.DefaultStateId = state.Id;
layer.BlendMode = layerIndex == 0 ? MetaCoreAnimatorLayerBlendMode::Override : MetaCoreAnimatorLayerBlendMode::Additive;
layer.States.push_back(std::move(state));
controller.Layers.push_back(std::move(layer));
}
MetaCoreScene scene;
for (int index = 0; index < 100; ++index) {
auto object = scene.CreateGameObject("Animated_" + std::to_string(index));
MetaCoreAnimatorComponent animator;
animator.ControllerAssetGuid = controllerGuid;
object.AddComponent<MetaCoreAnimatorComponent>(animator);
}
MetaCoreAnimationRuntime runtime(scene,
[&](MetaCoreAssetGuid guid) -> std::optional<MetaCoreAnimationClipDocument> { return guid == clipGuid ? std::optional(clip) : std::nullopt; },
[&](MetaCoreAssetGuid guid) -> std::optional<MetaCoreAnimatorControllerDocument> { return guid == controllerGuid ? std::optional(controller) : std::nullopt; });
runtime.Start();
for (int warmup = 0; warmup < 30; ++warmup) runtime.Update(1.0 / 60.0);
std::vector<double> samples;
samples.reserve(180);
for (int frame = 0; frame < 180; ++frame) {
const auto begin = std::chrono::steady_clock::now();
runtime.Update(1.0 / 60.0);
samples.push_back(std::chrono::duration<double, std::milli>(std::chrono::steady_clock::now() - begin).count());
}
std::sort(samples.begin(), samples.end());
const double p95 = samples[static_cast<std::size_t>(samples.size() * 0.95)];
std::cout << "AnimationBenchmark instances=100 bones=100 layers=2 p95_ms=" << p95 << '\n';
if (p95 > 4.0) {
std::cerr << "Animation CPU p95 exceeds the Linux x86_64 4 ms gate\n";
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}