From 0251db1447d4cea3b0f7bfff9fb8cd751c17df87 Mon Sep 17 00:00:00 2001 From: Omar Emara Date: Tue, 9 Jul 2024 16:10:58 +0200 Subject: [PATCH] Fix #124335: Viewport compositor crash upon scene change The viewport compositor crashes when the scene is changed in some situations. That's because the viewport compositor tries to use node tree data that was freed in the last depsgraph update, while it should have invalidate those references based on the same depsgraph update. The source of this issue is in the depsgraph itself. In particular, when the depsgraph evaluation happens in two passes, the ID recalculate flags are backed up for every pass then restored at the end of all passes, however, this doesn't happen for the ID Type Update table. So whenever evaluations happen in two passes, changes will not be propagated to engines that require those information, like the viewport compositor engine in that particular case. To fix this, we backup and restore the ID Type Update table in a similar manner to the ID recalculate flags. Fixes #107235, #124335, #116142. Pull Request: https://projects.blender.org/blender/blender/pulls/124409 --- source/blender/depsgraph/intern/depsgraph.cc | 1 + source/blender/depsgraph/intern/depsgraph.hh | 2 ++ source/blender/depsgraph/intern/depsgraph_tag.cc | 16 ++++++++++++++++ 3 files changed, 19 insertions(+) diff --git a/source/blender/depsgraph/intern/depsgraph.cc b/source/blender/depsgraph/intern/depsgraph.cc index 0c05659668d..8705831c88f 100644 --- a/source/blender/depsgraph/intern/depsgraph.cc +++ b/source/blender/depsgraph/intern/depsgraph.cc @@ -67,6 +67,7 @@ Depsgraph::Depsgraph(Main *bmain, Scene *scene, ViewLayer *view_layer, eEvaluati { BLI_spin_init(&lock); memset(id_type_updated, 0, sizeof(id_type_updated)); + memset(id_type_updated_backup, 0, sizeof(id_type_updated_backup)); memset(id_type_exist, 0, sizeof(id_type_exist)); memset(physics_relations, 0, sizeof(physics_relations)); diff --git a/source/blender/depsgraph/intern/depsgraph.hh b/source/blender/depsgraph/intern/depsgraph.hh index 0bc8de4c969..dd373f93136 100644 --- a/source/blender/depsgraph/intern/depsgraph.hh +++ b/source/blender/depsgraph/intern/depsgraph.hh @@ -108,6 +108,8 @@ struct Depsgraph { /* Indicates which ID types were updated. */ char id_type_updated[INDEX_ID_MAX]; + /* Accumulate id type updates from multiple update passes. */ + char id_type_updated_backup[INDEX_ID_MAX]; /* Indicates type of IDs present in the depsgraph. */ char id_type_exist[INDEX_ID_MAX]; diff --git a/source/blender/depsgraph/intern/depsgraph_tag.cc b/source/blender/depsgraph/intern/depsgraph_tag.cc index 1f4d9c7ac8a..36615e00d7d 100644 --- a/source/blender/depsgraph/intern/depsgraph_tag.cc +++ b/source/blender/depsgraph/intern/depsgraph_tag.cc @@ -14,6 +14,7 @@ #include /* required for memset */ #include +#include "BLI_index_range.hh" #include "BLI_math_bits.h" #include "BLI_task.h" #include "BLI_utildefines.h" @@ -968,6 +969,14 @@ void DEG_ids_clear_recalc(Depsgraph *depsgraph, const bool backup) deg_graph_clear_id_recalc_flags(id_node->id_orig); } } + + if (backup) { + for (const int64_t i : blender::IndexRange(INDEX_ID_MAX)) { + if (deg_graph->id_type_updated[i] != 0) { + deg_graph->id_type_updated_backup[i] = 1; + } + } + } memset(deg_graph->id_type_updated, 0, sizeof(deg_graph->id_type_updated)); } @@ -979,4 +988,11 @@ void DEG_ids_restore_recalc(Depsgraph *depsgraph) id_node->id_cow->recalc |= id_node->id_cow_recalc_backup; id_node->id_cow_recalc_backup = 0; } + + for (const int64_t i : blender::IndexRange(INDEX_ID_MAX)) { + if (deg_graph->id_type_updated_backup[i] != 0) { + deg_graph->id_type_updated[i] = 1; + } + } + memset(deg_graph->id_type_updated_backup, 0, sizeof(deg_graph->id_type_updated_backup)); }