[Bf-blender-cvs] [4674795591f] temp_bmesh_multires: Sculpt dyntopo: another attempt to fix undo memory corruption bug

Joseph Eagar noreply at git.blender.org
Sun Jul 11 19:14:47 CEST 2021


Commit: 4674795591f1d7ba436eb9c77e65ae7f30e9cf35
Author: Joseph Eagar
Date:   Sun Jul 11 13:14:24 2021 -0400
Branches: temp_bmesh_multires
https://developer.blender.org/rB4674795591f1d7ba436eb9c77e65ae7f30e9cf35

Sculpt dyntopo: another attempt to fix undo memory corruption bug

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

M	release/scripts/startup/bl_ui/space_view3d_toolbar.py
M	source/blender/blenkernel/BKE_pbvh.h
M	source/blender/blenkernel/intern/pbvh.c
M	source/blender/blenkernel/intern/pbvh_bmesh.c
M	source/blender/blenlib/intern/BLI_mempool.c
M	source/blender/bmesh/intern/bmesh_log.c
M	source/blender/editors/sculpt_paint/sculpt_undo.c

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

diff --git a/release/scripts/startup/bl_ui/space_view3d_toolbar.py b/release/scripts/startup/bl_ui/space_view3d_toolbar.py
index e534d53c0d3..5f5e369a213 100644
--- a/release/scripts/startup/bl_ui/space_view3d_toolbar.py
+++ b/release/scripts/startup/bl_ui/space_view3d_toolbar.py
@@ -17,7 +17,7 @@
 # ##### END GPL LICENSE BLOCK #####
 
 # <pep8 compliant>
-from bpy.types import Menu, Panel, UIList
+from bpy.types import Menu, Panel, UIList, WindowManager
 from bl_ui.properties_grease_pencil_common import (
     GreasePencilSculptOptionsPanel,
     GreasePencilDisplayPanel,
@@ -1015,7 +1015,7 @@ class VIEW3D_PT_sculpt_symmetry(Panel, View3DPaintPanel):
 
         layout.prop(sculpt, "symmetrize_direction")
         layout.operator("sculpt.symmetrize")
-        layout.prop(bpy.types.WindowManager.operator_properties_last("sculpt.symmetrize"), "merge_tolerance")
+        layout.prop(WindowManager.operator_properties_last("sculpt.symmetrize"), "merge_tolerance")
 
 
 class VIEW3D_PT_sculpt_symmetry_for_topbar(Panel):
diff --git a/source/blender/blenkernel/BKE_pbvh.h b/source/blender/blenkernel/BKE_pbvh.h
index 0cb4d9f58de..84c46ed5315 100644
--- a/source/blender/blenkernel/BKE_pbvh.h
+++ b/source/blender/blenkernel/BKE_pbvh.h
@@ -199,7 +199,8 @@ typedef enum {
   PBVH_UpdateColor = 1 << 14,
   PBVH_Delete = 1 << 15,
   PBVH_UpdateCurvatureDir = 1 << 16,
-  PBVH_UpdateTris = 1 << 17
+  PBVH_UpdateTris = 1 << 17,
+  PBVH_RebuildNodeVerts = 1 << 18
 } PBVHNodeFlags;
 
 typedef struct PBVHFrustumPlanes {
@@ -221,6 +222,7 @@ typedef void (*BKE_pbvh_HitOccludedCallback)(PBVHNode *node, void *data, float *
 typedef void (*BKE_pbvh_SearchNearestCallback)(PBVHNode *node, void *data, float *tmin);
 
 void BKE_pbvh_get_nodes(PBVH *pbvh, int flag, PBVHNode ***r_array, int *r_totnode);
+PBVHNode *BKE_pbvh_get_node(PBVH *pbvh, int node);
 
 /* Building */
 
@@ -465,6 +467,9 @@ struct TableGSet *BKE_pbvh_bmesh_node_unique_verts(PBVHNode *node);
 struct TableGSet *BKE_pbvh_bmesh_node_other_verts(PBVHNode *node);
 struct TableGSet *BKE_pbvh_bmesh_node_faces(PBVHNode *node);
 
+void BKE_pbvh_bmesh_regen_node_verts(PBVH *pbvh);
+void BKE_pbvh_bmesh_mark_node_regen(PBVH *pbvh, PBVHNode *node);
+
 // now generated PBVHTris
 void BKE_pbvh_bmesh_after_stroke(PBVH *pbvh);
 
diff --git a/source/blender/blenkernel/intern/pbvh.c b/source/blender/blenkernel/intern/pbvh.c
index 30ad1329cf0..a33c4f414fa 100644
--- a/source/blender/blenkernel/intern/pbvh.c
+++ b/source/blender/blenkernel/intern/pbvh.c
@@ -3826,3 +3826,8 @@ void SCULPT_update_flat_vcol_shading(Object *ob, Scene *scene)
     BKE_pbvh_set_flat_vcol_shading(ob->sculpt->pbvh, flat_vcol_shading);
   }
 }
+
+PBVHNode *BKE_pbvh_get_node(PBVH *pbvh, int node)
+{
+  return pbvh->nodes + node;
+}
diff --git a/source/blender/blenkernel/intern/pbvh_bmesh.c b/source/blender/blenkernel/intern/pbvh_bmesh.c
index 555b902365e..20629e51186 100644
--- a/source/blender/blenkernel/intern/pbvh_bmesh.c
+++ b/source/blender/blenkernel/intern/pbvh_bmesh.c
@@ -122,6 +122,46 @@ static void check_heap()
 /* Support for only operating on front-faces */
 #define USE_EDGEQUEUE_FRONTFACE
 
+static void check_nodes(PBVH *pbvh)
+{
+#if 0
+  for (int i = 0; i < pbvh->totnode; i++) {
+    PBVHNode *node = pbvh->nodes + i;
+    BMVert *v;
+    BMFace *f;
+
+    if (!(node->flag & PBVH_Leaf)) {
+      continue;
+    }
+
+    TGSET_ITER (v, node->bm_unique_verts) {
+      if (v->head.htype > 8) {
+        printf("corruption in pbvh! bm_unique_verts\n");
+      }
+    }
+    TGSET_ITER_END;
+
+    TGSET_ITER (v, node->bm_other_verts) {
+      if (v->head.htype > 8) {
+        printf("corruption in pbvh! bm_other_verts\n");
+      }
+    }
+    TGSET_ITER_END;
+
+    TGSET_ITER (f, node->bm_faces) {
+      if (f->head.htype > 8) {
+        printf("corruption in pbvh! bm_faces\n");
+      }
+    }
+    TGSET_ITER_END;
+  }
+#endif
+}
+
+void pbvh_bmesh_check_nodes(PBVH *pbvh)
+{
+  check_nodes(pbvh);
+}
 /**
  * Ensure we don't have dirty tags for the edge queue, and that they are left cleared.
  * (slow, even for debug mode, so leave disabled for now).
@@ -538,6 +578,8 @@ static bool pbvh_bmesh_node_limit_ensure(PBVH *pbvh, int node_index)
   TableGSet *bm_faces = pbvh->nodes[node_index].bm_faces;
   const int bm_faces_size = BLI_table_gset_len(bm_faces);
 
+  check_nodes(pbvh);
+
   if (bm_faces_size <= pbvh->leaf_limit) {
     /* Node limit not exceeded */
     return false;
@@ -582,6 +624,8 @@ static bool pbvh_bmesh_node_limit_ensure(PBVH *pbvh, int node_index)
 
   MEM_freeN(bbc_array);
 
+  check_nodes(pbvh);
+
   return true;
 }
 
@@ -2790,6 +2834,66 @@ static void pbvh_bmesh_collapse_edge(PBVH *pbvh,
   BLI_array_free(ls);
 }
 
+static void pbvh_bmesh_regen_node_verts(PBVH *pbvh, PBVHNode *node)
+{
+  int usize = BLI_table_gset_len(node->bm_other_verts);
+  int osize = BLI_table_gset_len(node->bm_other_verts);
+
+  BLI_table_gset_free(node->bm_other_verts, NULL);
+  BLI_table_gset_free(node->bm_unique_verts, NULL);
+
+  node->bm_unique_verts = BLI_table_gset_new("bm_unique_verts");
+  node->bm_other_verts = BLI_table_gset_new("bm_other_verts");
+
+  const int cd_vert_node = pbvh->cd_vert_node_offset;
+  const int ni = (int)(node - pbvh->nodes);
+
+  BMFace *f;
+  TGSET_ITER (f, node->bm_faces) {
+    BMLoop *l = f->l_first;
+    do {
+      int ni2 = BM_ELEM_CD_GET_INT(l->v, cd_vert_node);
+      if (ni2 == ni) {
+        BLI_table_gset_add(node->bm_unique_verts, l->v);
+      }
+      else {
+        BLI_table_gset_add(node->bm_other_verts, l->v);
+      }
+    } while ((l = l->next) != f->l_first);
+  }
+  TGSET_ITER_END;
+
+  if (usize != BLI_table_gset_len(node->bm_unique_verts)) {
+    printf("possible pbvh error: bm_unique_verts might have had bad data. old: %d, new: %d\n",
+           usize,
+           BLI_table_gset_len(node->bm_unique_verts));
+  }
+
+  if (osize != BLI_table_gset_len(node->bm_other_verts)) {
+    printf("possible pbvh error: bm_other_verts might have had bad data. old: %d, new: %d\n",
+           osize,
+           BLI_table_gset_len(node->bm_other_verts));
+  }
+}
+
+void BKE_pbvh_bmesh_mark_node_regen(PBVH *pbvh, PBVHNode *node)
+{
+  node->flag |= PBVH_RebuildNodeVerts;
+}
+
+void BKE_pbvh_bmesh_regen_node_verts(PBVH *pbvh)
+{
+  for (int i = 0; i < pbvh->totnode; i++) {
+    PBVHNode *node = pbvh->nodes + i;
+
+    if (!(node->flag & PBVH_Leaf) || !(node->flag & PBVH_RebuildNodeVerts)) {
+      continue;
+    }
+
+    pbvh_bmesh_regen_node_verts(pbvh, node);
+  }
+}
+
 void BKE_pbvh_bmesh_update_origvert(
     PBVH *pbvh, BMVert *v, float **r_co, float **r_no, float **r_color, bool log_undo)
 {
@@ -3723,6 +3827,13 @@ CLANG_OPT_BUG static bool cleanup_valence_3_4(PBVH *pbvh,
         continue;
       }
 
+      int ni = BM_ELEM_CD_GET_INT(v, pbvh->cd_vert_node_offset);
+
+      if (ni >= 0 && BLI_table_gset_haskey(pbvh->nodes[ni].bm_other_verts, v)) {
+        printf("error!\n");
+        BLI_table_gset_remove(pbvh->nodes[ni].bm_other_verts, v, NULL);
+      }
+
       BM_log_vert_removed(pbvh->bm_log, v, pbvh->cd_vert_mask_offset);
       pbvh_bmesh_vert_remove(pbvh, v);
 
@@ -3891,7 +4002,9 @@ bool BKE_pbvh_bmesh_update_topology(PBVH *pbvh,
 
     int max_steps = (int)((float)DYNTOPO_MAX_ITER * ratio);
 
+    check_nodes(pbvh);
     modified |= pbvh_bmesh_collapse_short_edges(&eq_ctx, pbvh, &deleted_faces, max_steps);
+    check_nodes(pbvh);
 
     BLI_heapsimple_free(q.heap, NULL);
     if (q.elems) {
@@ -3931,7 +4044,9 @@ bool BKE_pbvh_bmesh_update_topology(PBVH *pbvh,
 
     int max_steps = (int)((float)DYNTOPO_MAX_ITER * ratio);
 
+    check_nodes(pbvh);
     modified |= pbvh_bmesh_subdivide_long_edges(&eq_ctx, pbvh, &edge_loops, max_steps);
+    check_nodes(pbvh);
 
     if (q.elems) {
       MEM_freeN(q.elems);
@@ -3942,8 +4057,10 @@ bool BKE_pbvh_bmesh_update_topology(PBVH *pbvh,
 
 #endif
   if (mode & PBVH_Cleanup) {
+    check_nodes(pbvh);
     modified |= cleanup_valence_3_4(
         pbvh, center, view_normal, radius, use_frontface, use_projected);
+    check_nodes(pbvh);
   }
 
   if (modified) {
@@ -4686,7 +4803,9 @@ void BKE_pbvh_bmesh_after_stroke(PBVH *pbvh)
   check_heap();
   int totnode = pbvh->totnode;
 
+  check_nodes(pbvh);
   pbvh_bmesh_join_nodes(pbvh);
+  check_nodes(pbvh);
 
   check_heap();
 
diff --git a/source/blender/blenlib/intern/BLI_mempool.c b/source/blender/blenlib/intern/BLI_mempool.c
index e62b352ab27..9f052e45599 100644
--- a/source/blender/blenlib/intern/BLI_mempool.c
+++ b/source/blender/blenlib/intern/BLI_mempool.c
@@ -827,6 +827,8 @@ void *mempool_iter_threadsafe_step(BLI_mempool_threadsafe_iter *ts_iter)
   do {
     ret = curnode;
 
+    BLI_asan_unpoison(ret, esize);
+
     if (++iter->curindex != iter->pool->pchunk) {
       curnode = POINTER_OFFSET(curnode, esize);
     }
@@ -842,29 +844,37 @@ void *mempool_iter_threadsafe_step(BLI_mempool_threadsafe_iter *ts_iter)
         /* pass. */
       }
       if (UNLIKELY(iter->curchunk == NULL)) {
-        return (ret->freeword == FREEWORD) ? NULL : ret;
+        if (ret->freeword == FREEWORD) {
+          BLI_asan_poison(ret, esize);
+          return NULL;
+        }
+        else {
+          return ret;
+        }
       }
       /* End `threadsafe` exception. */
 
       iter->curchunk = iter->curchunk->next;
       if (UNLIKELY(iter->curchunk == NULL)) {
-        BLI_asan_unpoison(ret, iter->pool->esize);
-
-        void *ret2 = (ret->freeword == FREEWORD) ? NULL : ret;
-
         if (ret->freeword == FREEWORD) {
           BLI_asan_poison(ret, iter->pool->esize);
+          return NULL;
+        }
+        else {
+          return ret;
         }
-
-        return ret2;
       }
+
       curnode = CHUNK_DATA(iter->curchunk);
     }
 
     if (ret->freeword == FREEWORD) {
       BLI_asan_poison(ret, iter->pool->esize);
     }
-  } while (ret->freeword == FREEWORD);
+    else {
+      break;
+    }
+  } while (true);
 
   return ret;
 }
diff --git a/source/blender/bmesh/intern/bmesh_log.c b/source/blender/bmesh/intern/bmesh_log.c
index 50c518cf813..1c7bc3934fe 100644
--- a/source/blender/bmesh/intern/bmesh_log.c
+++ b/source/blender/bmesh/intern/bmesh_log.c
@@ -409,6 +409,22 @@ static BMLogFace *bm_log_face_alloc(BMLog

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list