From bb3a021427f2132f1db62a76eeca2ca4be1601da Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Mon, 12 Sep 2022 16:30:07 +0200 Subject: Fix T101004: Crash when invisible object becomes visible A regression since ac20970bc208 The issue was caused by depsgraph clearing all id->recalc flags wrongly assuming that all IDs are fully evaluated. This change makes it so the depsgraph becomes aware of possibly incompletely evaluated IDs. Differential Revision: https://developer.blender.org/D15946 --- .../blender/depsgraph/intern/builder/deg_builder_nodes.cc | 4 ++++ source/blender/depsgraph/intern/builder/deg_builder_nodes.h | 2 ++ source/blender/depsgraph/intern/depsgraph_tag.cc | 7 +++++++ source/blender/depsgraph/intern/eval/deg_eval_flush.cc | 13 +++++++++++++ source/blender/depsgraph/intern/node/deg_node_id.cc | 1 + source/blender/depsgraph/intern/node/deg_node_id.h | 3 +++ 6 files changed, 30 insertions(+) (limited to 'source') diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc index dcefb5528b2..324197118d2 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc @@ -155,12 +155,14 @@ IDNode *DepsgraphNodeBuilder::add_id_node(ID *id) IDComponentsMask previously_visible_components_mask = 0; uint32_t previous_eval_flags = 0; DEGCustomDataMeshMasks previous_customdata_masks; + int id_invisible_recalc = 0; IDInfo *id_info = id_info_hash_.lookup_default(id->session_uuid, nullptr); if (id_info != nullptr) { id_cow = id_info->id_cow; previously_visible_components_mask = id_info->previously_visible_components_mask; previous_eval_flags = id_info->previous_eval_flags; previous_customdata_masks = id_info->previous_customdata_masks; + id_invisible_recalc = id_info->id_invisible_recalc; /* Tag ID info to not free the CoW ID pointer. */ id_info->id_cow = nullptr; } @@ -168,6 +170,7 @@ IDNode *DepsgraphNodeBuilder::add_id_node(ID *id) id_node->previously_visible_components_mask = previously_visible_components_mask; id_node->previous_eval_flags = previous_eval_flags; id_node->previous_customdata_masks = previous_customdata_masks; + id_node->id_invisible_recalc = id_invisible_recalc; /* NOTE: Zero number of components indicates that ID node was just created. */ const bool is_newly_created = id_node->components.is_empty(); @@ -366,6 +369,7 @@ void DepsgraphNodeBuilder::begin_build() id_info->previously_visible_components_mask = id_node->visible_components_mask; id_info->previous_eval_flags = id_node->eval_flags; id_info->previous_customdata_masks = id_node->customdata_masks; + id_info->id_invisible_recalc = id_node->id_invisible_recalc; BLI_assert(!id_info_hash_.contains(id_node->id_orig_session_uuid)); id_info_hash_.add_new(id_node->id_orig_session_uuid, id_info); id_node->id_cow = nullptr; diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.h b/source/blender/depsgraph/intern/builder/deg_builder_nodes.h index d5ac601ebff..29cca0a8ddd 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.h +++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.h @@ -250,6 +250,8 @@ class DepsgraphNodeBuilder : public DepsgraphBuilder { IDComponentsMask previously_visible_components_mask; /* Special evaluation flag mask from the previous depsgraph. */ uint32_t previous_eval_flags; + /* Recalculation flags which were not evaluated for the ID in the previous depsgraph. */ + int id_invisible_recalc; /* Mesh CustomData mask from the previous depsgraph. */ DEGCustomDataMeshMasks previous_customdata_masks; }; diff --git a/source/blender/depsgraph/intern/depsgraph_tag.cc b/source/blender/depsgraph/intern/depsgraph_tag.cc index cc742b98866..a8c8b4a6538 100644 --- a/source/blender/depsgraph/intern/depsgraph_tag.cc +++ b/source/blender/depsgraph/intern/depsgraph_tag.cc @@ -890,6 +890,13 @@ void DEG_ids_clear_recalc(Depsgraph *depsgraph, const bool backup) } /* Go over all ID nodes, clearing tags. */ for (deg::IDNode *id_node : deg_graph->id_nodes) { + if (!id_node->is_enabled_on_eval) { + id_node->id_invisible_recalc |= id_node->id_cow->recalc; + } + else { + id_node->id_invisible_recalc = 0; + } + if (backup) { id_node->id_cow_recalc_backup |= id_node->id_cow->recalc; } diff --git a/source/blender/depsgraph/intern/eval/deg_eval_flush.cc b/source/blender/depsgraph/intern/eval/deg_eval_flush.cc index 30ee626f0f8..3f42d1a80c1 100644 --- a/source/blender/depsgraph/intern/eval/deg_eval_flush.cc +++ b/source/blender/depsgraph/intern/eval/deg_eval_flush.cc @@ -31,6 +31,7 @@ #include "intern/debug/deg_debug.h" #include "intern/depsgraph.h" #include "intern/depsgraph_relation.h" +#include "intern/depsgraph_tag.h" #include "intern/depsgraph_type.h" #include "intern/depsgraph_update.h" #include "intern/node/deg_node.h" @@ -99,6 +100,18 @@ inline void flush_prepare(Depsgraph *graph) inline void flush_schedule_entrypoints(Depsgraph *graph, FlushQueue *queue) { + /* Something changed in the scene, so re-tag IDs with flags which were previously ignored due to + * ID being hidden. This will ensure the ID is properly evaluated when it becomes visible. */ + for (IDNode *node : graph->id_nodes) { + if (node->id_invisible_recalc) { + graph_id_tag_update(graph->bmain, + graph, + node->id_orig, + node->id_invisible_recalc, + DEG_UPDATE_SOURCE_VISIBILITY); + } + } + for (OperationNode *op_node : graph->entry_tags) { queue->push_back(op_node); op_node->scheduled = true; diff --git a/source/blender/depsgraph/intern/node/deg_node_id.cc b/source/blender/depsgraph/intern/node/deg_node_id.cc index 735d606ac9e..9a7d27808be 100644 --- a/source/blender/depsgraph/intern/node/deg_node_id.cc +++ b/source/blender/depsgraph/intern/node/deg_node_id.cc @@ -75,6 +75,7 @@ void IDNode::init(const ID *id, const char *UNUSED(subdata)) has_base = false; is_user_modified = false; id_cow_recalc_backup = 0; + id_invisible_recalc = 0; visible_components_mask = 0; previously_visible_components_mask = 0; diff --git a/source/blender/depsgraph/intern/node/deg_node_id.h b/source/blender/depsgraph/intern/node/deg_node_id.h index 7f0a656cb8d..e9bbc816907 100644 --- a/source/blender/depsgraph/intern/node/deg_node_id.h +++ b/source/blender/depsgraph/intern/node/deg_node_id.h @@ -123,6 +123,9 @@ struct IDNode : public Node { /* Accumulate recalc flags from multiple update passes. */ int id_cow_recalc_backup; + /* Flags which components were not evaluated due to ID being invisible. */ + int id_invisible_recalc; + IDComponentsMask visible_components_mask; IDComponentsMask previously_visible_components_mask; -- cgit v1.2.3