diff options
author | Jacques Lucke <jacques@blender.org> | 2022-09-16 17:02:08 +0300 |
---|---|---|
committer | Jacques Lucke <jacques@blender.org> | 2022-09-16 17:03:50 +0300 |
commit | 4d67a995d91f000971312356c14c21559954f63e (patch) | |
tree | 7d70728429faf5ddaf7e45d23164f883e12f72ff /source/blender/depsgraph/intern | |
parent | 7042f4e4b2e3232da34fadfb83502d090809a211 (diff) |
Fix: crash when evaluating geometry nodes after deleting an unlinked node
This was essentially a use-after-free issue. When a geometry nodes
group changes it has to be preprocessed again before it can be evaluated.
This part was working, the issue was that parent node groups have to be
preprocessed as well, which was missing. The lazy-function graph cached
on the parent node group was still referencing data that was freed when
the child group changed.
Now the depsgraph makes sure that all relevant geometry node groups are
preprocessed again after a change.
This issue was found by Simon Thommes.
Diffstat (limited to 'source/blender/depsgraph/intern')
10 files changed, 53 insertions, 8 deletions
diff --git a/source/blender/depsgraph/intern/builder/deg_builder.cc b/source/blender/depsgraph/intern/builder/deg_builder.cc index 097c377ece4..16510d5f9a6 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder.cc @@ -178,6 +178,9 @@ void deg_graph_build_finalize(Main *bmain, Depsgraph *graph) if (GS(id_orig->name) == ID_OB) { flag |= ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY; } + if (GS(id_orig->name) == ID_NT) { + flag |= ID_RECALC_NTREE_OUTPUT; + } } /* Restore recalc flags from original ID, which could possibly contain recalc flags set by * an operator and then were carried on by the undo system. */ diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc index 67f454b608b..80be781da48 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc @@ -1741,14 +1741,19 @@ void DepsgraphNodeBuilder::build_nodetree(bNodeTree *ntree) /* Animation, */ build_animdata(&ntree->id); /* Output update. */ - ID *id_cow = get_cow_id(&ntree->id); - add_operation_node(&ntree->id, - NodeType::NTREE_OUTPUT, - OperationCode::NTREE_OUTPUT, - [id_cow](::Depsgraph * /*depsgraph*/) { - bNodeTree *ntree_cow = reinterpret_cast<bNodeTree *>(id_cow); - bke::node_tree_runtime::handle_node_tree_output_changed(*ntree_cow); - }); + add_operation_node(&ntree->id, NodeType::NTREE_OUTPUT, OperationCode::NTREE_OUTPUT); + if (ntree->type == NTREE_GEOMETRY) { + ID *id_cow = get_cow_id(&ntree->id); + add_operation_node(&ntree->id, + NodeType::NTREE_GEOMETRY_PREPROCESS, + OperationCode::NTREE_GEOMETRY_PREPROCESS, + [id_cow](::Depsgraph * /*depsgraph*/) { + bNodeTree *ntree_cow = reinterpret_cast<bNodeTree *>(id_cow); + bke::node_tree_runtime::preprocess_geometry_node_tree_for_evaluation( + *ntree_cow); + }); + } + /* nodetree's nodes... */ LISTBASE_FOREACH (bNode *, bnode, &ntree->nodes) { build_idproperties(bnode->prop); diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc index 39dad18ff2b..e5b03bd5291 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc @@ -1723,6 +1723,11 @@ void DepsgraphRelationBuilder::build_driver_data(ID *id, FCurve *fcu) if (GS(id_ptr->name) == ID_NT) { ComponentKey ntree_output_key(id_ptr, NodeType::NTREE_OUTPUT); add_relation(driver_key, ntree_output_key, "Drivers -> NTree Output"); + if (reinterpret_cast<bNodeTree *>(id_ptr)->type == NTREE_GEOMETRY) { + OperationKey ntree_geo_preprocess_key( + id, NodeType::NTREE_GEOMETRY_PREPROCESS, OperationCode::NTREE_GEOMETRY_PREPROCESS); + add_relation(driver_key, ntree_geo_preprocess_key, "Drivers -> NTree Geo Preprocess"); + } } } @@ -2611,6 +2616,16 @@ void DepsgraphRelationBuilder::build_nodetree(bNodeTree *ntree) build_animdata(&ntree->id); build_parameters(&ntree->id); OperationKey ntree_output_key(&ntree->id, NodeType::NTREE_OUTPUT, OperationCode::NTREE_OUTPUT); + OperationKey ntree_geo_preprocess_key( + &ntree->id, NodeType::NTREE_GEOMETRY_PREPROCESS, OperationCode::NTREE_GEOMETRY_PREPROCESS); + if (ntree->type == NTREE_GEOMETRY) { + OperationKey ntree_cow_key(&ntree->id, NodeType::COPY_ON_WRITE, OperationCode::COPY_ON_WRITE); + add_relation(ntree_cow_key, ntree_geo_preprocess_key, "COW -> Preprocess"); + add_relation(ntree_geo_preprocess_key, + ntree_output_key, + "Preprocess -> Output", + RELATION_FLAG_NO_FLUSH); + } /* nodetree's nodes... */ LISTBASE_FOREACH (bNode *, bnode, &ntree->nodes) { build_idproperties(bnode->prop); @@ -2687,6 +2702,12 @@ void DepsgraphRelationBuilder::build_nodetree(bNodeTree *ntree) * the output). Currently, we lack the infrastructure to check for these cases efficiently. * That can be added later. */ add_relation(group_output_key, ntree_output_key, "Group Node"); + if (group_ntree->type == NTREE_GEOMETRY) { + OperationKey group_preprocess_key(&group_ntree->id, + NodeType::NTREE_GEOMETRY_PREPROCESS, + OperationCode::NTREE_GEOMETRY_PREPROCESS); + add_relation(group_preprocess_key, ntree_geo_preprocess_key, "Group Node Preprocess"); + } } else { BLI_assert_msg(0, "Unknown ID type used for node"); @@ -2703,6 +2724,9 @@ void DepsgraphRelationBuilder::build_nodetree(bNodeTree *ntree) if (check_id_has_anim_component(&ntree->id)) { ComponentKey animation_key(&ntree->id, NodeType::ANIMATION); add_relation(animation_key, ntree_output_key, "NTree Shading Parameters"); + if (ntree->type == NTREE_GEOMETRY) { + add_relation(animation_key, ntree_geo_preprocess_key, "NTree Animation -> Preprocess"); + } } } diff --git a/source/blender/depsgraph/intern/debug/deg_debug_relations_graphviz.cc b/source/blender/depsgraph/intern/debug/deg_debug_relations_graphviz.cc index b8d0fb6c365..bd47cb77f56 100644 --- a/source/blender/depsgraph/intern/debug/deg_debug_relations_graphviz.cc +++ b/source/blender/depsgraph/intern/debug/deg_debug_relations_graphviz.cc @@ -408,6 +408,7 @@ static void deg_debug_graphviz_node(DotExportContext &ctx, case NodeType::GENERIC_DATABLOCK: case NodeType::VISIBILITY: case NodeType::NTREE_OUTPUT: + case NodeType::NTREE_GEOMETRY_PREPROCESS: case NodeType::SIMULATION: { ComponentNode *comp_node = (ComponentNode *)node; if (comp_node->operations.is_empty()) { diff --git a/source/blender/depsgraph/intern/node/deg_node.cc b/source/blender/depsgraph/intern/node/deg_node.cc index 7a515424e06..6303b22cac3 100644 --- a/source/blender/depsgraph/intern/node/deg_node.cc +++ b/source/blender/depsgraph/intern/node/deg_node.cc @@ -100,6 +100,8 @@ const char *nodeTypeAsString(NodeType type) return "SIMULATION"; case NodeType::NTREE_OUTPUT: return "NTREE_OUTPUT"; + case NodeType::NTREE_GEOMETRY_PREPROCESS: + return "NTREE_GEOMETRY_PREPROCESS"; /* Total number of meaningful node types. */ case NodeType::NUM_TYPES: @@ -158,6 +160,7 @@ eDepsSceneComponentType nodeTypeToSceneComponent(NodeType type) case NodeType::CACHE: case NodeType::SIMULATION: case NodeType::NTREE_OUTPUT: + case NodeType::NTREE_GEOMETRY_PREPROCESS: return DEG_SCENE_COMP_PARAMETERS; case NodeType::VISIBILITY: @@ -232,6 +235,7 @@ eDepsObjectComponentType nodeTypeToObjectComponent(NodeType type) case NodeType::SYNCHRONIZATION: case NodeType::SIMULATION: case NodeType::NTREE_OUTPUT: + case NodeType::NTREE_GEOMETRY_PREPROCESS: case NodeType::UNDEFINED: case NodeType::NUM_TYPES: return DEG_OB_COMP_PARAMETERS; diff --git a/source/blender/depsgraph/intern/node/deg_node.h b/source/blender/depsgraph/intern/node/deg_node.h index db912ee3a82..e31c1769a2a 100644 --- a/source/blender/depsgraph/intern/node/deg_node.h +++ b/source/blender/depsgraph/intern/node/deg_node.h @@ -130,6 +130,8 @@ enum class NodeType { SIMULATION, /* Node tree output component. */ NTREE_OUTPUT, + /* Preprocessing for geometry node trees before they can be evaluated. */ + NTREE_GEOMETRY_PREPROCESS, /* Total number of meaningful node types. */ NUM_TYPES, diff --git a/source/blender/depsgraph/intern/node/deg_node_component.cc b/source/blender/depsgraph/intern/node/deg_node_component.cc index f2d82e80fa6..40b4b36a29c 100644 --- a/source/blender/depsgraph/intern/node/deg_node_component.cc +++ b/source/blender/depsgraph/intern/node/deg_node_component.cc @@ -337,6 +337,7 @@ DEG_COMPONENT_NODE_DEFINE(GenericDatablock, GENERIC_DATABLOCK, 0); DEG_COMPONENT_NODE_DEFINE(Visibility, VISIBILITY, 0); DEG_COMPONENT_NODE_DEFINE(Simulation, SIMULATION, 0); DEG_COMPONENT_NODE_DEFINE(NTreeOutput, NTREE_OUTPUT, ID_RECALC_NTREE_OUTPUT); +DEG_COMPONENT_NODE_DEFINE(NTreeGeometryPreprocess, NTREE_GEOMETRY_PREPROCESS, 0); /** \} */ @@ -371,6 +372,7 @@ void deg_register_component_depsnodes() register_node_typeinfo(&DNTI_VISIBILITY); register_node_typeinfo(&DNTI_SIMULATION); register_node_typeinfo(&DNTI_NTREE_OUTPUT); + register_node_typeinfo(&DNTI_NTREE_GEOMETRY_PREPROCESS); } /** \} */ diff --git a/source/blender/depsgraph/intern/node/deg_node_component.h b/source/blender/depsgraph/intern/node/deg_node_component.h index f7f38b88854..44c63822ca3 100644 --- a/source/blender/depsgraph/intern/node/deg_node_component.h +++ b/source/blender/depsgraph/intern/node/deg_node_component.h @@ -208,6 +208,7 @@ DEG_COMPONENT_NODE_DECLARE_GENERIC(GenericDatablock); DEG_COMPONENT_NODE_DECLARE_NO_COW_TAG_ON_UPDATE(Visibility); DEG_COMPONENT_NODE_DECLARE_GENERIC(Simulation); DEG_COMPONENT_NODE_DECLARE_GENERIC(NTreeOutput); +DEG_COMPONENT_NODE_DECLARE_GENERIC(NTreeGeometryPreprocess); /* Bone Component */ struct BoneComponentNode : public ComponentNode { diff --git a/source/blender/depsgraph/intern/node/deg_node_operation.cc b/source/blender/depsgraph/intern/node/deg_node_operation.cc index 016af735fcf..d5401a6b0d1 100644 --- a/source/blender/depsgraph/intern/node/deg_node_operation.cc +++ b/source/blender/depsgraph/intern/node/deg_node_operation.cc @@ -173,6 +173,8 @@ const char *operationCodeAsString(OperationCode opcode) /* Node Tree. */ case OperationCode::NTREE_OUTPUT: return "NTREE_OUTPUT"; + case OperationCode::NTREE_GEOMETRY_PREPROCESS: + return "NTREE_GEOMETRY_PREPROCESS"; /* Movie clip. */ case OperationCode::MOVIECLIP_EVAL: return "MOVIECLIP_EVAL"; diff --git a/source/blender/depsgraph/intern/node/deg_node_operation.h b/source/blender/depsgraph/intern/node/deg_node_operation.h index cb3beb56556..b0685ac0351 100644 --- a/source/blender/depsgraph/intern/node/deg_node_operation.h +++ b/source/blender/depsgraph/intern/node/deg_node_operation.h @@ -165,6 +165,7 @@ enum class OperationCode { /* Node Tree. ----------------------------------------------------------- */ NTREE_OUTPUT, + NTREE_GEOMETRY_PREPROCESS, /* Batch caches. -------------------------------------------------------- */ GEOMETRY_SELECT_UPDATE, |