Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJacques Lucke <jacques@blender.org>2022-09-16 17:02:08 +0300
committerJacques Lucke <jacques@blender.org>2022-09-16 17:03:50 +0300
commit4d67a995d91f000971312356c14c21559954f63e (patch)
tree7d70728429faf5ddaf7e45d23164f883e12f72ff
parent7042f4e4b2e3232da34fadfb83502d090809a211 (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.
-rw-r--r--source/blender/blenkernel/BKE_node_runtime.hh5
-rw-r--r--source/blender/blenkernel/intern/node_runtime.cc14
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder.cc3
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_nodes.cc21
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_relations.cc24
-rw-r--r--source/blender/depsgraph/intern/debug/deg_debug_relations_graphviz.cc1
-rw-r--r--source/blender/depsgraph/intern/node/deg_node.cc4
-rw-r--r--source/blender/depsgraph/intern/node/deg_node.h2
-rw-r--r--source/blender/depsgraph/intern/node/deg_node_component.cc2
-rw-r--r--source/blender/depsgraph/intern/node/deg_node_component.h1
-rw-r--r--source/blender/depsgraph/intern/node/deg_node_operation.cc2
-rw-r--r--source/blender/depsgraph/intern/node/deg_node_operation.h1
12 files changed, 60 insertions, 20 deletions
diff --git a/source/blender/blenkernel/BKE_node_runtime.hh b/source/blender/blenkernel/BKE_node_runtime.hh
index 194820aa4ba..c3e0460bdb1 100644
--- a/source/blender/blenkernel/BKE_node_runtime.hh
+++ b/source/blender/blenkernel/BKE_node_runtime.hh
@@ -160,10 +160,9 @@ class bNodeRuntime : NonCopyable, NonMovable {
namespace node_tree_runtime {
/**
- * Is executed when the depsgraph determines that something in the node group changed that will
- * affect the output.
+ * Is executed when the node tree changed in the depsgraph.
*/
-void handle_node_tree_output_changed(bNodeTree &tree_cow);
+void preprocess_geometry_node_tree_for_evaluation(bNodeTree &tree_cow);
class AllowUsingOutdatedInfo : NonCopyable, NonMovable {
private:
diff --git a/source/blender/blenkernel/intern/node_runtime.cc b/source/blender/blenkernel/intern/node_runtime.cc
index 00b78284791..8b5b8bbc8b7 100644
--- a/source/blender/blenkernel/intern/node_runtime.cc
+++ b/source/blender/blenkernel/intern/node_runtime.cc
@@ -14,16 +14,12 @@
namespace blender::bke::node_tree_runtime {
-void handle_node_tree_output_changed(bNodeTree &tree_cow)
+void preprocess_geometry_node_tree_for_evaluation(bNodeTree &tree_cow)
{
- if (tree_cow.type == NTREE_GEOMETRY) {
- /* Rebuild geometry nodes lazy function graph. */
- {
- std::lock_guard lock{tree_cow.runtime->geometry_nodes_lazy_function_graph_info_mutex};
- tree_cow.runtime->geometry_nodes_lazy_function_graph_info.reset();
- }
- blender::nodes::ensure_geometry_nodes_lazy_function_graph(tree_cow);
- }
+ BLI_assert(tree_cow.type == NTREE_GEOMETRY);
+ /* Rebuild geometry nodes lazy function graph. */
+ tree_cow.runtime->geometry_nodes_lazy_function_graph_info.reset();
+ blender::nodes::ensure_geometry_nodes_lazy_function_graph(tree_cow);
}
static void double_checked_lock(std::mutex &mutex, bool &data_is_dirty, FunctionRef<void()> fn)
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,