diff options
Diffstat (limited to 'source/blender/depsgraph/intern')
3 files changed, 77 insertions, 35 deletions
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_key.h b/source/blender/depsgraph/intern/builder/deg_builder_key.h index cbb0daa4fc9..4f8b2dc9f8f 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_key.h +++ b/source/blender/depsgraph/intern/builder/deg_builder_key.h @@ -9,6 +9,9 @@ #include "intern/builder/deg_builder_rna.h" #include "intern/depsgraph_type.h" +#include "intern/node/deg_node_component.h" +#include "intern/node/deg_node_id.h" +#include "intern/node/deg_node_operation.h" #include "DNA_ID.h" @@ -120,6 +123,12 @@ struct OperationKey { { } + OperationKey(OperationKey &&other) noexcept = default; + OperationKey &operator=(OperationKey &&other) = default; + + OperationKey(const OperationKey &other) = default; + OperationKey &operator=(const OperationKey &other) = default; + string identifier() const; const ID *id = nullptr; @@ -130,6 +139,53 @@ struct OperationKey { int name_tag = -1; }; +/* Similar to the the OperationKey but does not contain external references, which makes it + * suitable to identify operations even after the original database or graph was destroyed. + * The downside of this key over the OperationKey is that it performs string allocation upon + * the key construction. */ +struct PersistentOperationKey : public OperationKey { + /* Create the key which identifies the given operation node. */ + PersistentOperationKey(const OperationNode *operation_node) + { + const ComponentNode *component_node = operation_node->owner; + const IDNode *id_node = component_node->owner; + + /* Copy names over to our object, so that the key stays valid even after the `operation_node` + * is destroyed.*/ + component_name_storage_ = component_node->name; + name_storage_ = operation_node->name; + + /* Assign fields used by the OperationKey API. */ + id = id_node->id_orig; + component_type = component_node->type; + component_name = component_name_storage_.c_str(); + opcode = operation_node->opcode; + name = name_storage_.c_str(); + name_tag = operation_node->name_tag; + } + + PersistentOperationKey(PersistentOperationKey &&other) noexcept : OperationKey(other) + { + component_name_storage_ = std::move(other.component_name_storage_); + name_storage_ = std::move(other.name_storage_); + + /* Re-assign pointers to the strings. + * This is needed because string content can actually change address if the string uses the + * small string optimization. */ + component_name = component_name_storage_.c_str(); + name = name_storage_.c_str(); + } + + PersistentOperationKey &operator=(PersistentOperationKey &&other) = delete; + + PersistentOperationKey(const PersistentOperationKey &other) = delete; + PersistentOperationKey &operator=(const PersistentOperationKey &other) = delete; + + private: + string component_name_storage_; + string name_storage_; +}; + struct RNAPathKey { RNAPathKey(ID *id, const char *path, RNAPointerSource source); RNAPathKey(ID *id, const PointerRNA &ptr, PropertyRNA *prop, RNAPointerSource source); diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc index db89a60f81e..f95c0700a47 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc @@ -104,6 +104,7 @@ #include "SEQ_sequencer.h" #include "intern/builder/deg_builder.h" +#include "intern/builder/deg_builder_key.h" #include "intern/builder/deg_builder_rna.h" #include "intern/depsgraph.h" #include "intern/depsgraph_tag.h" @@ -342,6 +343,12 @@ OperationNode *DepsgraphNodeBuilder::find_operation_node( return find_operation_node(id, comp_type, "", opcode, name, name_tag); } +OperationNode *DepsgraphNodeBuilder::find_operation_node(const OperationKey &key) +{ + return find_operation_node( + key.id, key.component_type, key.component_name, key.opcode, key.name, key.name_tag); +} + ID *DepsgraphNodeBuilder::get_cow_id(const ID *id_orig) const { return graph_->get_cow_id(id_orig); @@ -385,17 +392,8 @@ void DepsgraphNodeBuilder::begin_build() id_node->id_cow = nullptr; } - for (OperationNode *op_node : graph_->entry_tags) { - ComponentNode *comp_node = op_node->owner; - IDNode *id_node = comp_node->owner; - - SavedEntryTag entry_tag; - entry_tag.id_orig = id_node->id_orig; - entry_tag.component_type = comp_node->type; - entry_tag.opcode = op_node->opcode; - entry_tag.name = op_node->name; - entry_tag.name_tag = op_node->name_tag; - saved_entry_tags_.append(entry_tag); + for (const OperationNode *op_node : graph_->entry_tags) { + saved_entry_tags_.append_as(op_node); } /* Make sure graph has no nodes left from previous state. */ @@ -513,23 +511,15 @@ void DepsgraphNodeBuilder::update_invalid_cow_pointers() void DepsgraphNodeBuilder::tag_previously_tagged_nodes() { - for (const SavedEntryTag &entry_tag : saved_entry_tags_) { - IDNode *id_node = find_id_node(entry_tag.id_orig); - if (id_node == nullptr) { - continue; - } - ComponentNode *comp_node = id_node->find_component(entry_tag.component_type); - if (comp_node == nullptr) { - continue; - } - OperationNode *op_node = comp_node->find_operation( - entry_tag.opcode, entry_tag.name.c_str(), entry_tag.name_tag); - if (op_node == nullptr) { + for (const OperationKey &operation_key : saved_entry_tags_) { + OperationNode *operation_node = find_operation_node(operation_key); + if (operation_node == nullptr) { continue; } + /* Since the tag is coming from a saved copy of entry tags, this means * that originally node was explicitly tagged for user update. */ - op_node->tag_update(graph_, DEG_UPDATE_SOURCE_USER_EDIT); + operation_node->tag_update(graph_, DEG_UPDATE_SOURCE_USER_EDIT); } } diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.h b/source/blender/depsgraph/intern/builder/deg_builder_nodes.h index a749409b3ab..a8efe8fca9f 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.h +++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.h @@ -8,6 +8,7 @@ #pragma once #include "intern/builder/deg_builder.h" +#include "intern/builder/deg_builder_key.h" #include "intern/builder/deg_builder_map.h" #include "intern/depsgraph_type.h" #include "intern/node/deg_node_id.h" @@ -56,6 +57,7 @@ struct ComponentNode; struct Depsgraph; class DepsgraphBuilderCache; struct IDNode; +struct OperationKey; struct OperationNode; struct TimeSourceNode; @@ -151,6 +153,8 @@ class DepsgraphNodeBuilder : public DepsgraphBuilder { const char *name = "", int name_tag = -1); + OperationNode *find_operation_node(const OperationKey &key); + virtual void build_id(ID *id); /* Build function for ID types that do not need their own build_xxx() function. */ @@ -259,17 +263,9 @@ class DepsgraphNodeBuilder : public DepsgraphBuilder { }; protected: - /* Allows to identify an operation which was tagged for update at the time - * relations are being updated. We can not reuse operation node pointer - * since it will change during dependency graph construction. */ - struct SavedEntryTag { - ID *id_orig; - NodeType component_type; - OperationCode opcode; - string name; - int name_tag; - }; - Vector<SavedEntryTag> saved_entry_tags_; + /* Entry tags from the previous state of the dependency graph. + * Stored before the graph is re-created so that they can be transferred over. */ + Vector<PersistentOperationKey> saved_entry_tags_; struct BuilderWalkUserData { DepsgraphNodeBuilder *builder; |