Depsgraph: Fix particle system freeing accessing freed particle settings
Need to ensure CoW IDs are freed in the right order.
This commit is contained in:
parent
496d18614f
commit
53c1d15675
|
@ -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. */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue