diff options
Diffstat (limited to 'source/blender/depsgraph/intern')
40 files changed, 848 insertions, 477 deletions
diff --git a/source/blender/depsgraph/intern/builder/deg_builder.cc b/source/blender/depsgraph/intern/builder/deg_builder.cc index 5353f71685c..16510d5f9a6 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder.cc @@ -13,6 +13,7 @@ #include "DNA_anim_types.h" #include "DNA_armature_types.h" #include "DNA_layer_types.h" +#include "DNA_modifier_types.h" #include "DNA_object_types.h" #include "BLI_stack.h" @@ -95,6 +96,24 @@ bool DepsgraphBuilder::is_object_visibility_animated(const Object *object) return cache_->isPropertyAnimated(&object->id, property_id); } +bool DepsgraphBuilder::is_modifier_visibility_animated(const Object *object, + const ModifierData *modifier) +{ + AnimatedPropertyID property_id; + if (graph_->mode == DAG_EVAL_VIEWPORT) { + property_id = AnimatedPropertyID( + &object->id, &RNA_Modifier, (void *)modifier, "show_viewport"); + } + else if (graph_->mode == DAG_EVAL_RENDER) { + property_id = AnimatedPropertyID(&object->id, &RNA_Modifier, (void *)modifier, "show_render"); + } + else { + BLI_assert_msg(0, "Unknown evaluation mode."); + return false; + } + return cache_->isPropertyAnimated(&object->id, property_id); +} + bool DepsgraphBuilder::check_pchan_has_bbone(const Object *object, const bPoseChannel *pchan) { BLI_assert(object->type == OB_ARMATURE); @@ -159,6 +178,9 @@ void deg_graph_build_finalize(Main *bmain, Depsgraph *graph) if (GS(id_orig->name) == ID_OB) { flag |= ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY; } + if (GS(id_orig->name) == ID_NT) { + flag |= ID_RECALC_NTREE_OUTPUT; + } } /* Restore recalc flags from original ID, which could possibly contain recalc flags set by * an operator and then were carried on by the undo system. */ diff --git a/source/blender/depsgraph/intern/builder/deg_builder.h b/source/blender/depsgraph/intern/builder/deg_builder.h index c44e5fd5f4d..5d043f1fd3a 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder.h +++ b/source/blender/depsgraph/intern/builder/deg_builder.h @@ -10,6 +10,7 @@ struct Base; struct ID; struct Main; +struct ModifierData; struct Object; struct bPoseChannel; @@ -25,6 +26,7 @@ class DepsgraphBuilder { virtual bool need_pull_base_into_graph(const Base *base); virtual bool is_object_visibility_animated(const Object *object); + virtual bool is_modifier_visibility_animated(const Object *object, const ModifierData *modifier); virtual bool check_pchan_has_bbone(const Object *object, const bPoseChannel *pchan); virtual bool check_pchan_has_bbone_segments(const Object *object, const bPoseChannel *pchan); diff --git a/source/blender/depsgraph/intern/builder/deg_builder_cache.cc b/source/blender/depsgraph/intern/builder/deg_builder_cache.cc index 6474f853390..a9f8d1f73d3 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_cache.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_cache.cc @@ -15,6 +15,8 @@ #include "BKE_animsys.h" +#include "RNA_path.h" + namespace blender::deg { /* Animated property storage. */ @@ -57,9 +59,9 @@ bool operator==(const AnimatedPropertyID &a, const AnimatedPropertyID &b) uint64_t AnimatedPropertyID::hash() const { - uintptr_t ptr1 = (uintptr_t)data; - uintptr_t ptr2 = (uintptr_t)property_rna; - return static_cast<uint64_t>(((ptr1 >> 4) * 33) ^ (ptr2 >> 4)); + uintptr_t ptr1 = uintptr_t(data); + uintptr_t ptr2 = uintptr_t(property_rna); + return uint64_t(((ptr1 >> 4) * 33) ^ (ptr2 >> 4)); } namespace { diff --git a/source/blender/depsgraph/intern/builder/deg_builder_cycle.cc b/source/blender/depsgraph/intern/builder/deg_builder_cycle.cc index 8ba6c840a59..7f3c59f1522 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_cycle.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_cycle.cc @@ -60,7 +60,7 @@ struct CyclesSolverState { inline void set_node_visited_state(Node *node, eCyclicCheckVisitedState state) { - node->custom_flags = (node->custom_flags & ~0x3) | (int)state; + node->custom_flags = (node->custom_flags & ~0x3) | int(state); } inline eCyclicCheckVisitedState get_node_visited_state(Node *node) diff --git a/source/blender/depsgraph/intern/builder/deg_builder_key.cc b/source/blender/depsgraph/intern/builder/deg_builder_key.cc new file mode 100644 index 00000000000..741c415b5cd --- /dev/null +++ b/source/blender/depsgraph/intern/builder/deg_builder_key.cc @@ -0,0 +1,96 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later + * Copyright 2013 Blender Foundation. All rights reserved. */ + +/** \file + * \ingroup depsgraph + * + * Methods for constructing depsgraph + */ + +#include "intern/builder/deg_builder_key.h" + +#include "RNA_path.h" + +namespace blender::deg { + +/* -------------------------------------------------------------------- */ +/** \name Time source + * \{ */ + +string TimeSourceKey::identifier() const +{ + return string("TimeSourceKey"); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Component + * \{ */ + +string ComponentKey::identifier() const +{ + const char *idname = (id) ? id->name : "<None>"; + string result = string("ComponentKey("); + result += idname; + result += ", " + string(nodeTypeAsString(type)); + if (name[0] != '\0') { + result += ", '" + string(name) + "'"; + } + result += ')'; + return result; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Operation + * \{ */ + +string OperationKey::identifier() const +{ + string result = string("OperationKey("); + result += "type: " + string(nodeTypeAsString(component_type)); + result += ", component name: '" + string(component_name) + "'"; + result += ", operation code: " + string(operationCodeAsString(opcode)); + if (name[0] != '\0') { + result += ", '" + string(name) + "'"; + } + result += ")"; + return result; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name RNA path + * \{ */ + +RNAPathKey::RNAPathKey(ID *id, const char *path, RNAPointerSource source) : id(id), source(source) +{ + /* Create ID pointer for root of path lookup. */ + PointerRNA id_ptr; + RNA_id_pointer_create(id, &id_ptr); + /* Try to resolve path. */ + int index; + if (!RNA_path_resolve_full(&id_ptr, path, &ptr, &prop, &index)) { + ptr = PointerRNA_NULL; + prop = nullptr; + } +} + +RNAPathKey::RNAPathKey(ID *id, const PointerRNA &ptr, PropertyRNA *prop, RNAPointerSource source) + : id(id), ptr(ptr), prop(prop), source(source) +{ +} + +string RNAPathKey::identifier() const +{ + const char *id_name = (id) ? id->name : "<No ID>"; + const char *prop_name = (prop) ? RNA_property_identifier(prop) : "<No Prop>"; + return string("RnaPathKey(") + "id: " + id_name + ", prop: '" + prop_name + "')"; +} + +/** \} */ + +} // namespace blender::deg diff --git a/source/blender/depsgraph/intern/builder/deg_builder_key.h b/source/blender/depsgraph/intern/builder/deg_builder_key.h new file mode 100644 index 00000000000..4f8b2dc9f8f --- /dev/null +++ b/source/blender/depsgraph/intern/builder/deg_builder_key.h @@ -0,0 +1,201 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later + * Copyright 2013 Blender Foundation. All rights reserved. */ + +/** \file + * \ingroup depsgraph + */ + +#pragma once + +#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" + +#include "RNA_access.h" +#include "RNA_types.h" + +struct ID; +struct PropertyRNA; + +namespace blender::deg { + +struct TimeSourceKey { + TimeSourceKey() = default; + + string identifier() const; +}; + +struct ComponentKey { + ComponentKey() = default; + + inline ComponentKey(const ID *id, NodeType type, const char *name = "") + : id(id), type(type), name(name) + { + } + + string identifier() const; + + const ID *id = nullptr; + NodeType type = NodeType::UNDEFINED; + const char *name = ""; +}; + +struct OperationKey { + OperationKey() = default; + + inline OperationKey(const ID *id, NodeType component_type, const char *name, int name_tag = -1) + : id(id), + component_type(component_type), + component_name(""), + opcode(OperationCode::OPERATION), + name(name), + name_tag(name_tag) + { + } + + OperationKey(const ID *id, + NodeType component_type, + const char *component_name, + const char *name, + int name_tag) + : id(id), + component_type(component_type), + component_name(component_name), + opcode(OperationCode::OPERATION), + name(name), + name_tag(name_tag) + { + } + + OperationKey(const ID *id, NodeType component_type, OperationCode opcode) + : id(id), + component_type(component_type), + component_name(""), + opcode(opcode), + name(""), + name_tag(-1) + { + } + + OperationKey(const ID *id, + NodeType component_type, + const char *component_name, + OperationCode opcode) + : id(id), + component_type(component_type), + component_name(component_name), + opcode(opcode), + name(""), + name_tag(-1) + { + } + + OperationKey(const ID *id, + NodeType component_type, + OperationCode opcode, + const char *name, + int name_tag = -1) + : id(id), + component_type(component_type), + component_name(""), + opcode(opcode), + name(name), + name_tag(name_tag) + { + } + + OperationKey(const ID *id, + NodeType component_type, + const char *component_name, + OperationCode opcode, + const char *name, + int name_tag = -1) + : id(id), + component_type(component_type), + component_name(component_name), + opcode(opcode), + name(name), + name_tag(name_tag) + { + } + + 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; + NodeType component_type = NodeType::UNDEFINED; + const char *component_name = ""; + OperationCode opcode = OperationCode::OPERATION; + const char *name = ""; + 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); + + string identifier() const; + + ID *id; + PointerRNA ptr; + PropertyRNA *prop; + RNAPointerSource source; +}; + +} // namespace blender::deg diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc index 4cbb2ce7060..c84852788fd 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc @@ -93,6 +93,7 @@ #include "BKE_world.h" #include "RNA_access.h" +#include "RNA_path.h" #include "RNA_prototypes.h" #include "RNA_types.h" @@ -103,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" @@ -207,7 +209,7 @@ IDNode *DepsgraphNodeBuilder::add_id_node(ID *id) return id_node; } -IDNode *DepsgraphNodeBuilder::find_id_node(ID *id) +IDNode *DepsgraphNodeBuilder::find_id_node(const ID *id) { return graph_->find_id_node(id); } @@ -227,6 +229,17 @@ ComponentNode *DepsgraphNodeBuilder::add_component_node(ID *id, return comp_node; } +ComponentNode *DepsgraphNodeBuilder::find_component_node(const ID *id, + const NodeType comp_type, + const char *comp_name) +{ + IDNode *id_node = find_id_node(id); + if (id_node == nullptr) { + return nullptr; + } + return id_node->find_component(comp_type, comp_name); +} + OperationNode *DepsgraphNodeBuilder::add_operation_node(ComponentNode *comp_node, OperationCode opcode, const DepsEvalOperationCb &op, @@ -310,23 +323,32 @@ bool DepsgraphNodeBuilder::has_operation_node(ID *id, return find_operation_node(id, comp_type, comp_name, opcode, name, name_tag) != nullptr; } -OperationNode *DepsgraphNodeBuilder::find_operation_node(ID *id, +OperationNode *DepsgraphNodeBuilder::find_operation_node(const ID *id, NodeType comp_type, const char *comp_name, OperationCode opcode, const char *name, int name_tag) { - ComponentNode *comp_node = add_component_node(id, comp_type, comp_name); + ComponentNode *comp_node = find_component_node(id, comp_type, comp_name); + if (comp_node == nullptr) { + return nullptr; + } return comp_node->find_operation(opcode, name, name_tag); } OperationNode *DepsgraphNodeBuilder::find_operation_node( - ID *id, NodeType comp_type, OperationCode opcode, const char *name, int name_tag) + const ID *id, NodeType comp_type, OperationCode opcode, const char *name, int name_tag) { 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); @@ -370,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. */ @@ -440,6 +453,11 @@ static int foreach_id_cow_detect_need_for_update_callback(LibraryIDLinkCallbackD if (id == nullptr) { return IDWALK_RET_NOP; } + if (!ID_TYPE_IS_COW(GS(id->name))) { + /* No need to go further if the id never had a cow copy in the depsgraph. This function is + * only concerned with keeping the mapping between original and COW ids intact. */ + return IDWALK_RET_NOP; + } DepsgraphNodeBuilder *builder = static_cast<DepsgraphNodeBuilder *>(cb_data->user_data); ID *id_cow_self = cb_data->id_self; @@ -498,23 +516,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); } } @@ -768,11 +778,7 @@ void DepsgraphNodeBuilder::build_object(int base_index, build_object(-1, object->parent, DEG_ID_LINKED_INDIRECTLY, is_visible); } /* Modifiers. */ - if (object->modifiers.first != nullptr) { - BuilderWalkUserData data; - data.builder = this; - BKE_modifiers_foreach_ID_link(object, modifier_walk, &data); - } + build_object_modifiers(object); /* Grease Pencil Modifiers. */ if (object->greasepencil_modifiers.first != nullptr) { BuilderWalkUserData data; @@ -876,6 +882,44 @@ void DepsgraphNodeBuilder::build_object_instance_collection(Object *object, bool is_parent_collection_visible_ = is_current_parent_collection_visible; } +void DepsgraphNodeBuilder::build_object_modifiers(Object *object) +{ + if (BLI_listbase_is_empty(&object->modifiers)) { + return; + } + + const ModifierMode modifier_mode = (graph_->mode == DAG_EVAL_VIEWPORT) ? eModifierMode_Realtime : + eModifierMode_Render; + + IDNode *id_node = find_id_node(&object->id); + + add_operation_node(&object->id, + NodeType::GEOMETRY, + OperationCode::VISIBILITY, + [id_node](::Depsgraph *depsgraph) { + deg_evaluate_object_modifiers_mode_node_visibility(depsgraph, id_node); + }); + + LISTBASE_FOREACH (ModifierData *, modifier, &object->modifiers) { + OperationNode *modifier_node = add_operation_node( + &object->id, NodeType::GEOMETRY, OperationCode::MODIFIER, nullptr, modifier->name); + + /* Mute modifier mode if the modifier is not enabled for the dependency graph mode. + * This handles static (non-animated) mode of the modifier. */ + if ((modifier->mode & modifier_mode) == 0) { + modifier_node->flag |= DEPSOP_FLAG_MUTE; + } + + if (is_modifier_visibility_animated(object, modifier)) { + graph_->has_animated_visibility = true; + } + } + + BuilderWalkUserData data; + data.builder = this; + BKE_modifiers_foreach_ID_link(object, modifier_walk, &data); +} + void DepsgraphNodeBuilder::build_object_data(Object *object) { if (object->data == nullptr) { @@ -1183,12 +1227,16 @@ void DepsgraphNodeBuilder::build_driver_id_property(ID *id, const char *rna_path /* Custom properties of bones are placed in their components to improve granularity. */ if (RNA_struct_is_a(ptr.type, &RNA_PoseBone)) { const bPoseChannel *pchan = static_cast<const bPoseChannel *>(ptr.data); - ensure_operation_node( - id, NodeType::BONE, pchan->name, OperationCode::ID_PROPERTY, nullptr, prop_identifier); + ensure_operation_node(ptr.owner_id, + NodeType::BONE, + pchan->name, + OperationCode::ID_PROPERTY, + nullptr, + prop_identifier); } else { ensure_operation_node( - id, NodeType::PARAMETERS, OperationCode::ID_PROPERTY, nullptr, prop_identifier); + ptr.owner_id, NodeType::PARAMETERS, OperationCode::ID_PROPERTY, nullptr, prop_identifier); } } @@ -1703,6 +1751,18 @@ void DepsgraphNodeBuilder::build_nodetree(bNodeTree *ntree) build_animdata(&ntree->id); /* Output update. */ add_operation_node(&ntree->id, NodeType::NTREE_OUTPUT, OperationCode::NTREE_OUTPUT); + if (ntree->type == NTREE_GEOMETRY) { + ID *id_cow = get_cow_id(&ntree->id); + add_operation_node(&ntree->id, + NodeType::NTREE_GEOMETRY_PREPROCESS, + OperationCode::NTREE_GEOMETRY_PREPROCESS, + [id_cow](::Depsgraph * /*depsgraph*/) { + bNodeTree *ntree_cow = reinterpret_cast<bNodeTree *>(id_cow); + bke::node_tree_runtime::preprocess_geometry_node_tree_for_evaluation( + *ntree_cow); + }); + } + /* nodetree's nodes... */ LISTBASE_FOREACH (bNode *, bnode, &ntree->nodes) { build_idproperties(bnode->prop); @@ -2079,9 +2139,10 @@ void DepsgraphNodeBuilder::build_scene_audio(Scene *scene) }); } -void DepsgraphNodeBuilder::build_scene_speakers(Scene * /*scene*/, ViewLayer *view_layer) +void DepsgraphNodeBuilder::build_scene_speakers(Scene *scene, ViewLayer *view_layer) { - LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) { + BKE_view_layer_synced_ensure(scene, view_layer); + LISTBASE_FOREACH (Base *, base, BKE_view_layer_object_bases_get(view_layer)) { Object *object = base->object; if (object->type != OB_SPEAKER || !need_pull_base_into_graph(base)) { continue; diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.h b/source/blender/depsgraph/intern/builder/deg_builder_nodes.h index 18e28311132..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; @@ -92,10 +94,11 @@ class DepsgraphNodeBuilder : public DepsgraphBuilder { int foreach_id_cow_detect_need_for_update_callback(ID *id_cow_self, ID *id_pointer); IDNode *add_id_node(ID *id); - IDNode *find_id_node(ID *id); + IDNode *find_id_node(const ID *id); TimeSourceNode *add_time_source(); ComponentNode *add_component_node(ID *id, NodeType comp_type, const char *comp_name = ""); + ComponentNode *find_component_node(const ID *id, NodeType comp_type, const char *comp_name = ""); OperationNode *add_operation_node(ComponentNode *comp_node, OperationCode opcode, @@ -137,15 +140,20 @@ class DepsgraphNodeBuilder : public DepsgraphBuilder { const char *name = "", int name_tag = -1); - OperationNode *find_operation_node(ID *id, + OperationNode *find_operation_node(const ID *id, NodeType comp_type, const char *comp_name, OperationCode opcode, const char *name = "", int name_tag = -1); - OperationNode *find_operation_node( - ID *id, NodeType comp_type, OperationCode opcode, const char *name = "", int name_tag = -1); + OperationNode *find_operation_node(const ID *id, + NodeType comp_type, + OperationCode opcode, + const char *name = "", + int name_tag = -1); + + OperationNode *find_operation_node(const OperationKey &key); virtual void build_id(ID *id); @@ -174,6 +182,7 @@ class DepsgraphNodeBuilder : public DepsgraphBuilder { virtual void build_object_flags(int base_index, Object *object, eDepsNode_LinkedState_Type linked_state); + virtual void build_object_modifiers(Object *object); virtual void build_object_data(Object *object); virtual void build_object_data_camera(Object *object); virtual void build_object_data_geometry(Object *object); @@ -254,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; diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes_view_layer.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes_view_layer.cc index 5af9e7d4fe9..d7420b91db4 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_nodes_view_layer.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes_view_layer.cc @@ -90,7 +90,8 @@ void DepsgraphNodeBuilder::build_view_layer(Scene *scene, * but object is expected to be an original one. Hence we go into some * tricks here iterating over the view layer. */ int base_index = 0; - LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) { + BKE_view_layer_synced_ensure(scene, view_layer); + LISTBASE_FOREACH (Base *, base, BKE_view_layer_object_bases_get(view_layer)) { /* object itself */ if (!need_pull_base_into_graph(base)) { continue; diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc index f36d94c7563..b657d39df69 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc @@ -191,7 +191,7 @@ bool check_id_has_anim_component(ID *id) if (adt == nullptr) { return false; } - return (adt->action != nullptr) || (!BLI_listbase_is_empty(&adt->nla_tracks)); + return (adt->action != nullptr) || !BLI_listbase_is_empty(&adt->nla_tracks); } bool check_id_has_driver_component(ID *id) @@ -239,13 +239,8 @@ DepsgraphRelationBuilder::DepsgraphRelationBuilder(Main *bmain, { } -TimeSourceNode *DepsgraphRelationBuilder::get_node(const TimeSourceKey &key) const +TimeSourceNode *DepsgraphRelationBuilder::get_node(const TimeSourceKey & /*key*/) const { - if (key.id) { - /* XXX TODO */ - return nullptr; - } - return graph_->time_source; } @@ -298,12 +293,13 @@ bool DepsgraphRelationBuilder::has_node(const OperationKey &key) const return find_node(key) != nullptr; } -void DepsgraphRelationBuilder::add_modifier_to_transform_relation(const DepsNodeHandle *handle, - const char *description) +void DepsgraphRelationBuilder::add_depends_on_transform_relation(const DepsNodeHandle *handle, + const char *description) { IDNode *id_node = handle->node->owner->owner; ID *id = id_node->id_orig; - ComponentKey geometry_key(id, NodeType::GEOMETRY); + const OperationKey geometry_key( + id, NodeType::GEOMETRY, OperationCode::MODIFIER, handle->node->name.c_str()); /* Wire up the actual relation. */ add_depends_on_transform_relation(id, geometry_key, description); } @@ -723,11 +719,7 @@ void DepsgraphRelationBuilder::build_object(Object *object) } /* Modifiers. */ - if (object->modifiers.first != nullptr) { - BuilderWalkUserData data; - data.builder = this; - BKE_modifiers_foreach_ID_link(object, modifier_walk, &data); - } + build_object_modifiers(object); /* Grease Pencil Modifiers. */ if (object->greasepencil_modifiers.first != nullptr) { @@ -875,6 +867,63 @@ void DepsgraphRelationBuilder::build_object_layer_component_relations(Object *ob add_relation(object_from_layer_exit_key, synchronize_key, "Synchronize to Original"); } +void DepsgraphRelationBuilder::build_object_modifiers(Object *object) +{ + if (BLI_listbase_is_empty(&object->modifiers)) { + return; + } + + const OperationKey eval_init_key( + &object->id, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL_INIT); + const OperationKey eval_key(&object->id, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL); + + const ComponentKey object_visibility_key(&object->id, NodeType::VISIBILITY); + const OperationKey modifier_visibility_key( + &object->id, NodeType::GEOMETRY, OperationCode::VISIBILITY); + add_relation(modifier_visibility_key, + object_visibility_key, + "modifier -> object visibility", + RELATION_NO_VISIBILITY_CHANGE); + + add_relation(modifier_visibility_key, eval_key, "modifier visibility -> geometry eval"); + + ModifierUpdateDepsgraphContext ctx = {}; + ctx.scene = scene_; + ctx.object = object; + + OperationKey previous_key = eval_init_key; + LISTBASE_FOREACH (ModifierData *, modifier, &object->modifiers) { + const OperationKey modifier_key( + &object->id, NodeType::GEOMETRY, OperationCode::MODIFIER, modifier->name); + + /* Relation for the modifier stack chain. */ + add_relation(previous_key, modifier_key, "Modifier"); + + const ModifierTypeInfo *mti = BKE_modifier_get_info((ModifierType)modifier->type); + if (mti->updateDepsgraph) { + const BuilderStack::ScopedEntry stack_entry = stack_.trace(*modifier); + + DepsNodeHandle handle = create_node_handle(modifier_key); + ctx.node = reinterpret_cast<::DepsNodeHandle *>(&handle); + mti->updateDepsgraph(modifier, &ctx); + } + + /* Time dependency. */ + if (BKE_modifier_depends_ontime(scene_, modifier)) { + const TimeSourceKey time_src_key; + add_relation(time_src_key, modifier_key, "Time Source -> Modifier"); + } + + previous_key = modifier_key; + } + add_relation(previous_key, eval_key, "modifier stack order"); + + /* Build IDs referenced by the modifiers. */ + BuilderWalkUserData data; + data.builder = this; + BKE_modifiers_foreach_ID_link(object, modifier_walk, &data); +} + void DepsgraphRelationBuilder::build_object_data(Object *object) { if (object->data == nullptr) { @@ -1674,6 +1723,11 @@ void DepsgraphRelationBuilder::build_driver_data(ID *id, FCurve *fcu) if (GS(id_ptr->name) == ID_NT) { ComponentKey ntree_output_key(id_ptr, NodeType::NTREE_OUTPUT); add_relation(driver_key, ntree_output_key, "Drivers -> NTree Output"); + if (reinterpret_cast<bNodeTree *>(id_ptr)->type == NTREE_GEOMETRY) { + OperationKey ntree_geo_preprocess_key( + id, NodeType::NTREE_GEOMETRY_PREPROCESS, OperationCode::NTREE_GEOMETRY_PREPROCESS); + add_relation(driver_key, ntree_geo_preprocess_key, "Drivers -> NTree Geo Preprocess"); + } } } @@ -1816,18 +1870,20 @@ void DepsgraphRelationBuilder::build_driver_id_property(ID *id, const char *rna_ if (RNA_struct_is_a(ptr.type, &RNA_PoseBone)) { const bPoseChannel *pchan = static_cast<const bPoseChannel *>(ptr.data); id_property_key = OperationKey( - id, NodeType::BONE, pchan->name, OperationCode::ID_PROPERTY, prop_identifier); + ptr.owner_id, NodeType::BONE, pchan->name, OperationCode::ID_PROPERTY, prop_identifier); /* Create relation from the parameters component so that tagging armature for parameters update * properly propagates updates to all properties on bones and deeper (if needed). */ - OperationKey parameters_init_key(id, NodeType::PARAMETERS, OperationCode::PARAMETERS_ENTRY); + OperationKey parameters_init_key( + ptr.owner_id, NodeType::PARAMETERS, OperationCode::PARAMETERS_ENTRY); add_relation( parameters_init_key, id_property_key, "Init -> ID Property", RELATION_CHECK_BEFORE_ADD); } else { id_property_key = OperationKey( - id, NodeType::PARAMETERS, OperationCode::ID_PROPERTY, prop_identifier); + ptr.owner_id, NodeType::PARAMETERS, OperationCode::ID_PROPERTY, prop_identifier); } - OperationKey parameters_exit_key(id, NodeType::PARAMETERS, OperationCode::PARAMETERS_EXIT); + OperationKey parameters_exit_key( + ptr.owner_id, NodeType::PARAMETERS, OperationCode::PARAMETERS_EXIT); add_relation( id_property_key, parameters_exit_key, "ID Property -> Done", RELATION_CHECK_BEFORE_ADD); } @@ -1977,7 +2033,6 @@ void DepsgraphRelationBuilder::build_rigidbody(Scene *scene) void DepsgraphRelationBuilder::build_particle_systems(Object *object) { - TimeSourceKey time_src_key; OperationKey obdata_ubereval_key(&object->id, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL); OperationKey eval_init_key( &object->id, NodeType::PARTICLE_SYSTEM, OperationCode::PARTICLE_SYSTEM_INIT); @@ -2167,7 +2222,7 @@ void DepsgraphRelationBuilder::build_shapekeys(Key *key) * ========================== * * The evaluation of geometry on objects is as follows: - * - The actual evaluated of the derived geometry (e.g. Mesh, DispList) + * - The actual evaluated of the derived geometry (e.g. #Mesh, #Curves, etc.) * occurs in the Geometry component of the object which references this. * This includes modifiers, and the temporary "ubereval" for geometry. * Therefore, each user of a piece of shared geometry data ends up evaluating @@ -2199,26 +2254,6 @@ void DepsgraphRelationBuilder::build_object_data_geometry(Object *object) * evaluated prior to Scene's CoW is ready. */ OperationKey scene_key(&scene_->id, NodeType::PARAMETERS, OperationCode::SCENE_EVAL); add_relation(scene_key, obdata_ubereval_key, "CoW Relation", RELATION_FLAG_NO_FLUSH); - /* Modifiers */ - if (object->modifiers.first != nullptr) { - ModifierUpdateDepsgraphContext ctx = {}; - ctx.scene = scene_; - ctx.object = object; - LISTBASE_FOREACH (ModifierData *, md, &object->modifiers) { - const ModifierTypeInfo *mti = BKE_modifier_get_info((ModifierType)md->type); - if (mti->updateDepsgraph) { - const BuilderStack::ScopedEntry stack_entry = stack_.trace(*md); - - DepsNodeHandle handle = create_node_handle(obdata_ubereval_key); - ctx.node = reinterpret_cast<::DepsNodeHandle *>(&handle); - mti->updateDepsgraph(md, &ctx); - } - if (BKE_modifier_depends_ontime(scene_, md)) { - TimeSourceKey time_src_key; - add_relation(time_src_key, obdata_ubereval_key, "Time Source -> Modifier"); - } - } - } /* Grease Pencil Modifiers. */ if (object->greasepencil_modifiers.first != nullptr) { ModifierUpdateDepsgraphContext ctx = {}; @@ -2262,9 +2297,9 @@ void DepsgraphRelationBuilder::build_object_data_geometry(Object *object) if (ELEM(object->type, OB_MESH, OB_CURVES_LEGACY, OB_LATTICE)) { // add geometry collider relations } - /* Make sure uber update is the last in the dependencies. */ - if (object->type != OB_ARMATURE) { - /* Armatures does no longer require uber node. */ + /* Make sure uber update is the last in the dependencies. + * Only do it here unless there are modifiers. This avoids transitive relations. */ + if (BLI_listbase_is_empty(&object->modifiers)) { OperationKey obdata_ubereval_key( &object->id, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL); add_relation(geom_init_key, obdata_ubereval_key, "Object Geometry UberEval"); @@ -2581,6 +2616,16 @@ void DepsgraphRelationBuilder::build_nodetree(bNodeTree *ntree) build_animdata(&ntree->id); build_parameters(&ntree->id); OperationKey ntree_output_key(&ntree->id, NodeType::NTREE_OUTPUT, OperationCode::NTREE_OUTPUT); + OperationKey ntree_geo_preprocess_key( + &ntree->id, NodeType::NTREE_GEOMETRY_PREPROCESS, OperationCode::NTREE_GEOMETRY_PREPROCESS); + if (ntree->type == NTREE_GEOMETRY) { + OperationKey ntree_cow_key(&ntree->id, NodeType::COPY_ON_WRITE, OperationCode::COPY_ON_WRITE); + add_relation(ntree_cow_key, ntree_geo_preprocess_key, "COW -> Preprocess"); + add_relation(ntree_geo_preprocess_key, + ntree_output_key, + "Preprocess -> Output", + RELATION_FLAG_NO_FLUSH); + } /* nodetree's nodes... */ LISTBASE_FOREACH (bNode *, bnode, &ntree->nodes) { build_idproperties(bnode->prop); @@ -2657,6 +2702,12 @@ void DepsgraphRelationBuilder::build_nodetree(bNodeTree *ntree) * the output). Currently, we lack the infrastructure to check for these cases efficiently. * That can be added later. */ add_relation(group_output_key, ntree_output_key, "Group Node"); + if (group_ntree->type == NTREE_GEOMETRY) { + OperationKey group_preprocess_key(&group_ntree->id, + NodeType::NTREE_GEOMETRY_PREPROCESS, + OperationCode::NTREE_GEOMETRY_PREPROCESS); + add_relation(group_preprocess_key, ntree_geo_preprocess_key, "Group Node Preprocess"); + } } else { BLI_assert_msg(0, "Unknown ID type used for node"); @@ -2673,6 +2724,9 @@ void DepsgraphRelationBuilder::build_nodetree(bNodeTree *ntree) if (check_id_has_anim_component(&ntree->id)) { ComponentKey animation_key(&ntree->id, NodeType::ANIMATION); add_relation(animation_key, ntree_output_key, "NTree Shading Parameters"); + if (ntree->type == NTREE_GEOMETRY) { + add_relation(animation_key, ntree_geo_preprocess_key, "NTree Animation -> Preprocess"); + } } } @@ -3020,9 +3074,10 @@ void DepsgraphRelationBuilder::build_scene_audio(Scene *scene) } } -void DepsgraphRelationBuilder::build_scene_speakers(Scene * /*scene*/, ViewLayer *view_layer) +void DepsgraphRelationBuilder::build_scene_speakers(Scene *scene, ViewLayer *view_layer) { - LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) { + BKE_view_layer_synced_ensure(scene, view_layer); + LISTBASE_FOREACH (Base *, base, BKE_view_layer_object_bases_get(view_layer)) { Object *object = base->object; if (object->type != OB_SPEAKER || !need_pull_base_into_graph(base)) { continue; @@ -3097,7 +3152,6 @@ void DepsgraphRelationBuilder::build_copy_on_write_relations(IDNode *id_node) return; } - TimeSourceKey time_source_key; OperationKey copy_on_write_key(id_orig, NodeType::COPY_ON_WRITE, OperationCode::COPY_ON_WRITE); /* XXX: This is a quick hack to make Alt-A to work. */ // add_relation(time_source_key, copy_on_write_key, "Fluxgate capacitor hack"); diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.h b/source/blender/depsgraph/intern/builder/deg_builder_relations.h index 0cb0b60dfb0..901e4a1acbb 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations.h +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.h @@ -14,13 +14,13 @@ #include "DNA_ID.h" -#include "RNA_access.h" -#include "RNA_types.h" +#include "RNA_path.h" #include "BLI_string.h" #include "BLI_utildefines.h" #include "intern/builder/deg_builder.h" +#include "intern/builder/deg_builder_key.h" #include "intern/builder/deg_builder_map.h" #include "intern/builder/deg_builder_rna.h" #include "intern/builder/deg_builder_stack.h" @@ -68,8 +68,6 @@ struct bNodeTree; struct bPoseChannel; struct bSound; -struct PropertyRNA; - namespace blender::deg { struct ComponentNode; @@ -83,66 +81,6 @@ struct Relation; struct RootPChanMap; struct TimeSourceNode; -struct TimeSourceKey { - TimeSourceKey(); - TimeSourceKey(ID *id); - - string identifier() const; - - ID *id; -}; - -struct ComponentKey { - ComponentKey(); - ComponentKey(ID *id, NodeType type, const char *name = ""); - - string identifier() const; - - ID *id; - NodeType type; - const char *name; -}; - -struct OperationKey { - OperationKey(); - OperationKey(ID *id, NodeType component_type, const char *name, int name_tag = -1); - OperationKey( - ID *id, NodeType component_type, const char *component_name, const char *name, int name_tag); - - OperationKey(ID *id, NodeType component_type, OperationCode opcode); - OperationKey(ID *id, NodeType component_type, const char *component_name, OperationCode opcode); - - OperationKey( - ID *id, NodeType component_type, OperationCode opcode, const char *name, int name_tag = -1); - OperationKey(ID *id, - NodeType component_type, - const char *component_name, - OperationCode opcode, - const char *name, - int name_tag = -1); - - string identifier() const; - - ID *id; - NodeType component_type; - const char *component_name; - OperationCode opcode; - const char *name; - int name_tag; -}; - -struct RNAPathKey { - RNAPathKey(ID *id, const char *path, RNAPointerSource source); - RNAPathKey(ID *id, const PointerRNA &ptr, PropertyRNA *prop, RNAPointerSource source); - - string identifier() const; - - ID *id; - PointerRNA ptr; - PropertyRNA *prop; - RNAPointerSource source; -}; - class DepsgraphRelationBuilder : public DepsgraphBuilder { public: DepsgraphRelationBuilder(Main *bmain, Depsgraph *graph, DepsgraphBuilderCache *cache); @@ -176,7 +114,7 @@ class DepsgraphRelationBuilder : public DepsgraphBuilder { /* Adds relation from proper transformation operation to the modifier. * Takes care of checking for possible physics solvers modifying position * of this object. */ - void add_modifier_to_transform_relation(const DepsNodeHandle *handle, const char *description); + void add_depends_on_transform_relation(const DepsNodeHandle *handle, const char *description); void add_customdata_mask(Object *object, const DEGCustomDataMeshMasks &customdata_masks); void add_special_eval_flag(ID *id, uint32_t flag); @@ -202,6 +140,7 @@ class DepsgraphRelationBuilder : public DepsgraphBuilder { virtual void build_object(Object *object); virtual void build_object_from_view_layer_base(Object *object); virtual void build_object_layer_component_relations(Object *object); + virtual void build_object_modifiers(Object *object); virtual void build_object_data(Object *object); virtual void build_object_data_camera(Object *object); virtual void build_object_data_geometry(Object *object); diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations_keys.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations_keys.cc deleted file mode 100644 index eeaab623482..00000000000 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations_keys.cc +++ /dev/null @@ -1,179 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later - * Copyright 2013 Blender Foundation. All rights reserved. */ - -/** \file - * \ingroup depsgraph - * - * Methods for constructing depsgraph - */ - -#include "intern/builder/deg_builder_relations.h" - -namespace blender::deg { - -//////////////////////////////////////////////////////////////////////////////// -/* Time source. */ - -TimeSourceKey::TimeSourceKey() : id(nullptr) -{ -} - -TimeSourceKey::TimeSourceKey(ID *id) : id(id) -{ -} - -string TimeSourceKey::identifier() const -{ - return string("TimeSourceKey"); -} - -//////////////////////////////////////////////////////////////////////////////// -// Component. - -ComponentKey::ComponentKey() : id(nullptr), type(NodeType::UNDEFINED), name("") -{ -} - -ComponentKey::ComponentKey(ID *id, NodeType type, const char *name) - : id(id), type(type), name(name) -{ -} - -string ComponentKey::identifier() const -{ - const char *idname = (id) ? id->name : "<None>"; - string result = string("ComponentKey("); - result += idname; - result += ", " + string(nodeTypeAsString(type)); - if (name[0] != '\0') { - result += ", '" + string(name) + "'"; - } - result += ')'; - return result; -} - -//////////////////////////////////////////////////////////////////////////////// -// Operation. - -OperationKey::OperationKey() - : id(nullptr), - component_type(NodeType::UNDEFINED), - component_name(""), - opcode(OperationCode::OPERATION), - name(""), - name_tag(-1) -{ -} - -OperationKey::OperationKey(ID *id, NodeType component_type, const char *name, int name_tag) - : id(id), - component_type(component_type), - component_name(""), - opcode(OperationCode::OPERATION), - name(name), - name_tag(name_tag) -{ -} - -OperationKey::OperationKey( - ID *id, NodeType component_type, const char *component_name, const char *name, int name_tag) - : id(id), - component_type(component_type), - component_name(component_name), - opcode(OperationCode::OPERATION), - name(name), - name_tag(name_tag) -{ -} - -OperationKey::OperationKey(ID *id, NodeType component_type, OperationCode opcode) - : id(id), - component_type(component_type), - component_name(""), - opcode(opcode), - name(""), - name_tag(-1) -{ -} - -OperationKey::OperationKey(ID *id, - NodeType component_type, - const char *component_name, - OperationCode opcode) - : id(id), - component_type(component_type), - component_name(component_name), - opcode(opcode), - name(""), - name_tag(-1) -{ -} - -OperationKey::OperationKey( - ID *id, NodeType component_type, OperationCode opcode, const char *name, int name_tag) - : id(id), - component_type(component_type), - component_name(""), - opcode(opcode), - name(name), - name_tag(name_tag) -{ -} - -OperationKey::OperationKey(ID *id, - NodeType component_type, - const char *component_name, - OperationCode opcode, - const char *name, - int name_tag) - : id(id), - component_type(component_type), - component_name(component_name), - opcode(opcode), - name(name), - name_tag(name_tag) -{ -} - -string OperationKey::identifier() const -{ - string result = string("OperationKey("); - result += "type: " + string(nodeTypeAsString(component_type)); - result += ", component name: '" + string(component_name) + "'"; - result += ", operation code: " + string(operationCodeAsString(opcode)); - if (name[0] != '\0') { - result += ", '" + string(name) + "'"; - } - result += ")"; - return result; -} - -//////////////////////////////////////////////////////////////////////////////// -// RNA path. - -RNAPathKey::RNAPathKey(ID *id, const char *path, RNAPointerSource source) : id(id), source(source) -{ - /* Create ID pointer for root of path lookup. */ - PointerRNA id_ptr; - RNA_id_pointer_create(id, &id_ptr); - /* Try to resolve path. */ - int index; - if (!RNA_path_resolve_full(&id_ptr, path, &ptr, &prop, &index)) { - ptr = PointerRNA_NULL; - prop = nullptr; - } -} - -RNAPathKey::RNAPathKey(ID *id, const PointerRNA &ptr, PropertyRNA *prop, RNAPointerSource source) - : id(id), ptr(ptr), prop(prop), source(source) -{ -} - -string RNAPathKey::identifier() const -{ - const char *id_name = (id) ? id->name : "<No ID>"; - const char *prop_name = (prop) ? RNA_property_identifier(prop) : "<No Prop>"; - return string("RnaPathKey(") + "id: " + id_name + ", prop: '" + prop_name + "')"; -} - -} // namespace blender::deg diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations_view_layer.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations_view_layer.cc index d723e5beb75..938c0979de9 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations_view_layer.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations_view_layer.cc @@ -75,11 +75,12 @@ void DepsgraphRelationBuilder::build_view_layer(Scene *scene, { /* Setup currently building context. */ scene_ = scene; + BKE_view_layer_synced_ensure(scene, view_layer); /* Scene objects. */ /* NOTE: Nodes builder requires us to pass CoW base because it's being * passed to the evaluation functions. During relations builder we only * do nullptr-pointer check of the base, so it's fine to pass original one. */ - LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) { + LISTBASE_FOREACH (Base *, base, BKE_view_layer_object_bases_get(view_layer)) { if (need_pull_base_into_graph(base)) { build_object_from_view_layer_base(base->object); } diff --git a/source/blender/depsgraph/intern/builder/deg_builder_rna.cc b/source/blender/depsgraph/intern/builder/deg_builder_rna.cc index 5202ada5408..1a4356c4a92 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_rna.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_rna.cc @@ -138,8 +138,8 @@ bool RNANodeQuery::contains(const char *prop_identifier, const char *rna_path_co return false; } - /* If substr != prop_identifier, it means that the substring is found further in prop_identifier, - * and that thus index -1 is a valid memory location. */ + /* If `substr != prop_identifier`, it means that the sub-string is found further in + * `prop_identifier`, and that thus index -1 is a valid memory location. */ const bool start_ok = substr == prop_identifier || substr[-1] == '.'; if (!start_ok) { return false; @@ -225,6 +225,10 @@ RNANodeIdentifier RNANodeQuery::construct_node_identifier(const PointerRNA *ptr, } return node_identifier; } + + const char *prop_identifier = prop != nullptr ? RNA_property_identifier((PropertyRNA *)prop) : + ""; + if (RNA_struct_is_a(ptr->type, &RNA_Constraint)) { const Object *object = reinterpret_cast<const Object *>(ptr->owner_id); const bConstraint *constraint = static_cast<const bConstraint *>(ptr->data); @@ -264,6 +268,13 @@ RNANodeIdentifier RNANodeQuery::construct_node_identifier(const PointerRNA *ptr, return node_identifier; } } + else if (RNA_struct_is_a(ptr->type, &RNA_Modifier) && + (contains(prop_identifier, "show_viewport") || + contains(prop_identifier, "show_render"))) { + node_identifier.type = NodeType::GEOMETRY; + node_identifier.operation_code = OperationCode::VISIBILITY; + return node_identifier; + } else if (RNA_struct_is_a(ptr->type, &RNA_Mesh) || RNA_struct_is_a(ptr->type, &RNA_Modifier) || RNA_struct_is_a(ptr->type, &RNA_GpencilModifier) || RNA_struct_is_a(ptr->type, &RNA_Spline) || RNA_struct_is_a(ptr->type, &RNA_TextBox) || @@ -290,7 +301,6 @@ RNANodeIdentifier RNANodeQuery::construct_node_identifier(const PointerRNA *ptr, else if (ptr->type == &RNA_Object) { /* Transforms props? */ if (prop != nullptr) { - const char *prop_identifier = RNA_property_identifier((PropertyRNA *)prop); /* TODO(sergey): How to optimize this? */ if (contains(prop_identifier, "location") || contains(prop_identifier, "matrix_basis") || contains(prop_identifier, "matrix_channel") || diff --git a/source/blender/depsgraph/intern/debug/deg_debug_relations_graphviz.cc b/source/blender/depsgraph/intern/debug/deg_debug_relations_graphviz.cc index b8d0fb6c365..bd47cb77f56 100644 --- a/source/blender/depsgraph/intern/debug/deg_debug_relations_graphviz.cc +++ b/source/blender/depsgraph/intern/debug/deg_debug_relations_graphviz.cc @@ -408,6 +408,7 @@ static void deg_debug_graphviz_node(DotExportContext &ctx, case NodeType::GENERIC_DATABLOCK: case NodeType::VISIBILITY: case NodeType::NTREE_OUTPUT: + case NodeType::NTREE_GEOMETRY_PREPROCESS: case NodeType::SIMULATION: { ComponentNode *comp_node = (ComponentNode *)node; if (comp_node->operations.is_empty()) { diff --git a/source/blender/depsgraph/intern/depsgraph_build.cc b/source/blender/depsgraph/intern/depsgraph_build.cc index a207c13d646..6da290d6c4e 100644 --- a/source/blender/depsgraph/intern/depsgraph_build.cc +++ b/source/blender/depsgraph/intern/depsgraph_build.cc @@ -199,11 +199,11 @@ void DEG_add_generic_id_relation(struct DepsNodeHandle *node_handle, deg_node_handle->builder->add_node_handle_relation(operation_key, deg_node_handle, description); } -void DEG_add_modifier_to_transform_relation(struct DepsNodeHandle *node_handle, - const char *description) +void DEG_add_depends_on_transform_relation(struct DepsNodeHandle *node_handle, + const char *description) { deg::DepsNodeHandle *deg_node_handle = get_node_handle(node_handle); - deg_node_handle->builder->add_modifier_to_transform_relation(deg_node_handle, description); + deg_node_handle->builder->add_depends_on_transform_relation(deg_node_handle, description); } void DEG_add_special_eval_flag(struct DepsNodeHandle *node_handle, ID *id, uint32_t flag) diff --git a/source/blender/depsgraph/intern/depsgraph_debug.cc b/source/blender/depsgraph/intern/depsgraph_debug.cc index ddad00bc0e8..2f528873f1d 100644 --- a/source/blender/depsgraph/intern/depsgraph_debug.cc +++ b/source/blender/depsgraph/intern/depsgraph_debug.cc @@ -171,7 +171,7 @@ bool DEG_debug_consistency_check(Depsgraph *graph) node->identifier().c_str(), node->num_links_pending, num_links_pending); - printf("Number of inlinks: %d\n", (int)node->inlinks.size()); + printf("Number of inlinks: %d\n", int(node->inlinks.size())); return false; } } diff --git a/source/blender/depsgraph/intern/depsgraph_physics.cc b/source/blender/depsgraph/intern/depsgraph_physics.cc index 5660d5eb1bd..d7d03ec3261 100644 --- a/source/blender/depsgraph/intern/depsgraph_physics.cc +++ b/source/blender/depsgraph/intern/depsgraph_physics.cc @@ -32,7 +32,7 @@ namespace deg = blender::deg; /*************************** Evaluation Query API *****************************/ -static ePhysicsRelationType modifier_to_relation_type(unsigned int modifier_type) +static ePhysicsRelationType modifier_to_relation_type(uint modifier_type) { switch (modifier_type) { case eModifierType_Collision: @@ -72,7 +72,7 @@ ListBase *DEG_get_effector_relations(const Depsgraph *graph, Collection *collect ListBase *DEG_get_collision_relations(const Depsgraph *graph, Collection *collection, - unsigned int modifier_type) + uint modifier_type) { const deg::Depsgraph *deg_graph = reinterpret_cast<const deg::Depsgraph *>(graph); const ePhysicsRelationType type = modifier_to_relation_type(modifier_type); @@ -91,7 +91,7 @@ ListBase *DEG_get_collision_relations(const Depsgraph *graph, void DEG_add_collision_relations(DepsNodeHandle *handle, Object *object, Collection *collection, - unsigned int modifier_type, + uint modifier_type, DEG_CollobjFilterFunction filter_function, const char *name) { @@ -174,13 +174,11 @@ ListBase *build_effector_relations(Depsgraph *graph, Collection *collection) ID *collection_id = object_id_safe(collection); return hash->lookup_or_add_cb(collection_id, [&]() { ::Depsgraph *depsgraph = reinterpret_cast<::Depsgraph *>(graph); - return BKE_effector_relations_create(depsgraph, graph->view_layer, collection); + return BKE_effector_relations_create(depsgraph, graph->scene, graph->view_layer, collection); }); } -ListBase *build_collision_relations(Depsgraph *graph, - Collection *collection, - unsigned int modifier_type) +ListBase *build_collision_relations(Depsgraph *graph, Collection *collection, uint modifier_type) { const ePhysicsRelationType type = modifier_to_relation_type(modifier_type); Map<const ID *, ListBase *> *hash = graph->physics_relations[type]; diff --git a/source/blender/depsgraph/intern/depsgraph_query.cc b/source/blender/depsgraph/intern/depsgraph_query.cc index 9a047c70d01..19339fa34ea 100644 --- a/source/blender/depsgraph/intern/depsgraph_query.cc +++ b/source/blender/depsgraph/intern/depsgraph_query.cc @@ -23,6 +23,7 @@ #include "DNA_scene_types.h" #include "RNA_access.h" +#include "RNA_path.h" #include "RNA_prototypes.h" #include "DEG_depsgraph.h" diff --git a/source/blender/depsgraph/intern/depsgraph_query_foreach.cc b/source/blender/depsgraph/intern/depsgraph_query_foreach.cc index 2839f0daed7..4f28210ba8f 100644 --- a/source/blender/depsgraph/intern/depsgraph_query_foreach.cc +++ b/source/blender/depsgraph/intern/depsgraph_query_foreach.cc @@ -45,7 +45,7 @@ bool deg_foreach_needs_visit(const OperationNode *op_node, const int flags) return true; } -void deg_foreach_dependent_operation(const Depsgraph *UNUSED(graph), +void deg_foreach_dependent_operation(const Depsgraph * /*graph*/, const IDNode *target_id_node, eDepsObjectComponentType source_component_type, int flags, diff --git a/source/blender/depsgraph/intern/depsgraph_query_iter.cc b/source/blender/depsgraph/intern/depsgraph_query_iter.cc index 171c9875e2a..4636011e18b 100644 --- a/source/blender/depsgraph/intern/depsgraph_query_iter.cc +++ b/source/blender/depsgraph/intern/depsgraph_query_iter.cc @@ -127,14 +127,11 @@ bool deg_object_hide_original(eEvaluationMode eval_mode, Object *ob, DupliObject return false; } -void deg_iterator_duplis_init(DEGObjectIterData *data, Object *object) +void deg_iterator_duplis_init(DEGObjectIterData *data, Object *object, ListBase *duplis) { - if ((data->flag & DEG_ITER_OBJECT_FLAG_DUPLI) && - ((object->transflag & OB_DUPLI) || object->runtime.geometry_set_eval != nullptr)) { - data->dupli_parent = object; - data->dupli_list = object_duplilist(data->graph, data->scene, object); - data->dupli_object_next = (DupliObject *)data->dupli_list->first; - } + data->dupli_parent = object; + data->dupli_list = duplis; + data->dupli_object_next = static_cast<DupliObject *>(duplis->first); } /* Returns false when iterator is exhausted. */ @@ -153,10 +150,10 @@ bool deg_iterator_duplis_step(DEGObjectIterData *data) if (dob->no_draw) { continue; } - if (obd->type == OB_MBALL) { + if (dob->ob_data && GS(dob->ob_data->name) == ID_MB) { continue; } - if (deg_object_hide_original(data->eval_mode, dob->ob, dob)) { + if (obd->type != OB_MBALL && deg_object_hide_original(data->eval_mode, dob->ob, dob)) { continue; } @@ -182,7 +179,7 @@ bool deg_iterator_duplis_step(DEGObjectIterData *data) } /* Duplicated elements shouldn't care whether their original collection is visible or not. */ - temp_dupli_object->base_flag |= BASE_VISIBLE_DEPSGRAPH; + temp_dupli_object->base_flag |= BASE_ENABLED_AND_MAYBE_VISIBLE_IN_VIEWPORT; int ob_visibility = BKE_object_visibility(temp_dupli_object, data->eval_mode); if ((ob_visibility & (OB_VISIBLE_SELF | OB_VISIBLE_PARTICLES)) == 0) { @@ -250,7 +247,18 @@ bool deg_iterator_objects_step(DEGObjectIterData *data) } Object *object = (Object *)id_node->id_cow; + Object *object_orig = DEG_get_original_object(object); BLI_assert(deg::deg_validate_copy_on_write_datablock(&object->id)); + object->runtime.select_id = object_orig->runtime.select_id; + + const bool use_preview = object_orig == data->object_orig_with_preview; + if (use_preview) { + ListBase *preview_duplis = object_duplilist_preview( + data->graph, data->scene, object, data->settings->viewer_path); + deg_iterator_duplis_init(data, object, preview_duplis); + data->id_node_index++; + return true; + } int ob_visibility = OB_VISIBLE_ALL; if (data->flag & DEG_ITER_OBJECT_FLAG_VISIBLE) { @@ -261,9 +269,12 @@ bool deg_iterator_objects_step(DEGObjectIterData *data) } } - object->runtime.select_id = DEG_get_original_object(object)->runtime.select_id; if (ob_visibility & OB_VISIBLE_INSTANCES) { - deg_iterator_duplis_init(data, object); + if ((data->flag & DEG_ITER_OBJECT_FLAG_DUPLI) && + ((object->transflag & OB_DUPLI) || object->runtime.geometry_set_eval != nullptr)) { + ListBase *duplis = object_duplilist(data->graph, data->scene, object); + deg_iterator_duplis_init(data, object, duplis); + } } if (ob_visibility & (OB_VISIBLE_SELF | OB_VISIBLE_PARTICLES)) { @@ -301,6 +312,22 @@ void DEG_iterator_objects_begin(BLI_Iterator *iter, DEGObjectIterData *data) data->eval_mode = DEG_get_mode(depsgraph); deg_invalidate_iterator_work_data(data); + /* Determine if the preview of any object should be in the iterator. */ + const ViewerPath *viewer_path = data->settings->viewer_path; + if (viewer_path != nullptr) { + if (!BLI_listbase_is_empty(&viewer_path->path)) { + const ViewerPathElem *elem = static_cast<const ViewerPathElem *>(viewer_path->path.first); + if (elem->type == VIEWER_PATH_ELEM_TYPE_ID) { + const IDViewerPathElem *id_elem = reinterpret_cast<const IDViewerPathElem *>(elem); + if (id_elem->id != nullptr) { + if (GS(id_elem->id->name) == ID_OB) { + data->object_orig_with_preview = reinterpret_cast<Object *>(id_elem->id); + } + } + } + } + } + DEG_iterator_objects_next(iter); } @@ -408,6 +435,6 @@ void DEG_iterator_ids_next(BLI_Iterator *iter) } while (iter->skip); } -void DEG_iterator_ids_end(BLI_Iterator *UNUSED(iter)) +void DEG_iterator_ids_end(BLI_Iterator * /*iter*/) { } diff --git a/source/blender/depsgraph/intern/depsgraph_relation.h b/source/blender/depsgraph/intern/depsgraph_relation.h index 1bacb9abfa6..3f316fa84e8 100644 --- a/source/blender/depsgraph/intern/depsgraph_relation.h +++ b/source/blender/depsgraph/intern/depsgraph_relation.h @@ -28,6 +28,8 @@ enum RelationFlag { RELATION_FLAG_GODMODE = (1 << 4), /* Relation will check existence before being added. */ RELATION_CHECK_BEFORE_ADD = (1 << 5), + /* The relation does not participate in visibility checks. */ + RELATION_NO_VISIBILITY_CHANGE = (1 << 6), }; /* B depends on A (A -> B) */ diff --git a/source/blender/depsgraph/intern/depsgraph_tag.cc b/source/blender/depsgraph/intern/depsgraph_tag.cc index 9cd5980d8fe..0c003cf23b2 100644 --- a/source/blender/depsgraph/intern/depsgraph_tag.cc +++ b/source/blender/depsgraph/intern/depsgraph_tag.cc @@ -220,17 +220,28 @@ void depsgraph_tag_to_component_opcode(const ID *id, *component_type = NodeType::NTREE_OUTPUT; *operation_code = OperationCode::NTREE_OUTPUT; break; + + case ID_RECALC_PROVISION_26: + case ID_RECALC_PROVISION_27: + case ID_RECALC_PROVISION_28: + case ID_RECALC_PROVISION_29: + case ID_RECALC_PROVISION_30: + case ID_RECALC_PROVISION_31: + /* Silently ignore. + * The bits might be passed here from ID_RECALC_ALL. This is not a code-mistake, but just the + * way how the recalc flags are handled. */ + break; } } void id_tag_update_ntree_special( - Main *bmain, Depsgraph *graph, ID *id, int flag, eUpdateSource update_source) + Main *bmain, Depsgraph *graph, ID *id, uint flags, eUpdateSource update_source) { bNodeTree *ntree = ntreeFromID(id); if (ntree == nullptr) { return; } - graph_id_tag_update(bmain, graph, &ntree->id, flag, update_source); + graph_id_tag_update(bmain, graph, &ntree->id, flags, update_source); } void depsgraph_update_editors_tag(Main *bmain, Depsgraph *graph, ID *id) @@ -407,13 +418,13 @@ string stringify_append_bit(const string &str, IDRecalcFlag tag) return result; } -string stringify_update_bitfield(int flag) +string stringify_update_bitfield(uint flags) { - if (flag == 0) { + if (flags == 0) { return "LEGACY_0"; } string result; - int current_flag = flag; + uint current_flag = flags; /* Special cases to avoid ALL flags form being split into * individual bits. */ if ((current_flag & ID_RECALC_PSYS_ALL) == ID_RECALC_PSYS_ALL) { @@ -421,7 +432,7 @@ string stringify_update_bitfield(int flag) } /* Handle all the rest of the flags. */ while (current_flag != 0) { - IDRecalcFlag tag = (IDRecalcFlag)(1 << bitscan_forward_clear_i(¤t_flag)); + IDRecalcFlag tag = (IDRecalcFlag)(1 << bitscan_forward_clear_uint(¤t_flag)); result = stringify_append_bit(result, tag); } return result; @@ -449,7 +460,7 @@ int deg_recalc_flags_for_legacy_zero() ID_RECALC_SOURCE | ID_RECALC_EDITORS); } -int deg_recalc_flags_effective(Depsgraph *graph, int flags) +int deg_recalc_flags_effective(Depsgraph *graph, uint flags) { if (graph != nullptr) { if (!graph->is_active) { @@ -520,12 +531,12 @@ void graph_tag_ids_for_visible_update(Depsgraph *graph) * No need bother with it to tag or anything. */ continue; } - int flag = 0; + uint flags = 0; if (!deg::deg_copy_on_write_is_expanded(id_node->id_cow)) { - flag |= ID_RECALC_COPY_ON_WRITE; + flags |= ID_RECALC_COPY_ON_WRITE; if (do_time) { if (BKE_animdata_from_id(id_node->id_orig) != nullptr) { - flag |= ID_RECALC_ANIMATION; + flags |= ID_RECALC_ANIMATION; } } } @@ -542,9 +553,9 @@ void graph_tag_ids_for_visible_update(Depsgraph *graph) * * TODO(sergey): Need to generalize this somehow. */ if (id_type == ID_OB) { - flag |= ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY; + flags |= ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY; } - graph_id_tag_update(bmain, graph, id_node->id_orig, flag, DEG_UPDATE_SOURCE_VISIBILITY); + graph_id_tag_update(bmain, graph, id_node->id_orig, flags, DEG_UPDATE_SOURCE_VISIBILITY); if (id_type == ID_SCE) { /* Make sure collection properties are up to date. */ id_node->tag_update(graph, DEG_UPDATE_SOURCE_VISIBILITY); @@ -614,20 +625,20 @@ NodeType geometry_tag_to_component(const ID *id) return NodeType::UNDEFINED; } -void id_tag_update(Main *bmain, ID *id, int flag, eUpdateSource update_source) +void id_tag_update(Main *bmain, ID *id, uint flags, eUpdateSource update_source) { - graph_id_tag_update(bmain, nullptr, id, flag, update_source); + graph_id_tag_update(bmain, nullptr, id, flags, update_source); for (deg::Depsgraph *depsgraph : deg::get_all_registered_graphs(bmain)) { - graph_id_tag_update(bmain, depsgraph, id, flag, update_source); + graph_id_tag_update(bmain, depsgraph, id, flags, update_source); } /* Accumulate all tags for an ID between two undo steps, so they can be * replayed for undo. */ - id->recalc_after_undo_push |= deg_recalc_flags_effective(nullptr, flag); + id->recalc_after_undo_push |= deg_recalc_flags_effective(nullptr, flags); } void graph_id_tag_update( - Main *bmain, Depsgraph *graph, ID *id, int flag, eUpdateSource update_source) + Main *bmain, Depsgraph *graph, ID *id, uint flags, eUpdateSource update_source) { const int debug_flags = (graph != nullptr) ? DEG_debug_flags_get((::Depsgraph *)graph) : G.debug; if (graph != nullptr && graph->is_evaluating) { @@ -640,20 +651,20 @@ void graph_id_tag_update( printf("%s: id=%s flags=%s source=%s\n", __func__, id->name, - stringify_update_bitfield(flag).c_str(), + stringify_update_bitfield(flags).c_str(), update_source_as_string(update_source)); } IDNode *id_node = (graph != nullptr) ? graph->find_id_node(id) : nullptr; if (graph != nullptr) { DEG_graph_id_type_tag(reinterpret_cast<::Depsgraph *>(graph), GS(id->name)); } - if (flag == 0) { + if (flags == 0) { deg_graph_node_tag_zero(bmain, graph, id_node, update_source); } /* Store original flag in the ID. * Allows to have more granularity than a node-factory based flags. */ if (id_node != nullptr) { - id_node->id_cow->recalc |= flag; + id_node->id_cow->recalc |= flags; } /* When ID is tagged for update based on an user edits store the recalc flags in the original ID. * This way IDs in the undo steps will have this flag preserved, making it possible to restore @@ -663,20 +674,20 @@ void graph_id_tag_update( * usually newly created dependency graph skips animation update to avoid loss of unkeyed * changes). */ if (update_source == DEG_UPDATE_SOURCE_USER_EDIT) { - id->recalc |= deg_recalc_flags_effective(graph, flag); + id->recalc |= deg_recalc_flags_effective(graph, flags); } - int current_flag = flag; + uint current_flag = flags; while (current_flag != 0) { - IDRecalcFlag tag = (IDRecalcFlag)(1 << bitscan_forward_clear_i(¤t_flag)); + IDRecalcFlag tag = (IDRecalcFlag)(1 << bitscan_forward_clear_uint(¤t_flag)); graph_id_tag_update_single_flag(bmain, graph, id, id_node, tag, update_source); } /* Special case for nested node tree data-blocks. */ - id_tag_update_ntree_special(bmain, graph, id, flag, update_source); + id_tag_update_ntree_special(bmain, graph, id, flags, update_source); /* Direct update tags means that something outside of simulated/cached * physics did change and that cache is to be invalidated. * This is only needed if data changes. If it's just a drawing, we keep the * point cache. */ - if (update_source == DEG_UPDATE_SOURCE_USER_EDIT && flag != ID_RECALC_SHADING) { + if (update_source == DEG_UPDATE_SOURCE_USER_EDIT && flags != ID_RECALC_SHADING) { graph_id_tag_update_single_flag( bmain, graph, id, id_node, ID_RECALC_POINT_CACHE, update_source); } @@ -741,33 +752,45 @@ const char *DEG_update_tag_as_string(IDRecalcFlag flag) return "TAG_FOR_UNDO"; case ID_RECALC_NTREE_OUTPUT: return "ID_RECALC_NTREE_OUTPUT"; + + case ID_RECALC_PROVISION_26: + case ID_RECALC_PROVISION_27: + case ID_RECALC_PROVISION_28: + case ID_RECALC_PROVISION_29: + case ID_RECALC_PROVISION_30: + case ID_RECALC_PROVISION_31: + /* Silently return nullptr, indicating that there is no string representation. + * + * This is needed due to the way how logging for ID_RECALC_ALL works: it iterates over all + * bits and converts then to string. */ + return nullptr; } return nullptr; } /* Data-Based Tagging. */ -void DEG_id_tag_update(ID *id, int flag) +void DEG_id_tag_update(ID *id, uint flags) { - DEG_id_tag_update_ex(G.main, id, flag); + DEG_id_tag_update_ex(G.main, id, flags); } -void DEG_id_tag_update_ex(Main *bmain, ID *id, int flag) +void DEG_id_tag_update_ex(Main *bmain, ID *id, uint flags) { if (id == nullptr) { /* Ideally should not happen, but old depsgraph allowed this. */ return; } - deg::id_tag_update(bmain, id, flag, deg::DEG_UPDATE_SOURCE_USER_EDIT); + deg::id_tag_update(bmain, id, flags, deg::DEG_UPDATE_SOURCE_USER_EDIT); } void DEG_graph_id_tag_update(struct Main *bmain, struct Depsgraph *depsgraph, struct ID *id, - int flag) + uint flags) { deg::Depsgraph *graph = (deg::Depsgraph *)depsgraph; - deg::graph_id_tag_update(bmain, graph, id, flag, deg::DEG_UPDATE_SOURCE_USER_EDIT); + deg::graph_id_tag_update(bmain, graph, id, flags, deg::DEG_UPDATE_SOURCE_USER_EDIT); } void DEG_time_tag_update(struct Main *bmain) diff --git a/source/blender/depsgraph/intern/depsgraph_tag.h b/source/blender/depsgraph/intern/depsgraph_tag.h index b722aab5719..61643e6f740 100644 --- a/source/blender/depsgraph/intern/depsgraph_tag.h +++ b/source/blender/depsgraph/intern/depsgraph_tag.h @@ -18,11 +18,11 @@ struct Depsgraph; NodeType geometry_tag_to_component(const ID *id); /* Tag given ID for an update in all registered dependency graphs. */ -void id_tag_update(Main *bmain, ID *id, int flag, eUpdateSource update_source); +void id_tag_update(Main *bmain, ID *id, unsigned int flags, eUpdateSource update_source); /* Tag given ID for an update with in a given dependency graph. */ void graph_id_tag_update( - Main *bmain, Depsgraph *graph, ID *id, int flag, eUpdateSource update_source); + Main *bmain, Depsgraph *graph, ID *id, unsigned int flags, eUpdateSource update_source); /* Tag IDs of the graph for the visibility update tags. * Will do nothing if the graph is not tagged for visibility update. */ diff --git a/source/blender/depsgraph/intern/eval/deg_eval.cc b/source/blender/depsgraph/intern/eval/deg_eval.cc index 426e04a5cf9..45a13b807af 100644 --- a/source/blender/depsgraph/intern/eval/deg_eval.cc +++ b/source/blender/depsgraph/intern/eval/deg_eval.cc @@ -58,7 +58,7 @@ void schedule_children(DepsgraphEvalState *state, ScheduleFunction *schedule_function, ScheduleFunctionArgs... schedule_function_args); -void schedule_node_to_pool(OperationNode *node, const int UNUSED(thread_id), TaskPool *pool) +void schedule_node_to_pool(OperationNode *node, const int /*thread_id*/, TaskPool *pool) { BLI_task_pool_push(pool, deg_task_run_func, node, false, nullptr); } @@ -70,7 +70,7 @@ enum class EvaluationStage { * involved. */ COPY_ON_WRITE, - /* Evaluate actual ID nodes visiblity based on the current state of animation and drivers. */ + /* Evaluate actual ID nodes visibility based on the current state of animation and drivers. */ DYNAMIC_VISIBILITY, /* Threaded evaluation of all possible operations. */ @@ -111,7 +111,8 @@ void evaluate_node(const DepsgraphEvalState *state, OperationNode *operation_nod * times. * This is a thread-safe modification as the node's flags are only read for a non-scheduled nodes * and this node has been scheduled. */ - operation_node->flag &= ~DEPSOP_FLAG_NEEDS_UPDATE; + operation_node->flag &= ~(DEPSOP_FLAG_DIRECTLY_MODIFIED | DEPSOP_FLAG_NEEDS_UPDATE | + DEPSOP_FLAG_USER_MODIFIED); } void deg_task_run_func(TaskPool *pool, void *taskdata) @@ -136,7 +137,7 @@ bool check_operation_node_visible(const DepsgraphEvalState *state, OperationNode return true; } - /* Special case for dynamic visiblity pass: the actual visibility is not yet known, so limit to + /* Special case for dynamic visibility pass: the actual visibility is not yet known, so limit to * only operations which affects visibility. */ if (state->stage == EvaluationStage::DYNAMIC_VISIBILITY) { return op_node->flag & OperationFlag::DEPSOP_FLAG_AFFECTS_VISIBILITY; @@ -272,7 +273,7 @@ void schedule_node(DepsgraphEvalState *state, return; } /* Actually schedule the node. */ - bool is_scheduled = atomic_fetch_and_or_uint8((uint8_t *)&node->scheduled, (uint8_t) true); + bool is_scheduled = atomic_fetch_and_or_uint8((uint8_t *)&node->scheduled, uint8_t(true)); if (!is_scheduled) { if (node->is_noop()) { /* skip NOOP node, schedule children right away */ @@ -436,7 +437,7 @@ void deg_evaluate_on_refresh(Depsgraph *graph) evaluate_graph_threaded_stage(&state, task_pool, EvaluationStage::COPY_ON_WRITE); - if (graph->has_animated_visibility) { + if (graph->has_animated_visibility || graph->need_update_nodes_visibility) { /* Update pending parents including only the ones which are affecting operations which are * affecting visibility. */ state.need_update_pending_parents = true; @@ -466,7 +467,7 @@ void deg_evaluate_on_refresh(Depsgraph *graph) deg_eval_stats_aggregate(graph); } - /* Clear any uncleared tags - just in case. */ + /* Clear any uncleared tags. */ deg_graph_clear_tags(graph); graph->is_evaluating = false; diff --git a/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc b/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc index 058f57e5a61..4e07a7b173c 100644 --- a/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc +++ b/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc @@ -414,13 +414,16 @@ void scene_remove_all_bases(Scene *scene_cow) /* Makes it so given view layer only has bases corresponding to enabled * objects. */ -void view_layer_remove_disabled_bases(const Depsgraph *depsgraph, ViewLayer *view_layer) +void view_layer_remove_disabled_bases(const Depsgraph *depsgraph, + const Scene *scene, + ViewLayer *view_layer) { if (view_layer == nullptr) { return; } ListBase enabled_bases = {nullptr, nullptr}; - LISTBASE_FOREACH_MUTABLE (Base *, base, &view_layer->object_bases) { + BKE_view_layer_synced_ensure(scene, view_layer); + LISTBASE_FOREACH_MUTABLE (Base *, base, BKE_view_layer_object_bases_get(view_layer)) { /* TODO(sergey): Would be cool to optimize this somehow, or make it so * builder tags bases. * @@ -479,7 +482,7 @@ void scene_setup_view_layers_after_remap(const Depsgraph *depsgraph, const ViewLayer *view_layer_orig = get_original_view_layer(depsgraph, id_node); ViewLayer *view_layer_eval = reinterpret_cast<ViewLayer *>(scene_cow->view_layers.first); view_layer_update_orig_base_pointers(view_layer_orig, view_layer_eval); - view_layer_remove_disabled_bases(depsgraph, view_layer_eval); + view_layer_remove_disabled_bases(depsgraph, scene_cow, view_layer_eval); /* TODO(sergey): Remove objects from collections as well. * Not a HUGE deal for now, nobody is looking into those CURRENTLY. * Still not an excuse to have those. */ diff --git a/source/blender/depsgraph/intern/eval/deg_eval_flush.cc b/source/blender/depsgraph/intern/eval/deg_eval_flush.cc index de4e26aa4b5..a5b29ae56a9 100644 --- a/source/blender/depsgraph/intern/eval/deg_eval_flush.cc +++ b/source/blender/depsgraph/intern/eval/deg_eval_flush.cc @@ -129,7 +129,18 @@ inline void flush_handle_component_node(IDNode *id_node, * * TODO(sergey): Make this a more generic solution. */ if (!ELEM(comp_node->type, NodeType::PARTICLE_SETTINGS, NodeType::PARTICLE_SYSTEM)) { + const bool is_geometry_component = comp_node->type == NodeType::GEOMETRY; for (OperationNode *op : comp_node->operations) { + /* Special case for the visibility operation in the geometry component. + * + * This operation is a part of the geometry component so that manual tag for geometry recalc + * ensures that the visibility is re-evaluated. This operation is not to be re-evaluated when + * an update is flushed to the geometry component via a time dependency or a driver targeting + * a modifier. Skipping update in this case avoids CPU time unnecessarily spent looping over + * modifiers and looking up operations by name in the visibility evaluation function. */ + if (is_geometry_component && op->opcode == OperationCode::VISIBILITY) { + continue; + } op->flag |= DEPSOP_FLAG_NEEDS_UPDATE; } } @@ -224,7 +235,7 @@ void flush_editors_id_update(Depsgraph *graph, const DEGEditorUpdateContext *upd EVAL, "Accumulated recalc bits for %s: %u\n", id_orig->name, - (unsigned int)id_cow->recalc); + uint(id_cow->recalc)); /* Inform editors. Only if the data-block is being evaluated a second * time, to distinguish between user edits and initial evaluation when @@ -378,11 +389,6 @@ void deg_graph_flush_updates(Depsgraph *graph) void deg_graph_clear_tags(Depsgraph *graph) { - /* Go over all operation nodes, clearing tags. */ - for (OperationNode *node : graph->operations) { - node->flag &= ~(DEPSOP_FLAG_DIRECTLY_MODIFIED | DEPSOP_FLAG_NEEDS_UPDATE | - DEPSOP_FLAG_USER_MODIFIED); - } /* Clear any entry tags which haven't been flushed. */ graph->entry_tags.clear(); diff --git a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup.cc b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup.cc index 96ab9388023..9ccd7ed447b 100644 --- a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup.cc +++ b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup.cc @@ -62,6 +62,7 @@ void RuntimeBackup::init_from_id(ID *id) break; case ID_GD: gpencil_backup.init_from_gpencil(reinterpret_cast<bGPdata *>(id)); + break; default: break; } @@ -104,6 +105,7 @@ void RuntimeBackup::restore_to_id(ID *id) break; case ID_GD: gpencil_backup.restore_to_gpencil(reinterpret_cast<bGPdata *>(id)); + break; default: break; } diff --git a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_gpencil.cc b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_gpencil.cc index c5def69a70f..e3d7593eb3c 100644 --- a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_gpencil.cc +++ b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_gpencil.cc @@ -19,7 +19,7 @@ GPencilBackup::GPencilBackup(const Depsgraph *depsgraph) : depsgraph(depsgraph) { } -void GPencilBackup::init_from_gpencil(bGPdata *UNUSED(gpd)) +void GPencilBackup::init_from_gpencil(bGPdata * /*gpd*/) { } diff --git a/source/blender/depsgraph/intern/eval/deg_eval_visibility.cc b/source/blender/depsgraph/intern/eval/deg_eval_visibility.cc index 8bf26e45e2a..a056ba1dfa7 100644 --- a/source/blender/depsgraph/intern/eval/deg_eval_visibility.cc +++ b/source/blender/depsgraph/intern/eval/deg_eval_visibility.cc @@ -8,6 +8,7 @@ #include "intern/eval/deg_eval_visibility.h" #include "DNA_layer_types.h" +#include "DNA_modifier_types.h" #include "DNA_object_types.h" #include "BLI_assert.h" @@ -47,6 +48,42 @@ void deg_evaluate_object_node_visibility(::Depsgraph *depsgraph, IDNode *id_node } } +void deg_evaluate_object_modifiers_mode_node_visibility(::Depsgraph *depsgraph, IDNode *id_node) +{ + BLI_assert(GS(id_node->id_cow->name) == ID_OB); + + Depsgraph *graph = reinterpret_cast<Depsgraph *>(depsgraph); + const Object *object = reinterpret_cast<const Object *>(id_node->id_cow); + + DEG_debug_print_eval(depsgraph, __func__, object->id.name, &object->id); + + if (BLI_listbase_is_empty(&object->modifiers)) { + return; + } + + const ModifierMode modifier_mode = (graph->mode == DAG_EVAL_VIEWPORT) ? eModifierMode_Realtime : + eModifierMode_Render; + + const ComponentNode *geometry_component = id_node->find_component(NodeType::GEOMETRY); + LISTBASE_FOREACH (ModifierData *, modifier, &object->modifiers) { + OperationNode *modifier_node = geometry_component->find_operation(OperationCode::MODIFIER, + modifier->name); + + BLI_assert_msg(modifier_node != nullptr, + "Modifier node in depsgraph is not found. Likely due to missing " + "DEG_relations_tag_update()."); + + const bool modifier_enabled = modifier->mode & modifier_mode; + const int mute_flag = modifier_enabled ? 0 : DEPSOP_FLAG_MUTE; + if ((modifier_node->flag & DEPSOP_FLAG_MUTE) != mute_flag) { + modifier_node->flag &= ~DEPSOP_FLAG_MUTE; + modifier_node->flag |= mute_flag; + + graph->need_update_nodes_visibility = true; + } + } +} + void deg_graph_flush_visibility_flags(Depsgraph *graph) { enum { @@ -57,6 +94,27 @@ void deg_graph_flush_visibility_flags(Depsgraph *graph) for (ComponentNode *comp_node : id_node->components.values()) { comp_node->possibly_affects_visible_id = id_node->is_visible_on_build; comp_node->affects_visible_id = id_node->is_visible_on_build && id_node->is_enabled_on_eval; + + /* Visibility component is always to be considered to have the same visibility as the + * `id_node->is_visible_on_build`. This is because the visibility is to be evaluated + * regardless of its current state as it might get changed due to animation. */ + if (comp_node->type == NodeType::VISIBILITY) { + comp_node->affects_visible_id = id_node->is_visible_on_build; + } + + /* Enforce "visibility" of the synchronization component. + * + * This component is never connected to other ID nodes, and hence can not be handled in the + * same way as other components needed for evaluation. It is only needed for proper + * evaluation of the ID node it belongs to. + * + * The design is such that the synchronization is supposed to happen whenever any part of the + * ID changed/evaluated. Here we mark the component as "visible" so that genetic recalc flag + * flushing and scheduling will handle the component in a generic manner. */ + if (comp_node->type == NodeType::SYNCHRONIZATION) { + comp_node->possibly_affects_visible_id = true; + comp_node->affects_visible_id = true; + } } } @@ -85,13 +143,40 @@ void deg_graph_flush_visibility_flags(Depsgraph *graph) if (rel->from->type == NodeType::OPERATION) { const OperationNode *op_to = reinterpret_cast<const OperationNode *>(rel->to); const ComponentNode *comp_to = op_to->owner; + + /* Ignore the synchronization target. + * It is always visible and should not affect on other components. */ + if (comp_to->type == NodeType::SYNCHRONIZATION) { + continue; + } + OperationNode *op_from = reinterpret_cast<OperationNode *>(rel->from); ComponentNode *comp_from = op_from->owner; + op_from->flag |= (op_to->flag & OperationFlag::DEPSOP_FLAG_AFFECTS_VISIBILITY); + + if (rel->flag & RELATION_NO_VISIBILITY_CHANGE) { + continue; + } + const bool target_possibly_affects_visible_id = comp_to->possibly_affects_visible_id; - const bool target_affects_visible_id = comp_to->affects_visible_id; - op_from->flag |= (op_to->flag & OperationFlag::DEPSOP_FLAG_AFFECTS_VISIBILITY); + bool target_affects_visible_id = comp_to->affects_visible_id; + + /* This is a bit arbitrary but the idea here is following: + * + * - When another object is used by a disabled modifier we do not want that object to + * be considered needed for evaluation. + * + * - However, we do not want to take mute flag during visibility propagation within the + * same object. Otherwise drivers and transform dependencies of the geometry component + * entry component might not be properly handled. + * + * This code works fine for muting modifiers, but might need tweaks when mute is used for + * something else. */ + if (comp_from != comp_to && (op_to->flag & DEPSOP_FLAG_MUTE)) { + target_affects_visible_id = false; + } /* Visibility component forces all components of the current ID to be considered as * affecting directly visible. */ diff --git a/source/blender/depsgraph/intern/eval/deg_eval_visibility.h b/source/blender/depsgraph/intern/eval/deg_eval_visibility.h index 9e9db8ab34a..6544654f3cf 100644 --- a/source/blender/depsgraph/intern/eval/deg_eval_visibility.h +++ b/source/blender/depsgraph/intern/eval/deg_eval_visibility.h @@ -18,6 +18,9 @@ struct IDNode; * restriction flags. */ void deg_evaluate_object_node_visibility(::Depsgraph *depsgraph, IDNode *id_node); +/* Update node visibility flags based on actual modifiers mode flags. */ +void deg_evaluate_object_modifiers_mode_node_visibility(::Depsgraph *depsgraph, IDNode *id_node); + /* Flush both static and dynamic visibility flags from leaves up to the roots, making it possible * to know whether a node has affect on something (potentially) visible. */ void deg_graph_flush_visibility_flags(Depsgraph *graph); diff --git a/source/blender/depsgraph/intern/node/deg_node.cc b/source/blender/depsgraph/intern/node/deg_node.cc index 7a515424e06..6303b22cac3 100644 --- a/source/blender/depsgraph/intern/node/deg_node.cc +++ b/source/blender/depsgraph/intern/node/deg_node.cc @@ -100,6 +100,8 @@ const char *nodeTypeAsString(NodeType type) return "SIMULATION"; case NodeType::NTREE_OUTPUT: return "NTREE_OUTPUT"; + case NodeType::NTREE_GEOMETRY_PREPROCESS: + return "NTREE_GEOMETRY_PREPROCESS"; /* Total number of meaningful node types. */ case NodeType::NUM_TYPES: @@ -158,6 +160,7 @@ eDepsSceneComponentType nodeTypeToSceneComponent(NodeType type) case NodeType::CACHE: case NodeType::SIMULATION: case NodeType::NTREE_OUTPUT: + case NodeType::NTREE_GEOMETRY_PREPROCESS: return DEG_SCENE_COMP_PARAMETERS; case NodeType::VISIBILITY: @@ -232,6 +235,7 @@ eDepsObjectComponentType nodeTypeToObjectComponent(NodeType type) case NodeType::SYNCHRONIZATION: case NodeType::SIMULATION: case NodeType::NTREE_OUTPUT: + case NodeType::NTREE_GEOMETRY_PREPROCESS: case NodeType::UNDEFINED: case NodeType::NUM_TYPES: return DEG_OB_COMP_PARAMETERS; diff --git a/source/blender/depsgraph/intern/node/deg_node.h b/source/blender/depsgraph/intern/node/deg_node.h index 5b33528df33..e31c1769a2a 100644 --- a/source/blender/depsgraph/intern/node/deg_node.h +++ b/source/blender/depsgraph/intern/node/deg_node.h @@ -64,7 +64,7 @@ enum class NodeType { ANIMATION, /* Transform Component (Parenting/Constraints) */ TRANSFORM, - /* Geometry Component (#Mesh / #DispList) */ + /* Geometry Component (#Mesh, #Curves, etc.) */ GEOMETRY, /* Sequencer Component (Scene Only) */ SEQUENCER, @@ -130,6 +130,8 @@ enum class NodeType { SIMULATION, /* Node tree output component. */ NTREE_OUTPUT, + /* Preprocessing for geometry node trees before they can be evaluated. */ + NTREE_GEOMETRY_PREPROCESS, /* Total number of meaningful node types. */ NUM_TYPES, diff --git a/source/blender/depsgraph/intern/node/deg_node_component.cc b/source/blender/depsgraph/intern/node/deg_node_component.cc index 32942f45a4a..718097b4ef8 100644 --- a/source/blender/depsgraph/intern/node/deg_node_component.cc +++ b/source/blender/depsgraph/intern/node/deg_node_component.cc @@ -48,18 +48,18 @@ ComponentNode::OperationIDKey::OperationIDKey(OperationCode opcode, const char * string ComponentNode::OperationIDKey::identifier() const { - const string codebuf = to_string(static_cast<int>(opcode)); + const string codebuf = to_string(int(opcode)); return "OperationIDKey(" + codebuf + ", " + name + ")"; } bool ComponentNode::OperationIDKey::operator==(const OperationIDKey &other) const { - return (opcode == other.opcode) && (STREQ(name, other.name)) && (name_tag == other.name_tag); + return (opcode == other.opcode) && STREQ(name, other.name) && (name_tag == other.name_tag); } uint64_t ComponentNode::OperationIDKey::hash() const { - const int opcode_as_int = static_cast<int>(opcode); + const int opcode_as_int = int(opcode); return BLI_ghashutil_combine_hash( name_tag, BLI_ghashutil_combine_hash(BLI_ghashutil_uinthash(opcode_as_int), @@ -90,10 +90,11 @@ ComponentNode::~ComponentNode() string ComponentNode::identifier() const { - const string idname = this->owner->name; - const string typebuf = "" + to_string(static_cast<int>(type)) + ")"; - return typebuf + name + " : " + idname + - "( affects_visible_id: " + (affects_visible_id ? "true" : "false") + ")"; + const string type_name = type_get_factory(type)->type_name(); + const string name_part = name[0] ? (string(" '") + name + "'") : ""; + + return "[" + type_name + "]" + name_part + " : " + + "(affects_visible_id: " + (affects_visible_id ? "true" : "false") + ")"; } OperationNode *ComponentNode::find_operation(OperationIDKey key) const @@ -218,10 +219,9 @@ void ComponentNode::clear_operations() void ComponentNode::tag_update(Depsgraph *graph, eUpdateSource source) { - OperationNode *entry_op = get_entry_operation(); - if (entry_op != nullptr && entry_op->flag & DEPSOP_FLAG_NEEDS_UPDATE) { - return; - } + /* Note that the node might already be tagged for an update due invisible state of the node + * during previous dependency evaluation. Here the node gets re-tagged, so we need to give + * the evaluated clues that evaluation needs to happen again. */ for (OperationNode *op_node : operations) { op_node->tag_update(graph, source); } @@ -338,6 +338,7 @@ DEG_COMPONENT_NODE_DEFINE(GenericDatablock, GENERIC_DATABLOCK, 0); DEG_COMPONENT_NODE_DEFINE(Visibility, VISIBILITY, 0); DEG_COMPONENT_NODE_DEFINE(Simulation, SIMULATION, 0); DEG_COMPONENT_NODE_DEFINE(NTreeOutput, NTREE_OUTPUT, ID_RECALC_NTREE_OUTPUT); +DEG_COMPONENT_NODE_DEFINE(NTreeGeometryPreprocess, NTREE_GEOMETRY_PREPROCESS, 0); /** \} */ @@ -372,6 +373,7 @@ void deg_register_component_depsnodes() register_node_typeinfo(&DNTI_VISIBILITY); register_node_typeinfo(&DNTI_SIMULATION); register_node_typeinfo(&DNTI_NTREE_OUTPUT); + register_node_typeinfo(&DNTI_NTREE_GEOMETRY_PREPROCESS); } /** \} */ diff --git a/source/blender/depsgraph/intern/node/deg_node_component.h b/source/blender/depsgraph/intern/node/deg_node_component.h index a616dfdfe4c..44c63822ca3 100644 --- a/source/blender/depsgraph/intern/node/deg_node_component.h +++ b/source/blender/depsgraph/intern/node/deg_node_component.h @@ -201,31 +201,14 @@ DEG_COMPONENT_NODE_DECLARE_GENERIC(ShadingParameters); DEG_COMPONENT_NODE_DECLARE_GENERIC(Transform); DEG_COMPONENT_NODE_DECLARE_NO_COW_TAG_ON_UPDATE(ObjectFromLayer); DEG_COMPONENT_NODE_DECLARE_GENERIC(Dupli); +DEG_COMPONENT_NODE_DECLARE_GENERIC(Synchronization); DEG_COMPONENT_NODE_DECLARE_GENERIC(Audio); DEG_COMPONENT_NODE_DECLARE_GENERIC(Armature); DEG_COMPONENT_NODE_DECLARE_GENERIC(GenericDatablock); DEG_COMPONENT_NODE_DECLARE_NO_COW_TAG_ON_UPDATE(Visibility); DEG_COMPONENT_NODE_DECLARE_GENERIC(Simulation); DEG_COMPONENT_NODE_DECLARE_GENERIC(NTreeOutput); - -/* Synchronization Component. */ -struct SynchronizationComponentNode : public ComponentNode { - SynchronizationComponentNode() - { - /* Enforce "visibility" of the synchronization component. - * - * This component is never connected to other ID nodes, and hence can not be handled in the - * same way as other components needed for evaluation. It is only needed for proper - * evaluation of the ID node it belongs to. - * - * The design is such that the synchronization is supposed to happen whenever any part of the - * ID changed/evaluated. Here we mark the component as "visible" so that genetic recalc flag - * flushing and scheduling will handle the component in a generic manner. */ - affects_visible_id = true; - } - - DEG_COMPONENT_NODE_DECLARE; -}; +DEG_COMPONENT_NODE_DECLARE_GENERIC(NTreeGeometryPreprocess); /* Bone Component */ struct BoneComponentNode : public ComponentNode { diff --git a/source/blender/depsgraph/intern/node/deg_node_factory.cc b/source/blender/depsgraph/intern/node/deg_node_factory.cc index bcdfdbec604..4c08d4ee7bb 100644 --- a/source/blender/depsgraph/intern/node/deg_node_factory.cc +++ b/source/blender/depsgraph/intern/node/deg_node_factory.cc @@ -10,19 +10,19 @@ namespace blender::deg { /* Global type registry */ -static DepsNodeFactory *node_typeinfo_registry[static_cast<int>(NodeType::NUM_TYPES)] = {nullptr}; +static DepsNodeFactory *node_typeinfo_registry[int(NodeType::NUM_TYPES)] = {nullptr}; void register_node_typeinfo(DepsNodeFactory *factory) { BLI_assert(factory != nullptr); - const int type_as_int = static_cast<int>(factory->type()); + const int type_as_int = int(factory->type()); node_typeinfo_registry[type_as_int] = factory; } DepsNodeFactory *type_get_factory(const NodeType type) { /* Look up type - at worst, it doesn't exist in table yet, and we fail. */ - const int type_as_int = static_cast<int>(type); + const int type_as_int = int(type); return node_typeinfo_registry[type_as_int]; } diff --git a/source/blender/depsgraph/intern/node/deg_node_factory_impl.h b/source/blender/depsgraph/intern/node/deg_node_factory_impl.h index d9d0a1c1e3e..5059368120e 100644 --- a/source/blender/depsgraph/intern/node/deg_node_factory_impl.h +++ b/source/blender/depsgraph/intern/node/deg_node_factory_impl.h @@ -34,15 +34,8 @@ Node *DepsNodeFactoryImpl<ModeObjectType>::create_node(const ID *id, const char *name) const { Node *node = new ModeObjectType(); - /* Populate base node settings. */ node->type = type(); - /* Set name if provided, or use default type name. */ - if (name[0] != '\0') { - node->name = name; - } - else { - node->name = type_name(); - } + node->name = name; node->init(id, subdata); return node; } diff --git a/source/blender/depsgraph/intern/node/deg_node_id.cc b/source/blender/depsgraph/intern/node/deg_node_id.cc index 735d606ac9e..a37feb7b95d 100644 --- a/source/blender/depsgraph/intern/node/deg_node_id.cc +++ b/source/blender/depsgraph/intern/node/deg_node_id.cc @@ -52,12 +52,12 @@ bool IDNode::ComponentIDKey::operator==(const ComponentIDKey &other) const uint64_t IDNode::ComponentIDKey::hash() const { - const int type_as_int = static_cast<int>(type); + const int type_as_int = int(type); return BLI_ghashutil_combine_hash(BLI_ghashutil_uinthash(type_as_int), BLI_ghashutil_strhash_p(name)); } -void IDNode::init(const ID *id, const char *UNUSED(subdata)) +void IDNode::init(const ID *id, const char * /*subdata*/) { BLI_assert(id != nullptr); /* Store ID-pointer. */ @@ -190,7 +190,7 @@ IDComponentsMask IDNode::get_visible_components_mask() const IDComponentsMask result = 0; for (ComponentNode *comp_node : components.values()) { if (comp_node->possibly_affects_visible_id) { - const int component_type_as_int = static_cast<int>(comp_node->type); + const int component_type_as_int = int(comp_node->type); BLI_assert(component_type_as_int < 64); result |= (1ULL << component_type_as_int); } diff --git a/source/blender/depsgraph/intern/node/deg_node_operation.cc b/source/blender/depsgraph/intern/node/deg_node_operation.cc index 3029379d141..d5401a6b0d1 100644 --- a/source/blender/depsgraph/intern/node/deg_node_operation.cc +++ b/source/blender/depsgraph/intern/node/deg_node_operation.cc @@ -84,6 +84,8 @@ const char *operationCodeAsString(OperationCode opcode) /* Geometry. */ case OperationCode::GEOMETRY_EVAL_INIT: return "GEOMETRY_EVAL_INIT"; + case OperationCode::MODIFIER: + return "MODIFIER"; case OperationCode::GEOMETRY_EVAL: return "GEOMETRY_EVAL"; case OperationCode::GEOMETRY_EVAL_DONE: @@ -171,6 +173,8 @@ const char *operationCodeAsString(OperationCode opcode) /* Node Tree. */ case OperationCode::NTREE_OUTPUT: return "NTREE_OUTPUT"; + case OperationCode::NTREE_GEOMETRY_PREPROCESS: + return "NTREE_GEOMETRY_PREPROCESS"; /* Movie clip. */ case OperationCode::MOVIECLIP_EVAL: return "MOVIECLIP_EVAL"; @@ -218,9 +222,23 @@ string OperationNode::full_identifier() const void OperationNode::tag_update(Depsgraph *graph, eUpdateSource source) { - if ((flag & DEPSOP_FLAG_NEEDS_UPDATE) == 0) { - graph->add_entry_tag(this); + /* Ensure that there is an entry tag for this update. + * + * Note that the node might already be tagged for an update due invisible state of the node + * during previous dependency evaluation. Here the node gets re-tagged, so we need to give + * the evaluated clues that evaluation needs to happen again. */ + graph->add_entry_tag(this); + + /* Enforce dynamic visibility code-path update. + * This ensures visibility flags are consistently propagated throughout the dependency graph when + * there is no animated visibility in the graph. + * + * For example this ensures that graph is updated properly when manually toggling non-animated + * modifier visibility. */ + if (opcode == OperationCode::VISIBILITY) { + graph->need_update_nodes_visibility = true; } + /* Tag for update, but also note that this was the source of an update. */ flag |= (DEPSOP_FLAG_NEEDS_UPDATE | DEPSOP_FLAG_DIRECTLY_MODIFIED); switch (source) { diff --git a/source/blender/depsgraph/intern/node/deg_node_operation.h b/source/blender/depsgraph/intern/node/deg_node_operation.h index 656b27550f6..b0685ac0351 100644 --- a/source/blender/depsgraph/intern/node/deg_node_operation.h +++ b/source/blender/depsgraph/intern/node/deg_node_operation.h @@ -84,6 +84,8 @@ enum class OperationCode { /* Initialize evaluation of the geometry. Is an entry operation of geometry * component. */ GEOMETRY_EVAL_INIT, + /* Modifier. */ + MODIFIER, /* Evaluate the whole geometry, including modifiers. */ GEOMETRY_EVAL, /* Evaluation of geometry is completely done. */ @@ -163,6 +165,7 @@ enum class OperationCode { /* Node Tree. ----------------------------------------------------------- */ NTREE_OUTPUT, + NTREE_GEOMETRY_PREPROCESS, /* Batch caches. -------------------------------------------------------- */ GEOMETRY_SELECT_UPDATE, @@ -217,6 +220,9 @@ enum OperationFlag { /* The operation directly or indirectly affects ID node visibility. */ DEPSOP_FLAG_AFFECTS_VISIBILITY = (1 << 4), + /* Evaluation of the node is temporarily disabled. */ + DEPSOP_FLAG_MUTE = (1 << 5), + /* Set of flags which gets flushed along the relations. */ DEPSOP_FLAG_FLUSH = (DEPSOP_FLAG_USER_MODIFIED), }; |