[Bf-blender-cvs] [118edbef0e6] sculpt-dev: Sculpt-dev: bke_pbvh_update_vert_boundary is now atomic

Joseph Eagar noreply at git.blender.org
Sat Jan 8 22:01:51 CET 2022


Commit: 118edbef0e644883812f72a2ac9bda07f0e5db72
Author: Joseph Eagar
Date:   Sat Jan 8 12:57:29 2022 -0800
Branches: sculpt-dev
https://developer.blender.org/rB118edbef0e644883812f72a2ac9bda07f0e5db72

Sculpt-dev: bke_pbvh_update_vert_boundary is
            now atomic

* bke_pbvh_update_vert_boundary now uses atomics
* This allows dyntopo surface smoothing
  (surface_smooth_v_safe) to update vertex boundary
  flags inside of a thread.  This lessens degenerate
  geometry created by hard edged brushes like
  clay strips.

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

M	source/blender/blenkernel/intern/dyntopo.c
M	source/blender/blenkernel/intern/pbvh_bmesh.c

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

diff --git a/source/blender/blenkernel/intern/dyntopo.c b/source/blender/blenkernel/intern/dyntopo.c
index f5b695275c0..15b35676bcb 100644
--- a/source/blender/blenkernel/intern/dyntopo.c
+++ b/source/blender/blenkernel/intern/dyntopo.c
@@ -34,8 +34,9 @@
 
 #include <stdio.h>
 
-//#define DYNTOPO_REPORT
+#define DYNTOPO_REPORT
 //#define WITH_ADAPTIVE_CURVATURE
+//#define DYNTOPO_NO_THREADING
 
 #define SCULPTVERT_VALENCE_TEMP SCULPTVERT_SPLIT_TEMP
 
@@ -595,7 +596,7 @@ BLI_INLINE void surface_smooth_v_safe(PBVH *pbvh, BMVert *v, float fac)
   }
 
   if (mv1->flag & SCULPTVERT_NEED_BOUNDARY) {
-    return;  // can't update boundary in thread
+    pbvh_check_vert_boundary(pbvh, v);
   }
 
   // pbvh_check_vert_boundary(pbvh, v);
@@ -2843,8 +2844,12 @@ static void long_edge_queue_create(EdgeQueueContext *eq_ctx,
   TaskParallelSettings settings;
 
   BLI_parallel_range_settings_defaults(&settings);
+#ifdef DYNTOPO_NO_THREADING
+  settings.use_threading = false;
+#endif
 
   BLI_task_parallel_range(0, count, tdata, long_edge_queue_task_cb, &settings);
+
   const int cd_sculpt_vert = pbvh->cd_sculpt_vert;
 
   for (int i = 0; i < count; i++) {
@@ -2967,6 +2972,10 @@ static void edge_queue_create_local(EdgeQueueContext *eq_ctx,
   TaskParallelSettings settings;
 
   BLI_parallel_range_settings_defaults(&settings);
+#ifdef DYNTOPO_NO_THREADING
+  settings.use_threading = false;
+#endif
+
   BLI_task_parallel_range(0, count, tdata, short_edge_queue_task_cb_local, &settings);
 
   const int cd_sculpt_vert = pbvh->cd_sculpt_vert;
@@ -3240,6 +3249,10 @@ static void short_edge_queue_create(EdgeQueueContext *eq_ctx,
   TaskParallelSettings settings;
 
   BLI_parallel_range_settings_defaults(&settings);
+#ifdef DYNTOPO_NO_THREADING
+  settings.use_threading = false;
+#endif
+
   BLI_task_parallel_range(0, count, tdata, short_edge_queue_task_cb, &settings);
 
   const int cd_sculpt_vert = pbvh->cd_sculpt_vert;
diff --git a/source/blender/blenkernel/intern/pbvh_bmesh.c b/source/blender/blenkernel/intern/pbvh_bmesh.c
index 6f1d4f95491..efb166bc8a3 100644
--- a/source/blender/blenkernel/intern/pbvh_bmesh.c
+++ b/source/blender/blenkernel/intern/pbvh_bmesh.c
@@ -1760,6 +1760,19 @@ static int color_boundary_key(float col[4])
 }
 #endif
 
+/* calls atomic_cas_uint32 on two adjacent (and int aligned) shorts */
+BLI_INLINE void atomic_cas_short2(ushort *base, ushort olda, ushort oldb, ushort newa, ushort newb) {
+  uint oldi, newi;
+
+  ((ushort *)&oldi)[0] = olda;
+  ((ushort *)&oldi)[1] = oldb;
+
+  ((ushort *)&newi)[0] = newa;
+  ((ushort *)&newi)[1] = newb;
+
+  atomic_cas_uint32((uint32_t *)base, oldi, newi);
+}
+
 void bke_pbvh_update_vert_boundary(int cd_sculpt_vert,
                                    int cd_faceset_offset,
                                    int cd_vert_node_offset,
@@ -1774,16 +1787,25 @@ void bke_pbvh_update_vert_boundary(int cd_sculpt_vert,
 
   float curv = 0.0f, totcurv = 0.0f;
 
+  int newflag = mv->flag;
+  int oldflag = newflag;
+  int oldval = mv->valence;
+
   BMEdge *e = v->e;
-  mv->flag &= ~(SCULPTVERT_BOUNDARY | SCULPTVERT_FSET_BOUNDARY | SCULPTVERT_NEED_BOUNDARY |
+  newflag &= ~(SCULPTVERT_BOUNDARY | SCULPTVERT_FSET_BOUNDARY | SCULPTVERT_NEED_BOUNDARY |
                 SCULPTVERT_NEED_TRIANGULATE | SCULPTVERT_FSET_CORNER | SCULPTVERT_CORNER |
                 SCULPTVERT_NEED_VALENCE | SCULPTVERT_SEAM_BOUNDARY | SCULPTVERT_SHARP_BOUNDARY |
                 SCULPTVERT_SEAM_CORNER | SCULPTVERT_SHARP_CORNER | SCULPTVERT_PBVH_BOUNDARY |
                 SCULPTVERT_UV_BOUNDARY | SCULPTVERT_UV_CORNER);
 
+  ushort stroke_id = (ushort)mv->stroke_id;
+
   if (!e) {
-    mv->flag |= SCULPTVERT_BOUNDARY;
-    mv->valence = 0;
+    newflag |= SCULPTVERT_BOUNDARY;
+
+    atomic_cas_int32(&mv->flag, oldflag, newflag);
+    atomic_cas_short2(&mv->valence, (ushort)oldval, stroke_id, 0, stroke_id); 
+    
     return;
   }
 
@@ -1838,15 +1860,15 @@ void bke_pbvh_update_vert_boundary(int cd_sculpt_vert,
 #endif
 
     if (BM_ELEM_CD_GET_INT(v2, cd_vert_node_offset) != ni) {
-      mv->flag |= SCULPTVERT_PBVH_BOUNDARY;
+      newflag |= SCULPTVERT_PBVH_BOUNDARY;
     }
 
     if (e->head.hflag & BM_ELEM_SEAM) {
-      mv->flag |= SCULPTVERT_SEAM_BOUNDARY;
+      newflag |= SCULPTVERT_SEAM_BOUNDARY;
       seamcount++;
 
       if (seamcount > 2) {
-        mv->flag |= SCULPTVERT_SEAM_CORNER;
+        newflag |= SCULPTVERT_SEAM_CORNER;
       }
     }
 
@@ -1863,17 +1885,17 @@ void bke_pbvh_update_vert_boundary(int cd_sculpt_vert,
       int colorkey2 = color_boundary_key(color2);
 
       if (colorkey1 != colorkey2) {
-        mv->flag |= SCULPTVERT_FSET_BOUNDARY;
+        newflag |= SCULPTVERT_FSET_BOUNDARY;
       }
     }
 #endif
 
     if (!(e->head.hflag & BM_ELEM_SMOOTH)) {
-      mv->flag |= SCULPTVERT_SHARP_BOUNDARY;
+      newflag |= SCULPTVERT_SHARP_BOUNDARY;
       sharpcount++;
 
       if (sharpcount > 2) {
-        mv->flag |= SCULPTVERT_SHARP_CORNER;
+        newflag |= SCULPTVERT_SHARP_CORNER;
       }
     }
 
@@ -1904,11 +1926,11 @@ void bke_pbvh_update_vert_boundary(int cd_sculpt_vert,
                           len_squared_v2v2(lastuv2[i], luv->uv) > uv_snap_limit;
 
             if (!same) {
-              mv->flag |= SCULPTVERT_UV_BOUNDARY;
+              newflag |= SCULPTVERT_UV_BOUNDARY;
             }
 
             if (corner) {
-              mv->flag |= SCULPTVERT_UV_CORNER;
+              newflag |= SCULPTVERT_UV_CORNER;
             }
 
             if (!same) {
@@ -1922,7 +1944,7 @@ void bke_pbvh_update_vert_boundary(int cd_sculpt_vert,
       }
 
       if (BM_ELEM_CD_GET_INT(e->l->f, cd_face_node_offset) != ni) {
-        mv->flag |= SCULPTVERT_PBVH_BOUNDARY;
+        newflag |= SCULPTVERT_PBVH_BOUNDARY;
       }
 
       if (e->l != e->l->radial_next) {
@@ -1935,7 +1957,7 @@ void bke_pbvh_update_vert_boundary(int cd_sculpt_vert,
         }
 
         if (BM_ELEM_CD_GET_INT(e->l->radial_next->f, cd_face_node_offset) != ni) {
-          mv->flag |= SCULPTVERT_PBVH_BOUNDARY;
+          newflag |= SCULPTVERT_PBVH_BOUNDARY;
         }
       }
 
@@ -1943,7 +1965,7 @@ void bke_pbvh_update_vert_boundary(int cd_sculpt_vert,
           BM_ELEM_CD_GET_INT(e->l->f, cd_faceset_offset), bound_symmetry, v2->co);
 
       if (e->l->f->len > 3) {
-        mv->flag |= SCULPTVERT_NEED_TRIANGULATE;
+        newflag |= SCULPTVERT_NEED_TRIANGULATE;
       }
 
       bool ok = true;
@@ -1983,37 +2005,36 @@ void bke_pbvh_update_vert_boundary(int cd_sculpt_vert,
         }
 
         if (e->l->radial_next->f->len > 3) {
-          mv->flag |= SCULPTVERT_NEED_TRIANGULATE;
+          newflag |= SCULPTVERT_NEED_TRIANGULATE;
         }
       }
     }
 
     if (!e->l || e->l->radial_next == e->l) {
-      mv->flag |= SCULPTVERT_BOUNDARY;
+      newflag |= SCULPTVERT_BOUNDARY;
     }
 
     val++;
   } while ((e = BM_DISK_EDGE_NEXT(e, v)) != v->e);
 
   if (BLI_array_len(fsets) > 1) {
-    mv->flag |= SCULPTVERT_FSET_BOUNDARY;
+    newflag |= SCULPTVERT_FSET_BOUNDARY;
   }
 
   if (BLI_array_len(fsets) > 2) {
-    mv->flag |= SCULPTVERT_FSET_CORNER;
+    newflag |= SCULPTVERT_FSET_CORNER;
   }
 
   if (sharpcount == 1) {
-    mv->flag |= SCULPTVERT_SHARP_CORNER;
+    newflag |= SCULPTVERT_SHARP_CORNER;
   }
 
   if (seamcount == 1) {
-    mv->flag |= SCULPTVERT_SEAM_CORNER;
+    newflag |= SCULPTVERT_SEAM_CORNER;
   }
 
-  mv->valence = val;
-  if ((mv->flag & SCULPTVERT_BOUNDARY) && quadcount >= 3) {
-    mv->flag |= SCULPTVERT_CORNER;
+  if ((newflag & SCULPTVERT_BOUNDARY) && quadcount >= 3) {
+    newflag |= SCULPTVERT_CORNER;
   }
 
 #if 0
@@ -2034,8 +2055,16 @@ void bke_pbvh_update_vert_boundary(int cd_sculpt_vert,
   }
 #endif
 
-  // mv->curv = (short)(fabsf(min_ff(curv * 50.0f, 1.0f)) * 32767.0f);
-  mv->curv = (short)(min_ff(fabsf(curv), 1.0f) * 65535.0f);
+  atomic_cas_int32(&mv->flag, oldflag, newflag);
+  atomic_cas_short2(&mv->valence, (ushort)oldval, stroke_id, (ushort)val, stroke_id); 
+
+  /* no atomic_cas_int16, so do origmask and curv at once */
+
+  ushort newcurv = (unsigned short)(min_ff(fabsf(curv), 1.0f) * 65535.0f);
+  ushort oldcurv = mv->curv;
+  ushort origmask = mv->origmask;
+
+  atomic_cas_short2(&mv->origmask, origmask, oldcurv, origmask, newcurv);
 
   BLI_array_free(fsets);
 }



More information about the Bf-blender-cvs mailing list