diff options
Diffstat (limited to 'source/blender/depsgraph')
36 files changed, 318 insertions, 99 deletions
diff --git a/source/blender/depsgraph/DEG_depsgraph.h b/source/blender/depsgraph/DEG_depsgraph.h index 567916fdebe..740124f6113 100644 --- a/source/blender/depsgraph/DEG_depsgraph.h +++ b/source/blender/depsgraph/DEG_depsgraph.h @@ -139,16 +139,19 @@ void DEG_graph_time_tag_update(struct Depsgraph *depsgraph); void DEG_graph_id_type_tag(struct Depsgraph *depsgraph, short id_type); void DEG_id_type_tag(struct Main *bmain, short id_type); -void DEG_ids_clear_recalc(struct Main *bmain, Depsgraph *depsgraph); +/* Set a depsgraph to flush updates to editors. This would be done + * for viewport depsgraphs, but not render or export depsgraph for example. */ +void DEG_enable_editors_update(struct Depsgraph *depsgraph); -/* Check if something was changed in the database and inform - * editors about this. - */ -void DEG_ids_check_recalc(struct Main *bmain, - struct Depsgraph *depsgraph, - struct Scene *scene, - struct ViewLayer *view_layer, - bool time); +/* Check if something was changed in the database and inform editors about this. */ +void DEG_editors_update(struct Depsgraph *depsgraph, bool time); + +/* Clear recalc flags after editors or renderers have handled updates. */ +void DEG_ids_clear_recalc(Depsgraph *depsgraph, const bool backup); + +/* Restore recalc flags, backed up by a previous call to DEG_ids_clear_recalc. + * This also clears the backup. */ +void DEG_ids_restore_recalc(Depsgraph *depsgraph); /* ************************************************ */ /* Evaluation Engine API */ diff --git a/source/blender/depsgraph/DEG_depsgraph_build.h b/source/blender/depsgraph/DEG_depsgraph_build.h index 4e618d8625d..b4acf9b010c 100644 --- a/source/blender/depsgraph/DEG_depsgraph_build.h +++ b/source/blender/depsgraph/DEG_depsgraph_build.h @@ -40,6 +40,7 @@ struct Object; struct Scene; struct Simulation; struct bNodeTree; +struct Collection; #include "BLI_sys_types.h" @@ -137,6 +138,12 @@ void DEG_add_object_relation(struct DepsNodeHandle *node_handle, struct Object *object, eDepsObjectComponentType component, const char *description); +void DEG_add_collection_geometry_relation(struct DepsNodeHandle *node_handle, + struct Collection *collection, + const char *description); +void DEG_add_collection_geometry_customdata_mask(struct DepsNodeHandle *node_handle, + struct Collection *collection, + const struct CustomData_MeshMasks *masks); void DEG_add_simulation_relation(struct DepsNodeHandle *node_handle, struct Simulation *simulation, const char *description); @@ -182,6 +189,8 @@ void DEG_add_customdata_mask(struct DepsNodeHandle *handle, struct ID *DEG_get_id_from_handle(struct DepsNodeHandle *node_handle); struct Depsgraph *DEG_get_graph_from_handle(struct DepsNodeHandle *node_handle); +bool DEG_object_has_geometry_component(struct Object *object); + /* ************************************************ */ #ifdef __cplusplus diff --git a/source/blender/depsgraph/intern/builder/deg_builder.cc b/source/blender/depsgraph/intern/builder/deg_builder.cc index e4660c34762..f4d65698bee 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder.cc @@ -77,10 +77,6 @@ DepsgraphBuilder::DepsgraphBuilder(Main *bmain, Depsgraph *graph, DepsgraphBuild { } -DepsgraphBuilder::~DepsgraphBuilder() -{ -} - bool DepsgraphBuilder::need_pull_base_into_graph(Base *base) { /* Simple check: enabled bases are always part of dependency graph. */ diff --git a/source/blender/depsgraph/intern/builder/deg_builder.h b/source/blender/depsgraph/intern/builder/deg_builder.h index 36b6b1bf17d..6e1c8d8526f 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder.h +++ b/source/blender/depsgraph/intern/builder/deg_builder.h @@ -37,7 +37,7 @@ class DepsgraphBuilderCache; class DepsgraphBuilder { public: - virtual ~DepsgraphBuilder(); + virtual ~DepsgraphBuilder() = default; virtual bool need_pull_base_into_graph(Base *base); diff --git a/source/blender/depsgraph/intern/builder/deg_builder_cache.cc b/source/blender/depsgraph/intern/builder/deg_builder_cache.cc index df108072142..af7717d7595 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_cache.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_cache.cc @@ -149,10 +149,6 @@ bool AnimatedPropertyStorage::isPropertyAnimated(const PointerRNA *pointer_rna, /* Builder cache itself. */ -DepsgraphBuilderCache::DepsgraphBuilderCache() -{ -} - DepsgraphBuilderCache::~DepsgraphBuilderCache() { for (AnimatedPropertyStorage *animated_property_storage : diff --git a/source/blender/depsgraph/intern/builder/deg_builder_cache.h b/source/blender/depsgraph/intern/builder/deg_builder_cache.h index e04ae3a3727..c955a22a5cf 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_cache.h +++ b/source/blender/depsgraph/intern/builder/deg_builder_cache.h @@ -81,7 +81,6 @@ class AnimatedPropertyStorage { /* Cached data which can be re-used by multiple builders. */ class DepsgraphBuilderCache { public: - DepsgraphBuilderCache(); ~DepsgraphBuilderCache(); /* Makes sure storage for animated properties exists and initialized for the given ID. */ diff --git a/source/blender/depsgraph/intern/builder/deg_builder_map.cc b/source/blender/depsgraph/intern/builder/deg_builder_map.cc index 5da54350cfc..6e926da6b29 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_map.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_map.cc @@ -27,14 +27,6 @@ namespace blender::deg { -BuilderMap::BuilderMap() -{ -} - -BuilderMap::~BuilderMap() -{ -} - bool BuilderMap::checkIsBuilt(ID *id, int tag) const { return (getIDTag(id) & tag) == tag; diff --git a/source/blender/depsgraph/intern/builder/deg_builder_map.h b/source/blender/depsgraph/intern/builder/deg_builder_map.h index 8b23d3d0d3b..53f6a722e85 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_map.h +++ b/source/blender/depsgraph/intern/builder/deg_builder_map.h @@ -47,9 +47,6 @@ class BuilderMap { TAG_SCENE_COMPOSITOR | TAG_SCENE_SEQUENCER | TAG_SCENE_AUDIO), }; - BuilderMap(); - ~BuilderMap(); - /* Check whether given ID is already handled by builder (or if it's being handled). */ bool checkIsBuilt(ID *id, int tag = TAG_COMPLETE) const; diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc index d8dc66883a0..ae530cc010e 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc @@ -84,6 +84,7 @@ #include "BKE_lattice.h" #include "BKE_layer.h" #include "BKE_lib_id.h" +#include "BKE_lib_query.h" #include "BKE_light.h" #include "BKE_mask.h" #include "BKE_material.h" @@ -114,6 +115,7 @@ #include "intern/builder/deg_builder.h" #include "intern/depsgraph.h" +#include "intern/depsgraph_tag.h" #include "intern/depsgraph_type.h" #include "intern/eval/deg_eval_copy_on_write.h" #include "intern/node/deg_node.h" @@ -360,7 +362,103 @@ void DepsgraphNodeBuilder::begin_build() graph_->entry_tags.clear(); } -void DepsgraphNodeBuilder::end_build() +/* Util callbacks for `BKE_library_foreach_ID_link`, used to detect when a COW ID is using ID + * pointers that are either: + * - COW ID pointers that do not exist anymore in current depsgraph. + * - Orig ID pointers that do have now a COW version in current depsgraph. + * In both cases, it means the COW ID user needs to be flushed, to ensure its pointers are properly + * remapped. + * + * NOTE: This is split in two, a static function and a public method of the node builder, to allow + * the code to access the builder's data more easily. */ + +/* `id_cow_self` is the user of `id_pointer`, see also `LibraryIDLinkCallbackData` struct + * definition. */ +int DepsgraphNodeBuilder::foreach_id_cow_detect_need_for_update_callback(ID *id_cow_self, + ID *id_pointer) +{ + if (id_pointer->orig_id == nullptr) { + /* `id_cow_self` uses a non-cow ID, if that ID has a COW copy in current depsgraph its owner + * needs to be remapped, i.e. COW-flushed. */ + IDNode *id_node = find_id_node(id_pointer); + if (id_node != nullptr && id_node->id_cow != nullptr) { + graph_id_tag_update(bmain_, + graph_, + id_cow_self->orig_id, + ID_RECALC_COPY_ON_WRITE, + DEG_UPDATE_SOURCE_RELATIONS); + return IDWALK_RET_STOP_ITER; + } + } + else { + /* `id_cow_self` uses a COW ID, if that COW copy is removed from current depsgraph its owner + * needs to be remapped, i.e. COW-flushed. */ + /* NOTE: at that stage, old existing COW copies that are to be removed from current state of + * evaluated depsgraph are still valid pointers, they are freed later (typically during + * destruction of the builder itself). */ + IDNode *id_node = find_id_node(id_pointer->orig_id); + if (id_node == nullptr) { + graph_id_tag_update(bmain_, + graph_, + id_cow_self->orig_id, + ID_RECALC_COPY_ON_WRITE, + DEG_UPDATE_SOURCE_RELATIONS); + return IDWALK_RET_STOP_ITER; + } + } + return IDWALK_RET_NOP; +} + +static int foreach_id_cow_detect_need_for_update_callback(LibraryIDLinkCallbackData *cb_data) +{ + ID *id = *cb_data->id_pointer; + if (id == nullptr) { + return IDWALK_RET_NOP; + } + + DepsgraphNodeBuilder *builder = static_cast<DepsgraphNodeBuilder *>(cb_data->user_data); + ID *id_cow_self = cb_data->id_self; + + return builder->foreach_id_cow_detect_need_for_update_callback(id_cow_self, id); +} + +/* Check for IDs that need to be flushed (COW-updated) because the depsgraph itself created or + * removed some of their evaluated dependencies. + * + * NOTE: Currently the only ID types that depsgraph may decide to not evaluate/generate COW + * copies for, even though they are referenced by other data-blocks, are Collections and Objects + * (through their various visibility flags, and the ones from LayerCollections too). However, this + * code is kept generic as it makes it more future-proof, and optimization here would give + * negligible performance improvements in typical cases. + * + * NOTE: This mechanism may also 'fix' some missing update tagging from non-depsgraph code in + * some cases. This is slightly unfortunate (as it may hide issues in other parts of Blender + * code), but cannot really be avoided currently. + */ +void DepsgraphNodeBuilder::update_invalid_cow_pointers() +{ + for (const IDNode *id_node : graph_->id_nodes) { + if (id_node->previously_visible_components_mask == 0) { + /* Newly added node/ID, no need to check it. */ + continue; + } + if (ELEM(id_node->id_cow, id_node->id_orig, nullptr)) { + /* Node/ID with no COW data, no need to check it. */ + continue; + } + if ((id_node->id_cow->recalc & ID_RECALC_COPY_ON_WRITE) != 0) { + /* Node/ID already tagged for COW flush, no need to check it. */ + continue; + } + BKE_library_foreach_ID_link(nullptr, + id_node->id_cow, + deg::foreach_id_cow_detect_need_for_update_callback, + this, + IDWALK_IGNORE_EMBEDDED_ID | IDWALK_READONLY); + } +} + +void DepsgraphNodeBuilder::tag_previously_tagged_nodes() { for (const SavedEntryTag &entry_tag : saved_entry_tags_) { IDNode *id_node = find_id_node(entry_tag.id_orig); @@ -382,6 +480,12 @@ void DepsgraphNodeBuilder::end_build() } } +void DepsgraphNodeBuilder::end_build() +{ + tag_previously_tagged_nodes(); + update_invalid_cow_pointers(); +} + void DepsgraphNodeBuilder::build_id(ID *id) { if (id == nullptr) { @@ -554,6 +658,7 @@ void DepsgraphNodeBuilder::build_collection(LayerCollection *from_layer_collecti id_node->is_directly_visible = is_collection_visible; build_idproperties(collection->id.properties); + add_operation_node(&collection->id, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL_DONE); } if (from_layer_collection != nullptr) { /* If we came from layer collection we don't go deeper, view layer @@ -1556,6 +1661,12 @@ void DepsgraphNodeBuilder::build_nodetree_socket(bNodeSocket *socket) else if (socket->type == SOCK_COLLECTION) { build_id((ID *)((bNodeSocketValueCollection *)socket->default_value)->value); } + else if (socket->type == SOCK_TEXTURE) { + build_id((ID *)((bNodeSocketValueTexture *)socket->default_value)->value); + } + else if (socket->type == SOCK_MATERIAL) { + build_id((ID *)((bNodeSocketValueMaterial *)socket->default_value)->value); + } } void DepsgraphNodeBuilder::build_nodetree(bNodeTree *ntree) diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.h b/source/blender/depsgraph/intern/builder/deg_builder_nodes.h index a7033c8c8f3..151e0d844b6 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.h +++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.h @@ -101,6 +101,8 @@ class DepsgraphNodeBuilder : public DepsgraphBuilder { virtual void begin_build(); virtual void end_build(); + int foreach_id_cow_detect_need_for_update_callback(ID *id_cow_self, ID *id_pointer); + IDNode *add_id_node(ID *id); IDNode *find_id_node(ID *id); TimeSourceNode *add_time_source(); @@ -276,6 +278,9 @@ class DepsgraphNodeBuilder : public DepsgraphBuilder { bool is_reference, void *user_data); + void tag_previously_tagged_nodes(); + void update_invalid_cow_pointers(); + /* State which demotes currently built entities. */ Scene *scene_; ViewLayer *view_layer_; diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes_rig.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes_rig.cc index 13caba67713..00c78b8edce 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_nodes_rig.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes_rig.cc @@ -169,7 +169,7 @@ void DepsgraphNodeBuilder::build_rig(Object *object, bool is_object_visible) } /* Speed optimization for animation lookups. */ if (object->pose != nullptr) { - BKE_pose_channels_hash_make(object->pose); + BKE_pose_channels_hash_ensure(object->pose); if (object->pose->flag & POSE_CONSTRAINTS_NEED_UPDATE_FLAGS) { BKE_pose_update_constraint_flags(object->pose); } @@ -318,7 +318,7 @@ void DepsgraphNodeBuilder::build_proxy_rig(Object *object, bool is_object_visibl /* Armature. */ build_armature(armature); /* speed optimization for animation lookups */ - BKE_pose_channels_hash_make(object->pose); + BKE_pose_channels_hash_ensure(object->pose); if (object->pose->flag & POSE_CONSTRAINTS_NEED_UPDATE_FLAGS) { BKE_pose_update_constraint_flags(object->pose); } diff --git a/source/blender/depsgraph/intern/builder/deg_builder_pchanmap.cc b/source/blender/depsgraph/intern/builder/deg_builder_pchanmap.cc index 197e14c1a21..17c2925b7f4 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_pchanmap.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_pchanmap.cc @@ -30,14 +30,6 @@ namespace blender::deg { -RootPChanMap::RootPChanMap() -{ -} - -RootPChanMap::~RootPChanMap() -{ -} - /* Debug contents of map */ void RootPChanMap::print_debug() { diff --git a/source/blender/depsgraph/intern/builder/deg_builder_pchanmap.h b/source/blender/depsgraph/intern/builder/deg_builder_pchanmap.h index 7a6ea38a0f0..0dd4062c353 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_pchanmap.h +++ b/source/blender/depsgraph/intern/builder/deg_builder_pchanmap.h @@ -29,10 +29,6 @@ namespace blender { namespace deg { struct RootPChanMap { - /* Constructor and destructor - Create and free the internal map respectively. */ - RootPChanMap(); - ~RootPChanMap(); - /* Debug contents of map. */ void print_debug(); diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc index 3cc2ec02165..8a02228146a 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc @@ -635,11 +635,38 @@ void DepsgraphRelationBuilder::build_collection(LayerCollection *from_layer_coll ComponentKey duplicator_key(object != nullptr ? &object->id : nullptr, NodeType::DUPLI); if (!group_done) { build_idproperties(collection->id.properties); + OperationKey collection_geometry_key{ + &collection->id, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL_DONE}; LISTBASE_FOREACH (CollectionObject *, cob, &collection->gobject) { build_object(cob->ob); + + /* The geometry of a collection depends on the positions of the elements in it. */ + OperationKey object_transform_key{ + &cob->ob->id, NodeType::TRANSFORM, OperationCode::TRANSFORM_FINAL}; + add_relation(object_transform_key, collection_geometry_key, "Collection Geometry"); + + /* Only create geometry relations to child objects, if they have a geometry component. */ + OperationKey object_geometry_key{ + &cob->ob->id, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL}; + if (find_node(object_geometry_key) != nullptr) { + add_relation(object_geometry_key, collection_geometry_key, "Collection Geometry"); + } + + /* An instance is part of the geometry of the collection. */ + if (cob->ob->type == OB_EMPTY) { + Collection *collection_instance = cob->ob->instance_collection; + if (collection_instance != nullptr) { + OperationKey collection_instance_key{ + &collection_instance->id, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL_DONE}; + add_relation(collection_instance_key, collection_geometry_key, "Collection Geometry"); + } + } } LISTBASE_FOREACH (CollectionChild *, child, &collection->children) { build_collection(nullptr, nullptr, child->collection); + OperationKey child_collection_geometry_key{ + &child->collection->id, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL_DONE}; + add_relation(child_collection_geometry_key, collection_geometry_key, "Collection Geometry"); } } if (object != nullptr) { @@ -2374,6 +2401,18 @@ void DepsgraphRelationBuilder::build_nodetree_socket(bNodeSocket *socket) build_collection(nullptr, nullptr, collection); } } + else if (socket->type == SOCK_TEXTURE) { + Tex *texture = ((bNodeSocketValueTexture *)socket->default_value)->value; + if (texture != nullptr) { + build_texture(texture); + } + } + else if (socket->type == SOCK_MATERIAL) { + Material *material = ((bNodeSocketValueMaterial *)socket->default_value)->value; + if (material != nullptr) { + build_material(material); + } + } } void DepsgraphRelationBuilder::build_nodetree(bNodeTree *ntree) diff --git a/source/blender/depsgraph/intern/builder/deg_builder_rna.cc b/source/blender/depsgraph/intern/builder/deg_builder_rna.cc index 4064058f231..54c51adec66 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_rna.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_rna.cc @@ -119,9 +119,7 @@ RNANodeQuery::RNANodeQuery(Depsgraph *depsgraph, DepsgraphBuilder *builder) { } -RNANodeQuery::~RNANodeQuery() -{ -} +RNANodeQuery::~RNANodeQuery() = default; Node *RNANodeQuery::find_node(const PointerRNA *ptr, const PropertyRNA *prop, diff --git a/source/blender/depsgraph/intern/builder/pipeline.cc b/source/blender/depsgraph/intern/builder/pipeline.cc index f7feeea9593..10bc7213061 100644 --- a/source/blender/depsgraph/intern/builder/pipeline.cc +++ b/source/blender/depsgraph/intern/builder/pipeline.cc @@ -40,10 +40,6 @@ AbstractBuilderPipeline::AbstractBuilderPipeline(::Depsgraph *graph) { } -AbstractBuilderPipeline::~AbstractBuilderPipeline() -{ -} - void AbstractBuilderPipeline::build() { double start_time = 0.0; @@ -98,7 +94,7 @@ void AbstractBuilderPipeline::build_step_finalize() if (G.debug_value == 799) { deg_graph_transitive_reduction(deg_graph_); } - /* Store pointers to commonly used valuated datablocks. */ + /* Store pointers to commonly used evaluated datablocks. */ deg_graph_->scene_cow = (Scene *)deg_graph_->get_cow_id(°_graph_->scene->id); /* Flush visibility layer and re-schedule nodes for update. */ deg_graph_build_finalize(bmain_, deg_graph_); diff --git a/source/blender/depsgraph/intern/builder/pipeline.h b/source/blender/depsgraph/intern/builder/pipeline.h index dcd1bc6f26e..d0ccf352c21 100644 --- a/source/blender/depsgraph/intern/builder/pipeline.h +++ b/source/blender/depsgraph/intern/builder/pipeline.h @@ -50,7 +50,7 @@ class DepsgraphRelationBuilder; class AbstractBuilderPipeline { public: AbstractBuilderPipeline(::Depsgraph *graph); - virtual ~AbstractBuilderPipeline(); + virtual ~AbstractBuilderPipeline() = default; void build(); diff --git a/source/blender/depsgraph/intern/depsgraph.cc b/source/blender/depsgraph/intern/depsgraph.cc index 3d30e7e79b9..8e1ab23fae0 100644 --- a/source/blender/depsgraph/intern/depsgraph.cc +++ b/source/blender/depsgraph/intern/depsgraph.cc @@ -70,7 +70,8 @@ Depsgraph::Depsgraph(Main *bmain, Scene *scene, ViewLayer *view_layer, eEvaluati scene_cow(nullptr), is_active(false), is_evaluating(false), - is_render_pipeline_depsgraph(false) + is_render_pipeline_depsgraph(false), + use_editors_update(false) { BLI_spin_init(&lock); memset(id_type_updated, 0, sizeof(id_type_updated)); @@ -285,7 +286,9 @@ Depsgraph *DEG_graph_new(Main *bmain, Scene *scene, ViewLayer *view_layer, eEval } /* Replace the "owner" pointers (currently Main/Scene/ViewLayer) of this depsgraph. - * Used during undo steps when we do want to re-use the old depsgraph data as much as possible. */ + * Used for: + * - Undo steps when we do want to re-use the old depsgraph data as much as possible. + * - Rendering where we want to re-use objects between different view layers. */ void DEG_graph_replace_owners(struct Depsgraph *depsgraph, Main *bmain, Scene *scene, diff --git a/source/blender/depsgraph/intern/depsgraph.h b/source/blender/depsgraph/intern/depsgraph.h index df8c8215d2f..b87ce94709a 100644 --- a/source/blender/depsgraph/intern/depsgraph.h +++ b/source/blender/depsgraph/intern/depsgraph.h @@ -161,6 +161,9 @@ struct Depsgraph { * does not need any bases. */ bool is_render_pipeline_depsgraph; + /* Notify editors about changes to IDs in this depsgraph. */ + bool use_editors_update; + /* Cached list of colliders/effectors for collections and the scene * created along with relations, for fast lookup during evaluation. */ Map<const ID *, ListBase *> *physics_relations[DEG_PHYSICS_RELATIONS_NUM]; diff --git a/source/blender/depsgraph/intern/depsgraph_build.cc b/source/blender/depsgraph/intern/depsgraph_build.cc index 6717ba521f6..9e9191c5ab9 100644 --- a/source/blender/depsgraph/intern/depsgraph_build.cc +++ b/source/blender/depsgraph/intern/depsgraph_build.cc @@ -32,11 +32,13 @@ #include "PIL_time_utildefines.h" #include "DNA_cachefile_types.h" +#include "DNA_collection_types.h" #include "DNA_node_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" #include "DNA_simulation_types.h" +#include "BKE_collection.h" #include "BKE_main.h" #include "BKE_scene.h" @@ -60,6 +62,7 @@ #include "intern/depsgraph_registry.h" #include "intern/depsgraph_relation.h" +#include "intern/depsgraph_tag.h" #include "intern/depsgraph_type.h" /* ****************** */ @@ -107,6 +110,34 @@ void DEG_add_object_relation(DepsNodeHandle *node_handle, deg_node_handle->builder->add_node_handle_relation(comp_key, deg_node_handle, description); } +bool DEG_object_has_geometry_component(Object *object) +{ + return deg::geometry_tag_to_component(&object->id) != deg::NodeType::UNDEFINED; +} + +void DEG_add_collection_geometry_relation(DepsNodeHandle *node_handle, + Collection *collection, + const char *description) +{ + deg::OperationKey operation_key{ + &collection->id, deg::NodeType::GEOMETRY, deg::OperationCode::GEOMETRY_EVAL_DONE}; + deg::DepsNodeHandle *deg_node_handle = get_node_handle(node_handle); + deg_node_handle->builder->add_node_handle_relation(operation_key, deg_node_handle, description); +} + +void DEG_add_collection_geometry_customdata_mask(DepsNodeHandle *node_handle, + Collection *collection, + const CustomData_MeshMasks *masks) +{ + FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN (collection, ob) { + DEG_add_customdata_mask(node_handle, ob, masks); + if (ob->type == OB_EMPTY && ob->instance_collection != nullptr) { + DEG_add_collection_geometry_customdata_mask(node_handle, ob->instance_collection, masks); + } + } + FOREACH_COLLECTION_OBJECT_RECURSIVE_END; +} + void DEG_add_simulation_relation(DepsNodeHandle *node_handle, Simulation *simulation, const char *description) diff --git a/source/blender/depsgraph/intern/depsgraph_query.cc b/source/blender/depsgraph/intern/depsgraph_query.cc index 57de62e1880..aab4c3ca0f6 100644 --- a/source/blender/depsgraph/intern/depsgraph_query.cc +++ b/source/blender/depsgraph/intern/depsgraph_query.cc @@ -168,7 +168,7 @@ ViewLayer *DEG_get_evaluated_view_layer(const Depsgraph *graph) const deg::Depsgraph *deg_graph = reinterpret_cast<const deg::Depsgraph *>(graph); Scene *scene_cow = DEG_get_evaluated_scene(graph); if (scene_cow == nullptr) { - return nullptr; /* Happens with new, not-yet-built/evaluated graphes. */ + return nullptr; /* Happens with new, not-yet-built/evaluated graphs. */ } /* Do name-based lookup. */ /* TODO(sergey): Can this be optimized? */ diff --git a/source/blender/depsgraph/intern/depsgraph_query_iter.cc b/source/blender/depsgraph/intern/depsgraph_query_iter.cc index ed002321729..df1cf8cc771 100644 --- a/source/blender/depsgraph/intern/depsgraph_query_iter.cc +++ b/source/blender/depsgraph/intern/depsgraph_query_iter.cc @@ -219,6 +219,29 @@ bool deg_iterator_components_step(BLI_Iterator *iter) } } + /* The curve component. */ + if (data->geometry_component_id == 3) { + data->geometry_component_id++; + + const CurveComponent *component = geometry_set->get_component_for_read<CurveComponent>(); + if (component != nullptr) { + const Curve *curve = component->get_curve_for_render(); + + if (curve != nullptr) { + Object *temp_object = &data->temp_geometry_component_object; + *temp_object = *data->geometry_component_owner; + temp_object->type = OB_CURVE; + temp_object->data = (void *)curve; + /* Assign data_eval here too, because curve rendering code tries + * to use a mesh if it can find one in this pointer. */ + temp_object->runtime.data_eval = (ID *)curve; + temp_object->runtime.select_id = data->geometry_component_owner->runtime.select_id; + iter->current = temp_object; + return true; + } + } + } + data->geometry_component_owner = nullptr; return false; } diff --git a/source/blender/depsgraph/intern/depsgraph_tag.cc b/source/blender/depsgraph/intern/depsgraph_tag.cc index 2051ee3657a..204143d7cbd 100644 --- a/source/blender/depsgraph/intern/depsgraph_tag.cc +++ b/source/blender/depsgraph/intern/depsgraph_tag.cc @@ -594,6 +594,7 @@ NodeType geometry_tag_to_component(const ID *id) case ID_HA: case ID_PT: case ID_VO: + case ID_GR: return NodeType::GEOMETRY; case ID_PA: /* Particles */ return NodeType::UNDEFINED; @@ -816,11 +817,24 @@ void DEG_on_visible_update(Main *bmain, const bool do_time) } } +void DEG_enable_editors_update(Depsgraph *depsgraph) +{ + deg::Depsgraph *graph = (deg::Depsgraph *)depsgraph; + graph->use_editors_update = true; +} + /* Check if something was changed in the database and inform * editors about this. */ -void DEG_ids_check_recalc( - Main *bmain, Depsgraph *depsgraph, Scene *scene, ViewLayer *view_layer, bool time) +void DEG_editors_update(Depsgraph *depsgraph, bool time) { + deg::Depsgraph *graph = (deg::Depsgraph *)depsgraph; + if (!graph->use_editors_update) { + return; + } + + Scene *scene = DEG_get_input_scene(depsgraph); + ViewLayer *view_layer = DEG_get_input_view_layer(depsgraph); + Main *bmain = DEG_get_bmain(depsgraph); bool updated = time || DEG_id_type_any_updated(depsgraph); DEGEditorUpdateContext update_ctx = {nullptr}; @@ -842,7 +856,7 @@ static void deg_graph_clear_id_recalc_flags(ID *id) /* XXX And what about scene's master collection here? */ } -void DEG_ids_clear_recalc(Main *UNUSED(bmain), Depsgraph *depsgraph) +void DEG_ids_clear_recalc(Depsgraph *depsgraph, const bool backup) { deg::Depsgraph *deg_graph = reinterpret_cast<deg::Depsgraph *>(depsgraph); /* TODO(sergey): Re-implement POST_UPDATE_HANDLER_WORKAROUND using entry_tags @@ -852,6 +866,9 @@ void DEG_ids_clear_recalc(Main *UNUSED(bmain), Depsgraph *depsgraph) } /* Go over all ID nodes nodes, clearing tags. */ for (deg::IDNode *id_node : deg_graph->id_nodes) { + if (backup) { + id_node->id_cow_recalc_backup |= id_node->id_cow->recalc; + } /* TODO: we clear original ID recalc flags here, but this may not work * correctly when there are multiple depsgraph with others still using * the recalc flag. */ @@ -863,3 +880,13 @@ void DEG_ids_clear_recalc(Main *UNUSED(bmain), Depsgraph *depsgraph) } memset(deg_graph->id_type_updated, 0, sizeof(deg_graph->id_type_updated)); } + +void DEG_ids_restore_recalc(Depsgraph *depsgraph) +{ + deg::Depsgraph *deg_graph = reinterpret_cast<deg::Depsgraph *>(depsgraph); + + for (deg::IDNode *id_node : deg_graph->id_nodes) { + id_node->id_cow->recalc |= id_node->id_cow_recalc_backup; + id_node->id_cow_recalc_backup = 0; + } +} diff --git a/source/blender/depsgraph/intern/eval/deg_eval.cc b/source/blender/depsgraph/intern/eval/deg_eval.cc index 620e86550cc..2107e075139 100644 --- a/source/blender/depsgraph/intern/eval/deg_eval.cc +++ b/source/blender/depsgraph/intern/eval/deg_eval.cc @@ -353,7 +353,8 @@ static TaskPool *deg_evaluate_task_pool_create(DepsgraphEvalState *state) return BLI_task_pool_create_no_threads(state); } - return BLI_task_pool_create_suspended(state, TASK_PRIORITY_HIGH); + /* TODO: Disable task isolation. */ + return BLI_task_pool_create_suspended(state, TASK_PRIORITY_HIGH, TASK_ISOLATION_ON); } /** 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 2544bb1642c..0d367762b00 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 @@ -304,7 +304,8 @@ bool id_copy_inplace_no_main(const ID *id, ID *newid) bool result = (BKE_id_copy_ex(nullptr, (ID *)id_for_copy, &newid, - LIB_ID_COPY_LOCALIZE | LIB_ID_CREATE_NO_ALLOCATE) != nullptr); + (LIB_ID_COPY_LOCALIZE | LIB_ID_CREATE_NO_ALLOCATE | + LIB_ID_COPY_SET_COPIED_ON_WRITE)) != nullptr); #ifdef NESTED_ID_NASTY_WORKAROUND if (result) { @@ -319,7 +320,6 @@ bool id_copy_inplace_no_main(const ID *id, ID *newid) * is already allocated. */ bool scene_copy_inplace_no_main(const Scene *scene, Scene *new_scene) { - const ID *id_for_copy = &scene->id; if (G.debug & G_DEBUG_DEPSGRAPH_UUID) { SEQ_relations_check_uuids_unique_and_report(scene); @@ -327,13 +327,15 @@ bool scene_copy_inplace_no_main(const Scene *scene, Scene *new_scene) #ifdef NESTED_ID_NASTY_WORKAROUND NestedIDHackTempStorage id_hack_storage; - id_for_copy = nested_id_hack_get_discarded_pointers(&id_hack_storage, &scene->id); + const ID *id_for_copy = nested_id_hack_get_discarded_pointers(&id_hack_storage, &scene->id); +#else + const ID *id_for_copy = &scene->id; #endif - bool result = (BKE_id_copy_ex(nullptr, id_for_copy, (ID **)&new_scene, - LIB_ID_COPY_LOCALIZE | LIB_ID_CREATE_NO_ALLOCATE) != nullptr); + (LIB_ID_COPY_LOCALIZE | LIB_ID_CREATE_NO_ALLOCATE | + LIB_ID_COPY_SET_COPIED_ON_WRITE)) != nullptr); #ifdef NESTED_ID_NASTY_WORKAROUND if (result) { @@ -604,20 +606,12 @@ void update_lattice_edit_mode_pointers(const Depsgraph * /*depsgraph*/, void update_mesh_edit_mode_pointers(const ID *id_orig, ID *id_cow) { - /* For meshes we need to update edit_mesh to make it to point - * to the CoW version of object. - * - * This is kind of confusing, because actual bmesh is not owned by - * the CoW object, so need to be accurate about using link from - * edit_mesh to object. */ const Mesh *mesh_orig = (const Mesh *)id_orig; Mesh *mesh_cow = (Mesh *)id_cow; if (mesh_orig->edit_mesh == nullptr) { return; } - mesh_cow->edit_mesh = (BMEditMesh *)MEM_dupallocN(mesh_orig->edit_mesh); - mesh_cow->edit_mesh->mesh_eval_cage = nullptr; - mesh_cow->edit_mesh->mesh_eval_final = nullptr; + mesh_cow->edit_mesh = mesh_orig->edit_mesh; } /* Edit data is stored and owned by original datablocks, copied ones @@ -653,11 +647,17 @@ void update_list_orig_pointers(const ListBase *listbase_orig, { T *element_orig = reinterpret_cast<T *>(listbase_orig->first); T *element_cow = reinterpret_cast<T *>(listbase->first); - while (element_orig != nullptr) { + + /* Both lists should have the same number of elements, so the check on + * `element_cow` is just to prevent a crash if this is not the case. */ + while (element_orig != nullptr && element_cow != nullptr) { element_cow->*orig_field = element_orig; element_cow = element_cow->next; element_orig = element_orig->next; } + + BLI_assert((element_orig == nullptr && element_cow == nullptr) || + !"list of pointers of different sizes, unable to reliably set orig pointer"); } void update_particle_system_orig_pointers(const Object *object_orig, Object *object_cow) @@ -993,11 +993,6 @@ void discard_lattice_edit_mode_pointers(ID *id_cow) void discard_mesh_edit_mode_pointers(ID *id_cow) { Mesh *mesh_cow = (Mesh *)id_cow; - if (mesh_cow->edit_mesh == nullptr) { - return; - } - BKE_editmesh_free_derivedmesh(mesh_cow->edit_mesh); - MEM_freeN(mesh_cow->edit_mesh); mesh_cow->edit_mesh = nullptr; } 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 7a0c1b5b693..7893e8c64c1 100644 --- a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup.cc +++ b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup.cc @@ -33,6 +33,7 @@ namespace blender::deg { RuntimeBackup::RuntimeBackup(const Depsgraph *depsgraph) : have_backup(false), + id_data({nullptr}), animation_backup(depsgraph), scene_backup(depsgraph), sound_backup(depsgraph), @@ -51,6 +52,8 @@ void RuntimeBackup::init_from_id(ID *id) } have_backup = true; + id_data.py_instance = id->py_instance; + animation_backup.init_from_id(id); const ID_Type id_type = GS(id->name); @@ -89,6 +92,8 @@ void RuntimeBackup::restore_to_id(ID *id) return; } + id->py_instance = id_data.py_instance; + animation_backup.restore_to_id(id); const ID_Type id_type = GS(id->name); 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 c6249c83daa..0629dbe62b4 100644 --- a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup.h +++ b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup.h @@ -58,6 +58,11 @@ class RuntimeBackup { * copy-on-write mechanism. */ bool have_backup; + /* Struct members of the ID pointer. */ + struct { + void *py_instance; + } id_data; + AnimationBackup animation_backup; SceneBackup scene_backup; SoundBackup sound_backup; diff --git a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_animation.cc b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_animation.cc index c1d2dd8b6cc..bd872d40825 100644 --- a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_animation.cc +++ b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_animation.cc @@ -75,19 +75,11 @@ void animated_property_store_cb(ID *id, FCurve *fcurve, void *data_v) } // namespace -AnimationValueBackup::AnimationValueBackup() -{ -} - AnimationValueBackup::AnimationValueBackup(const string &rna_path, int array_index, float value) : rna_path(rna_path), array_index(array_index), value(value) { } -AnimationValueBackup::~AnimationValueBackup() -{ -} - AnimationBackup::AnimationBackup(const Depsgraph *depsgraph) { meed_value_backup = !depsgraph->is_active; 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 6b5d5eab75f..8f71457ae6f 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 @@ -34,9 +34,8 @@ struct Depsgraph; class AnimationValueBackup { public: - AnimationValueBackup(); + AnimationValueBackup() = default; AnimationValueBackup(const string &rna_path, int array_index, float value); - ~AnimationValueBackup(); AnimationValueBackup(const AnimationValueBackup &other) = default; AnimationValueBackup(AnimationValueBackup &&other) noexcept = default; diff --git a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_object.cc b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_object.cc index 61299a2d49c..30ec9e948fd 100644 --- a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_object.cc +++ b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_object.cc @@ -55,7 +55,7 @@ void ObjectRuntimeBackup::init_from_object(Object *object) /* Make a backup of base flags. */ base_flag = object->base_flag; base_local_view_bits = object->base_local_view_bits; - /* Backup tuntime data of all modifiers. */ + /* Backup runtime data of all modifiers. */ backup_modifier_runtime_data(object); /* Backup runtime data of all pose channels. */ backup_pose_channel_runtime_data(object); @@ -98,7 +98,7 @@ void ObjectRuntimeBackup::restore_to_object(Object *object) object->runtime = runtime; object->runtime.data_orig = data_orig; object->runtime.bb = bb; - if (object->type == OB_MESH && data_eval != nullptr) { + if (ELEM(object->type, OB_MESH, OB_LATTICE) && data_eval != nullptr) { if (object->id.recalc & ID_RECALC_GEOMETRY) { /* If geometry is tagged for update it means, that part of * evaluated mesh are not valid anymore. In this case we can not diff --git a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_sequence.cc b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_sequence.cc index 35720140f97..d481e0c39a8 100644 --- a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_sequence.cc +++ b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_sequence.cc @@ -35,24 +35,28 @@ SequenceBackup::SequenceBackup(const Depsgraph * /*depsgraph*/) void SequenceBackup::reset() { scene_sound = nullptr; + BLI_listbase_clear(&anims); } void SequenceBackup::init_from_sequence(Sequence *sequence) { scene_sound = sequence->scene_sound; + anims = sequence->anims; sequence->scene_sound = nullptr; + BLI_listbase_clear(&sequence->anims); } void SequenceBackup::restore_to_sequence(Sequence *sequence) { sequence->scene_sound = scene_sound; + sequence->anims = anims; reset(); } bool SequenceBackup::isEmpty() const { - return (scene_sound == nullptr); + return (scene_sound == nullptr) && BLI_listbase_is_empty(&anims); } } // 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 eb38dc3dc5b..3b3aa496496 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 @@ -23,6 +23,8 @@ #pragma once +#include "BLI_listbase.h" + struct Sequence; namespace blender { @@ -43,6 +45,7 @@ class SequenceBackup { bool isEmpty() const; void *scene_sound; + ListBase anims; }; } // namespace deg diff --git a/source/blender/depsgraph/intern/node/deg_node_id.cc b/source/blender/depsgraph/intern/node/deg_node_id.cc index 8e159a7ff08..688afe141e9 100644 --- a/source/blender/depsgraph/intern/node/deg_node_id.cc +++ b/source/blender/depsgraph/intern/node/deg_node_id.cc @@ -90,6 +90,7 @@ void IDNode::init(const ID *id, const char *UNUSED(subdata)) is_collection_fully_expanded = false; has_base = false; is_user_modified = false; + id_cow_recalc_backup = 0; visible_components_mask = 0; previously_visible_components_mask = 0; diff --git a/source/blender/depsgraph/intern/node/deg_node_id.h b/source/blender/depsgraph/intern/node/deg_node_id.h index e2d3b3fc36f..073469598dc 100644 --- a/source/blender/depsgraph/intern/node/deg_node_id.h +++ b/source/blender/depsgraph/intern/node/deg_node_id.h @@ -120,6 +120,9 @@ struct IDNode : public Node { /* Accumulated flag from operation. Is initialized and used during updates flush. */ bool is_user_modified; + /* Accumulate recalc flags from multiple update passes. */ + int id_cow_recalc_backup; + IDComponentsMask visible_components_mask; IDComponentsMask previously_visible_components_mask; diff --git a/source/blender/depsgraph/intern/node/deg_node_operation.cc b/source/blender/depsgraph/intern/node/deg_node_operation.cc index 97aca6280be..7e57467f905 100644 --- a/source/blender/depsgraph/intern/node/deg_node_operation.cc +++ b/source/blender/depsgraph/intern/node/deg_node_operation.cc @@ -213,10 +213,6 @@ OperationNode::OperationNode() : name_tag(-1), flag(0) { } -OperationNode::~OperationNode() -{ -} - string OperationNode::identifier() const { return string(operationCodeAsString(opcode)) + "(" + name + ")"; diff --git a/source/blender/depsgraph/intern/node/deg_node_operation.h b/source/blender/depsgraph/intern/node/deg_node_operation.h index 40369de08f5..1d966cffd5d 100644 --- a/source/blender/depsgraph/intern/node/deg_node_operation.h +++ b/source/blender/depsgraph/intern/node/deg_node_operation.h @@ -231,7 +231,6 @@ enum OperationFlag { /* Atomic Operation - Base type for all operations */ struct OperationNode : public Node { OperationNode(); - ~OperationNode(); virtual string identifier() const override; string full_identifier() const; |