[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, ¶ms->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