[Bf-blender-cvs] [9fab16f0f3a] temp_bmesh_multires: * Fix null ptr bug in automasking code

Joseph Eagar noreply at git.blender.org
Tue Apr 27 18:01:47 CEST 2021


Commit: 9fab16f0f3ab1fbd49de885cdcb4680b49bdefa2
Author: Joseph Eagar
Date:   Tue Apr 27 09:01:32 2021 -0700
Branches: temp_bmesh_multires
https://developer.blender.org/rB9fab16f0f3ab1fbd49de885cdcb4680b49bdefa2

* Fix null ptr bug in automasking code

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

M	source/blender/blenlib/BLI_mempool.h
M	source/blender/blenlib/intern/BLI_mempool.c
M	source/blender/bmesh/CMakeLists.txt
A	source/blender/bmesh/intern/bmesh_mesh_convert_threaded.c
M	source/blender/editors/sculpt_paint/sculpt_automasking.c

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

diff --git a/source/blender/blenlib/BLI_mempool.h b/source/blender/blenlib/BLI_mempool.h
index 3ee6f182593..65f60071771 100644
--- a/source/blender/blenlib/BLI_mempool.h
+++ b/source/blender/blenlib/BLI_mempool.h
@@ -93,6 +93,19 @@ BLI_mempool_iter *BLI_mempool_iter_threadsafe_create(BLI_mempool *pool,
     ATTR_NONNULL();
 void BLI_mempool_iter_threadsafe_free(BLI_mempool_iter *iter_arr) ATTR_NONNULL();
 
+
+/*
+This preallocates a mempool suitable for threading.  totelem elements are preallocated
+in chunks of size pchunk, and returned in r_chunks.
+*/
+
+BLI_mempool *BLI_mempool_create_for_tasks(const unsigned int esize,
+                                          unsigned int totelem,
+                                          const unsigned int pchunk,
+                                          void ***r_chunks,
+                                          unsigned int *r_totchunk,
+                                          unsigned int flag);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/source/blender/blenlib/intern/BLI_mempool.c b/source/blender/blenlib/intern/BLI_mempool.c
index 75f934c1fb8..f5d318286c6 100644
--- a/source/blender/blenlib/intern/BLI_mempool.c
+++ b/source/blender/blenlib/intern/BLI_mempool.c
@@ -250,6 +250,82 @@ static BLI_freenode *mempool_chunk_add(BLI_mempool *pool,
   return curnode;
 }
 
+/*
+This preallocates a mempool suitable for threading.  totelem elements are preallocated
+in chunks of size pchunk, and returned in r_chunks.  The idea is to pass these
+to tasks.
+*/
+
+BLI_mempool *BLI_mempool_create_for_tasks(const unsigned int esize,
+                                          unsigned int totelem,
+                                          const unsigned int pchunk,
+                                          void ***r_chunks,
+                                          unsigned int *r_totchunk,
+                                          unsigned int flag)
+{
+  BLI_mempool *pool = BLI_mempool_create(esize, totelem, pchunk, flag);
+
+  BLI_mempool_chunk **chunks = MEM_callocN(sizeof(void *) * pool->maxchunks,
+                                           "BLI_mempool_create_for_tasks r_chunks");
+
+  int totalloc = 0;
+  *r_totchunk = 0;
+
+  BLI_mempool_chunk *chunk = pool->chunks, *lastchunk = NULL;
+
+  while (chunk) {
+    chunk = chunk->next;
+    totalloc += pool->pchunk;
+    lastchunk = chunk;
+  }
+
+  pool->totused = totalloc;
+  pool->free = NULL;
+
+  int i = pool->pchunk - 1;
+
+  while (lastchunk && totalloc > totelem) {
+    if (i < 0) {
+      BLI_mempool_chunk *lastchunk2 = NULL;
+
+      for (chunk = pool->chunks; chunk; chunk = chunk->next) {
+        if (chunk == lastchunk) {
+          lastchunk = lastchunk2;
+        }
+      }
+
+      if (!lastchunk) {
+        break;
+      }
+
+      i = pool->pchunk - 1;
+    }
+
+    char *elem = CHUNK_DATA(lastchunk);
+    elem += pool->esize * (unsigned int)i;
+
+    BLI_mempool_free(pool, elem);
+
+    totalloc--;
+  }
+
+  unsigned int ci = 0;
+
+  chunk = pool->chunks;
+  while (chunk && chunk != lastchunk) {
+    chunks[ci++] = CHUNK_DATA(chunk);
+    chunk = chunk->next;
+  }
+
+  if (lastchunk && i >= 0) {
+    chunks[ci++] = CHUNK_DATA(lastchunk);
+  }
+
+  *r_totchunk = ci;
+
+  return pool;
+}
+
 static void mempool_chunk_free(BLI_mempool_chunk *mpchunk)
 {
   MEM_freeN(mpchunk);
diff --git a/source/blender/bmesh/CMakeLists.txt b/source/blender/bmesh/CMakeLists.txt
index c215cf69e3a..da077bf4542 100644
--- a/source/blender/bmesh/CMakeLists.txt
+++ b/source/blender/bmesh/CMakeLists.txt
@@ -99,6 +99,7 @@ set(SRC
   intern/bmesh_mesh.c
   intern/bmesh_mesh.h
   intern/bmesh_mesh_convert.c
+  intern/bmesh_mesh_convert_threaded.c
   intern/bmesh_mesh_convert.h
   intern/bmesh_mesh_duplicate.c
   intern/bmesh_mesh_duplicate.h
diff --git a/source/blender/bmesh/intern/bmesh_mesh_convert_threaded.c b/source/blender/bmesh/intern/bmesh_mesh_convert_threaded.c
new file mode 100644
index 00000000000..04d92990b35
--- /dev/null
+++ b/source/blender/bmesh/intern/bmesh_mesh_convert_threaded.c
@@ -0,0 +1,1693 @@
+#if 0
+#  include "DNA_key_types.h"
+#  include "DNA_mesh_types.h"
+#  include "DNA_meshdata_types.h"
+#  include "DNA_modifier_types.h"
+#  include "DNA_object_types.h"
+
+#  include "MEM_guardedalloc.h"
+
+#  include "BLI_alloca.h"
+#  include "BLI_listbase.h"
+#  include "BLI_math_vector.h"
+
+#  include "BKE_customdata.h"
+#  include "BKE_mesh.h"
+#  include "BKE_mesh_runtime.h"
+#  include "BKE_multires.h"
+
+#  include "BKE_key.h"
+#  include "BKE_main.h"
+
+#  include "DEG_depsgraph_query.h"
+
+#  include "bmesh.h"
+#  include "intern/bmesh_private.h" /* For element checking. */
+
+#  include "BLI_task.h"
+
+#  include "atomic_ops.h"
+
+#  define ECHUNK 512
+#  define VCHUNK 512
+#  define FCHUNK 512
+#  define LCHUNK 1024
+
+typedef struct BMThreadData {
+  BMesh *bm;
+  Object *ob;
+  Mesh *me;
+
+  struct BMeshFromMeshParams *params;
+
+  void **vdata, **edata, **ldata, **fdata;
+  int totdv, totde, totdl, totdf;
+
+  BMVert **verts;
+  BMEdge **edges;
+  BMLoop **loops;
+  BMFace **faces;
+
+  // chunk sizes
+  int totcv, totce, totcl, totcf;
+} BMThreadData;
+
+void bm_vert_task(void *__restrict userdata, const int n, const TaskParallelTLS *__restrict tls)
+{
+  BMThreadData *data = userdata;
+  BMesh *bm = data->bm;
+  Mesh *me = data->me;
+
+  int starti = n * data->totcv;
+
+  int ilen = starti + data->totcv > bm->totvert ? bm->totvert - starti : data->totcv;
+  MVert *mv = me->mvert + starti;
+  BMVert *v = data->verts[n];
+
+  for (i = 0; i < ilen; i++, mv++, v++) {
+    v->head.data = NULL;
+
+    v->head.htype = BM_VERT;
+    v->head.hflag = 0;
+    v->head.api_flag = 0;
+
+    copy_v3_v3(v->co, mv->co);
+    normal_short_to_float_v3(v->no, mv->no);
+
+    v->e = NULL;
+  }
+}
+
+void bm_edge_task(void *__restrict userdata, const int n, const TaskParallelTLS *__restrict tls)
+{
+  BMThreadData *data = userdata;
+  BMesh *bm = data->bm;
+  Mesh *me = data->me;
+
+  int starti = n * data->totce;
+
+  int ilen = starti + data->totce > bm->totedge ? bm->totedge - starti : data->totce;
+  MEdge *med = me->medge + starti;
+  BMEdge *e = data->verts[n];
+
+  for (i = 0; i < ilen; i++, med++, e++) {
+    e->head.data = NULL;
+
+    e->head.htype = BM_EDGE;
+    e->head.hflag = 0;
+    e->head.api_flag = 0;
+
+    e->v1 = &data->verts[med->v1 / data->totcv][med->v1 % data->totcv];
+    e->v2 = &data->verts[med->v2 / data->totcv][med->v2 % data->totcv];
+
+    e->l = NULL;
+
+    atomic_cas_ptr((void **)&e->v1->e, NULL, (void *)e);
+    atomic_cas_ptr((void **)&e->v2->e, NULL, (void *)e);
+  }
+}
+
+BMesh *BM_mesh_bm_from_me_threaded(Object *ob,
+                                   const Mesh *me,
+                                   const struct BMeshFromMeshParams *params)
+{
+  BMesh *bm = MEM_callocN(sizeof(BMesh), "BM_mesh_bm_from_me_threaded bm");
+  const bool is_new = true;
+
+  bm->totvert = me->totvert;
+  bm->totedge = me->totedge;
+  bm->totface = me->totpoly;
+  bm->totloop = me->totloop;
+
+  bm->elem_index_dirty = bm->elem_table_dirty = BM_VERT | BM_EDGE | BM_LOOP | BM_FACE;
+  bm->spacearr_dirty = BM_SPACEARR_DIRTY_ALL;
+
+  BMVert **verts;
+  BMEdge **edges;
+  BMLoop **loops;
+  BMFace **faces;
+
+  void **vdata, **edata, **ldata, **fdata;
+  int totdv, totde, totdl, totdf;
+
+  int totcv, totce, totcl, totcf;
+
+  BMThreadData data = {0};
+
+  bm->vpool = BLI_mempool_create_for_tasks(
+      sizeof(BMVert), bm->totvert, VCHUNK, &verts, &totcv, BLI_MEMPOOL_ALLOW_ITER);
+  bm->epool = BLI_mempool_create_for_tasks(
+      sizeof(BMVert), bm->totvert, VCHUNK, &edges, &totce, BLI_MEMPOOL_ALLOW_ITER);
+  bm->lpool = BLI_mempool_create_for_tasks(
+      sizeof(BMVert), bm->totvert, VCHUNK, &loops, &totcf, BLI_MEMPOOL_ALLOW_ITER);
+  bm->fpool = BLI_mempool_create_for_tasks(
+      sizeof(BMVert), bm->totvert, VCHUNK, &faces, &totcl, BLI_MEMPOOL_ALLOW_ITER);
+
+  data.verts = verts;
+  data.edges = edges;
+  data.loops = loops;
+  data.faces = faces;
+  data.bm = bm;
+  data.me = me;
+
+  // bm->vpool = BLI_mem
+
+  MVert *mvert;
+  MEdge *medge;
+  MLoop *mloop;
+  MPoly *mp;
+  KeyBlock *actkey, *block;
+  BMVert *v, **vtable = NULL;
+  BMEdge *e, **etable = NULL;
+  BMFace *f, **ftable = NULL;
+  float(*keyco)[3] = NULL;
+  int totloops, i;
+  CustomData_MeshMasks mask = CD_MASK_BMESH;
+  CustomData_MeshMasks_update(&mask, &params->cd_mask_extra);
+
+  MultiresModifierData *mmd = ob ? get_multires_modifier(NULL, ob, true) : NULL;
+
+  if (mmd) {
+    bm->multires = *mmd;
+    bm->haveMultiResSettings = true;
+    bm->multiresSpace = MULTIRES_SPACE_TANGENT;
+  }
+  else {
+    bm->haveMultiResSettings = false;
+  }
+
+  CustomData_copy(&me->vdata, &bm->vdata, mask.vmask, CD_ASSIGN, 0);
+  CustomData_copy(&me->edata, &bm->edata, mask.emask, CD_ASSIGN, 0);
+  CustomData_copy(&me->ldata, &bm->ldata, mask.lmask, CD_ASSIGN, 0);
+  CustomData_copy(&me->pdata, &bm->pdata, mask.pmask, CD_ASSIGN, 0);
+
+  if (bm->vdata.totlayer) {
+    bm->vdata.pool = BLI_mempool_create_for_tasks(
+        bm->vdata.totsize, bm->totvert, VCHUNK, &vdata, &totdv, BLI_MEMPOOL_NOP);
+  }
+  if (bm->edata.totlayer) {
+    bm->edata.pool = BLI_mempool_create_for_tasks(
+        bm->edata.totsize, bm->totedge, ECHUNK, &edata, &totde, BLI_MEMPOOL_NOP);
+  }
+  if (bm->ldata.totlayer) {
+    bm->ldata.pool = BLI_mempool_create_for_tasks(
+        bm->ldata.totsize, bm->totloop, LCHUNK, &ldata, &totdl, BLI_MEMPOOL_NOP);
+  }
+  if (bm->pdata.totlayer) {
+    bm->pdata.pool = BLI_mempool_create_for_tasks(
+        bm->pdata.totsize, bm->totface, VCHUNK, &fdata, &totdf, BLI_MEMPOOL_NOP);
+  }
+
+  data.vdata = vdata;
+  data.edata = edata;
+  data.ldata = ldata;
+  data.fdata = fdata;
+
+  data.totdv = totdv;
+  data.totde = totde;
+  data.totdl = totdl;
+  data.totdf = totdf;
+
+  /* -------------------------------------------------------------------- */
+  /* Shape Key */
+  int tot_shape_keys = 0;
+  if (me->key != NULL && DEG_is_original_id(&me->id)) {
+    /* Evaluated meshes can be topologically inconsistent with their shape keys.
+     * Shape keys are also already integrated into the state of the evaluated
+     * mesh, so considering them here would kind of a

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list