[Bf-blender-cvs] [27986e9b56e] temp_bmesh_multires: Sculpt dyntopo: Added a function to add multiple customdata layers to a bmesh at once. Helpful since bmesh customdata layers are allocated in single blocks, thus adding layers individually can lead to lots of memory copying.

Joseph Eagar noreply at git.blender.org
Sun Jun 27 06:35:00 CEST 2021


Commit: 27986e9b56ee311ed80c1b17f06d7d3e7640d06b
Author: Joseph Eagar
Date:   Sat Jun 26 19:12:07 2021 -0700
Branches: temp_bmesh_multires
https://developer.blender.org/rB27986e9b56ee311ed80c1b17f06d7d3e7640d06b

Sculpt dyntopo: Added a function to add multiple customdata
layers to a bmesh at once.  Helpful since bmesh customdata
layers are allocated in single blocks, thus adding
layers individually can lead to lots of memory
copying.

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

M	source/blender/bmesh/intern/bmesh_interp.c
M	source/blender/bmesh/intern/bmesh_interp.h
M	source/blender/editors/sculpt_paint/sculpt_dyntopo.c

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

diff --git a/source/blender/bmesh/intern/bmesh_interp.c b/source/blender/bmesh/intern/bmesh_interp.c
index ffce5386428..f49ea5c6535 100644
--- a/source/blender/bmesh/intern/bmesh_interp.c
+++ b/source/blender/bmesh/intern/bmesh_interp.c
@@ -1336,6 +1336,102 @@ static void update_data_blocks(BMesh *bm, CustomData *olddata, CustomData *data)
   }
 }
 
+ATTR_NO_OPT void BM_data_layers_ensure(BMesh *bm,
+                                       CustomData *data,
+                                       BMCustomLayerReq *layers,
+                                       int totlayer)
+{
+  bool modified = false;
+  CustomData old = *data;
+  CustomData temp;
+  CustomDataMask mask = 0;
+
+  if (old.layers) {
+    old.layers = MEM_dupallocN(old.layers);
+  }
+
+  memset(&temp, 0, sizeof(temp));
+  CustomData_reset(&temp);
+
+  for (int i = 0; i < totlayer; i++) {
+    BMCustomLayerReq *req = layers + i;
+    int idx;
+
+    mask |= 1ULL << (CustomDataMask)req->type;
+
+    if (req->name) {
+      idx = CustomData_get_named_layer_index(data, req->type, req->name);
+    }
+    else {
+      idx = CustomData_get_layer_index(data, req->type);
+    }
+
+    if (idx < 0) {
+      modified = true;
+
+      if (req->name) {
+        CustomData_add_layer_named(&temp, req->type, CD_ASSIGN, NULL, 0, req->name);
+      }
+      else {
+        CustomData_add_layer(&temp, req->type, CD_ASSIGN, NULL, 0);
+      }
+    }
+  }
+
+  int htype;
+  if (data == &bm->vdata) {
+    htype = BM_VERT;
+  }
+  else if (data == &bm->edata) {
+    htype = BM_EDGE;
+  }
+  else if (data == &bm->ldata) {
+    htype = BM_LOOP;
+  }
+  else if (data == &bm->pdata) {
+    htype = BM_FACE;
+  }
+  else {
+    printf("error in %s!\n", __func__);
+    CustomData_free(&temp, 0);
+    return;
+  }
+
+  if (modified) {
+    CustomData_merge(&temp, data, mask, CD_ASSIGN, 0);
+  }
+
+  for (int i = 0; i < totlayer; i++) {
+    BMCustomLayerReq *req = layers + i;
+    int idx;
+
+    mask |= 1 << req->type;
+
+    if (req->name) {
+      idx = CustomData_get_named_layer_index(data, req->type, req->name);
+    }
+    else {
+      idx = CustomData_get_layer_index(data, req->type);
+    }
+
+    data->layers[idx].flag |= req->flag;
+  }
+
+  if (modified) {
+    /* the pool is now owned by olddata and must not be shared */
+    data->pool = NULL;
+
+    update_data_blocks(bm, &old, data);
+    bm_update_idmap_cdlayers(bm);
+  }
+
+  if (old.layers) {
+    MEM_freeN(old.layers);
+  }
+
+  CustomData_free(&temp, 0);
+}
+
 void BM_data_layer_add(BMesh *bm, CustomData *data, int type)
 {
   CustomData olddata;
diff --git a/source/blender/bmesh/intern/bmesh_interp.h b/source/blender/bmesh/intern/bmesh_interp.h
index 686053fa78b..c5c5579df26 100644
--- a/source/blender/bmesh/intern/bmesh_interp.h
+++ b/source/blender/bmesh/intern/bmesh_interp.h
@@ -24,6 +24,12 @@
 struct LinkNode;
 struct MemArena;
 
+typedef struct BMCustomLayerReq {
+  int type;
+  char *name;  // can be NULL
+  int flag;
+} BMCustomLayerReq;
+
 void BM_face_multires_stitch(BMesh *bm, BMFace *f);
 void BM_loop_interp_multires_ex(BMesh *bm,
                                 BMLoop *l_dst,
@@ -53,6 +59,9 @@ void BM_data_interp_face_vert_edge(BMesh *bm,
                                    BMVert *v,
                                    BMEdge *e,
                                    const float fac);
+
+void BM_data_layers_ensure(BMesh *bm, CustomData *data, BMCustomLayerReq *layers, int totlayer);
+
 void BM_data_layer_add(BMesh *bm, CustomData *data, int type);
 void BM_data_layer_add_named(BMesh *bm, CustomData *data, int type, const char *name);
 void BM_data_layer_free(BMesh *bm, CustomData *data, int type);
diff --git a/source/blender/editors/sculpt_paint/sculpt_dyntopo.c b/source/blender/editors/sculpt_paint/sculpt_dyntopo.c
index 0abb895146c..9632d5d948c 100644
--- a/source/blender/editors/sculpt_paint/sculpt_dyntopo.c
+++ b/source/blender/editors/sculpt_paint/sculpt_dyntopo.c
@@ -296,18 +296,11 @@ void SCULPT_dyntopo_node_layers_add(SculptSession *ss)
   int cd_origco_index, cd_origno_index, cd_origvcol_index = -1;
   bool have_vcol = CustomData_has_layer(&ss->bm->vdata, CD_PROP_COLOR);
 
-  if (!CustomData_has_layer(&ss->bm->vdata, CD_DYNTOPO_VERT)) {
-    BM_data_layer_add(ss->bm, &ss->bm->vdata, CD_DYNTOPO_VERT);
+  BMCustomLayerReq vlayers[] = {{CD_PAINT_MASK, NULL, 0},
+                                {CD_DYNTOPO_VERT, NULL, CD_FLAG_TEMPORARY},
+                                {CD_PROP_INT32, dyntopop_node_idx_layer_id, CD_FLAG_TEMPORARY}};
 
-    int cd_dyn_vert = CustomData_get_layer_index(&ss->bm->vdata, CD_DYNTOPO_VERT);
-    ss->bm->vdata.layers[cd_dyn_vert].flag |= CD_FLAG_TEMPORARY;
-  }
-
-  cd_node_layer_index = CustomData_get_named_layer_index(
-      &ss->bm->vdata, CD_PROP_INT32, dyntopop_node_idx_layer_id);
-  if (cd_node_layer_index == -1) {
-    BM_data_layer_add_named(ss->bm, &ss->bm->vdata, CD_PROP_INT32, dyntopop_node_idx_layer_id);
-  }
+  BM_data_layers_ensure(ss->bm, &ss->bm->vdata, vlayers, 3);
 
   cd_face_node_layer_index = CustomData_get_named_layer_index(
       &ss->bm->pdata, CD_PROP_INT32, dyntopop_node_idx_layer_id);
@@ -513,8 +506,6 @@ void SCULPT_dynamic_topology_enable_ex(Main *bmain, Depsgraph *depsgraph, Scene
 #endif
   SCULPT_dynamic_topology_triangulate(ss, ss->bm);
 
-  BM_data_layer_add(ss->bm, &ss->bm->vdata, CD_PAINT_MASK);
-
   SCULPT_dyntopo_node_layers_add(ss);
   SCULPT_dyntopo_save_origverts(ss);
 
@@ -527,10 +518,12 @@ void SCULPT_dynamic_topology_enable_ex(Main *bmain, Depsgraph *depsgraph, Scene
 
   // convert layer brush data
   if (ss->persistent_base) {
-    SCULPT_dyntopo_ensure_templayer(ss, CD_PROP_FLOAT3, SCULPT_LAYER_PERS_CO);
-    SCULPT_dyntopo_ensure_templayer(ss, CD_PROP_FLOAT3, SCULPT_LAYER_PERS_NO);
-    SCULPT_dyntopo_ensure_templayer(ss, CD_PROP_FLOAT, SCULPT_LAYER_PERS_DISP);
-    SCULPT_dyntopo_ensure_templayer(ss, CD_PROP_FLOAT, SCULPT_LAYER_DISP);
+    BMCustomLayerReq layers[] = {{CD_PROP_FLOAT3, SCULPT_LAYER_PERS_CO, CD_FLAG_TEMPORARY},
+                                 {CD_PROP_FLOAT3, SCULPT_LAYER_PERS_NO, CD_FLAG_TEMPORARY},
+                                 {CD_PROP_FLOAT, SCULPT_LAYER_PERS_DISP, CD_FLAG_TEMPORARY},
+                                 {CD_PROP_FLOAT, SCULPT_LAYER_DISP, CD_FLAG_TEMPORARY}};
+
+    BM_data_layers_ensure(ss->bm, &ss->bm->vdata, layers, 4);
 
     cd_pers_co = SCULPT_dyntopo_get_templayer(ss, CD_PROP_FLOAT3, SCULPT_LAYER_PERS_CO);
     cd_pers_no = SCULPT_dyntopo_get_templayer(ss, CD_PROP_FLOAT3, SCULPT_LAYER_PERS_NO);



More information about the Bf-blender-cvs mailing list