[Bf-blender-cvs] [5133abce4c0] temp-T97352-3d-texturing-seam-bleeding-b2: Fix: crash when evaluating geometry nodes after deleting an unlinked node

Jacques Lucke noreply at git.blender.org
Tue Sep 20 10:32:08 CEST 2022


Commit: 5133abce4c0d8727a16173f6761320a2ad97e190
Author: Jacques Lucke
Date:   Fri Sep 16 16:02:08 2022 +0200
Branches: temp-T97352-3d-texturing-seam-bleeding-b2
https://developer.blender.org/rB5133abce4c0d8727a16173f6761320a2ad97e190

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.

===================================================================

M	source/blender/blenkernel/BKE_node_runtime.hh
M	source/blender/blenkernel/intern/node_runtime.cc
M	source/blender/depsgraph/intern/builder/deg_builder.cc
M	source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
M	source/blender/depsgraph/intern/builder/deg_builder_relations.cc
M	source/blender/depsgraph/intern/debug/deg_debug_relations_graphviz.cc
M	source/blender/depsgraph/intern/node/deg_node.cc
M	source/blender/depsgraph/intern/node/deg_node.h
M	source/blender/depsgraph/intern/node/deg_node_component.cc
M	source/blender/depsgraph/intern/node/deg_node_component.h
M	source/blender/depsgraph/intern/node/deg_node_operation.cc
M	source/blender/depsgraph/intern/node/deg_node_operation.h

===================================================================

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_D

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list