From cbd6c8d5613c0c942414926240cf2c409d83243b Mon Sep 17 00:00:00 2001 From: lawnjelly Date: Fri, 9 May 2025 20:47:19 +0100 Subject: [PATCH] `SceneTreeFTI` faster access to `Node` children --- scene/main/node.h | 2 ++ scene/main/scene_tree_fti.cpp | 15 +++++++++++---- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/scene/main/node.h b/scene/main/node.h index 21389dcc3f..5a7988b64a 100644 --- a/scene/main/node.h +++ b/scene/main/node.h @@ -47,6 +47,8 @@ SAFE_NUMERIC_TYPE_PUN_GUARANTEES(uint32_t) class Node : public Object { GDCLASS(Node, Object); + friend class SceneTreeFTI; + protected: // During group processing, these are thread-safe. // Outside group processing, these avoid the cost of sync by working as plain primitive types. diff --git a/scene/main/scene_tree_fti.cpp b/scene/main/scene_tree_fti.cpp index fa71a45d8e..4a9ccb005a 100644 --- a/scene/main/scene_tree_fti.cpp +++ b/scene/main/scene_tree_fti.cpp @@ -318,12 +318,19 @@ void SceneTreeFTI::_update_dirty_nodes(Node *p_node, uint32_t p_current_frame, f return; } + // Temporary direct access to children cache for speed. + // Maybe replaced later by a more generic fast access method + // for children. + p_node->_update_children_cache(); + Span children = p_node->data.children_cache.span(); + uint32_t num_children = children.size(); + // Not a Node3D. // Could be e.g. a viewport or something // so we should still recurse to children. if (!s) { - for (int n = 0; n < p_node->get_child_count(); n++) { - _update_dirty_nodes(p_node->get_child(n), p_current_frame, p_interpolation_fraction, p_active, nullptr, p_depth + 1); + for (uint32_t n = 0; n < num_children; n++) { + _update_dirty_nodes(children.ptr()[n], p_current_frame, p_interpolation_fraction, p_active, nullptr, p_depth + 1); } return; } @@ -424,8 +431,8 @@ void SceneTreeFTI::_update_dirty_nodes(Node *p_node, uint32_t p_current_frame, f s->_clear_dirty_bits(Node3D::DIRTY_GLOBAL_INTERPOLATED_TRANSFORM); // Recurse to children. - for (int n = 0; n < p_node->get_child_count(); n++) { - _update_dirty_nodes(p_node->get_child(n), p_current_frame, p_interpolation_fraction, p_active, s->data.fti_global_xform_interp_set ? &s->data.global_transform_interpolated : &s->data.global_transform, p_depth + 1); + for (uint32_t n = 0; n < num_children; n++) { + _update_dirty_nodes(children.ptr()[n], p_current_frame, p_interpolation_fraction, p_active, s->data.fti_global_xform_interp_set ? &s->data.global_transform_interpolated : &s->data.global_transform, p_depth + 1); } }