From 7a2d04a5c432f560ec8ddafad0c0fafa9b3f7e0d Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 19 Jan 2024 15:21:53 +0100 Subject: [PATCH] Fix #117335: Slow selection in scene with drivers Change parameters tagging from implicit based on the copy-on-write to more explicit, allowing to ignore tagging of parameters component for changes which do not affect drivers. There is still implicit parameters tagging based on tags for geometry or transform components to avoid making changes in too many places of Blender. Should be no functional changes, only expecting better performance. Pull Request: https://projects.blender.org/blender/blender/pulls/117336 --- .../intern/builder/deg_builder_relations.cc | 9 +---- .../blender/depsgraph/intern/depsgraph_tag.cc | 36 +++++++++++++++++++ source/blender/makesrna/intern/rna_access.cc | 2 +- 3 files changed, 38 insertions(+), 9 deletions(-) diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc index 3145c204bc9..bb7927159df 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc @@ -3427,19 +3427,12 @@ void DepsgraphRelationBuilder::build_copy_on_write_relations(IDNode *id_node) rel_flag &= ~RELATION_FLAG_NO_FLUSH; } /* Notes on exceptions: - * - Parameters component is where drivers are living. Changing any - * of the (custom) properties in the original datablock (even the - * ones which do not imply other component update) need to make - * sure drivers are properly updated. - * This way, for example, changing ID property will properly poke - * all drivers to be updated. - * * - View layers have cached array of bases in them, which is not * copied by copy-on-write, and not preserved. PROBABLY it is better * to preserve that cache in copy-on-write, but for the time being * we allow flush to layer collections component which will ensure * that cached array of bases exists and is up-to-date. */ - if (ELEM(comp_node->type, NodeType::PARAMETERS, NodeType::LAYER_COLLECTIONS)) { + if (ELEM(comp_node->type, NodeType::LAYER_COLLECTIONS)) { rel_flag &= ~RELATION_FLAG_NO_FLUSH; } /* Compatibility with the legacy tagging: groups are only tagged for Copy-on-Write when their diff --git a/source/blender/depsgraph/intern/depsgraph_tag.cc b/source/blender/depsgraph/intern/depsgraph_tag.cc index 6624f21f16f..385a53b0bdf 100644 --- a/source/blender/depsgraph/intern/depsgraph_tag.cc +++ b/source/blender/depsgraph/intern/depsgraph_tag.cc @@ -507,6 +507,41 @@ void deg_graph_node_tag_zero(Main *bmain, deg_graph_id_tag_legacy_compat(bmain, graph, id, (IDRecalcFlag)0, update_source); } +/* Implicit tagging of the parameters component on other changes. + * + * This takes care of ensuring that if a change made in C side on parameters which affect, + * say, geometry and explicit tag only done for geometry, parameters are also tagged to give + * drivers a chance to re-evaluate for the new values. */ +void deg_graph_tag_parameters_if_needed(Main *bmain, + Depsgraph *graph, + ID *id, + IDNode *id_node, + const uint flags, + const eUpdateSource update_source) +{ + if (flags == 0) { + /* Tagging for 0 flags is handled in deg_graph_node_tag_zero(), and parameters are handled + * there as well. */ + return; + } + + if (flags & ID_RECALC_PARAMETERS) { + /* Parameters are already tagged for update explicitly, no need to run extra logic here. */ + return; + } + + /* Clear flags which are known to not affect parameters usable by drivers. */ + const uint clean_flags = flags & + ~(ID_RECALC_COPY_ON_WRITE | ID_RECALC_SELECT | ID_RECALC_BASE_FLAGS); + + if (clean_flags == 0) { + /* Changes are limited to only things which are not usable by drivers. */ + return; + } + + graph_id_tag_update_single_flag(bmain, graph, id, id_node, ID_RECALC_PARAMETERS, update_source); +} + void graph_tag_on_visible_update(Depsgraph *graph, const bool do_time) { graph->need_tag_id_on_graph_visibility_update = true; @@ -709,6 +744,7 @@ void graph_id_tag_update( graph_id_tag_update_single_flag( bmain, graph, id, id_node, ID_RECALC_POINT_CACHE, update_source); } + deg_graph_tag_parameters_if_needed(bmain, graph, id, id_node, flags, update_source); } } // namespace blender::deg diff --git a/source/blender/makesrna/intern/rna_access.cc b/source/blender/makesrna/intern/rna_access.cc index 112643da487..d272293df0d 100644 --- a/source/blender/makesrna/intern/rna_access.cc +++ b/source/blender/makesrna/intern/rna_access.cc @@ -2276,7 +2276,7 @@ static void rna_property_update( if (ptr->owner_id != nullptr && ((prop->flag & PROP_NO_DEG_UPDATE) == 0)) { const short id_type = GS(ptr->owner_id->name); if (ID_TYPE_IS_COW(id_type)) { - DEG_id_tag_update(ptr->owner_id, ID_RECALC_COPY_ON_WRITE); + DEG_id_tag_update(ptr->owner_id, ID_RECALC_COPY_ON_WRITE | ID_RECALC_PARAMETERS); } } /* End message bus. */