diff options
author | Sergey Sharybin <sergey.vfx@gmail.com> | 2017-07-19 16:50:49 +0300 |
---|---|---|
committer | Sergey Sharybin <sergey.vfx@gmail.com> | 2017-07-19 17:21:12 +0300 |
commit | 53c1d15675bf6240369ee0dbdc6f06780f7b68ba (patch) | |
tree | f2cadec793c170f57bf7b908d9b25e964cc58779 /source | |
parent | 496d18614f1487c62f55dde13b211e7d12fc45ab (diff) |
Depsgraph: Fix particle system freeing accessing freed particle settings
Need to ensure CoW IDs are freed in the right order.
Diffstat (limited to 'source')
5 files changed, 47 insertions, 0 deletions
diff --git a/source/blender/depsgraph/intern/depsgraph.cc b/source/blender/depsgraph/intern/depsgraph.cc index 1b94216d706..e1fdb2daf29 100644 --- a/source/blender/depsgraph/intern/depsgraph.cc +++ b/source/blender/depsgraph/intern/depsgraph.cc @@ -53,6 +53,8 @@ extern "C" { #include "DEG_depsgraph.h" +#include "intern/eval/deg_eval_copy_on_write.h" + #include "intern/nodes/deg_node.h" #include "intern/nodes/deg_node_component.h" #include "intern/nodes/deg_node_operation.h" @@ -250,11 +252,13 @@ 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() { @@ -299,7 +303,27 @@ IDDepsNode *Depsgraph::add_id_node(ID *id, const char *name, bool do_tag) 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) + { + if (!deg_copy_on_write_is_expanded(id_node->id_cow)) { + continue; + } + const short id_type = GS(id_node->id_cow->name); + if (id_type != ID_PA) { + id_node->destroy(); + } + } + GHASH_FOREACH_END(); + GHASH_FOREACH_BEGIN(IDDepsNode *, id_node, id_hash) + { + OBJECT_GUARDED_DELETE(id_node, IDDepsNode); + } + GHASH_FOREACH_END(); +#endif } /* Add new relationship between two nodes. */ 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 f7e08915531..10547da2505 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 @@ -742,4 +742,9 @@ void deg_tag_copy_on_write_id(ID *id_cow, const ID *id_orig) id_cow->newid = (ID *)id_orig; } +bool deg_copy_on_write_is_expanded(const struct ID *id_cow) +{ + return check_datablock_expanded(id_cow); +} + } // namespace DEG 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 c5668ed4271..4ae1de3fdbc 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 @@ -86,4 +86,10 @@ bool deg_validate_copy_on_write_datablock(ID *id_cow); /* Tag given ID block as being copy-on-wtritten. */ void deg_tag_copy_on_write_id(struct ID *id_cow, const struct ID *id_orig); +/* Check whether ID datablock is expanded. + * + * TODO(sergey): Make it an inline function or a macro. + */ +bool deg_copy_on_write_is_expanded(const struct ID *id_cow); + } // namespace DEG diff --git a/source/blender/depsgraph/intern/nodes/deg_node.cc b/source/blender/depsgraph/intern/nodes/deg_node.cc index b01fa502b36..b80d95e9076 100644 --- a/source/blender/depsgraph/intern/nodes/deg_node.cc +++ b/source/blender/depsgraph/intern/nodes/deg_node.cc @@ -191,6 +191,15 @@ void IDDepsNode::init(const ID *id, const char *UNUSED(subdata)) /* Free 'id' node. */ IDDepsNode::~IDDepsNode() { + destroy(); +} + +void IDDepsNode::destroy() +{ + if (id_orig == NULL) { + return; + } + BLI_ghash_free(components, id_deps_node_hash_key_free, id_deps_node_hash_value_free); @@ -202,6 +211,8 @@ IDDepsNode::~IDDepsNode() 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; } ComponentDepsNode *IDDepsNode::find_component(eDepsNode_Type type, diff --git a/source/blender/depsgraph/intern/nodes/deg_node.h b/source/blender/depsgraph/intern/nodes/deg_node.h index 4e03072d486..a12a43d8658 100644 --- a/source/blender/depsgraph/intern/nodes/deg_node.h +++ b/source/blender/depsgraph/intern/nodes/deg_node.h @@ -139,6 +139,7 @@ struct IDDepsNode : public DepsNode { void init(const ID *id, const char *subdata); ~IDDepsNode(); + void destroy(); ComponentDepsNode *find_component(eDepsNode_Type type, const char *name = "") const; |