Added profiling statements to SyncedAnimationGraph.

This commit is contained in:
Martin Felis 2026-01-16 09:51:49 +01:00
parent 338a77d5e2
commit a5577eceea
5 changed files with 30 additions and 10 deletions

View File

@ -10,7 +10,7 @@ extends Node3D
# Called when the node enters the scene tree for the first time. # Called when the node enters the scene tree for the first time.
func _ready() -> void: func _ready() -> void:
blend_weight_slider.value = 0.0 blend_weight_slider.value = 0.5
# Called every frame. 'delta' is the elapsed time since the previous frame. # Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta: float) -> void: func _process(delta: float) -> void:

View File

@ -1,6 +1,7 @@
#include "synced_animation_graph.h" #include "synced_animation_graph.h"
#include "core/os/time.h" #include "core/os/time.h"
#include "core/profiling/profiling.h"
#include "scene/3d/skeleton_3d.h" #include "scene/3d/skeleton_3d.h"
#include "scene/animation/animation_player.h" #include "scene/animation/animation_player.h"
@ -141,6 +142,8 @@ void SyncedAnimationGraph::_tree_changed() {
} }
void SyncedAnimationGraph::_notification(int p_what) { void SyncedAnimationGraph::_notification(int p_what) {
GodotProfileZone("SyncedAnimationGraph::_notification");
switch (p_what) { switch (p_what) {
case Node::NOTIFICATION_READY: { case Node::NOTIFICATION_READY: {
_setup_evaluation_context(); _setup_evaluation_context();
@ -292,6 +295,8 @@ void SyncedAnimationGraph::_process_graph(double p_delta, bool p_update_only) {
return; return;
} }
GodotProfileZone("SyncedAnimationGraph::_process_graph");
_update_properties(); _update_properties();
root_animation_node->activate_inputs(Vector<Ref<SyncedAnimationNode>>()); root_animation_node->activate_inputs(Vector<Ref<SyncedAnimationNode>>());
@ -303,6 +308,8 @@ void SyncedAnimationGraph::_process_graph(double p_delta, bool p_update_only) {
} }
void SyncedAnimationGraph::_apply_animation_data(const AnimationData &output_data) const { void SyncedAnimationGraph::_apply_animation_data(const AnimationData &output_data) const {
GodotProfileZone("SyncedAnimationGraph::_apply_animation_data");
for (const KeyValue<Animation::TypeHash, AnimationData::TrackValue *> &K : output_data.track_values) { for (const KeyValue<Animation::TypeHash, AnimationData::TrackValue *> &K : output_data.track_values) {
const AnimationData::TrackValue *track_value = K.value; const AnimationData::TrackValue *track_value = K.value;
switch (track_value->type) { switch (track_value->type) {

View File

@ -3,8 +3,6 @@
#include "scene/animation/animation_player.h" #include "scene/animation/animation_player.h"
#include "synced_animation_node.h" #include "synced_animation_node.h"
#include <cassert>
class Skeleton3D; class Skeleton3D;
class SyncedAnimationGraph : public Node { class SyncedAnimationGraph : public Node {

View File

@ -135,7 +135,9 @@ bool SyncedBlendTree::_set(const StringName &p_name, const Variant &p_value) {
} }
void AnimationData::sample_from_animation(const Ref<Animation> &animation, const Skeleton3D *skeleton_3d, double p_time) { void AnimationData::sample_from_animation(const Ref<Animation> &animation, const Skeleton3D *skeleton_3d, double p_time) {
const Vector<Animation::Track *> tracks = animation->get_tracks(); GodotProfileZone("AnimationData::sample_from_animation");
const LocalVector<Animation::Track *> tracks = animation->get_tracks();
Animation::Track *const *tracks_ptr = tracks.ptr(); Animation::Track *const *tracks_ptr = tracks.ptr();
int count = tracks.size(); int count = tracks.size();
@ -250,6 +252,8 @@ void AnimationSamplerNode::update_time(double p_time) {
} }
void AnimationSamplerNode::evaluate(GraphEvaluationContext &context, const LocalVector<AnimationData *> &inputs, AnimationData &output) { void AnimationSamplerNode::evaluate(GraphEvaluationContext &context, const LocalVector<AnimationData *> &inputs, AnimationData &output) {
GodotProfileZone("AnimationSamplerNode::evaluate");
assert(inputs.size() == 0); assert(inputs.size() == 0);
if (node_time_info.is_synced) { if (node_time_info.is_synced) {
@ -276,6 +280,8 @@ void AnimationSamplerNode::_bind_methods() {
} }
void AnimationBlend2Node::evaluate(GraphEvaluationContext &context, const LocalVector<AnimationData *> &inputs, AnimationData &output) { void AnimationBlend2Node::evaluate(GraphEvaluationContext &context, const LocalVector<AnimationData *> &inputs, AnimationData &output) {
GodotProfileZone("AnimationBlend2Node::evaluate");
output = *inputs[0]; output = *inputs[0];
output.blend(*inputs[1], blend_weight); output.blend(*inputs[1], blend_weight);
} }

View File

@ -1,9 +1,10 @@
#pragma once #pragma once
#include "scene/animation/animation_player.h"
#include "core/io/resource.h" #include "core/io/resource.h"
#include "core/profiling/profiling.h"
#include "scene/3d/skeleton_3d.h" #include "scene/3d/skeleton_3d.h"
#include "scene/animation/animation_player.h"
#include "sync_track.h" #include "sync_track.h"
#include <cassert> #include <cassert>
@ -113,9 +114,8 @@ struct AnimationData {
}; };
AnimationData() = default; AnimationData() = default;
~AnimationData() { ~AnimationData() = default;
_clear_values();
}
AnimationData(const AnimationData &other) { AnimationData(const AnimationData &other) {
for (const KeyValue<Animation::TypeHash, TrackValue *> &K : other.track_values) { for (const KeyValue<Animation::TypeHash, TrackValue *> &K : other.track_values) {
track_values.insert(K.key, K.value->clone()); track_values.insert(K.key, K.value->clone());
@ -165,6 +165,8 @@ struct AnimationData {
} }
void blend(const AnimationData &to_data, const float lambda) { void blend(const AnimationData &to_data, const float lambda) {
GodotProfileZone("AnimationData::blend");
if (!has_same_tracks(to_data)) { if (!has_same_tracks(to_data)) {
print_error("Cannot blend AnimationData: tracks do not match."); print_error("Cannot blend AnimationData: tracks do not match.");
return; return;
@ -502,7 +504,7 @@ struct BlendTreeGraph {
LocalVector<int> sorted_node_indices = get_sorted_node_indices(); LocalVector<int> sorted_node_indices = get_sorted_node_indices();
Vector<Ref<SyncedAnimationNode>> sorted_nodes; Vector<Ref<SyncedAnimationNode>> sorted_nodes;
Vector<NodeConnectionInfo> old_node_connection_info = node_connection_info; LocalVector<NodeConnectionInfo> old_node_connection_info = node_connection_info;
for (unsigned int i = 0; i < sorted_node_indices.size(); i++) { for (unsigned int i = 0; i < sorted_node_indices.size(); i++) {
int node_index = sorted_node_indices[i]; int node_index = sorted_node_indices[i];
sorted_nodes.push_back(nodes[node_index]); sorted_nodes.push_back(nodes[node_index]);
@ -714,6 +716,8 @@ public:
} }
void activate_inputs(Vector<Ref<SyncedAnimationNode>> input_nodes) override { void activate_inputs(Vector<Ref<SyncedAnimationNode>> input_nodes) override {
GodotProfileZone("SyncedBlendTree::activate_inputs");
tree_graph.nodes[0]->active = true; tree_graph.nodes[0]->active = true;
for (int i = 0; i < tree_graph.nodes.size(); i++) { for (int i = 0; i < tree_graph.nodes.size(); i++) {
const Ref<SyncedAnimationNode> &node = tree_graph.nodes[i]; const Ref<SyncedAnimationNode> &node = tree_graph.nodes[i];
@ -728,6 +732,7 @@ public:
} }
void calculate_sync_track(Vector<Ref<SyncedAnimationNode>> input_nodes) override { void calculate_sync_track(Vector<Ref<SyncedAnimationNode>> input_nodes) override {
GodotProfileZone("SyncedBlendTree::calculate_sync_track");
for (int i = tree_graph.nodes.size() - 1; i > 0; i--) { for (int i = tree_graph.nodes.size() - 1; i > 0; i--) {
const Ref<SyncedAnimationNode> &node = tree_graph.nodes[i]; const Ref<SyncedAnimationNode> &node = tree_graph.nodes[i];
@ -742,6 +747,8 @@ public:
} }
void update_time(double p_delta) override { void update_time(double p_delta) override {
GodotProfileZone("SyncedBlendTree::update_time");
tree_graph.nodes[0]->node_time_info.delta = p_delta; tree_graph.nodes[0]->node_time_info.delta = p_delta;
tree_graph.nodes[0]->node_time_info.position += p_delta; tree_graph.nodes[0]->node_time_info.position += p_delta;
@ -763,6 +770,8 @@ public:
} }
void evaluate(GraphEvaluationContext &context, const LocalVector<AnimationData *> &input_datas, AnimationData &output_data) override { void evaluate(GraphEvaluationContext &context, const LocalVector<AnimationData *> &input_datas, AnimationData &output_data) override {
ZoneScopedN("SyncedBlendTree::evaluate");
for (int i = tree_graph.nodes.size() - 1; i > 0; i--) { for (int i = tree_graph.nodes.size() - 1; i > 0; i--) {
const Ref<SyncedAnimationNode> &node = tree_graph.nodes[i]; const Ref<SyncedAnimationNode> &node = tree_graph.nodes[i];