Skip to content

Commit b7caebc

Browse files
committed
Merge pull request #107175 from lawnjelly/scenetreefti_fix_show_updates
`SceneTreeFTI` - Fix `force_update` flag getting out of sync with invisible nodes
2 parents da05a6b + a7b7d96 commit b7caebc

File tree

1 file changed

+18
-7
lines changed

1 file changed

+18
-7
lines changed

scene/main/scene_tree_fti.cpp

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -291,7 +291,12 @@ void SceneTreeFTI::_create_depth_lists() {
291291
}
292292
#endif
293293

294+
// Prevent being added to the dest_list twice when on
295+
// the frame_xform_list AND the frame_xform_list_forced.
294296
if ((l == 0) && s->data.fti_frame_xform_force_update) {
297+
#ifdef GODOT_SCENE_TREE_FTI_EXTRA_CHECKS
298+
DEV_ASSERT(data.frame_xform_list_forced.find(s) != -1);
299+
#endif
295300
continue;
296301
}
297302

@@ -520,14 +525,14 @@ void SceneTreeFTI::_update_dirty_nodes(Node *p_node, uint32_t p_current_half_fra
520525

521526
if (p_active) {
522527
#ifdef GODOT_SCENE_TREE_FTI_PRINT_TREE
523-
bool dirty = s->data.dirty & Node3D::DIRTY_GLOBAL_INTERPOLATED;
528+
bool dirty = s->_test_dirty_bits(Node3D::DIRTY_GLOBAL_INTERPOLATED_TRANSFORM);
524529

525530
if (data.periodic_debug_log && !data.use_optimized_traversal_method && !data.frame_start) {
526531
String sz;
527532
for (int n = 0; n < p_depth; n++) {
528533
sz += "\t";
529534
}
530-
print_line(sz + p_node->get_name() + (dirty ? " DIRTY" : "") + (s->get_transform() == Transform() ? "\t[IDENTITY]" : ""));
535+
print_line(sz + p_node->get_name() + (dirty ? " DIRTY" : "") + (s->get_transform() == Transform3D() ? "\t[IDENTITY]" : ""));
531536
}
532537
#endif
533538

@@ -575,11 +580,6 @@ void SceneTreeFTI::_update_dirty_nodes(Node *p_node, uint32_t p_current_half_fra
575580
// Upload to RenderingServer the interpolated global xform.
576581
s->fti_update_servers_xform();
577582

578-
// Only do this at most for one frame,
579-
// it is used to catch objects being removed from the tick lists
580-
// that have a deferred frame update.
581-
s->data.fti_frame_xform_force_update = false;
582-
583583
// Ensure branches are only processed once on each traversal.
584584
s->data.fti_processed = true;
585585

@@ -719,6 +719,17 @@ void SceneTreeFTI::frame_update(Node *p_root, bool p_frame_start) {
719719

720720
#endif // not GODOT_SCENE_TREE_FTI_VERIFY
721721

722+
// In theory we could clear the `force_update` flags from the nodes in the traversal.
723+
// The problem is that hidden nodes are not recursed into, therefore the flags would
724+
// never get cleared and could get out of sync with the forced list.
725+
// So instead we are clearing them here manually.
726+
// This is not ideal in terms of cache coherence so perhaps another method can be
727+
// explored in future.
728+
uint32_t forced_list_size = data.frame_xform_list_forced.size();
729+
for (uint32_t n = 0; n < forced_list_size; n++) {
730+
Node3D *s = data.frame_xform_list_forced[n];
731+
s->data.fti_frame_xform_force_update = false;
732+
}
722733
data.frame_xform_list_forced.clear();
723734

724735
if (!p_frame_start && data.periodic_debug_log) {

0 commit comments

Comments
 (0)