diff options
author | Sergey Sharybin <sergey.vfx@gmail.com> | 2017-10-18 15:35:34 +0300 |
---|---|---|
committer | Sergey Sharybin <sergey.vfx@gmail.com> | 2017-10-18 15:35:34 +0300 |
commit | 3e8abc0535aaeb736310a1b7a5447df1721ff349 (patch) | |
tree | de35daa1ec122c33b2e6803cb7cb61bb20406882 /source/blender/depsgraph | |
parent | 46f0b97d208c21d3ce192b71b65e1fa0776f7825 (diff) |
Depsgraph: Make Copy-on-Write a command line option
Before it was a compile time option which was not very easy to use or test. Now
the project is getting more mature, so very soon we will be able to call for a
public tests of limited features.
The copy-on-write (which includes animation, modifiers) is enabled using
--enable-copy-on-write command line argument.
Diffstat (limited to 'source/blender/depsgraph')
13 files changed, 112 insertions, 99 deletions
diff --git a/source/blender/depsgraph/CMakeLists.txt b/source/blender/depsgraph/CMakeLists.txt index 17a13b66aaa..b4509c7a61a 100644 --- a/source/blender/depsgraph/CMakeLists.txt +++ b/source/blender/depsgraph/CMakeLists.txt @@ -128,8 +128,4 @@ if(WITH_OPENSUBDIV) add_definitions(-DWITH_OPENSUBDIV) endif() -if(WITH_DEPSGRAPH_COPY_ON_WRITE) - add_definitions(-DWITH_COPY_ON_WRITE) -endif() - blender_add_lib(bf_depsgraph "${SRC}" "${INC}" "${INC_SYS}") diff --git a/source/blender/depsgraph/DEG_depsgraph.h b/source/blender/depsgraph/DEG_depsgraph.h index f925c37e23e..894adbee8c9 100644 --- a/source/blender/depsgraph/DEG_depsgraph.h +++ b/source/blender/depsgraph/DEG_depsgraph.h @@ -105,6 +105,9 @@ enum { extern "C" { #endif +bool DEG_depsgraph_use_copy_on_write(void); +void DEG_depsgraph_enable_copy_on_write(void); + /* ************************************************ */ /* Depsgraph API */ diff --git a/source/blender/depsgraph/intern/builder/deg_builder.cc b/source/blender/depsgraph/intern/builder/deg_builder.cc index deee2227f81..587d2021b52 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder.cc @@ -47,6 +47,7 @@ namespace DEG { void deg_graph_build_finalize(Depsgraph *graph) { + const bool use_copy_on_write = DEG_depsgraph_use_copy_on_write(); /* Re-tag IDs for update if it was tagged before the relations * update tag. */ @@ -63,9 +64,12 @@ void deg_graph_build_finalize(Depsgraph *graph) id_node->tag_update(graph); } } -#ifdef WITH_COPY_ON_WRITE - DEG_id_tag_update_ex(graph->bmain, id_node->id_orig, DEG_TAG_COPY_ON_WRITE); -#endif + /* TODO(sergey): This is not ideal at all, since this forces + * re-evaluaiton of the whole tree. + */ + if (use_copy_on_write) { + DEG_id_tag_update_ex(graph->bmain, id_node->id_orig, DEG_TAG_COPY_ON_WRITE); + } } GHASH_FOREACH_END(); } diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc index 02d20913177..a4c3c11d922 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc @@ -174,7 +174,9 @@ DepsgraphNodeBuilder::~DepsgraphNodeBuilder() IDDepsNode *DepsgraphNodeBuilder::add_id_node(ID *id, bool do_tag) { -#ifdef WITH_COPY_ON_WRITE + if (!DEG_depsgraph_use_copy_on_write()) { + return m_graph->add_id_node(id); + } IDDepsNode *id_node = NULL; ID *id_cow = (ID *)BLI_ghash_lookup(m_cow_id_hash, id); if (id_cow != NULL) { @@ -197,10 +199,6 @@ IDDepsNode *DepsgraphNodeBuilder::add_id_node(ID *id, bool do_tag) "", -1); m_graph->operations.push_back(op_cow); } -#else - IDDepsNode *id_node = m_graph->add_id_node(id); - UNUSED_VARS(do_tag); -#endif return id_node; } @@ -358,23 +356,25 @@ void DepsgraphNodeBuilder::begin_build(Main *bmain) { } FOREACH_NODETREE_END; -#ifdef WITH_COPY_ON_WRITE - /* Store existing copy-on-write versions of datablock, so we can re-use - * them for new ID nodes. - */ - m_cow_id_hash = BLI_ghash_ptr_new("Depsgraph id hash"); - GHASH_FOREACH_BEGIN(IDDepsNode *, id_node, m_graph->id_hash) - { - if (GS(id_node->id_orig->name) != ID_SCE) { - continue; - } - if (deg_copy_on_write_is_expanded(id_node->id_cow)) { - BLI_ghash_insert(m_cow_id_hash, id_node->id_orig, id_node->id_cow); - id_node->id_cow = NULL; + if (DEG_depsgraph_use_copy_on_write()) { + /* Store existing copy-on-write versions of datablock, so we can re-use + * them for new ID nodes. + */ + m_cow_id_hash = BLI_ghash_ptr_new("Depsgraph id hash"); + GHASH_FOREACH_BEGIN(IDDepsNode *, id_node, m_graph->id_hash) + { + if (GS(id_node->id_orig->name) != ID_SCE) { + continue; + } + if (deg_copy_on_write_is_expanded(id_node->id_cow)) { + BLI_ghash_insert(m_cow_id_hash, + id_node->id_orig, + id_node->id_cow); + id_node->id_cow = NULL; + } } + GHASH_FOREACH_END(); } - GHASH_FOREACH_END(); -#endif /* Make sure graph has no nodes left from previous state. */ m_graph->clear_all_nodes(); diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.h b/source/blender/depsgraph/intern/builder/deg_builder_nodes.h index 7e28df1276d..dbb126e2078 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.h +++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.h @@ -32,6 +32,8 @@ #include "intern/depsgraph_types.h" +#include "DEG_depsgraph.h" /* used for DEG_depsgraph_use_copy_on_write() */ + struct CacheFile; struct bGPdata; struct ListBase; @@ -98,11 +100,12 @@ struct DepsgraphNodeBuilder { /* For a given COW datablock get corresponding original one. */ template<typename T> T *get_orig_datablock(const T *cow) const { -#ifdef WITH_COPY_ON_WRITE - return (T *)cow->id.newid; -#else - return (T *)cow; -#endif + if (DEG_depsgraph_use_copy_on_write()) { + return (T *)cow->id.newid; + } + else { + return (T *)cow; + } } void begin_build(Main *bmain); diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes_layer.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes_layer.cc index b3a88d8ac4d..660d7fedb52 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_nodes_layer.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes_layer.cc @@ -96,12 +96,14 @@ void DepsgraphNodeBuilder::build_layer_collections(Scene *scene, void DepsgraphNodeBuilder::build_scene_layer_collections(Scene *scene) { -#ifdef WITH_COPY_ON_WRITE - /* Make sure we've got ID node, so we can get pointer to CoW datablock. */ - Scene *scene_cow = expand_cow_datablock(scene); -#else - Scene *scene_cow = scene; -#endif + Scene *scene_cow; + if (DEG_depsgraph_use_copy_on_write()) { + /* Make sure we've got ID node, so we can get pointer to CoW datablock. */ + scene_cow = expand_cow_datablock(scene); + } + else { + scene_cow = scene; + } LayerCollectionState state; state.index = 0; 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 eb7fbaefb95..20263e1d751 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_nodes_rig.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes_rig.cc @@ -138,18 +138,22 @@ void DepsgraphNodeBuilder::build_rig(Scene *scene, Object *object) { bArmature *armature = (bArmature *)object->data; const short armature_tag = armature->id.tag; -#ifdef WITH_COPY_ON_WRITE - /* NOTE: We need to expand both object and armature, so this way we can - * safely create object level pose. - */ - Scene *scene_cow = get_cow_datablock(scene); - Object *object_cow = expand_cow_datablock(object); - bArmature *armature_cow = expand_cow_datablock(armature); -#else - Scene *scene_cow = scene; - Object *object_cow = object; - bArmature *armature_cow = armature; -#endif + Scene *scene_cow; + Object *object_cow; + bArmature *armature_cow; + if (DEG_depsgraph_use_copy_on_write()) { + /* NOTE: We need to expand both object and armature, so this way we can + * safely create object level pose. + */ + scene_cow = get_cow_datablock(scene); + object_cow = expand_cow_datablock(object); + armature_cow = expand_cow_datablock(armature); + } + else { + scene_cow = scene; + object_cow = object; + armature_cow = armature; + } OperationDepsNode *op_node; /* Animation and/or drivers linking posebones to base-armature used to diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc index 0c5150f2f42..10c4c44d14e 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc @@ -1803,18 +1803,18 @@ void DepsgraphRelationBuilder::build_lamp(Object *ob) /* textures */ build_texture_stack(la->mtex); -#ifdef WITH_COPY_ON_WRITE - /* Make sure copy on write of lamp data is always properly updated for - * visible lamps. - */ - OperationKey ob_copy_on_write_key(&ob->id, - DEG_NODE_TYPE_COPY_ON_WRITE, - DEG_OPCODE_COPY_ON_WRITE); - OperationKey lamp_copy_on_write_key(lamp_id, - DEG_NODE_TYPE_COPY_ON_WRITE, - DEG_OPCODE_COPY_ON_WRITE); - add_relation(lamp_copy_on_write_key, ob_copy_on_write_key, "Eval Order"); -#endif + if (DEG_depsgraph_use_copy_on_write()) { + /* Make sure copy on write of lamp data is always properly updated for + * visible lamps. + */ + OperationKey ob_copy_on_write_key(&ob->id, + DEG_NODE_TYPE_COPY_ON_WRITE, + DEG_OPCODE_COPY_ON_WRITE); + OperationKey lamp_copy_on_write_key(lamp_id, + DEG_NODE_TYPE_COPY_ON_WRITE, + DEG_OPCODE_COPY_ON_WRITE); + add_relation(lamp_copy_on_write_key, ob_copy_on_write_key, "Eval Order"); + } } void DepsgraphRelationBuilder::build_nodetree(bNodeTree *ntree) diff --git a/source/blender/depsgraph/intern/depsgraph.cc b/source/blender/depsgraph/intern/depsgraph.cc index 81a4f2bc0cc..b146d4a432b 100644 --- a/source/blender/depsgraph/intern/depsgraph.cc +++ b/source/blender/depsgraph/intern/depsgraph.cc @@ -62,6 +62,18 @@ extern "C" { #include "intern/depsgraph_intern.h" #include "util/deg_util_foreach.h" +static bool use_copy_on_write = true; + +bool DEG_depsgraph_use_copy_on_write(void) +{ + return use_copy_on_write; +} + +void DEG_depsgraph_enable_copy_on_write(void) +{ + use_copy_on_write = true; +} + namespace DEG { static DEG_EditorUpdateIDCb deg_editor_update_id_cb = NULL; @@ -252,14 +264,6 @@ DepsNode *Depsgraph::find_node_from_pointer(const PointerRNA *ptr, /* Node Management ---------------------------- */ -#ifndef WITH_COPY_ON_WRITE -static void id_node_deleter(void *value) -{ - IDDepsNode *id_node = reinterpret_cast<IDDepsNode *>(value); - OBJECT_GUARDED_DELETE(id_node, IDDepsNode); -} -#endif - TimeSourceDepsNode *Depsgraph::add_time_source() { if (time_source == NULL) { @@ -305,9 +309,6 @@ IDDepsNode *Depsgraph::add_id_node(ID *id, bool do_tag, ID *id_cow_hint) void Depsgraph::clear_id_nodes() { -#ifndef WITH_COPY_ON_WRITE - BLI_ghash_clear(id_hash, NULL, id_node_deleter); -#else /* Stupid workaround to ensure we free IDs in a proper order. */ GHASH_FOREACH_BEGIN(IDDepsNode *, id_node, id_hash) { @@ -331,7 +332,6 @@ void Depsgraph::clear_id_nodes() OBJECT_GUARDED_DELETE(id_node, IDDepsNode); } GHASH_FOREACH_END(); -#endif } /* Add new relationship between two nodes. */ diff --git a/source/blender/depsgraph/intern/depsgraph_build.cc b/source/blender/depsgraph/intern/depsgraph_build.cc index e21c3d29aa5..e4b6434b9c7 100644 --- a/source/blender/depsgraph/intern/depsgraph_build.cc +++ b/source/blender/depsgraph/intern/depsgraph_build.cc @@ -216,9 +216,9 @@ void DEG_graph_build_from_scene(Depsgraph *graph, Main *bmain, Scene *scene) DEG::DepsgraphRelationBuilder relation_builder(deg_graph); relation_builder.begin_build(bmain); relation_builder.build_scene(bmain, scene); -#ifdef WITH_COPY_ON_WRITE - relation_builder.build_copy_on_write_relations(); -#endif + if (DEG_depsgraph_use_copy_on_write()) { + relation_builder.build_copy_on_write_relations(); + } /* Detect and solve cycles. */ DEG::deg_graph_detect_cycles(deg_graph); diff --git a/source/blender/depsgraph/intern/depsgraph_tag.cc b/source/blender/depsgraph/intern/depsgraph_tag.cc index 0df2420d662..927593b6d8f 100644 --- a/source/blender/depsgraph/intern/depsgraph_tag.cc +++ b/source/blender/depsgraph/intern/depsgraph_tag.cc @@ -269,16 +269,17 @@ void id_tag_update_shading(Depsgraph *graph, IDDepsNode *id_node) shading_comp->tag_update(graph); } -#ifdef WITH_COPY_ON_WRITE /* Tag corresponding to DEG_TAG_COPY_ON_WRITE. */ void id_tag_update_copy_on_write(Depsgraph *graph, IDDepsNode *id_node) { + if (!DEG_depsgraph_use_copy_on_write()) { + return; + } ComponentDepsNode *cow_comp = id_node->find_component(DEG_NODE_TYPE_COPY_ON_WRITE); OperationDepsNode *cow_node = cow_comp->get_entry_operation(); cow_node->tag_update(graph); } -#endif void id_tag_update_ntree_special(Main *bmain, Depsgraph *graph, ID *id, int flag) { @@ -320,16 +321,16 @@ void deg_graph_id_tag_update(Main *bmain, Depsgraph *graph, ID *id, int flag) } if (flag & OB_RECALC_DATA) { id_tag_update_object_data(graph, id_node); -#ifdef WITH_COPY_ON_WRITE - if (flag & DEG_TAG_COPY_ON_WRITE) { - const ID_Type id_type = GS(id_node->id_orig->name); - if (id_type == ID_OB) { - Object *object = (Object *)id_node->id_orig; - ID *ob_data = (ID *)object->data; - DEG_id_tag_update_ex(bmain, ob_data, flag); + if (DEG_depsgraph_use_copy_on_write()) { + if (flag & DEG_TAG_COPY_ON_WRITE) { + const ID_Type id_type = GS(id_node->id_orig->name); + if (id_type == ID_OB) { + Object *object = (Object *)id_node->id_orig; + ID *ob_data = (ID *)object->data; + DEG_id_tag_update_ex(bmain, ob_data, flag); + } } } -#endif } if (flag & OB_RECALC_TIME) { id_tag_update_object_time(graph, id_node); @@ -340,11 +341,9 @@ void deg_graph_id_tag_update(Main *bmain, Depsgraph *graph, ID *id, int flag) if (flag & DEG_TAG_SHADING_UPDATE) { id_tag_update_shading(graph, id_node); } -#ifdef WITH_COPY_ON_WRITE if (flag & DEG_TAG_COPY_ON_WRITE) { id_tag_update_copy_on_write(graph, id_node); } -#endif id_tag_update_ntree_special(bmain, graph, id, flag); } diff --git a/source/blender/depsgraph/intern/eval/deg_eval_flush.cc b/source/blender/depsgraph/intern/eval/deg_eval_flush.cc index 54a3a499e36..86e69458f41 100644 --- a/source/blender/depsgraph/intern/eval/deg_eval_flush.cc +++ b/source/blender/depsgraph/intern/eval/deg_eval_flush.cc @@ -82,6 +82,7 @@ static void flush_init_func(void *data_v, int i) */ void deg_graph_flush_updates(Main *bmain, Depsgraph *graph) { + const bool use_copy_on_write = DEG_depsgraph_use_copy_on_write(); /* Sanity check. */ if (graph == NULL) { return; @@ -146,18 +147,17 @@ void deg_graph_flush_updates(Main *bmain, Depsgraph *graph) } if (comp_node->done != COMPONENT_STATE_DONE) { -#ifdef WITH_COPY_ON_WRITE /* Currently this is needed to get ob->mesh to be replaced with * original mesh (rather than being evaluated_mesh). * * TODO(sergey): This is something we need to avoid. */ - if (comp_node->depends_on_cow()) { + if (use_copy_on_write && comp_node->depends_on_cow()) { ComponentDepsNode *cow_comp = id_node->find_component(DEG_NODE_TYPE_COPY_ON_WRITE); cow_comp->tag_update(graph); } -#endif + Object *object = NULL; if (GS(id_orig->name) == ID_OB) { object = (Object *)id_orig; diff --git a/source/blender/depsgraph/intern/nodes/deg_node.cc b/source/blender/depsgraph/intern/nodes/deg_node.cc index 5e7ed249365..b313059e1bd 100644 --- a/source/blender/depsgraph/intern/nodes/deg_node.cc +++ b/source/blender/depsgraph/intern/nodes/deg_node.cc @@ -177,7 +177,14 @@ void IDDepsNode::init(const ID *id, const char *UNUSED(subdata)) void IDDepsNode::init_copy_on_write(ID *id_cow_hint) { -#ifdef WITH_COPY_ON_WRITE + /* Early output for non-copy-on-write case: we keep CoW pointer same as + * an original one. + */ + if (!DEG_depsgraph_use_copy_on_write()) { + UNUSED_VARS(id_cow_hint); + id_cow = id_orig; + return; + } /* Create pointer as early as possible, so we can use it for function * bindings. Rest of data we'll be copying to the new datablock when * it is actually needed. @@ -200,10 +207,6 @@ void IDDepsNode::init_copy_on_write(ID *id_cow_hint) else { id_cow = id_orig; } -#else - UNUSED_VARS(id_cow_hint); - id_cow = id_orig; -#endif } /* Free 'id' node. */ @@ -222,7 +225,6 @@ void IDDepsNode::destroy() id_deps_node_hash_key_free, id_deps_node_hash_value_free); -#ifdef WITH_COPY_ON_WRITE /* Free memory used by this CoW ID. */ if (id_cow != id_orig && id_cow != NULL) { deg_free_copy_on_write_datablock(id_cow); @@ -230,7 +232,7 @@ void IDDepsNode::destroy() DEG_COW_PRINT("Destroy CoW for %s: id_orig=%p id_cow=%p\n", id_orig->name, id_orig, id_cow); } -#endif + /* Tag that the node is freed. */ id_orig = NULL; } |