diff options
Diffstat (limited to 'source/blender/depsgraph/intern')
76 files changed, 1085 insertions, 667 deletions
diff --git a/source/blender/depsgraph/intern/builder/deg_builder.cc b/source/blender/depsgraph/intern/builder/deg_builder.cc index a3cd821e82f..097c377ece4 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" @@ -29,6 +30,7 @@ #include "intern/depsgraph_tag.h" #include "intern/depsgraph_type.h" #include "intern/eval/deg_eval_copy_on_write.h" +#include "intern/eval/deg_eval_visibility.h" #include "intern/node/deg_node.h" #include "intern/node/deg_node_component.h" #include "intern/node/deg_node_id.h" @@ -63,7 +65,7 @@ DepsgraphBuilder::DepsgraphBuilder(Main *bmain, Depsgraph *graph, DepsgraphBuild { } -bool DepsgraphBuilder::need_pull_base_into_graph(Base *base) +bool DepsgraphBuilder::need_pull_base_into_graph(const Base *base) { /* Simple check: enabled bases are always part of dependency graph. */ const int base_flag = (graph_->mode == DAG_EVAL_VIEWPORT) ? BASE_ENABLED_VIEWPORT : @@ -71,10 +73,15 @@ bool DepsgraphBuilder::need_pull_base_into_graph(Base *base) if (base->flag & base_flag) { return true; } + /* More involved check: since we don't support dynamic changes in dependency graph topology and * all visible objects are to be part of dependency graph, we pull all objects which has animated * visibility. */ - Object *object = base->object; + return is_object_visibility_animated(base->object); +} + +bool DepsgraphBuilder::is_object_visibility_animated(const Object *object) +{ AnimatedPropertyID property_id; if (graph_->mode == DAG_EVAL_VIEWPORT) { property_id = AnimatedPropertyID(&object->id, &RNA_Object, "hide_viewport"); @@ -89,7 +96,25 @@ bool DepsgraphBuilder::need_pull_base_into_graph(Base *base) return cache_->isPropertyAnimated(&object->id, property_id); } -bool DepsgraphBuilder::check_pchan_has_bbone(Object *object, const bPoseChannel *pchan) +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); if (pchan == nullptr || pchan->bone == nullptr) { @@ -109,12 +134,13 @@ bool DepsgraphBuilder::check_pchan_has_bbone(Object *object, const bPoseChannel cache_->isPropertyAnimated(&armature->id, property_id); } -bool DepsgraphBuilder::check_pchan_has_bbone_segments(Object *object, const bPoseChannel *pchan) +bool DepsgraphBuilder::check_pchan_has_bbone_segments(const Object *object, + const bPoseChannel *pchan) { return check_pchan_has_bbone(object, pchan); } -bool DepsgraphBuilder::check_pchan_has_bbone_segments(Object *object, const char *bone_name) +bool DepsgraphBuilder::check_pchan_has_bbone_segments(const Object *object, const char *bone_name) { const bPoseChannel *pchan = BKE_pose_channel_find_name(object->pose, bone_name); return check_pchan_has_bbone_segments(object, pchan); @@ -126,97 +152,9 @@ bool DepsgraphBuilder::check_pchan_has_bbone_segments(Object *object, const char /** \name Builder Finalizer. * \{ */ -namespace { - -void deg_graph_build_flush_visibility(Depsgraph *graph) -{ - enum { - DEG_NODE_VISITED = (1 << 0), - }; - - BLI_Stack *stack = BLI_stack_new(sizeof(OperationNode *), "DEG flush layers stack"); - for (IDNode *id_node : graph->id_nodes) { - for (ComponentNode *comp_node : id_node->components.values()) { - comp_node->affects_directly_visible |= id_node->is_directly_visible; - - /* 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->affects_directly_visible = true; - } - } - } - - for (OperationNode *op_node : graph->operations) { - op_node->custom_flags = 0; - op_node->num_links_pending = 0; - for (Relation *rel : op_node->outlinks) { - if ((rel->from->type == NodeType::OPERATION) && (rel->flag & RELATION_FLAG_CYCLIC) == 0) { - ++op_node->num_links_pending; - } - } - if (op_node->num_links_pending == 0) { - BLI_stack_push(stack, &op_node); - op_node->custom_flags |= DEG_NODE_VISITED; - } - } - - while (!BLI_stack_is_empty(stack)) { - OperationNode *op_node; - BLI_stack_pop(stack, &op_node); - /* Flush layers to parents. */ - for (Relation *rel : op_node->inlinks) { - if (rel->from->type == NodeType::OPERATION) { - OperationNode *op_from = (OperationNode *)rel->from; - ComponentNode *comp_from = op_from->owner; - const bool target_directly_visible = op_node->owner->affects_directly_visible; - - /* Visibility component forces all components of the current ID to be considered as - * affecting directly visible. */ - if (comp_from->type == NodeType::VISIBILITY) { - if (target_directly_visible) { - IDNode *id_node_from = comp_from->owner; - for (ComponentNode *comp_node : id_node_from->components.values()) { - comp_node->affects_directly_visible |= target_directly_visible; - } - } - } - else { - comp_from->affects_directly_visible |= target_directly_visible; - } - } - } - /* Schedule parent nodes. */ - for (Relation *rel : op_node->inlinks) { - if (rel->from->type == NodeType::OPERATION) { - OperationNode *op_from = (OperationNode *)rel->from; - if ((rel->flag & RELATION_FLAG_CYCLIC) == 0) { - BLI_assert(op_from->num_links_pending > 0); - --op_from->num_links_pending; - } - if ((op_from->num_links_pending == 0) && (op_from->custom_flags & DEG_NODE_VISITED) == 0) { - BLI_stack_push(stack, &op_from); - op_from->custom_flags |= DEG_NODE_VISITED; - } - } - } - } - BLI_stack_free(stack); -} - -} // namespace - void deg_graph_build_finalize(Main *bmain, Depsgraph *graph) { - /* Make sure dependencies of visible ID data-blocks are visible. */ - deg_graph_build_flush_visibility(graph); + deg_graph_flush_visibility_flags(graph); deg_graph_remove_unused_noops(graph); /* Re-tag IDs for update if it was tagged before the relations diff --git a/source/blender/depsgraph/intern/builder/deg_builder.h b/source/blender/depsgraph/intern/builder/deg_builder.h index 8fbe255ed9d..5d043f1fd3a 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder.h +++ b/source/blender/depsgraph/intern/builder/deg_builder.h @@ -10,11 +10,11 @@ struct Base; struct ID; struct Main; +struct ModifierData; struct Object; struct bPoseChannel; -namespace blender { -namespace deg { +namespace blender::deg { struct Depsgraph; class DepsgraphBuilderCache; @@ -23,11 +23,14 @@ class DepsgraphBuilder { public: virtual ~DepsgraphBuilder() = default; - virtual bool need_pull_base_into_graph(Base *base); + virtual bool need_pull_base_into_graph(const Base *base); - virtual bool check_pchan_has_bbone(Object *object, const bPoseChannel *pchan); - virtual bool check_pchan_has_bbone_segments(Object *object, const bPoseChannel *pchan); - virtual bool check_pchan_has_bbone_segments(Object *object, const char *bone_name); + 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); + virtual bool check_pchan_has_bbone_segments(const Object *object, const char *bone_name); protected: /* NOTE: The builder does NOT take ownership over any of those resources. */ @@ -43,5 +46,4 @@ bool deg_check_id_in_depsgraph(const Depsgraph *graph, ID *id_orig); bool deg_check_base_in_depsgraph(const Depsgraph *graph, Base *base); void deg_graph_build_finalize(Main *bmain, Depsgraph *graph); -} // namespace deg -} // namespace blender +} // namespace blender::deg diff --git a/source/blender/depsgraph/intern/builder/deg_builder_cache.cc b/source/blender/depsgraph/intern/builder/deg_builder_cache.cc index 7f88f54fdca..129e0093d11 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. */ @@ -35,13 +37,13 @@ AnimatedPropertyID::AnimatedPropertyID(const PointerRNA &pointer_rna, { } -AnimatedPropertyID::AnimatedPropertyID(ID *id, StructRNA *type, const char *property_name) +AnimatedPropertyID::AnimatedPropertyID(const ID *id, StructRNA *type, const char *property_name) : data(id) { property_rna = RNA_struct_type_find_property(type, property_name); } -AnimatedPropertyID::AnimatedPropertyID(ID * /*id*/, +AnimatedPropertyID::AnimatedPropertyID(const ID * /*id*/, StructRNA *type, void *data, const char *property_name) @@ -100,13 +102,13 @@ AnimatedPropertyStorage::AnimatedPropertyStorage() : is_fully_initialized(false) { } -void AnimatedPropertyStorage::initializeFromID(DepsgraphBuilderCache *builder_cache, ID *id) +void AnimatedPropertyStorage::initializeFromID(DepsgraphBuilderCache *builder_cache, const ID *id) { AnimatedPropertyCallbackData data; - RNA_id_pointer_create(id, &data.pointer_rna); + RNA_id_pointer_create(const_cast<ID *>(id), &data.pointer_rna); data.animated_property_storage = this; data.builder_cache = builder_cache; - BKE_fcurves_id_cb(id, animated_property_cb, &data); + BKE_fcurves_id_cb(const_cast<ID *>(id), animated_property_cb, &data); } void AnimatedPropertyStorage::tagPropertyAsAnimated(const AnimatedPropertyID &property_id) @@ -147,13 +149,14 @@ DepsgraphBuilderCache::~DepsgraphBuilderCache() } } -AnimatedPropertyStorage *DepsgraphBuilderCache::ensureAnimatedPropertyStorage(ID *id) +AnimatedPropertyStorage *DepsgraphBuilderCache::ensureAnimatedPropertyStorage(const ID *id) { return animated_property_storage_map_.lookup_or_add_cb( id, []() { return new AnimatedPropertyStorage(); }); } -AnimatedPropertyStorage *DepsgraphBuilderCache::ensureInitializedAnimatedPropertyStorage(ID *id) +AnimatedPropertyStorage *DepsgraphBuilderCache::ensureInitializedAnimatedPropertyStorage( + const ID *id) { AnimatedPropertyStorage *animated_property_storage = ensureAnimatedPropertyStorage(id); if (!animated_property_storage->is_fully_initialized) { diff --git a/source/blender/depsgraph/intern/builder/deg_builder_cache.h b/source/blender/depsgraph/intern/builder/deg_builder_cache.h index 2d2bdeaf825..d85269c0f8b 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_cache.h +++ b/source/blender/depsgraph/intern/builder/deg_builder_cache.h @@ -17,8 +17,7 @@ struct ID; struct PointerRNA; struct PropertyRNA; -namespace blender { -namespace deg { +namespace blender::deg { class DepsgraphBuilderCache; @@ -28,14 +27,14 @@ class AnimatedPropertyID { AnimatedPropertyID(); AnimatedPropertyID(const PointerRNA *pointer_rna, const PropertyRNA *property_rna); AnimatedPropertyID(const PointerRNA &pointer_rna, const PropertyRNA *property_rna); - AnimatedPropertyID(ID *id, StructRNA *type, const char *property_name); - AnimatedPropertyID(ID *id, StructRNA *type, void *data, const char *property_name); + AnimatedPropertyID(const ID *id, StructRNA *type, const char *property_name); + AnimatedPropertyID(const ID *id, StructRNA *type, void *data, const char *property_name); uint64_t hash() const; friend bool operator==(const AnimatedPropertyID &a, const AnimatedPropertyID &b); /* Corresponds to PointerRNA.data. */ - void *data; + const void *data; const PropertyRNA *property_rna; MEM_CXX_CLASS_ALLOC_FUNCS("AnimatedPropertyID"); @@ -45,7 +44,7 @@ class AnimatedPropertyStorage { public: AnimatedPropertyStorage(); - void initializeFromID(DepsgraphBuilderCache *builder_cache, ID *id); + void initializeFromID(DepsgraphBuilderCache *builder_cache, const ID *id); void tagPropertyAsAnimated(const AnimatedPropertyID &property_id); void tagPropertyAsAnimated(const PointerRNA *pointer_rna, const PropertyRNA *property_rna); @@ -59,7 +58,7 @@ class AnimatedPropertyStorage { bool is_fully_initialized; /* indexed by PointerRNA.data. */ - Set<void *> animated_objects_set; + Set<const void *> animated_objects_set; Set<AnimatedPropertyID> animated_properties_set; MEM_CXX_CLASS_ALLOC_FUNCS("AnimatedPropertyStorage"); @@ -71,8 +70,8 @@ class DepsgraphBuilderCache { ~DepsgraphBuilderCache(); /* Makes sure storage for animated properties exists and initialized for the given ID. */ - AnimatedPropertyStorage *ensureAnimatedPropertyStorage(ID *id); - AnimatedPropertyStorage *ensureInitializedAnimatedPropertyStorage(ID *id); + AnimatedPropertyStorage *ensureAnimatedPropertyStorage(const ID *id); + AnimatedPropertyStorage *ensureInitializedAnimatedPropertyStorage(const ID *id); /* Shortcuts to go through ensureInitializedAnimatedPropertyStorage and its * isPropertyAnimated. @@ -82,7 +81,7 @@ class DepsgraphBuilderCache { * * TODO(sergey): Technically, this makes this class something else than just a cache, but what is * the better name? */ - template<typename... Args> bool isPropertyAnimated(ID *id, Args... args) + template<typename... Args> bool isPropertyAnimated(const ID *id, Args... args) { AnimatedPropertyStorage *animated_property_storage = ensureInitializedAnimatedPropertyStorage( id); @@ -96,10 +95,9 @@ class DepsgraphBuilderCache { return animated_property_storage->isAnyPropertyAnimated(ptr); } - Map<ID *, AnimatedPropertyStorage *> animated_property_storage_map_; + Map<const ID *, AnimatedPropertyStorage *> animated_property_storage_map_; MEM_CXX_CLASS_ALLOC_FUNCS("DepsgraphBuilderCache"); }; -} // namespace deg -} // namespace blender +} // namespace blender::deg diff --git a/source/blender/depsgraph/intern/builder/deg_builder_cycle.h b/source/blender/depsgraph/intern/builder/deg_builder_cycle.h index 8e94e0ae21f..83d25f8c23f 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_cycle.h +++ b/source/blender/depsgraph/intern/builder/deg_builder_cycle.h @@ -7,13 +7,11 @@ #pragma once -namespace blender { -namespace deg { +namespace blender::deg { struct Depsgraph; /* Detect and solve dependency cycles. */ void deg_graph_detect_cycles(Depsgraph *graph); -} // namespace deg -} // namespace blender +} // namespace blender::deg diff --git a/source/blender/depsgraph/intern/builder/deg_builder_map.h b/source/blender/depsgraph/intern/builder/deg_builder_map.h index 50ebadeb382..2b2b4d089e9 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_map.h +++ b/source/blender/depsgraph/intern/builder/deg_builder_map.h @@ -11,8 +11,7 @@ struct ID; -namespace blender { -namespace deg { +namespace blender::deg { class BuilderMap { public: @@ -60,5 +59,4 @@ class BuilderMap { Map<ID *, int> id_tags_; }; -} // namespace deg -} // namespace blender +} // 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 657bc3eb25c..67f454b608b 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc @@ -26,6 +26,7 @@ #include "DNA_collection_types.h" #include "DNA_constraint_types.h" #include "DNA_curve_types.h" +#include "DNA_curves_types.h" #include "DNA_effect_types.h" #include "DNA_gpencil_types.h" #include "DNA_key_types.h" @@ -92,6 +93,7 @@ #include "BKE_world.h" #include "RNA_access.h" +#include "RNA_path.h" #include "RNA_prototypes.h" #include "RNA_types.h" @@ -107,6 +109,7 @@ #include "intern/depsgraph_tag.h" #include "intern/depsgraph_type.h" #include "intern/eval/deg_eval_copy_on_write.h" +#include "intern/eval/deg_eval_visibility.h" #include "intern/node/deg_node.h" #include "intern/node/deg_node_component.h" #include "intern/node/deg_node_id.h" @@ -174,18 +177,32 @@ IDNode *DepsgraphNodeBuilder::add_id_node(ID *id) ComponentNode *comp_cow = id_node->add_component(NodeType::COPY_ON_WRITE); OperationNode *op_cow = comp_cow->add_operation( [id_node](::Depsgraph *depsgraph) { deg_evaluate_copy_on_write(depsgraph, id_node); }, - OperationCode::COPY_ON_WRITE, - "", - -1); + OperationCode::COPY_ON_WRITE); graph_->operations.append(op_cow); } ComponentNode *visibility_component = id_node->add_component(NodeType::VISIBILITY); - OperationNode *visibility_operation = visibility_component->add_operation( - nullptr, OperationCode::OPERATION, "", -1); + OperationNode *visibility_operation; + + /* Optimization: currently only objects need a special visibility evaluation. For the rest ID + * types keep the node as a NO-OP so that relations can still be routed, but without penalty + * during the graph evaluation. */ + if (id_type == ID_OB) { + visibility_operation = visibility_component->add_operation( + [id_node](::Depsgraph *depsgraph) { + deg_evaluate_object_node_visibility(depsgraph, id_node); + }, + OperationCode::VISIBILITY); + } + else { + visibility_operation = visibility_component->add_operation(nullptr, + OperationCode::VISIBILITY); + } + /* Pin the node so that it and its relations are preserved by the unused nodes/relations * deletion. This is mainly to make it easier to debug visibility. */ - visibility_operation->flag |= OperationFlag::DEPSOP_FLAG_PINNED; + visibility_operation->flag |= (OperationFlag::DEPSOP_FLAG_PINNED | + OperationFlag::DEPSOP_FLAG_AFFECTS_VISIBILITY); graph_->operations.append(visibility_operation); } return id_node; @@ -654,7 +671,7 @@ void DepsgraphNodeBuilder::build_collection(LayerCollection *from_layer_collecti IDNode *id_node; if (built_map_.checkIsBuiltAndTag(collection)) { id_node = find_id_node(&collection->id); - if (is_collection_visible && id_node->is_directly_visible == false && + if (is_collection_visible && id_node->is_visible_on_build == false && id_node->is_collection_fully_expanded == true) { /* Collection became visible, make sure nested collections and * objects are poked with the new visibility flag, since they @@ -671,7 +688,7 @@ void DepsgraphNodeBuilder::build_collection(LayerCollection *from_layer_collecti else { /* Collection itself. */ id_node = add_id_node(&collection->id); - id_node->is_directly_visible = is_collection_visible; + id_node->is_visible_on_build = is_collection_visible; build_idproperties(collection->id.properties); add_operation_node(&collection->id, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL_DONE); @@ -718,7 +735,7 @@ void DepsgraphNodeBuilder::build_object(int base_index, build_object_flags(base_index, object, linked_state); } id_node->linked_state = max(id_node->linked_state, linked_state); - id_node->is_directly_visible |= is_visible; + id_node->is_visible_on_build |= is_visible; id_node->has_base |= (base_index != -1); /* There is no relation path which will connect current object with all the ones which come @@ -737,10 +754,10 @@ void DepsgraphNodeBuilder::build_object(int base_index, * Probably need to assign that to something non-nullptr, but then the logic here will still be * somewhat weird. */ if (scene_ != nullptr && object == scene_->camera) { - id_node->is_directly_visible = true; + id_node->is_visible_on_build = true; } else { - id_node->is_directly_visible = is_visible; + id_node->is_visible_on_build = is_visible; } id_node->has_base |= (base_index != -1); /* Various flags, flushing from bases/collections. */ @@ -752,11 +769,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; @@ -860,6 +873,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) { @@ -1167,12 +1218,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); } } @@ -1548,8 +1603,14 @@ void DepsgraphNodeBuilder::build_object_data_geometry_datablock(ID *obdata) break; } case ID_CV: { + Curves *curves_id = reinterpret_cast<Curves *>(obdata); + op_node = add_operation_node(obdata, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL); op_node->set_as_entry(); + + if (curves_id->surface != nullptr) { + build_object(-1, curves_id->surface, DEG_ID_LINKED_INDIRECTLY, false); + } break; } case ID_PT: { @@ -1680,7 +1741,14 @@ void DepsgraphNodeBuilder::build_nodetree(bNodeTree *ntree) /* Animation, */ build_animdata(&ntree->id); /* Output update. */ - add_operation_node(&ntree->id, NodeType::NTREE_OUTPUT, OperationCode::NTREE_OUTPUT); + ID *id_cow = get_cow_id(&ntree->id); + add_operation_node(&ntree->id, + NodeType::NTREE_OUTPUT, + OperationCode::NTREE_OUTPUT, + [id_cow](::Depsgraph * /*depsgraph*/) { + bNodeTree *ntree_cow = reinterpret_cast<bNodeTree *>(id_cow); + bke::node_tree_runtime::handle_node_tree_output_changed(*ntree_cow); + }); /* nodetree's nodes... */ LISTBASE_FOREACH (bNode *, bnode, &ntree->nodes) { build_idproperties(bnode->prop); @@ -2057,9 +2125,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 be9983edf85..d5ac601ebff 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.h +++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.h @@ -50,8 +50,7 @@ struct bNodeTree; struct bPoseChannel; struct bSound; -namespace blender { -namespace deg { +namespace blender::deg { struct ComponentNode; struct Depsgraph; @@ -175,6 +174,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); @@ -306,5 +306,4 @@ class DepsgraphNodeBuilder : public DepsgraphBuilder { BuilderMap built_map_; }; -} // namespace deg -} // namespace blender +} // namespace blender::deg 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 32ec94211a0..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,16 +90,23 @@ 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)) { - /* NOTE: We consider object visible even if it's currently - * restricted by the base/restriction flags. Otherwise its drivers - * will never be evaluated. - * - * TODO(sergey): Need to go more granular on visibility checks. */ - build_object(base_index, base->object, linked_state, true); - base_index++; + if (!need_pull_base_into_graph(base)) { + continue; + } + + /* NOTE: We consider object visible even if it's currently + * restricted by the base/restriction flags. Otherwise its drivers + * will never be evaluated. + * + * TODO(sergey): Need to go more granular on visibility checks. */ + build_object(base_index, base->object, linked_state, true); + base_index++; + + if (!graph_->has_animated_visibility) { + graph_->has_animated_visibility |= is_object_visibility_animated(base->object); } } build_layer_collections(&view_layer->layer_collections); diff --git a/source/blender/depsgraph/intern/builder/deg_builder_pchanmap.h b/source/blender/depsgraph/intern/builder/deg_builder_pchanmap.h index 2f98c8b419c..afb3a3c22bd 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_pchanmap.h +++ b/source/blender/depsgraph/intern/builder/deg_builder_pchanmap.h @@ -9,8 +9,7 @@ #include "intern/depsgraph_type.h" -namespace blender { -namespace deg { +namespace blender::deg { struct RootPChanMap { /** Debug contents of map. */ @@ -30,5 +29,4 @@ struct RootPChanMap { Map<StringRefNull, Set<StringRefNull>> map_; }; -} // namespace deg -} // namespace blender +} // namespace blender::deg diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc index c13c6d2f870..39dad18ff2b 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc @@ -27,6 +27,7 @@ #include "DNA_collection_types.h" #include "DNA_constraint_types.h" #include "DNA_curve_types.h" +#include "DNA_curves_types.h" #include "DNA_effect_types.h" #include "DNA_gpencil_types.h" #include "DNA_key_types.h" @@ -238,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; } @@ -297,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); } @@ -692,7 +689,7 @@ void DepsgraphRelationBuilder::build_object(Object *object) const BuilderStack::ScopedEntry stack_entry = stack_.trace(object->id); - /* Object Transforms */ + /* Object Transforms. */ OperationCode base_op = (object->parent) ? OperationCode::TRANSFORM_PARENT : OperationCode::TRANSFORM_LOCAL; OperationKey base_op_key(&object->id, NodeType::TRANSFORM, base_op); @@ -705,9 +702,12 @@ void DepsgraphRelationBuilder::build_object(Object *object) OperationKey final_transform_key( &object->id, NodeType::TRANSFORM, OperationCode::TRANSFORM_FINAL); OperationKey ob_eval_key(&object->id, NodeType::TRANSFORM, OperationCode::TRANSFORM_EVAL); + add_relation(init_transform_key, local_transform_key, "Transform Init"); + /* Various flags, flushing from bases/collections. */ build_object_layer_component_relations(object); + /* Parenting. */ if (object->parent != nullptr) { /* Make sure parent object's relations are built. */ @@ -717,30 +717,31 @@ void DepsgraphRelationBuilder::build_object(Object *object) /* Local -> parent. */ add_relation(local_transform_key, parent_transform_key, "ObLocal -> ObParent"); } + /* 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; data.builder = this; BKE_gpencil_modifiers_foreach_ID_link(object, modifier_walk, &data); } + /* Shader FX. */ if (object->shader_fx.first != nullptr) { BuilderWalkUserData data; data.builder = this; BKE_shaderfx_foreach_ID_link(object, modifier_walk, &data); } + /* Constraints. */ if (object->constraints.first != nullptr) { BuilderWalkUserData data; data.builder = this; BKE_constraints_id_loop(&object->constraints, constraint_walk, &data); } + /* Object constraints. */ OperationKey object_transform_simulation_init_key( &object->id, NodeType::TRANSFORM, OperationCode::TRANSFORM_SIMULATION_INIT); @@ -767,32 +768,48 @@ void DepsgraphRelationBuilder::build_object(Object *object) final_transform_key, "Simulation -> Final Transform"); } + build_idproperties(object->id.properties); + /* Animation data */ build_animdata(&object->id); + /* Object data. */ build_object_data(object); + /* Particle systems. */ if (object->particlesystem.first != nullptr) { build_particle_systems(object); } + /* Force field Texture. */ if ((object->pd != nullptr) && (object->pd->forcefield == PFIELD_TEXTURE) && (object->pd->tex != nullptr)) { build_texture(object->pd->tex); } + /* Object dupligroup. */ if (object->instance_collection != nullptr) { build_collection(nullptr, object, object->instance_collection); } + /* Point caches. */ build_object_pointcache(object); + /* Synchronization back to original object. */ OperationKey synchronize_key( &object->id, NodeType::SYNCHRONIZATION, OperationCode::SYNCHRONIZE_TO_ORIGINAL); add_relation(final_transform_key, synchronize_key, "Synchronize to Original"); + /* Parameters. */ build_parameters(&object->id); + + /* Visibility. + * Evaluate visibility node after the object's base_flags has been updated to the current state + * of collections restrict and object's restrict flags. */ + const ComponentKey object_from_layer_entry_key(&object->id, NodeType::OBJECT_FROM_LAYER); + const ComponentKey visibility_key(&object->id, NodeType::VISIBILITY); + add_relation(object_from_layer_entry_key, visibility_key, "Object Visibility"); } /* NOTE: Implies that the object has base in the current view layer. */ @@ -850,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) { @@ -1791,18 +1865,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); } @@ -1952,7 +2028,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); @@ -2142,7 +2217,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 @@ -2173,28 +2248,7 @@ void DepsgraphRelationBuilder::build_object_data_geometry(Object *object) * data mask to be used. We add relation here to ensure object is never * evaluated prior to Scene's CoW is ready. */ OperationKey scene_key(&scene_->id, NodeType::PARAMETERS, OperationCode::SCENE_EVAL); - Relation *rel = add_relation(scene_key, obdata_ubereval_key, "CoW Relation"); - rel->flag |= 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_object_modifier_use_time(scene_, object, md)) { - TimeSourceKey time_src_key; - add_relation(time_src_key, obdata_ubereval_key, "Time Source"); - } - } - } + add_relation(scene_key, obdata_ubereval_key, "CoW Relation", RELATION_FLAG_NO_FLUSH); /* Grease Pencil Modifiers. */ if (object->greasepencil_modifiers.first != nullptr) { ModifierUpdateDepsgraphContext ctx = {}; @@ -2208,7 +2262,7 @@ void DepsgraphRelationBuilder::build_object_data_geometry(Object *object) ctx.node = reinterpret_cast<::DepsNodeHandle *>(&handle); mti->updateDepsgraph(md, &ctx, graph_->mode); } - if (BKE_object_modifier_gpencil_use_time(object, md)) { + if (BKE_gpencil_modifier_depends_ontime(md)) { TimeSourceKey time_src_key; add_relation(time_src_key, obdata_ubereval_key, "Time Source"); } @@ -2226,7 +2280,7 @@ void DepsgraphRelationBuilder::build_object_data_geometry(Object *object) ctx.node = reinterpret_cast<::DepsNodeHandle *>(&handle); fxi->updateDepsgraph(fx, &ctx); } - if (BKE_object_shaderfx_use_time(object, fx)) { + if (BKE_shaderfx_depends_ontime(fx)) { TimeSourceKey time_src_key; add_relation(time_src_key, obdata_ubereval_key, "Time Source"); } @@ -2238,9 +2292,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"); @@ -2402,8 +2456,16 @@ void DepsgraphRelationBuilder::build_object_data_geometry_datablock(ID *obdata) } break; } - case ID_CV: + case ID_CV: { + Curves *curves_id = reinterpret_cast<Curves *>(obdata); + if (curves_id->surface != nullptr) { + build_object(curves_id->surface); + + /* The relations between the surface and the curves are handled as part of the modifier + * stack building. */ + } break; + } case ID_PT: break; case ID_VO: { @@ -2459,6 +2521,13 @@ void DepsgraphRelationBuilder::build_camera(Camera *camera) ComponentKey camera_parameters_key(&camera->id, NodeType::PARAMETERS); ComponentKey dof_ob_key(&camera->dof.focus_object->id, NodeType::TRANSFORM); add_relation(dof_ob_key, camera_parameters_key, "Camera DOF"); + if (camera->dof.focus_subtarget[0]) { + OperationKey target_key(&camera->dof.focus_object->id, + NodeType::BONE, + camera->dof.focus_subtarget, + OperationCode::BONE_DONE); + add_relation(target_key, camera_parameters_key, "Camera DOF subtarget"); + } } } @@ -2981,9 +3050,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; @@ -3058,7 +3128,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 64bdd2334d8..7d3a0fd9217 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations.h +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.h @@ -15,6 +15,7 @@ #include "DNA_ID.h" #include "RNA_access.h" +#include "RNA_path.h" #include "RNA_types.h" #include "BLI_string.h" @@ -70,8 +71,7 @@ struct bSound; struct PropertyRNA; -namespace blender { -namespace deg { +namespace blender::deg { struct ComponentNode; struct DepsNodeHandle; @@ -85,51 +85,113 @@ struct RootPChanMap; struct TimeSourceNode; struct TimeSourceKey { - TimeSourceKey(); - TimeSourceKey(ID *id); + TimeSourceKey() = default; string identifier() const; - - ID *id; }; struct ComponentKey { - ComponentKey(); - ComponentKey(ID *id, NodeType type, const char *name = ""); + ComponentKey() = default; + + inline ComponentKey(const ID *id, NodeType type, const char *name = "") + : id(id), type(type), name(name) + { + } string identifier() const; - ID *id; - NodeType type; - const char *name; + const ID *id = nullptr; + NodeType type = NodeType::UNDEFINED; + 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() = 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(ID *id, NodeType component_type, OperationCode opcode); - OperationKey(ID *id, NodeType component_type, const char *component_name, OperationCode opcode); + 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( - ID *id, NodeType component_type, OperationCode opcode, const char *name, int name_tag = -1); - OperationKey(ID *id, + 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); + int name_tag = -1) + : id(id), + component_type(component_type), + component_name(component_name), + opcode(opcode), + name(name), + name_tag(name_tag) + { + } string identifier() const; - ID *id; - NodeType component_type; - const char *component_name; - OperationCode opcode; - const char *name; - int name_tag; + const ID *id = nullptr; + NodeType component_type = NodeType::UNDEFINED; + const char *component_name = ""; + OperationCode opcode = OperationCode::OPERATION; + const char *name = ""; + int name_tag = -1; }; struct RNAPathKey { @@ -177,7 +239,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); @@ -203,6 +265,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); @@ -381,7 +444,6 @@ struct DepsNodeHandle { const char *default_name; }; -} // namespace deg -} // namespace blender +} // namespace blender::deg #include "intern/builder/deg_builder_relations_impl.h" diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations_drivers.h b/source/blender/depsgraph/intern/builder/deg_builder_relations_drivers.h index e517dd6a927..9860b17fd56 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations_drivers.h +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations_drivers.h @@ -15,8 +15,7 @@ struct FCurve; -namespace blender { -namespace deg { +namespace blender::deg { /* Helper class for determining which relations are needed between driver evaluation nodes. */ class DriverDescriptor { @@ -59,5 +58,4 @@ class DriverDescriptor { bool resolve_rna(); }; -} // namespace deg -} // namespace blender +} // namespace blender::deg diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations_impl.h b/source/blender/depsgraph/intern/builder/deg_builder_relations_impl.h index aba4a011e72..76066ce97a7 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations_impl.h +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations_impl.h @@ -15,8 +15,7 @@ #include "DNA_object_types.h" #include "DNA_rigidbody_types.h" -namespace blender { -namespace deg { +namespace blender::deg { template<typename KeyType> OperationNode *DepsgraphRelationBuilder::find_operation_node(const KeyType &key) @@ -209,5 +208,4 @@ bool DepsgraphRelationBuilder::is_same_nodetree_node_dependency(const KeyFrom &k return true; } -} // namespace deg -} // namespace blender +} // namespace blender::deg diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations_keys.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations_keys.cc index eeaab623482..8506a97c408 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations_keys.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations_keys.cc @@ -14,14 +14,6 @@ namespace blender::deg { //////////////////////////////////////////////////////////////////////////////// /* Time source. */ -TimeSourceKey::TimeSourceKey() : id(nullptr) -{ -} - -TimeSourceKey::TimeSourceKey(ID *id) : id(id) -{ -} - string TimeSourceKey::identifier() const { return string("TimeSourceKey"); @@ -30,15 +22,6 @@ string TimeSourceKey::identifier() const //////////////////////////////////////////////////////////////////////////////// // 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>"; @@ -55,86 +38,6 @@ string ComponentKey::identifier() const //////////////////////////////////////////////////////////////////////////////// // 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("); 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_remove_noop.h b/source/blender/depsgraph/intern/builder/deg_builder_remove_noop.h index 922d2d7dc05..ad10eb7cd10 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_remove_noop.h +++ b/source/blender/depsgraph/intern/builder/deg_builder_remove_noop.h @@ -7,13 +7,11 @@ #pragma once -namespace blender { -namespace deg { +namespace blender::deg { struct Depsgraph; /* Remove all no-op nodes that have zero outgoing relations. */ void deg_graph_remove_unused_noops(Depsgraph *graph); -} // namespace deg -} // namespace blender +} // namespace blender::deg diff --git a/source/blender/depsgraph/intern/builder/deg_builder_rna.cc b/source/blender/depsgraph/intern/builder/deg_builder_rna.cc index ac7a5bc2f30..d94746fb7fa 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_rna.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_rna.cc @@ -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) || @@ -271,7 +282,8 @@ RNANodeIdentifier RNANodeQuery::construct_node_identifier(const PointerRNA *ptr, RNA_struct_is_a(ptr->type, &RNA_LatticePoint) || RNA_struct_is_a(ptr->type, &RNA_MeshUVLoop) || RNA_struct_is_a(ptr->type, &RNA_MeshLoopColor) || - RNA_struct_is_a(ptr->type, &RNA_VertexGroupElement)) { + RNA_struct_is_a(ptr->type, &RNA_VertexGroupElement) || + RNA_struct_is_a(ptr->type, &RNA_ShaderFx)) { /* When modifier is used as FROM operation this is likely referencing to * the property (for example, modifier's influence). * But when it's used as TO operation, this is geometry component. */ @@ -289,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/builder/deg_builder_rna.h b/source/blender/depsgraph/intern/builder/deg_builder_rna.h index 4f482d4352d..9baa956bd80 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_rna.h +++ b/source/blender/depsgraph/intern/builder/deg_builder_rna.h @@ -14,8 +14,7 @@ struct ID; struct PointerRNA; struct PropertyRNA; -namespace blender { -namespace deg { +namespace blender::deg { struct Depsgraph; struct Node; @@ -94,5 +93,4 @@ class RNANodeQuery { bool rna_prop_affects_parameters_node(const PointerRNA *ptr, const PropertyRNA *prop); -} // namespace deg -} // namespace blender +} // namespace blender::deg diff --git a/source/blender/depsgraph/intern/builder/deg_builder_transitive.h b/source/blender/depsgraph/intern/builder/deg_builder_transitive.h index 8b208610203..63016431eec 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_transitive.h +++ b/source/blender/depsgraph/intern/builder/deg_builder_transitive.h @@ -7,13 +7,11 @@ #pragma once -namespace blender { -namespace deg { +namespace blender::deg { struct Depsgraph; /* Performs a transitive reduction to remove redundant relations. */ void deg_graph_transitive_reduction(Depsgraph *graph); -} // namespace deg -} // namespace blender +} // namespace blender::deg diff --git a/source/blender/depsgraph/intern/builder/pipeline.cc b/source/blender/depsgraph/intern/builder/pipeline.cc index 540b8e173f1..815a06d03d1 100644 --- a/source/blender/depsgraph/intern/builder/pipeline.cc +++ b/source/blender/depsgraph/intern/builder/pipeline.cc @@ -90,7 +90,7 @@ void AbstractBuilderPipeline::build_step_finalize() } #endif /* Relations are up to date. */ - deg_graph_->need_update = false; + deg_graph_->need_update_relations = false; } unique_ptr<DepsgraphNodeBuilder> AbstractBuilderPipeline::construct_node_builder() diff --git a/source/blender/depsgraph/intern/builder/pipeline.h b/source/blender/depsgraph/intern/builder/pipeline.h index b106e73b97c..7568aa78106 100644 --- a/source/blender/depsgraph/intern/builder/pipeline.h +++ b/source/blender/depsgraph/intern/builder/pipeline.h @@ -16,8 +16,7 @@ struct Main; struct Scene; struct ViewLayer; -namespace blender { -namespace deg { +namespace blender::deg { struct Depsgraph; class DepsgraphNodeBuilder; @@ -57,5 +56,4 @@ class AbstractBuilderPipeline { virtual void build_relations(DepsgraphRelationBuilder &relation_builder) = 0; }; -} // namespace deg -} // namespace blender +} // namespace blender::deg diff --git a/source/blender/depsgraph/intern/builder/pipeline_all_objects.cc b/source/blender/depsgraph/intern/builder/pipeline_all_objects.cc index 74d151c65d7..6bc3b59a9d6 100644 --- a/source/blender/depsgraph/intern/builder/pipeline_all_objects.cc +++ b/source/blender/depsgraph/intern/builder/pipeline_all_objects.cc @@ -20,7 +20,7 @@ class AllObjectsNodeBuilder : public DepsgraphNodeBuilder { { } - bool need_pull_base_into_graph(Base * /*base*/) override + bool need_pull_base_into_graph(const Base * /*base*/) override { return true; } @@ -33,7 +33,7 @@ class AllObjectsRelationBuilder : public DepsgraphRelationBuilder { { } - bool need_pull_base_into_graph(Base * /*base*/) override + bool need_pull_base_into_graph(const Base * /*base*/) override { return true; } diff --git a/source/blender/depsgraph/intern/builder/pipeline_all_objects.h b/source/blender/depsgraph/intern/builder/pipeline_all_objects.h index 75d9605dec7..fde5e7e2163 100644 --- a/source/blender/depsgraph/intern/builder/pipeline_all_objects.h +++ b/source/blender/depsgraph/intern/builder/pipeline_all_objects.h @@ -9,8 +9,7 @@ #include "pipeline_view_layer.h" -namespace blender { -namespace deg { +namespace blender::deg { /* Builds a dependency graph that contains all objects in the view layer. * This is contrary to the regular ViewLayerBuilderPipeline, which is limited to visible objects @@ -24,5 +23,4 @@ class AllObjectsBuilderPipeline : public ViewLayerBuilderPipeline { virtual unique_ptr<DepsgraphRelationBuilder> construct_relation_builder() override; }; -} // namespace deg -} // namespace blender +} // namespace blender::deg diff --git a/source/blender/depsgraph/intern/builder/pipeline_compositor.h b/source/blender/depsgraph/intern/builder/pipeline_compositor.h index 3325741c94a..304f2d4ec9a 100644 --- a/source/blender/depsgraph/intern/builder/pipeline_compositor.h +++ b/source/blender/depsgraph/intern/builder/pipeline_compositor.h @@ -11,8 +11,7 @@ struct bNodeTree; -namespace blender { -namespace deg { +namespace blender::deg { class CompositorBuilderPipeline : public AbstractBuilderPipeline { public: @@ -26,5 +25,4 @@ class CompositorBuilderPipeline : public AbstractBuilderPipeline { bNodeTree *nodetree_; }; -} // namespace deg -} // namespace blender +} // namespace blender::deg diff --git a/source/blender/depsgraph/intern/builder/pipeline_from_ids.cc b/source/blender/depsgraph/intern/builder/pipeline_from_ids.cc index ee10b28a306..e256c8271f2 100644 --- a/source/blender/depsgraph/intern/builder/pipeline_from_ids.cc +++ b/source/blender/depsgraph/intern/builder/pipeline_from_ids.cc @@ -39,7 +39,7 @@ class DepsgraphFromIDsNodeBuilder : public DepsgraphNodeBuilder { { } - bool need_pull_base_into_graph(Base *base) override + bool need_pull_base_into_graph(const Base *base) override { if (!filter_.contains(&base->object->id)) { return false; @@ -61,7 +61,7 @@ class DepsgraphFromIDsRelationBuilder : public DepsgraphRelationBuilder { { } - bool need_pull_base_into_graph(Base *base) override + bool need_pull_base_into_graph(const Base *base) override { if (!filter_.contains(&base->object->id)) { return false; diff --git a/source/blender/depsgraph/intern/builder/pipeline_from_ids.h b/source/blender/depsgraph/intern/builder/pipeline_from_ids.h index a2c75c048cb..c277d44aaad 100644 --- a/source/blender/depsgraph/intern/builder/pipeline_from_ids.h +++ b/source/blender/depsgraph/intern/builder/pipeline_from_ids.h @@ -9,8 +9,7 @@ #include "pipeline.h" -namespace blender { -namespace deg { +namespace blender::deg { /* Optimized builders for dependency graph built from a given set of IDs. * @@ -37,5 +36,4 @@ class FromIDsBuilderPipeline : public AbstractBuilderPipeline { Span<ID *> ids_; }; -} // namespace deg -} // namespace blender +} // namespace blender::deg diff --git a/source/blender/depsgraph/intern/builder/pipeline_render.h b/source/blender/depsgraph/intern/builder/pipeline_render.h index cb704f84c59..7eb65168ea6 100644 --- a/source/blender/depsgraph/intern/builder/pipeline_render.h +++ b/source/blender/depsgraph/intern/builder/pipeline_render.h @@ -9,8 +9,7 @@ #include "pipeline.h" -namespace blender { -namespace deg { +namespace blender::deg { class RenderBuilderPipeline : public AbstractBuilderPipeline { public: @@ -21,5 +20,4 @@ class RenderBuilderPipeline : public AbstractBuilderPipeline { virtual void build_relations(DepsgraphRelationBuilder &relation_builder) override; }; -} // namespace deg -} // namespace blender +} // namespace blender::deg diff --git a/source/blender/depsgraph/intern/builder/pipeline_view_layer.h b/source/blender/depsgraph/intern/builder/pipeline_view_layer.h index 18b9ce5d5ff..ffd6fa07776 100644 --- a/source/blender/depsgraph/intern/builder/pipeline_view_layer.h +++ b/source/blender/depsgraph/intern/builder/pipeline_view_layer.h @@ -9,8 +9,7 @@ #include "pipeline.h" -namespace blender { -namespace deg { +namespace blender::deg { class ViewLayerBuilderPipeline : public AbstractBuilderPipeline { public: @@ -21,5 +20,4 @@ class ViewLayerBuilderPipeline : public AbstractBuilderPipeline { virtual void build_relations(DepsgraphRelationBuilder &relation_builder) override; }; -} // namespace deg -} // namespace blender +} // namespace blender::deg diff --git a/source/blender/depsgraph/intern/debug/deg_debug.h b/source/blender/depsgraph/intern/debug/deg_debug.h index ee6c5b046b7..8f18bd70d36 100644 --- a/source/blender/depsgraph/intern/debug/deg_debug.h +++ b/source/blender/depsgraph/intern/debug/deg_debug.h @@ -14,8 +14,7 @@ #include "DEG_depsgraph_debug.h" -namespace blender { -namespace deg { +namespace blender::deg { class DepsgraphDebug { public: @@ -74,5 +73,4 @@ bool terminal_do_color(void); string color_for_pointer(const void *pointer); string color_end(void); -} // namespace deg -} // namespace blender +} // namespace blender::deg diff --git a/source/blender/depsgraph/intern/debug/deg_time_average.h b/source/blender/depsgraph/intern/debug/deg_time_average.h index cc47f03b221..d4eb05a9ddb 100644 --- a/source/blender/depsgraph/intern/debug/deg_time_average.h +++ b/source/blender/depsgraph/intern/debug/deg_time_average.h @@ -7,8 +7,7 @@ #pragma once -namespace blender { -namespace deg { +namespace blender::deg { /* Utility class which takes care of calculating average of time series, such as FPS counters. */ template<int MaxSamples> class AveragedTimeSampler { @@ -52,5 +51,4 @@ template<int MaxSamples> class AveragedTimeSampler { int next_sample_index_; }; -} // namespace deg -} // namespace blender +} // namespace blender::deg diff --git a/source/blender/depsgraph/intern/depsgraph.cc b/source/blender/depsgraph/intern/depsgraph.cc index 4514084059a..316d0b615c6 100644 --- a/source/blender/depsgraph/intern/depsgraph.cc +++ b/source/blender/depsgraph/intern/depsgraph.cc @@ -45,9 +45,11 @@ namespace blender::deg { Depsgraph::Depsgraph(Main *bmain, Scene *scene, ViewLayer *view_layer, eEvaluationMode mode) : time_source(nullptr), - need_update(true), - need_visibility_update(true), - need_visibility_time_update(false), + has_animated_visibility(false), + need_update_relations(true), + need_update_nodes_visibility(true), + need_tag_id_on_graph_visibility_update(true), + need_tag_id_on_graph_visibility_time_update(false), bmain(bmain), scene(scene), view_layer(view_layer), diff --git a/source/blender/depsgraph/intern/depsgraph.h b/source/blender/depsgraph/intern/depsgraph.h index ca4ce058904..2f88199384d 100644 --- a/source/blender/depsgraph/intern/depsgraph.h +++ b/source/blender/depsgraph/intern/depsgraph.h @@ -31,8 +31,7 @@ struct ID; struct Scene; struct ViewLayer; -namespace blender { -namespace deg { +namespace blender::deg { struct IDNode; struct Node; @@ -89,13 +88,19 @@ struct Depsgraph { /* Top-level time source node. */ TimeSourceNode *time_source; + /* The graph contains data-blocks whose visibility depends on evaluation (driven or animated). */ + bool has_animated_visibility; + /* Indicates whether relations needs to be updated. */ - bool need_update; + bool need_update_relations; + + /* Indicates whether indirect effect of nodes on a directly visible ones needs to be updated. */ + bool need_update_nodes_visibility; /* Indicated whether IDs in this graph are to be tagged as if they first appear visible, with * an optional tag for their animation (time) update. */ - bool need_visibility_update; - bool need_visibility_time_update; + bool need_tag_id_on_graph_visibility_update; + bool need_tag_id_on_graph_visibility_time_update; /* Indicates which ID types were updated. */ char id_type_updated[INDEX_ID_MAX]; @@ -162,5 +167,4 @@ struct Depsgraph { MEM_CXX_CLASS_ALLOC_FUNCS("Depsgraph"); }; -} // namespace deg -} // namespace blender +} // namespace blender::deg diff --git a/source/blender/depsgraph/intern/depsgraph_build.cc b/source/blender/depsgraph/intern/depsgraph_build.cc index c64b7bc1eb7..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) @@ -270,7 +270,7 @@ void DEG_graph_tag_relations_update(Depsgraph *graph) { DEG_DEBUG_PRINTF(graph, TAG, "%s: Tagging relations for update.\n", __func__); deg::Depsgraph *deg_graph = reinterpret_cast<deg::Depsgraph *>(graph); - deg_graph->need_update = true; + deg_graph->need_update_relations = true; /* NOTE: When relations are updated, it's quite possible that * we've got new bases in the scene. This means, we need to * re-create flat array of bases in view layer. @@ -286,7 +286,7 @@ void DEG_graph_tag_relations_update(Depsgraph *graph) void DEG_graph_relations_update(Depsgraph *graph) { deg::Depsgraph *deg_graph = (deg::Depsgraph *)graph; - if (!deg_graph->need_update) { + if (!deg_graph->need_update_relations) { /* Graph is up to date, nothing to do. */ return; } diff --git a/source/blender/depsgraph/intern/depsgraph_physics.cc b/source/blender/depsgraph/intern/depsgraph_physics.cc index 5660d5eb1bd..cf5cccac580 100644 --- a/source/blender/depsgraph/intern/depsgraph_physics.cc +++ b/source/blender/depsgraph/intern/depsgraph_physics.cc @@ -174,7 +174,7 @@ 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); }); } diff --git a/source/blender/depsgraph/intern/depsgraph_physics.h b/source/blender/depsgraph/intern/depsgraph_physics.h index a8d37f76b09..2105eb62ce1 100644 --- a/source/blender/depsgraph/intern/depsgraph_physics.h +++ b/source/blender/depsgraph/intern/depsgraph_physics.h @@ -10,8 +10,7 @@ struct Collection; struct ListBase; -namespace blender { -namespace deg { +namespace blender::deg { struct Depsgraph; @@ -21,5 +20,4 @@ ListBase *build_collision_relations(Depsgraph *graph, unsigned int modifier_type); void clear_physics_relations(Depsgraph *graph); -} // namespace deg -} // namespace blender +} // namespace blender::deg diff --git a/source/blender/depsgraph/intern/depsgraph_query.cc b/source/blender/depsgraph/intern/depsgraph_query.cc index 6ffc711a475..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" @@ -328,7 +329,7 @@ bool DEG_is_fully_evaluated(const struct Depsgraph *depsgraph) { const deg::Depsgraph *deg_graph = (const deg::Depsgraph *)depsgraph; /* Check whether relations are up to date. */ - if (deg_graph->need_update) { + if (deg_graph->need_update_relations) { return false; } /* Check whether IDs are up to date. */ diff --git a/source/blender/depsgraph/intern/depsgraph_query_iter.cc b/source/blender/depsgraph/intern/depsgraph_query_iter.cc index bcde1839a0f..bcae5de1e1e 100644 --- a/source/blender/depsgraph/intern/depsgraph_query_iter.cc +++ b/source/blender/depsgraph/intern/depsgraph_query_iter.cc @@ -153,10 +153,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 +182,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) { @@ -219,7 +219,9 @@ bool deg_iterator_objects_step(DEGObjectIterData *data) for (; data->id_node_index < data->num_id_nodes; data->id_node_index++) { deg::IDNode *id_node = deg_graph->id_nodes[data->id_node_index]; - if (!id_node->is_directly_visible) { + /* Use the build time visibility so that the ID is not appearing/disappearing throughout + * animation export. */ + if (!id_node->is_visible_on_build) { continue; } @@ -338,10 +340,13 @@ static void DEG_iterator_ids_step(BLI_Iterator *iter, deg::IDNode *id_node, bool { ID *id_cow = id_node->id_cow; - if (!id_node->is_directly_visible) { + /* Use the build time visibility so that the ID is not appearing/disappearing throughout + * animation export. */ + if (!id_node->is_visible_on_build) { iter->skip = true; return; } + if (only_updated && !(id_cow->recalc & ID_RECALC_ALL)) { /* Node-tree is considered part of the data-block. */ bNodeTree *ntree = ntreeFromID(id_cow); diff --git a/source/blender/depsgraph/intern/depsgraph_registry.h b/source/blender/depsgraph/intern/depsgraph_registry.h index 2746f17590a..4ab63dcc77d 100644 --- a/source/blender/depsgraph/intern/depsgraph_registry.h +++ b/source/blender/depsgraph/intern/depsgraph_registry.h @@ -11,8 +11,7 @@ struct Main; -namespace blender { -namespace deg { +namespace blender::deg { struct Depsgraph; @@ -20,5 +19,4 @@ void register_graph(Depsgraph *depsgraph); void unregister_graph(Depsgraph *depsgraph); Span<Depsgraph *> get_all_registered_graphs(Main *bmain); -} // namespace deg -} // namespace blender +} // namespace blender::deg diff --git a/source/blender/depsgraph/intern/depsgraph_relation.h b/source/blender/depsgraph/intern/depsgraph_relation.h index 4d51ad85878..3f316fa84e8 100644 --- a/source/blender/depsgraph/intern/depsgraph_relation.h +++ b/source/blender/depsgraph/intern/depsgraph_relation.h @@ -9,8 +9,7 @@ #include "MEM_guardedalloc.h" -namespace blender { -namespace deg { +namespace blender::deg { struct Node; @@ -29,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) */ @@ -49,5 +50,4 @@ struct Relation { MEM_CXX_CLASS_ALLOC_FUNCS("Relation"); }; -} // namespace deg -} // namespace blender +} // namespace blender::deg diff --git a/source/blender/depsgraph/intern/depsgraph_tag.cc b/source/blender/depsgraph/intern/depsgraph_tag.cc index b50081458ad..cc742b98866 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, unsigned int 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(unsigned int flags) { - if (flag == 0) { + if (flags == 0) { return "LEGACY_0"; } string result; - int current_flag = flag; + unsigned int 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, unsigned int flags) { if (graph != nullptr) { if (!graph->is_active) { @@ -494,19 +505,19 @@ void deg_graph_node_tag_zero(Main *bmain, void graph_tag_on_visible_update(Depsgraph *graph, const bool do_time) { - graph->need_visibility_update = true; - graph->need_visibility_time_update |= do_time; + graph->need_tag_id_on_graph_visibility_update = true; + graph->need_tag_id_on_graph_visibility_time_update |= do_time; } } /* namespace */ void graph_tag_ids_for_visible_update(Depsgraph *graph) { - if (!graph->need_visibility_update) { + if (!graph->need_tag_id_on_graph_visibility_update) { return; } - const bool do_time = graph->need_visibility_time_update; + const bool do_time = graph->need_tag_id_on_graph_visibility_time_update; Main *bmain = graph->bmain; /* NOTE: It is possible to have this function called with `do_time=false` first and later (prior @@ -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; + unsigned int 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); @@ -561,8 +572,8 @@ void graph_tag_ids_for_visible_update(Depsgraph *graph) id_node->previously_visible_components_mask = id_node->visible_components_mask; } - graph->need_visibility_update = false; - graph->need_visibility_time_update = false; + graph->need_tag_id_on_graph_visibility_update = false; + graph->need_tag_id_on_graph_visibility_time_update = false; } NodeType geometry_tag_to_component(const ID *id) @@ -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, unsigned int 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, unsigned int 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; + unsigned int 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, unsigned int 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, unsigned int 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) + unsigned int 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 a0518420bfb..61643e6f740 100644 --- a/source/blender/depsgraph/intern/depsgraph_tag.h +++ b/source/blender/depsgraph/intern/depsgraph_tag.h @@ -10,8 +10,7 @@ struct ID; struct Main; -namespace blender { -namespace deg { +namespace blender::deg { struct Depsgraph; @@ -19,15 +18,14 @@ 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. */ void graph_tag_ids_for_visible_update(Depsgraph *graph); -} // namespace deg -} // namespace blender +} // namespace blender::deg diff --git a/source/blender/depsgraph/intern/depsgraph_type.h b/source/blender/depsgraph/intern/depsgraph_type.h index 9cf14a831bc..9e21d124f83 100644 --- a/source/blender/depsgraph/intern/depsgraph_type.h +++ b/source/blender/depsgraph/intern/depsgraph_type.h @@ -34,8 +34,7 @@ struct Depsgraph; struct CustomData_MeshMasks; -namespace blender { -namespace deg { +namespace blender::deg { /* Commonly used types. */ using std::deque; @@ -153,5 +152,4 @@ struct DEGCustomDataMeshMasks { } }; -} // namespace deg -} // namespace blender +} // namespace blender::deg diff --git a/source/blender/depsgraph/intern/depsgraph_update.h b/source/blender/depsgraph/intern/depsgraph_update.h index 18f8e6acab6..c5a72157bd2 100644 --- a/source/blender/depsgraph/intern/depsgraph_update.h +++ b/source/blender/depsgraph/intern/depsgraph_update.h @@ -10,12 +10,10 @@ struct DEGEditorUpdateContext; struct ID; -namespace blender { -namespace deg { +namespace blender::deg { void deg_editors_id_update(const DEGEditorUpdateContext *update_ctx, struct ID *id); void deg_editors_scene_update(const DEGEditorUpdateContext *update_ctx, bool updated); -} // namespace deg -} // namespace blender +} // namespace blender::deg diff --git a/source/blender/depsgraph/intern/eval/deg_eval.cc b/source/blender/depsgraph/intern/eval/deg_eval.cc index 2d9d40aede6..cd0015ff717 100644 --- a/source/blender/depsgraph/intern/eval/deg_eval.cc +++ b/source/blender/depsgraph/intern/eval/deg_eval.cc @@ -37,6 +37,7 @@ #include "intern/eval/deg_eval_copy_on_write.h" #include "intern/eval/deg_eval_flush.h" #include "intern/eval/deg_eval_stats.h" +#include "intern/eval/deg_eval_visibility.h" #include "intern/node/deg_node.h" #include "intern/node/deg_node_component.h" #include "intern/node/deg_node_id.h" @@ -69,6 +70,9 @@ enum class EvaluationStage { * involved. */ COPY_ON_WRITE, + /* Evaluate actual ID nodes visibility based on the current state of animation and drivers. */ + DYNAMIC_VISIBILITY, + /* Threaded evaluation of all possible operations. */ THREADED_EVALUATION, @@ -83,7 +87,8 @@ struct DepsgraphEvalState { Depsgraph *graph; bool do_stats; EvaluationStage stage; - bool need_single_thread_pass; + bool need_update_pending_parents = true; + bool need_single_thread_pass = false; }; void evaluate_node(const DepsgraphEvalState *state, OperationNode *operation_node) @@ -101,6 +106,13 @@ void evaluate_node(const DepsgraphEvalState *state, OperationNode *operation_nod else { operation_node->evaluate(depsgraph); } + + /* Clear the flag early on, allowing partial updates without re-evaluating the same node multiple + * 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_DIRECTLY_MODIFIED | DEPSOP_FLAG_NEEDS_UPDATE | + DEPSOP_FLAG_USER_MODIFIED); } void deg_task_run_func(TaskPool *pool, void *taskdata) @@ -116,24 +128,31 @@ void deg_task_run_func(TaskPool *pool, void *taskdata) schedule_children(state, operation_node, schedule_node_to_pool, pool); } -bool check_operation_node_visible(OperationNode *op_node) +bool check_operation_node_visible(const DepsgraphEvalState *state, OperationNode *op_node) { const ComponentNode *comp_node = op_node->owner; - /* Special exception, copy on write component is to be always evaluated, - * to keep copied "database" in a consistent state. */ + /* Special case for copy on write component: it is to be always evaluated, to keep copied + * "database" in a consistent state. */ if (comp_node->type == NodeType::COPY_ON_WRITE) { return true; } - return comp_node->affects_directly_visible; + + /* 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; + } + + return comp_node->affects_visible_id; } -void calculate_pending_parents_for_node(OperationNode *node) +void calculate_pending_parents_for_node(const DepsgraphEvalState *state, OperationNode *node) { /* Update counters, applies for both visible and invisible IDs. */ node->num_links_pending = 0; node->scheduled = false; /* Invisible IDs requires no pending operations. */ - if (!check_operation_node_visible(node)) { + if (!check_operation_node_visible(state, node)) { return; } /* No need to bother with anything if node is not tagged for update. */ @@ -147,7 +166,7 @@ void calculate_pending_parents_for_node(OperationNode *node) * calculation, but how is it possible that visible object depends * on an invisible? This is something what is prohibited after * deg_graph_build_flush_layers(). */ - if (!check_operation_node_visible(from)) { + if (!check_operation_node_visible(state, from)) { continue; } /* No need to wait for operation which is up to date. */ @@ -159,20 +178,24 @@ void calculate_pending_parents_for_node(OperationNode *node) } } -void calculate_pending_parents(Depsgraph *graph) +void calculate_pending_parents_if_needed(DepsgraphEvalState *state) { - for (OperationNode *node : graph->operations) { - calculate_pending_parents_for_node(node); + if (!state->need_update_pending_parents) { + return; } + + for (OperationNode *node : state->graph->operations) { + calculate_pending_parents_for_node(state, node); + } + + state->need_update_pending_parents = false; } void initialize_execution(DepsgraphEvalState *state, Depsgraph *graph) { - const bool do_stats = state->do_stats; - calculate_pending_parents(graph); /* Clear tags and other things which needs to be clear. */ - for (OperationNode *node : graph->operations) { - if (do_stats) { + if (state->do_stats) { + for (OperationNode *node : graph->operations) { node->stats.reset_current(); } } @@ -197,11 +220,10 @@ bool need_evaluate_operation_at_stage(DepsgraphEvalState *state, case EvaluationStage::COPY_ON_WRITE: return (component_node->type == NodeType::COPY_ON_WRITE); + case EvaluationStage::DYNAMIC_VISIBILITY: + return operation_node->flag & OperationFlag::DEPSOP_FLAG_AFFECTS_VISIBILITY; + case EvaluationStage::THREADED_EVALUATION: - /* Sanity check: copy-on-write node should be evaluated already. This will be indicated by - * scheduled flag (we assume that scheduled operations have been actually handled by previous - * stage). */ - BLI_assert(operation_node->scheduled || component_node->type != NodeType::COPY_ON_WRITE); if (is_metaball_object_operation(operation_node)) { state->need_single_thread_pass = true; return false; @@ -227,7 +249,7 @@ void schedule_node(DepsgraphEvalState *state, ScheduleFunctionArgs... schedule_function_args) { /* No need to schedule nodes of invisible ID. */ - if (!check_operation_node_visible(node)) { + if (!check_operation_node_visible(state, node)) { return; } /* No need to schedule operations which are not tagged for update, they are @@ -302,8 +324,32 @@ void schedule_node_to_queue(OperationNode *node, BLI_gsqueue_push(evaluation_queue, &node); } -void evaluate_graph_single_threaded(DepsgraphEvalState *state) +/* Evaluate given stage of the dependency graph evaluation using multiple threads. + * + * NOTE: Will assign the `state->stage` to the given stage. */ +void evaluate_graph_threaded_stage(DepsgraphEvalState *state, + TaskPool *task_pool, + const EvaluationStage stage) +{ + state->stage = stage; + + calculate_pending_parents_if_needed(state); + + schedule_graph(state, schedule_node_to_pool, task_pool); + BLI_task_pool_work_and_wait(task_pool); +} + +/* Evaluate remaining operations of the dependency graph in a single threaded manner. */ +void evaluate_graph_single_threaded_if_needed(DepsgraphEvalState *state) { + if (!state->need_single_thread_pass) { + return; + } + + BLI_assert(!state->need_update_pending_parents); + + state->stage = EvaluationStage::SINGLE_THREADED_WORKAROUND; + GSQueue *evaluation_queue = BLI_gsqueue_new(sizeof(OperationNode *)); schedule_graph(state, schedule_node_to_queue, evaluation_queue); @@ -334,9 +380,7 @@ void depsgraph_ensure_view_layer(Depsgraph *graph) deg_update_copy_on_write_datablock(graph, scene_id_node); } -} // namespace - -static TaskPool *deg_evaluate_task_pool_create(DepsgraphEvalState *state) +TaskPool *deg_evaluate_task_pool_create(DepsgraphEvalState *state) { if (G.debug & G_DEBUG_DEPSGRAPH_NO_THREADS) { return BLI_task_pool_create_no_threads(state); @@ -345,6 +389,8 @@ static TaskPool *deg_evaluate_task_pool_create(DepsgraphEvalState *state) return BLI_task_pool_create_suspended(state, TASK_PRIORITY_HIGH); } +} // namespace + void deg_evaluate_on_refresh(Depsgraph *graph) { /* Nothing to update, early out. */ @@ -361,41 +407,67 @@ void deg_evaluate_on_refresh(Depsgraph *graph) graph->is_evaluating = true; depsgraph_ensure_view_layer(graph); + /* Set up evaluation state. */ DepsgraphEvalState state; state.graph = graph; state.do_stats = graph->debug.do_time_debug(); - state.need_single_thread_pass = false; + /* Prepare all nodes for evaluation. */ initialize_execution(&state, graph); - /* Do actual evaluation now. */ - /* First, process all Copy-On-Write nodes. */ - state.stage = EvaluationStage::COPY_ON_WRITE; + /* Evaluation happens in several incremental steps: + * + * - Start with the copy-on-write operations which never form dependency cycles. This will ensure + * that if a dependency graph has a cycle evaluation functions will always "see" valid expanded + * datablock. It might not be evaluated yet, but at least the datablock will be valid. + * + * - If there is potentially dynamically changing visibility in the graph update the actual + * nodes visibilities, so that actual heavy data evaluation can benefit from knowledge that + * something heavy is not currently visible. + * + * - Multi-threaded evaluation of all possible nodes. + * Certain operations (and their subtrees) could be ignored. For example, meta-balls are not + * safe from threading point of view, so the threaded evaluation will stop at the metaball + * operation node. + * + * - Single-threaded pass of all remaining operations. */ + TaskPool *task_pool = deg_evaluate_task_pool_create(&state); - schedule_graph(&state, schedule_node_to_pool, task_pool); - BLI_task_pool_work_and_wait(task_pool); - BLI_task_pool_free(task_pool); - /* After that, process all other nodes. */ - state.stage = EvaluationStage::THREADED_EVALUATION; - task_pool = deg_evaluate_task_pool_create(&state); - schedule_graph(&state, schedule_node_to_pool, task_pool); - BLI_task_pool_work_and_wait(task_pool); - BLI_task_pool_free(task_pool); + evaluate_graph_threaded_stage(&state, task_pool, EvaluationStage::COPY_ON_WRITE); + + 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; + + evaluate_graph_threaded_stage(&state, task_pool, EvaluationStage::DYNAMIC_VISIBILITY); + + deg_graph_flush_visibility_flags_if_needed(graph); - if (state.need_single_thread_pass) { - state.stage = EvaluationStage::SINGLE_THREADED_WORKAROUND; - evaluate_graph_single_threaded(&state); + /* Update parents to an updated visibility and evaluation stage. + * + * Need to do it regardless of whether visibility is actually changed or not: current state of + * the pending parents are all zeroes because it was previously calculated for only visibility + * related nodes and those are fully evaluated by now. */ + state.need_update_pending_parents = true; } + evaluate_graph_threaded_stage(&state, task_pool, EvaluationStage::THREADED_EVALUATION); + + BLI_task_pool_free(task_pool); + + evaluate_graph_single_threaded_if_needed(&state); + /* Finalize statistics gathering. This is because we only gather single * operation timing here, without aggregating anything to avoid any extra * synchronization. */ if (state.do_stats) { 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.h b/source/blender/depsgraph/intern/eval/deg_eval.h index ba86e1a349d..6937231d81a 100644 --- a/source/blender/depsgraph/intern/eval/deg_eval.h +++ b/source/blender/depsgraph/intern/eval/deg_eval.h @@ -9,8 +9,7 @@ #pragma once -namespace blender { -namespace deg { +namespace blender::deg { struct Depsgraph; @@ -23,5 +22,4 @@ struct Depsgraph; */ void deg_evaluate_on_refresh(Depsgraph *graph); -} // namespace deg -} // namespace blender +} // namespace blender::deg 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_copy_on_write.h b/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.h index 29322d58218..cbf450aa3f1 100644 --- a/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.h +++ b/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.h @@ -27,8 +27,7 @@ struct ID; struct Depsgraph; -namespace blender { -namespace deg { +namespace blender::deg { struct Depsgraph; class DepsgraphNodeBuilder; @@ -77,5 +76,4 @@ bool deg_copy_on_write_is_expanded(const struct ID *id_cow); bool deg_copy_on_write_is_needed(const ID *id_orig); bool deg_copy_on_write_is_needed(const ID_Type id_type); -} // namespace deg -} // namespace blender +} // namespace blender::deg diff --git a/source/blender/depsgraph/intern/eval/deg_eval_flush.cc b/source/blender/depsgraph/intern/eval/deg_eval_flush.cc index de4e26aa4b5..09981eb32c5 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; } } @@ -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_flush.h b/source/blender/depsgraph/intern/eval/deg_eval_flush.h index 6eb232e76e5..614ca66faed 100644 --- a/source/blender/depsgraph/intern/eval/deg_eval_flush.h +++ b/source/blender/depsgraph/intern/eval/deg_eval_flush.h @@ -9,8 +9,7 @@ #pragma once -namespace blender { -namespace deg { +namespace blender::deg { struct Depsgraph; @@ -24,5 +23,4 @@ void deg_graph_flush_updates(struct Depsgraph *graph); */ void deg_graph_clear_tags(struct Depsgraph *graph); -} // namespace deg -} // namespace blender +} // namespace blender::deg 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.h b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup.h index deb21715a28..3d9b308c5ad 100644 --- a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup.h +++ b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup.h @@ -17,8 +17,7 @@ #include "intern/eval/deg_eval_runtime_backup_sound.h" #include "intern/eval/deg_eval_runtime_backup_volume.h" -namespace blender { -namespace deg { +namespace blender::deg { struct Depsgraph; @@ -59,5 +58,4 @@ class RuntimeBackup { GPencilBackup gpencil_backup; }; -} // namespace deg -} // namespace blender +} // namespace blender::deg diff --git a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_animation.h b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_animation.h index 92847b330e8..807cc91242e 100644 --- a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_animation.h +++ b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_animation.h @@ -11,8 +11,7 @@ #include "intern/depsgraph_type.h" -namespace blender { -namespace deg { +namespace blender::deg { struct Depsgraph; @@ -46,5 +45,4 @@ class AnimationBackup { Vector<AnimationValueBackup> values_backup; }; -} // namespace deg -} // namespace blender +} // namespace blender::deg diff --git a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_gpencil.h b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_gpencil.h index 68eff01fd60..95c0ca3a2fe 100644 --- a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_gpencil.h +++ b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_gpencil.h @@ -9,8 +9,7 @@ struct bGPdata; -namespace blender { -namespace deg { +namespace blender::deg { struct Depsgraph; @@ -25,5 +24,4 @@ class GPencilBackup { const Depsgraph *depsgraph; }; -} // namespace deg -} // namespace blender +} // namespace blender::deg diff --git a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_modifier.h b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_modifier.h index faec8f7c065..ee51204b24c 100644 --- a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_modifier.h +++ b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_modifier.h @@ -11,8 +11,7 @@ struct ModifierData; -namespace blender { -namespace deg { +namespace blender::deg { class ModifierDataBackup { public: @@ -22,5 +21,4 @@ class ModifierDataBackup { void *runtime; }; -} // namespace deg -} // namespace blender +} // namespace blender::deg diff --git a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_movieclip.h b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_movieclip.h index 0e826e8f72a..aa13914d8c8 100644 --- a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_movieclip.h +++ b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_movieclip.h @@ -11,8 +11,7 @@ struct MovieClip; struct MovieClipCache; struct anim; -namespace blender { -namespace deg { +namespace blender::deg { struct Depsgraph; @@ -30,5 +29,4 @@ class MovieClipBackup { struct MovieClipCache *cache; }; -} // namespace deg -} // namespace blender +} // namespace blender::deg diff --git a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_object.h b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_object.h index 3b138feec0b..c9cc167d927 100644 --- a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_object.h +++ b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_object.h @@ -17,8 +17,7 @@ struct Object; -namespace blender { -namespace deg { +namespace blender::deg { struct Depsgraph; @@ -46,5 +45,4 @@ class ObjectRuntimeBackup { Map<SessionUUID, bPoseChannel_Runtime> pose_channel_runtime_data; }; -} // namespace deg -} // namespace blender +} // namespace blender::deg diff --git a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_pose.h b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_pose.h index 8fd5de44001..2f6a3dd4371 100644 --- a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_pose.h +++ b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_pose.h @@ -11,8 +11,6 @@ #include "DNA_action_types.h" -namespace blender { -namespace deg { +namespace blender::deg { -} -} // namespace blender +} // namespace blender::deg diff --git a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_scene.h b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_scene.h index 17683966a22..155cb42a96d 100644 --- a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_scene.h +++ b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_scene.h @@ -11,8 +11,7 @@ struct Scene; -namespace blender { -namespace deg { +namespace blender::deg { struct Depsgraph; @@ -40,5 +39,4 @@ class SceneBackup { SequencerBackup sequencer_backup; }; -} // namespace deg -} // namespace blender +} // namespace blender::deg diff --git a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_sequence.h b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_sequence.h index 95fbd2a3e4e..f97b6b200e9 100644 --- a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_sequence.h +++ b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_sequence.h @@ -11,8 +11,7 @@ struct Sequence; -namespace blender { -namespace deg { +namespace blender::deg { struct Depsgraph; @@ -32,5 +31,4 @@ class SequenceBackup { ListBase anims; }; -} // namespace deg -} // namespace blender +} // namespace blender::deg diff --git a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_sequencer.h b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_sequencer.h index 19e1a63ab4c..38fb8e81cc3 100644 --- a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_sequencer.h +++ b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_sequencer.h @@ -16,8 +16,7 @@ struct Scene; -namespace blender { -namespace deg { +namespace blender::deg { struct Depsgraph; @@ -34,5 +33,4 @@ class SequencerBackup { Map<SessionUUID, SequenceBackup> sequences_backup; }; -} // namespace deg -} // namespace blender +} // namespace blender::deg diff --git a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_sound.h b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_sound.h index c4267be1421..9e1d15251e8 100644 --- a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_sound.h +++ b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_sound.h @@ -9,8 +9,7 @@ struct bSound; -namespace blender { -namespace deg { +namespace blender::deg { struct Depsgraph; @@ -29,5 +28,4 @@ class SoundBackup { void *playback_handle; }; -} // namespace deg -} // namespace blender +} // namespace blender::deg diff --git a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_volume.h b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_volume.h index bc263cc58f8..60cba64f120 100644 --- a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_volume.h +++ b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_volume.h @@ -10,8 +10,7 @@ struct Volume; struct VolumeGridVector; -namespace blender { -namespace deg { +namespace blender::deg { struct Depsgraph; @@ -27,5 +26,4 @@ class VolumeBackup { char filepath[1024]; /* FILE_MAX */ }; -} // namespace deg -} // namespace blender +} // namespace blender::deg diff --git a/source/blender/depsgraph/intern/eval/deg_eval_stats.h b/source/blender/depsgraph/intern/eval/deg_eval_stats.h index a1e3cdaca76..c24c5f07135 100644 --- a/source/blender/depsgraph/intern/eval/deg_eval_stats.h +++ b/source/blender/depsgraph/intern/eval/deg_eval_stats.h @@ -7,13 +7,11 @@ #pragma once -namespace blender { -namespace deg { +namespace blender::deg { struct Depsgraph; /* Aggregate operation timings to overall component and ID nodes timing. */ void deg_eval_stats_aggregate(Depsgraph *graph); -} // namespace deg -} // namespace blender +} // namespace blender::deg diff --git a/source/blender/depsgraph/intern/eval/deg_eval_visibility.cc b/source/blender/depsgraph/intern/eval/deg_eval_visibility.cc new file mode 100644 index 00000000000..a056ba1dfa7 --- /dev/null +++ b/source/blender/depsgraph/intern/eval/deg_eval_visibility.cc @@ -0,0 +1,232 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later + * Copyright 2022 Blender Foundation. All rights reserved. */ + +/** \file + * \ingroup depsgraph + */ + +#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" +#include "BLI_stack.h" + +#include "DEG_depsgraph.h" + +#include "intern/depsgraph.h" +#include "intern/depsgraph_relation.h" +#include "intern/node/deg_node.h" +#include "intern/node/deg_node_component.h" +#include "intern/node/deg_node_id.h" +#include "intern/node/deg_node_operation.h" + +namespace blender::deg { + +void deg_evaluate_object_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); + + const int required_flags = (graph->mode == DAG_EVAL_VIEWPORT) ? BASE_ENABLED_VIEWPORT : + BASE_ENABLED_RENDER; + + const bool is_enabled = object->base_flag & required_flags; + + if (id_node->is_enabled_on_eval != is_enabled) { + id_node->is_enabled_on_eval = is_enabled; + + /* Tag dependency graph for changed visibility, so that it is updated on all dependencies prior + * to a pass of an actual evaluation. */ + graph->need_update_nodes_visibility = true; + } +} + +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 { + DEG_NODE_VISITED = (1 << 0), + }; + + for (IDNode *id_node : graph->id_nodes) { + 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; + } + } + } + + BLI_Stack *stack = BLI_stack_new(sizeof(OperationNode *), "DEG flush layers stack"); + + for (OperationNode *op_node : graph->operations) { + op_node->custom_flags = 0; + op_node->num_links_pending = 0; + for (Relation *rel : op_node->outlinks) { + if ((rel->from->type == NodeType::OPERATION) && (rel->flag & RELATION_FLAG_CYCLIC) == 0) { + ++op_node->num_links_pending; + } + } + if (op_node->num_links_pending == 0) { + BLI_stack_push(stack, &op_node); + op_node->custom_flags |= DEG_NODE_VISITED; + } + } + + while (!BLI_stack_is_empty(stack)) { + OperationNode *op_node; + BLI_stack_pop(stack, &op_node); + + /* Flush flags to parents. */ + for (Relation *rel : op_node->inlinks) { + 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; + + 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. */ + if (comp_from->type == NodeType::VISIBILITY) { + const IDNode *id_node_from = comp_from->owner; + if (target_possibly_affects_visible_id) { + for (ComponentNode *comp_node : id_node_from->components.values()) { + comp_node->possibly_affects_visible_id |= target_possibly_affects_visible_id; + } + } + if (target_affects_visible_id) { + for (ComponentNode *comp_node : id_node_from->components.values()) { + comp_node->affects_visible_id |= target_affects_visible_id; + } + } + } + else { + comp_from->possibly_affects_visible_id |= target_possibly_affects_visible_id; + comp_from->affects_visible_id |= target_affects_visible_id; + } + } + } + + /* Schedule parent nodes. */ + for (Relation *rel : op_node->inlinks) { + if (rel->from->type == NodeType::OPERATION) { + OperationNode *op_from = (OperationNode *)rel->from; + if ((rel->flag & RELATION_FLAG_CYCLIC) == 0) { + BLI_assert(op_from->num_links_pending > 0); + --op_from->num_links_pending; + } + if ((op_from->num_links_pending == 0) && (op_from->custom_flags & DEG_NODE_VISITED) == 0) { + BLI_stack_push(stack, &op_from); + op_from->custom_flags |= DEG_NODE_VISITED; + } + } + } + } + BLI_stack_free(stack); + + graph->need_update_nodes_visibility = false; +} + +void deg_graph_flush_visibility_flags_if_needed(Depsgraph *graph) +{ + if (!graph->need_update_nodes_visibility) { + return; + } + + deg_graph_flush_visibility_flags(graph); +} + +} // namespace blender::deg diff --git a/source/blender/depsgraph/intern/eval/deg_eval_visibility.h b/source/blender/depsgraph/intern/eval/deg_eval_visibility.h new file mode 100644 index 00000000000..6544654f3cf --- /dev/null +++ b/source/blender/depsgraph/intern/eval/deg_eval_visibility.h @@ -0,0 +1,29 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later + * Copyright 2022 Blender Foundation. All rights reserved. */ + +/** \file + * \ingroup depsgraph + */ + +#pragma once + +struct Depsgraph; + +namespace blender::deg { + +struct Depsgraph; +struct IDNode; + +/* Evaluate actual node visibility flags based on the current state of object's visibility + * 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); +void deg_graph_flush_visibility_flags_if_needed(Depsgraph *graph); + +} // namespace blender::deg diff --git a/source/blender/depsgraph/intern/node/deg_node.h b/source/blender/depsgraph/intern/node/deg_node.h index 509867ad47a..db912ee3a82 100644 --- a/source/blender/depsgraph/intern/node/deg_node.h +++ b/source/blender/depsgraph/intern/node/deg_node.h @@ -18,8 +18,7 @@ struct ID; struct Scene; -namespace blender { -namespace deg { +namespace blender::deg { struct Depsgraph; struct OperationNode; @@ -65,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, @@ -217,5 +216,4 @@ struct Node { void deg_register_base_depsnodes(); -} // namespace deg -} // namespace blender +} // namespace blender::deg diff --git a/source/blender/depsgraph/intern/node/deg_node_component.cc b/source/blender/depsgraph/intern/node/deg_node_component.cc index cfcbec46569..f2d82e80fa6 100644 --- a/source/blender/depsgraph/intern/node/deg_node_component.cc +++ b/source/blender/depsgraph/intern/node/deg_node_component.cc @@ -67,7 +67,10 @@ uint64_t ComponentNode::OperationIDKey::hash() const } ComponentNode::ComponentNode() - : entry_operation(nullptr), exit_operation(nullptr), affects_directly_visible(false) + : entry_operation(nullptr), + exit_operation(nullptr), + possibly_affects_visible_id(false), + affects_visible_id(false) { operations_map = new Map<ComponentNode::OperationIDKey, OperationNode *>(); } @@ -90,7 +93,7 @@ string ComponentNode::identifier() const const string idname = this->owner->name; const string typebuf = "" + to_string(static_cast<int>(type)) + ")"; return typebuf + name + " : " + idname + - "( affects_directly_visible: " + (affects_directly_visible ? "true" : "false") + ")"; + "( affects_visible_id: " + (affects_visible_id ? "true" : "false") + ")"; } OperationNode *ComponentNode::find_operation(OperationIDKey key) const @@ -215,10 +218,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); } diff --git a/source/blender/depsgraph/intern/node/deg_node_component.h b/source/blender/depsgraph/intern/node/deg_node_component.h index 6958866af3b..f7f38b88854 100644 --- a/source/blender/depsgraph/intern/node/deg_node_component.h +++ b/source/blender/depsgraph/intern/node/deg_node_component.h @@ -22,10 +22,8 @@ struct ID; struct bPoseChannel; -namespace blender { -namespace deg { +namespace blender::deg { -struct BoneComponentNode; struct Depsgraph; struct IDNode; struct OperationNode; @@ -56,32 +54,45 @@ struct ComponentNode : public Node { virtual string identifier() const override; - /* Find an existing operation, if requested operation does not exist - * nullptr will be returned. */ + /* Find an existing operation, if requested operation does not exist nullptr will be returned. + * See #add_operation for the meaning and examples of #name and #name_tag. + */ OperationNode *find_operation(OperationIDKey key) const; - OperationNode *find_operation(OperationCode opcode, const char *name, int name_tag) const; + OperationNode *find_operation(OperationCode opcode, + const char *name = "", + int name_tag = -1) const; - /* Find an existing operation, will throw an assert() if it does not exist. */ + /* Find an existing operation, will throw an assert() if it does not exist. + * See #add_operation for the meaning and examples of #name and #name_tag. */ OperationNode *get_operation(OperationIDKey key) const; - OperationNode *get_operation(OperationCode opcode, const char *name, int name_tag) const; + OperationNode *get_operation(OperationCode opcode, + const char *name = "", + int name_tag = -1) const; /* Check operation exists and return it. */ bool has_operation(OperationIDKey key) const; - bool has_operation(OperationCode opcode, const char *name, int name_tag) const; + bool has_operation(OperationCode opcode, const char *name = "", int name_tag = -1) const; /** * Create a new node for representing an operation and add this to graph + * * \warning If an existing node is found, it will be modified. This helps * when node may have been partially created earlier (e.g. parent ref before * parent item is added) * * \param opcode: The operation to perform. - * \param name: Identifier for operation - used to find/locate it again. + * \param name: An optional identifier for operation. It will be used to tell operation nodes + * with the same code apart. For example, parameter operation code will have name + * set to the corresponding custom property name + * \param name_tag: An optional integer tag for the name. Is an additional way to tell operations + * apart. For example, RNA path to an array property will have the same opcode + * of PARAMETERS, name corresponding to the property name, and name tag + * corresponding to the array index within the property. */ OperationNode *add_operation(const DepsEvalOperationCb &op, OperationCode opcode, - const char *name, - int name_tag); + const char *name = "", + int name_tag = -1); /* Entry/exit operations management. * @@ -125,9 +136,17 @@ struct ComponentNode : public Node { return true; } - /* Denotes whether this component affects (possibly indirectly) on a - * directly visible object. */ - bool affects_directly_visible; + /* The component has (possibly indirect) effect on a data-block whose node has + * is_visible_on_build set to true. + * + * This field is ensured to be up-to-date prior to `IDNode::finalize_build()`. */ + bool possibly_affects_visible_id; + + /* Denotes whether this component actually affects (possibly indirectly) on a directly visible + * object. Includes possibly run-time visibility update of ID nodes. + * + * NOTE: Is only reliable after `deg_graph_flush_visibility()`. */ + bool affects_visible_id; }; /* ---------------------------------------- */ @@ -186,7 +205,7 @@ 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(Visibility); +DEG_COMPONENT_NODE_DECLARE_NO_COW_TAG_ON_UPDATE(Visibility); DEG_COMPONENT_NODE_DECLARE_GENERIC(Simulation); DEG_COMPONENT_NODE_DECLARE_GENERIC(NTreeOutput); @@ -218,5 +237,4 @@ struct ParametersComponentNode : public ComponentNode { void deg_register_component_depsnodes(); -} // namespace deg -} // namespace blender +} // namespace blender::deg diff --git a/source/blender/depsgraph/intern/node/deg_node_factory.h b/source/blender/depsgraph/intern/node/deg_node_factory.h index 6caf99ac9ba..ec5029e8352 100644 --- a/source/blender/depsgraph/intern/node/deg_node_factory.h +++ b/source/blender/depsgraph/intern/node/deg_node_factory.h @@ -14,9 +14,7 @@ struct ID; -namespace blender { -namespace deg { - +namespace blender::deg { struct DepsNodeFactory { virtual NodeType type() const = 0; virtual const char *type_name() const = 0; @@ -41,7 +39,6 @@ void register_node_typeinfo(DepsNodeFactory *factory); /* Get typeinfo for specified type */ DepsNodeFactory *type_get_factory(NodeType type); -} // namespace deg -} // namespace blender +} // namespace blender::deg #include "intern/node/deg_node_factory_impl.h" 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 76a91860cc1..d9d0a1c1e3e 100644 --- a/source/blender/depsgraph/intern/node/deg_node_factory_impl.h +++ b/source/blender/depsgraph/intern/node/deg_node_factory_impl.h @@ -11,8 +11,7 @@ struct ID; -namespace blender { -namespace deg { +namespace blender::deg { template<class ModeObjectType> NodeType DepsNodeFactoryImpl<ModeObjectType>::type() const { @@ -48,5 +47,4 @@ Node *DepsNodeFactoryImpl<ModeObjectType>::create_node(const ID *id, return node; } -} // namespace deg -} // namespace blender +} // namespace blender::deg diff --git a/source/blender/depsgraph/intern/node/deg_node_id.cc b/source/blender/depsgraph/intern/node/deg_node_id.cc index 99224501e98..735d606ac9e 100644 --- a/source/blender/depsgraph/intern/node/deg_node_id.cc +++ b/source/blender/depsgraph/intern/node/deg_node_id.cc @@ -69,7 +69,8 @@ void IDNode::init(const ID *id, const char *UNUSED(subdata)) customdata_masks = DEGCustomDataMeshMasks(); previous_customdata_masks = DEGCustomDataMeshMasks(); linked_state = DEG_ID_LINKED_INDIRECTLY; - is_directly_visible = true; + is_visible_on_build = true; + is_enabled_on_eval = true; is_collection_fully_expanded = false; has_base = false; is_user_modified = false; @@ -138,8 +139,8 @@ string IDNode::identifier() const BLI_snprintf(orig_ptr, sizeof(orig_ptr), "%p", id_orig); BLI_snprintf(cow_ptr, sizeof(cow_ptr), "%p", id_cow); return string(nodeTypeAsString(type)) + " : " + name + " (orig: " + orig_ptr + - ", eval: " + cow_ptr + ", is_directly_visible " + - (is_directly_visible ? "true" : "false") + ")"; + ", eval: " + cow_ptr + ", is_visible_on_build " + + (is_visible_on_build ? "true" : "false") + ")"; } ComponentNode *IDNode::find_component(NodeType type, const char *name) const @@ -188,7 +189,7 @@ IDComponentsMask IDNode::get_visible_components_mask() const { IDComponentsMask result = 0; for (ComponentNode *comp_node : components.values()) { - if (comp_node->affects_directly_visible) { + if (comp_node->possibly_affects_visible_id) { const int component_type_as_int = static_cast<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_id.h b/source/blender/depsgraph/intern/node/deg_node_id.h index a8b6294b482..7f0a656cb8d 100644 --- a/source/blender/depsgraph/intern/node/deg_node_id.h +++ b/source/blender/depsgraph/intern/node/deg_node_id.h @@ -12,8 +12,7 @@ #include "DNA_ID.h" #include "intern/node/deg_node.h" -namespace blender { -namespace deg { +namespace blender::deg { struct ComponentNode; @@ -92,8 +91,21 @@ struct IDNode : public Node { eDepsNode_LinkedState_Type linked_state; - /* Indicates the data-block is visible in the evaluated scene. */ - bool is_directly_visible; + /* Indicates the data-block is to be considered visible in the evaluated scene. + * + * This flag is set during dependency graph build where check for an actual visibility might not + * be available yet due to driven or animated restriction flags. So it is more of an intent or, + * in other words, plausibility of the data-block to be visible. */ + bool is_visible_on_build; + + /* Evaluated state of whether evaluation considered this data-block "enabled". + * + * For objects this is derived from the base restriction flags, which might be animated or + * driven. It is set to `BASE_ENABLED_<VIEWPORT, RENDER>` (depending on the graph mode) after + * the object's flags from layer were evaluated. + * + * For other data-types is currently always true. */ + bool is_enabled_on_eval; /* For the collection type of ID, denotes whether collection was fully * recursed into. */ @@ -117,5 +129,4 @@ struct IDNode : public Node { DEG_DEPSNODE_DECLARE; }; -} // namespace deg -} // namespace blender +} // namespace blender::deg diff --git a/source/blender/depsgraph/intern/node/deg_node_operation.cc b/source/blender/depsgraph/intern/node/deg_node_operation.cc index c29aeefd9b2..016af735fcf 100644 --- a/source/blender/depsgraph/intern/node/deg_node_operation.cc +++ b/source/blender/depsgraph/intern/node/deg_node_operation.cc @@ -32,6 +32,8 @@ const char *operationCodeAsString(OperationCode opcode) return "PARAMETERS_EVAL"; case OperationCode::PARAMETERS_EXIT: return "PARAMETERS_EXIT"; + case OperationCode::VISIBILITY: + return "VISIBILITY"; /* Animation, Drivers, etc. */ case OperationCode::ANIMATION_ENTRY: return "ANIMATION_ENTRY"; @@ -82,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: @@ -216,9 +220,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 d4916be1113..cb3beb56556 100644 --- a/source/blender/depsgraph/intern/node/deg_node_operation.h +++ b/source/blender/depsgraph/intern/node/deg_node_operation.h @@ -13,8 +13,7 @@ struct Depsgraph; -namespace blender { -namespace deg { +namespace blender::deg { struct ComponentNode; @@ -34,6 +33,7 @@ enum class OperationCode { PARAMETERS_ENTRY, PARAMETERS_EVAL, PARAMETERS_EXIT, + VISIBILITY, /* Animation, Drivers, etc. --------------------------------------------- */ /* NLA + Action */ @@ -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. */ @@ -202,15 +204,24 @@ const char *operationCodeAsString(OperationCode opcode); enum OperationFlag { /* Node needs to be updated. */ DEPSOP_FLAG_NEEDS_UPDATE = (1 << 0), + /* Node was directly modified, causing need for update. */ DEPSOP_FLAG_DIRECTLY_MODIFIED = (1 << 1), + /* Node was updated due to user input. */ DEPSOP_FLAG_USER_MODIFIED = (1 << 2), - /* Node may not be removed, even when it has no evaluation callback and no - * outgoing relations. This is for NO-OP nodes that are purely used to indicate a - * relation between components/IDs, and not for connecting to an operation. */ + + /* Node may not be removed, even when it has no evaluation callback and no outgoing relations. + * This is for NO-OP nodes that are purely used to indicate a relation between components/IDs, + * and not for connecting to an operation. */ DEPSOP_FLAG_PINNED = (1 << 3), + /* 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), }; @@ -268,5 +279,4 @@ struct OperationNode : public Node { void deg_register_operation_depsnodes(); -} // namespace deg -} // namespace blender +} // namespace blender::deg diff --git a/source/blender/depsgraph/intern/node/deg_node_time.h b/source/blender/depsgraph/intern/node/deg_node_time.h index fcfe9a0fa80..3946b63384d 100644 --- a/source/blender/depsgraph/intern/node/deg_node_time.h +++ b/source/blender/depsgraph/intern/node/deg_node_time.h @@ -9,8 +9,7 @@ #include "intern/node/deg_node.h" -namespace blender { -namespace deg { +namespace blender::deg { /* Time Source Node. */ struct TimeSourceNode : public Node { @@ -25,5 +24,4 @@ struct TimeSourceNode : public Node { DEG_DEPSNODE_DECLARE; }; -} // namespace deg -} // namespace blender +} // namespace blender::deg |