diff options
Diffstat (limited to 'source/blender/depsgraph/intern/depsgraph.cc')
-rw-r--r-- | source/blender/depsgraph/intern/depsgraph.cc | 229 |
1 files changed, 185 insertions, 44 deletions
diff --git a/source/blender/depsgraph/intern/depsgraph.cc b/source/blender/depsgraph/intern/depsgraph.cc index 34fb20ee2ba..b9681805cfb 100644 --- a/source/blender/depsgraph/intern/depsgraph.cc +++ b/source/blender/depsgraph/intern/depsgraph.cc @@ -48,15 +48,18 @@ extern "C" { #include "DNA_object_types.h" #include "DNA_sequence_types.h" -#include "BKE_depsgraph.h" - #include "RNA_access.h" + +#include "BKE_scene.h" } #include <algorithm> #include <cstring> #include "DEG_depsgraph.h" +#include "DEG_depsgraph_debug.h" + +#include "intern/eval/deg_eval_copy_on_write.h" #include "intern/nodes/deg_node.h" #include "intern/nodes/deg_node_component.h" @@ -71,7 +74,6 @@ namespace DEG { static DEG_EditorUpdateIDCb deg_editor_update_id_cb = NULL; static DEG_EditorUpdateSceneCb deg_editor_update_scene_cb = NULL; -static DEG_EditorUpdateScenePreCb deg_editor_update_scene_pre_cb = NULL; /* TODO(sergey): Find a better place for this. */ template <typename T> @@ -81,14 +83,23 @@ static void remove_from_vector(vector<T> *vector, const T& value) vector->end()); } -Depsgraph::Depsgraph() +Depsgraph::Depsgraph(Scene *scene, + ViewLayer *view_layer, + eEvaluationMode mode) : time_source(NULL), - need_update(false), - layers(0) + need_update(true), + scene(scene), + view_layer(view_layer), + mode(mode), + ctime(BKE_scene_frame_get(scene)), + scene_cow(NULL), + is_active(false) { BLI_spin_init(&lock); id_hash = BLI_ghash_ptr_new("Depsgraph id hash"); entry_tags = BLI_gset_ptr_new("Depsgraph entry_tags"); + debug_flags = G.debug; + memset(id_type_updated, 0, sizeof(id_type_updated)); } Depsgraph::~Depsgraph() @@ -214,6 +225,10 @@ static bool pointer_to_component_node_criteria( *subdata = seq->name; // xxx? return true; } + else if (RNA_struct_is_a(ptr->type, &RNA_NodeSocket)) { + *type = DEG_NODE_TYPE_SHADING; + return true; + } else if (ptr->type == &RNA_Curve) { *id = (ID *)ptr->id.data; *type = DEG_NODE_TYPE_GEOMETRY; @@ -274,12 +289,6 @@ DepsNode *Depsgraph::find_node_from_pointer(const PointerRNA *ptr, /* Node Management ---------------------------- */ -static void id_node_deleter(void *value) -{ - IDDepsNode *id_node = reinterpret_cast<IDDepsNode *>(value); - OBJECT_GUARDED_DELETE(id_node, IDDepsNode); -} - TimeSourceDepsNode *Depsgraph::add_time_source() { if (time_source == NULL) { @@ -299,13 +308,19 @@ IDDepsNode *Depsgraph::find_id_node(const ID *id) const return reinterpret_cast<IDDepsNode *>(BLI_ghash_lookup(id_hash, id)); } -IDDepsNode *Depsgraph::add_id_node(ID *id, const char *name) +IDDepsNode *Depsgraph::add_id_node(ID *id, ID *id_cow_hint) { + BLI_assert((id->tag & LIB_TAG_COPY_ON_WRITE) == 0); IDDepsNode *id_node = find_id_node(id); if (!id_node) { DepsNodeFactory *factory = deg_type_get_factory(DEG_NODE_TYPE_ID_REF); - id_node = (IDDepsNode *)factory->create_node(id, "", name); - /* register */ + id_node = (IDDepsNode *)factory->create_node(id, "", id->name); + id_node->init_copy_on_write(id_cow_hint); + /* Register node in ID hash. + * + * NOTE: We address ID nodes by the original ID pointer they are + * referencing to. + */ BLI_ghash_insert(id_hash, id, id_node); id_nodes.push_back(id_node); } @@ -314,7 +329,30 @@ IDDepsNode *Depsgraph::add_id_node(ID *id, const char *name) void Depsgraph::clear_id_nodes() { - BLI_ghash_clear(id_hash, NULL, id_node_deleter); + /* Free memory used by ID nodes. */ + { + /* Stupid workaround to ensure we free IDs in a proper order. */ + foreach (IDDepsNode *id_node, id_nodes) { + if (id_node->id_cow == NULL) { + /* This means builder "stole" ownership of the copy-on-written + * datablock for her own dirty needs. + */ + continue; + } + if (!deg_copy_on_write_is_expanded(id_node->id_cow)) { + continue; + } + const ID_Type id_type = GS(id_node->id_cow->name); + if (id_type != ID_PA) { + id_node->destroy(); + } + } + } + foreach (IDDepsNode *id_node, id_nodes) { + OBJECT_GUARDED_DELETE(id_node, IDDepsNode); + } + /* Clear containers. */ + BLI_ghash_clear(id_hash, NULL, NULL); id_nodes.clear(); } @@ -339,7 +377,7 @@ DepsRelation *Depsgraph::add_new_relation(OperationDepsNode *from, if (comp_node->type == DEG_NODE_TYPE_GEOMETRY) { IDDepsNode *id_to = to->owner->owner; IDDepsNode *id_from = from->owner->owner; - if (id_to != id_from && (id_to->id->recalc & ID_RECALC_ALL)) { + if (id_to != id_from && (id_to->id_orig->recalc & ID_RECALC_ALL)) { if ((id_from->eval_flags & DAG_EVAL_NEED_CPU) == 0) { id_from->tag_update(this); id_from->eval_flags |= DAG_EVAL_NEED_CPU; @@ -433,9 +471,9 @@ void DepsRelation::unlink() void Depsgraph::add_entry_tag(OperationDepsNode *node) { /* Sanity check. */ - if (!node) + if (node == NULL) { return; - + } /* Add to graph-level set of directly modified nodes to start searching from. * NOTE: this is necessary since we have several thousand nodes to play with... */ @@ -451,17 +489,46 @@ void Depsgraph::clear_all_nodes() } } -void deg_editors_id_update(Main *bmain, ID *id) +ID *Depsgraph::get_cow_id(const ID *id_orig) const +{ + IDDepsNode *id_node = find_id_node(id_orig); + if (id_node == NULL) { + /* This function is used from places where we expect ID to be either + * already a copy-on-write version or have a corresponding copy-on-write + * version. + * + * We try to enforce that in debug builds, for for release we play a bit + * safer game here. + */ + if ((id_orig->tag & LIB_TAG_COPY_ON_WRITE) == 0) { + /* TODO(sergey): This is nice sanity check to have, but it fails + * in following situations: + * + * - Material has link to texture, which is not needed by new + * shading system and hence can be ignored at construction. + * - Object or mesh has material at a slot which is not used (for + * example, object has material slot by materials are set to + * object data). + */ + // BLI_assert(!"Request for non-existing copy-on-write ID"); + } + return (ID *)id_orig; + } + return id_node->id_cow; +} + +void deg_editors_id_update(const DEGEditorUpdateContext *update_ctx, ID *id) { if (deg_editor_update_id_cb != NULL) { - deg_editor_update_id_cb(bmain, id); + deg_editor_update_id_cb(update_ctx, id); } } -void deg_editors_scene_update(Main *bmain, Scene *scene, bool updated) +void deg_editors_scene_update(const DEGEditorUpdateContext *update_ctx, + bool updated) { if (deg_editor_update_scene_cb != NULL) { - deg_editor_update_scene_cb(bmain, scene, updated); + deg_editor_update_scene_cb(update_ctx, updated); } } @@ -496,9 +563,14 @@ string deg_color_end(void) /* Public Graph API */ /* Initialize a new Depsgraph */ -Depsgraph *DEG_graph_new() -{ - DEG::Depsgraph *deg_depsgraph = OBJECT_GUARDED_NEW(DEG::Depsgraph); +Depsgraph *DEG_graph_new(Scene *scene, + ViewLayer *view_layer, + eEvaluationMode mode) +{ + DEG::Depsgraph *deg_depsgraph = OBJECT_GUARDED_NEW(DEG::Depsgraph, + scene, + view_layer, + mode); return reinterpret_cast<Depsgraph *>(deg_depsgraph); } @@ -512,32 +584,68 @@ void DEG_graph_free(Depsgraph *graph) /* Set callbacks which are being called when depsgraph changes. */ void DEG_editors_set_update_cb(DEG_EditorUpdateIDCb id_func, - DEG_EditorUpdateSceneCb scene_func, - DEG_EditorUpdateScenePreCb scene_pre_func) + DEG_EditorUpdateSceneCb scene_func) { DEG::deg_editor_update_id_cb = id_func; DEG::deg_editor_update_scene_cb = scene_func; - DEG::deg_editor_update_scene_pre_cb = scene_pre_func; } -void DEG_editors_update_pre(Main *bmain, Scene *scene, bool time) +bool DEG_is_active(const struct Depsgraph *depsgraph) { - if (DEG::deg_editor_update_scene_pre_cb != NULL) { - DEG::deg_editor_update_scene_pre_cb(bmain, scene, time); + if (depsgraph == NULL) { + /* Happens for such cases as work object in what_does_obaction(), + * and sine render pipeline parts. Shouldn't really be accepting + * NULL depsgraph, but is quite hard to get proper one in those + * cases. + */ + return false; } + const DEG::Depsgraph *deg_graph = + reinterpret_cast<const DEG::Depsgraph *>(depsgraph); + return deg_graph->is_active; +} + +void DEG_make_active(struct Depsgraph *depsgraph) +{ + DEG::Depsgraph *deg_graph = reinterpret_cast<DEG::Depsgraph *>(depsgraph); + deg_graph->is_active = true; + /* TODO(sergey): Copy data from evaluated state to original. */ +} + +void DEG_make_inactive(struct Depsgraph *depsgraph) +{ + DEG::Depsgraph *deg_graph = reinterpret_cast<DEG::Depsgraph *>(depsgraph); + deg_graph->is_active = false; } /* Evaluation and debug */ -void DEG_debug_print_eval(const char *function_name, +static DEG::string depsgraph_name_for_logging(struct Depsgraph *depsgraph) +{ + const char *name = DEG_debug_name_get(depsgraph); + if (name[0] == '\0') { + return ""; + } + return "[" + DEG::string(name) + "]: "; +} + +void DEG_debug_print_begin(struct Depsgraph *depsgraph) +{ + fprintf(stdout, "%s", + depsgraph_name_for_logging(depsgraph).c_str()); +} + +void DEG_debug_print_eval(struct Depsgraph *depsgraph, + const char *function_name, const char *object_name, const void *object_address) { - if ((G.debug & G_DEBUG_DEPSGRAPH_EVAL) == 0) { + if ((DEG_debug_flags_get(depsgraph) & G_DEBUG_DEPSGRAPH_EVAL) == 0) { return; } fprintf(stdout, - "%s on %s %s(%p)%s\n", + "%s%s on %s %s(%p)%s\n", + depsgraph_name_for_logging(depsgraph).c_str(), function_name, object_name, DEG::deg_color_for_pointer(object_address).c_str(), @@ -546,18 +654,20 @@ void DEG_debug_print_eval(const char *function_name, fflush(stdout); } -void DEG_debug_print_eval_subdata(const char *function_name, +void DEG_debug_print_eval_subdata(struct Depsgraph *depsgraph, + const char *function_name, const char *object_name, const void *object_address, const char *subdata_comment, const char *subdata_name, const void *subdata_address) { - if ((G.debug & G_DEBUG_DEPSGRAPH_EVAL) == 0) { + if ((DEG_debug_flags_get(depsgraph) & G_DEBUG_DEPSGRAPH_EVAL) == 0) { return; } fprintf(stdout, - "%s on %s %s(%p)%s %s %s %s(%p)%s\n", + "%s%s on %s %s(%p)%s %s %s %s(%p)%s\n", + depsgraph_name_for_logging(depsgraph).c_str(), function_name, object_name, DEG::deg_color_for_pointer(object_address).c_str(), @@ -571,7 +681,8 @@ void DEG_debug_print_eval_subdata(const char *function_name, fflush(stdout); } -void DEG_debug_print_eval_subdata_index(const char *function_name, +void DEG_debug_print_eval_subdata_index(struct Depsgraph *depsgraph, + const char *function_name, const char *object_name, const void *object_address, const char *subdata_comment, @@ -579,11 +690,12 @@ void DEG_debug_print_eval_subdata_index(const char *function_name, const void *subdata_address, const int subdata_index) { - if ((G.debug & G_DEBUG_DEPSGRAPH_EVAL) == 0) { + if ((DEG_debug_flags_get(depsgraph) & G_DEBUG_DEPSGRAPH_EVAL) == 0) { return; } fprintf(stdout, - "%s on %s %s(%p)^%s %s %s[%d] %s(%p)%s\n", + "%s%s on %s %s(%p)%s %s %s[%d] %s(%p)%s\n", + depsgraph_name_for_logging(depsgraph).c_str(), function_name, object_name, DEG::deg_color_for_pointer(object_address).c_str(), @@ -598,16 +710,45 @@ void DEG_debug_print_eval_subdata_index(const char *function_name, fflush(stdout); } -void DEG_debug_print_eval_time(const char *function_name, +void DEG_debug_print_eval_parent_typed(struct Depsgraph *depsgraph, + const char *function_name, + const char *object_name, + const void *object_address, + const char *parent_comment, + const char *parent_name, + const void *parent_address) +{ + if ((DEG_debug_flags_get(depsgraph) & G_DEBUG_DEPSGRAPH_EVAL) == 0) { + return; + } + fprintf(stdout, + "%s%s on %s %s(%p) [%s] %s %s %s(%p)%s\n", + depsgraph_name_for_logging(depsgraph).c_str(), + function_name, + object_name, + DEG::deg_color_for_pointer(object_address).c_str(), + object_address, + DEG::deg_color_end().c_str(), + parent_comment, + parent_name, + DEG::deg_color_for_pointer(parent_address).c_str(), + parent_address, + DEG::deg_color_end().c_str()); + fflush(stdout); +} + +void DEG_debug_print_eval_time(struct Depsgraph *depsgraph, + const char *function_name, const char *object_name, const void *object_address, float time) { - if ((G.debug & G_DEBUG_DEPSGRAPH_EVAL) == 0) { + if ((DEG_debug_flags_get(depsgraph) & G_DEBUG_DEPSGRAPH_EVAL) == 0) { return; } fprintf(stdout, - "%s on %s %s(%p)%s at time %f\n", + "%s%s on %s %s(%p)%s at time %f\n", + depsgraph_name_for_logging(depsgraph).c_str(), function_name, object_name, DEG::deg_color_for_pointer(object_address).c_str(), |