[Bf-blender-cvs] [76bd253be73] temp_bmesh_multires: Dyntopo sculpt: add dev operator to debug memory cache coherency

Joseph Eagar noreply at git.blender.org
Fri Aug 6 21:51:49 CEST 2021


Commit: 76bd253be73370145404aa4e31139911d9afb579
Author: Joseph Eagar
Date:   Fri Aug 6 09:58:46 2021 -0700
Branches: temp_bmesh_multires
https://developer.blender.org/rB76bd253be73370145404aa4e31139911d9afb579

Dyntopo sculpt: add dev operator to debug memory cache coherency

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

M	source/blender/blenkernel/intern/paint.c
M	source/blender/blenkernel/intern/pbvh_bmesh.c
M	source/blender/bmesh/intern/bmesh_mesh.c
M	source/blender/editors/sculpt_paint/sculpt.c
M	source/blender/gpu/intern/gpu_node_graph.c

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

diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c
index 800dbaaa1af..fd6c43ece2f 100644
--- a/source/blender/blenkernel/intern/paint.c
+++ b/source/blender/blenkernel/intern/paint.c
@@ -82,7 +82,6 @@
 // XXX todo: work our bad module cross ref
 void SCULPT_dynamic_topology_sync_layers(Object *ob, Mesh *me);
 void SCULPT_on_sculptsession_bmesh_free(SculptSession *ss);
-void SCULPT_reorder_bmesh(SculptSession *ss);
 
 static void palette_init_data(ID *id)
 {
diff --git a/source/blender/blenkernel/intern/pbvh_bmesh.c b/source/blender/blenkernel/intern/pbvh_bmesh.c
index c7f40d95109..66887e37af9 100644
--- a/source/blender/blenkernel/intern/pbvh_bmesh.c
+++ b/source/blender/blenkernel/intern/pbvh_bmesh.c
@@ -2410,7 +2410,7 @@ static void scan_edge_split(BMesh *bm, BMEdge **edges, int totedge)
   BLI_array_free(fmap);
 }
 
-BMesh *BKE_pbvh_reorder_bmesh(PBVH *pbvh)
+BMesh *BKE_pbvh_reorder_bmesh2(PBVH *pbvh)
 {
   if (BKE_pbvh_type(pbvh) != PBVH_BMESH || pbvh->totnode == 0) {
     return pbvh->bm;
@@ -2645,3 +2645,210 @@ BMesh *BKE_pbvh_reorder_bmesh(PBVH *pbvh)
 
   return bm2;
 }
+
+typedef struct SortElem {
+  BMElem *elem;
+  int index;
+  int cd_node_off;
+} SortElem;
+
+static int sort_verts_faces(const void *va, const void *vb)
+{
+  SortElem *a = (SortElem *)va;
+  SortElem *b = (SortElem *)vb;
+  int ni1 = BM_ELEM_CD_GET_INT(a->elem, a->cd_node_off);
+  int ni2 = BM_ELEM_CD_GET_INT(b->elem, b->cd_node_off);
+
+  return ni1 - ni2;
+}
+
+static int sort_edges(const void *va, const void *vb)
+{
+  SortElem *a = (SortElem *)va;
+  SortElem *b = (SortElem *)vb;
+
+  BMEdge *e1 = (BMEdge *)a->elem;
+  BMEdge *e2 = (BMEdge *)b->elem;
+
+  int ni1 = BM_ELEM_CD_GET_INT(e1->v1, a->cd_node_off);
+  int ni2 = BM_ELEM_CD_GET_INT(e1->v2, a->cd_node_off);
+  int ni3 = BM_ELEM_CD_GET_INT(e2->v1, b->cd_node_off);
+  int ni4 = BM_ELEM_CD_GET_INT(e2->v2, b->cd_node_off);
+
+  return (ni1 + ni2) - (ni3 + ni4);
+}
+
+BMesh *BKE_pbvh_reorder_bmesh(PBVH *pbvh)
+{
+  BMesh *bm = pbvh->bm;
+
+  int **save_other_vs = MEM_calloc_arrayN(pbvh->totnode, sizeof(int *), __func__);
+  int **save_unique_vs = MEM_calloc_arrayN(pbvh->totnode, sizeof(int *), __func__);
+  int **save_fs = MEM_calloc_arrayN(pbvh->totnode, sizeof(int *), __func__);
+
+  SortElem *verts = MEM_malloc_arrayN(bm->totvert, sizeof(SortElem), __func__);
+  SortElem *edges = MEM_malloc_arrayN(bm->totedge, sizeof(SortElem), __func__);
+  SortElem *faces = MEM_malloc_arrayN(bm->totface, sizeof(SortElem), __func__);
+
+  BMIter iter;
+  BMVert *v;
+  BMEdge *e;
+  BMFace *f;
+
+  int i = 0;
+
+  BM_ITER_MESH_INDEX (v, &iter, bm, BM_VERTS_OF_MESH, i) {
+    verts[i].elem = (BMElem *)v;
+    verts[i].cd_node_off = pbvh->cd_vert_node_offset;
+    verts[i].index = i;
+    v->head.index = i;
+  }
+  BM_ITER_MESH_INDEX (e, &iter, bm, BM_EDGES_OF_MESH, i) {
+    edges[i].elem = (BMElem *)e;
+    edges[i].cd_node_off = pbvh->cd_vert_node_offset;
+    edges[i].index = i;
+    e->head.index = i;
+  }
+  BM_ITER_MESH_INDEX (f, &iter, bm, BM_FACES_OF_MESH, i) {
+    faces[i].elem = (BMElem *)f;
+    faces[i].cd_node_off = pbvh->cd_face_node_offset;
+    faces[i].index = i;
+    f->head.index = i;
+  }
+
+  for (i = 0; i < pbvh->totnode; i++) {
+    int *other_vs = NULL;
+    int *unique_vs = NULL;
+    int *fs = NULL;
+
+    BLI_array_declare(other_vs);
+    BLI_array_declare(unique_vs);
+    BLI_array_declare(fs);
+
+    PBVHNode *node = pbvh->nodes + i;
+    if (!(node->flag & PBVH_Leaf)) {
+      continue;
+    }
+
+    BMVert *v;
+    BMFace *f;
+
+    TGSET_ITER (v, node->bm_unique_verts) {
+      BLI_array_append(unique_vs, v->head.index);
+    }
+    TGSET_ITER_END;
+    TGSET_ITER (v, node->bm_other_verts) {
+      BLI_array_append(other_vs, v->head.index);
+    }
+    TGSET_ITER_END;
+    TGSET_ITER (f, node->bm_faces) {
+      BLI_array_append(fs, f->head.index);
+    }
+    TGSET_ITER_END;
+
+    save_unique_vs[i] = unique_vs;
+    save_other_vs[i] = other_vs;
+    save_fs[i] = fs;
+  }
+
+  qsort(verts, bm->totvert, sizeof(SortElem), sort_verts_faces);
+  qsort(edges, bm->totedge, sizeof(SortElem), sort_edges);
+  qsort(faces, bm->totface, sizeof(SortElem), sort_verts_faces);
+
+  uint *vs = MEM_malloc_arrayN(bm->totvert, sizeof(int), __func__);
+  uint *es = MEM_malloc_arrayN(bm->totedge, sizeof(int), __func__);
+  uint *fs = MEM_malloc_arrayN(bm->totface, sizeof(int), __func__);
+
+  for (i = 0; i < bm->totvert; i++) {
+    vs[i] = (uint)verts[i].index;
+    verts[i].elem->head.index = verts[i].index;
+  }
+  for (i = 0; i < bm->totedge; i++) {
+    es[i] = (uint)edges[i].index;
+    edges[i].elem->head.index = edges[i].index;
+  }
+  for (i = 0; i < bm->totface; i++) {
+    fs[i] = (uint)faces[i].index;
+    faces[i].elem->head.index = faces[i].index;
+  }
+
+  BM_mesh_remap(bm, vs, es, fs);
+
+  // create new mappings
+  BMVert **mapvs = MEM_malloc_arrayN(bm->totvert, sizeof(BMVert *), __func__);
+  BMEdge **mapes = MEM_malloc_arrayN(bm->totedge, sizeof(BMEdge *), __func__);
+  BMFace **mapfs = MEM_malloc_arrayN(bm->totface, sizeof(BMFace *), __func__);
+
+  BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
+    mapvs[v->head.index] = v;
+  }
+  BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
+    mapes[e->head.index] = e;
+  }
+  BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
+    mapfs[f->head.index] = f;
+  }
+
+  // rebuild bm_unique_verts bm_other_verts and bm_faces in pbvh nodes
+  for (i = 0; i < pbvh->totnode; i++) {
+    PBVHNode *node = pbvh->nodes + i;
+
+    if (!(node->flag & PBVH_Leaf)) {
+      continue;
+    }
+
+    int tot_unique_vs = BLI_table_gset_len(node->bm_unique_verts);
+    int tot_other_vs = BLI_table_gset_len(node->bm_other_verts);
+    int tot_fs = BLI_table_gset_len(node->bm_faces);
+
+    BLI_table_gset_free(node->bm_unique_verts, NULL);
+    BLI_table_gset_free(node->bm_other_verts, NULL);
+    BLI_table_gset_free(node->bm_faces, NULL);
+
+    node->bm_unique_verts = BLI_table_gset_new("bm_unique_verts");
+    node->bm_other_verts = BLI_table_gset_new("bm_other_verts");
+    node->bm_faces = BLI_table_gset_new("bm_faces");
+
+    int *unique_vs = save_unique_vs[i];
+    int *other_vs = save_other_vs[i];
+    int *fs = save_fs[i];
+
+    for (int j = 0; j < tot_unique_vs; j++) {
+      BLI_table_gset_add(node->bm_unique_verts, mapvs[unique_vs[j]]);
+    }
+    for (int j = 0; j < tot_other_vs; j++) {
+      BLI_table_gset_add(node->bm_other_verts, mapvs[other_vs[j]]);
+    }
+
+    for (int j = 0; j < tot_fs; j++) {
+      BLI_table_gset_add(node->bm_faces, mapfs[fs[j]]);
+    }
+
+    MEM_SAFE_FREE(save_unique_vs[i]);
+    MEM_SAFE_FREE(save_other_vs[i]);
+    MEM_SAFE_FREE(save_fs[i]);
+
+    node->flag |= PBVH_UpdateTris;
+  }
+
+  MEM_SAFE_FREE(mapvs);
+  MEM_SAFE_FREE(mapes);
+  MEM_SAFE_FREE(mapfs);
+
+  bm->elem_index_dirty |= BM_VERT | BM_EDGE | BM_FACE;
+  bm->elem_table_dirty |= BM_VERT | BM_EDGE | BM_FACE;
+
+  MEM_SAFE_FREE(vs);
+  MEM_SAFE_FREE(es);
+  MEM_SAFE_FREE(fs);
+
+  MEM_SAFE_FREE(verts);
+  MEM_SAFE_FREE(edges);
+  MEM_SAFE_FREE(faces);
+
+  MEM_SAFE_FREE(save_other_vs);
+  MEM_SAFE_FREE(save_unique_vs);
+  MEM_SAFE_FREE(save_fs);
+
+  return pbvh->bm;
+}
diff --git a/source/blender/bmesh/intern/bmesh_mesh.c b/source/blender/bmesh/intern/bmesh_mesh.c
index 104ae6a349a..06ff1b1df55 100644
--- a/source/blender/bmesh/intern/bmesh_mesh.c
+++ b/source/blender/bmesh/intern/bmesh_mesh.c
@@ -1161,6 +1161,52 @@ void BM_mesh_remap(BMesh *bm, const uint *vert_idx, const uint *edge_idx, const
   if (fptr_map) {
     BLI_ghash_free(fptr_map, NULL, NULL);
   }
+
+  // regenerate idmap
+  if ((bm->idmap.flag & BM_HAS_IDS) && (bm->idmap.flag & BM_HAS_ID_MAP) && bm->idmap.map) {
+    memset(bm->idmap.map, 0, sizeof(void *) * bm->idmap.map_size);
+
+    char iters[4] = {BM_VERTS_OF_MESH, BM_EDGES_OF_MESH, 0, BM_FACES_OF_MESH};
+    CustomData *cdatas[4] = {&bm->vdata, &bm->edata, &bm->ldata, &bm->pdata};
+    const bool have_loop = bm->idmap.flag & BM_LOOP;
+
+    for (int i = 0; i < 4; i++) {
+      int type = 1 << i;
+
+      if (type == BM_LOOP) {  // handle loops with faces
+        continue;
+      }
+
+      int cd_id = CustomData_get_offset(cdatas[i], CD_MESH_ID);
+      int cd_loop_id = CustomData_get_offset(&bm->ldata, CD_MESH_ID);
+
+      BMIter iter;
+      BMElem *elem;
+
+      if (cd_id < 0 && !(type == BM_FACE && have_loop)) {
+        continue;
+      }
+
+      BM_ITER_MESH (elem, &iter, bm, iters[i]) {
+        if (type == BM_FACE && have_loop) {
+          BMFace *f = (BMFace *)elem;
+          BMLoop *l = f->l_first;
+
+          do {
+            int id_loop = BM_ELEM_CD_GET_INT(l, cd_loop_id);
+            bm->idmap.map[id_loop] = (BMElem *)l;
+          } while ((l = l->next) != f->l_first);
+        }
+
+        if (cd_id < 0) {
+          continue;
+        }
+
+        int id = BM_ELEM_CD_GET_INT(elem, cd_id);
+        bm->idmap.map[id] = elem;
+      }
+    }
+  }
 }
 
 /**
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c
index 9da164464c7..cf5bb8b9622 100644
--- a/source/blender/editors/sculpt_paint/sculpt.c
+++ b/source/blender/editors/sculpt_paint/sculpt.c
@@ -9429,6 +9429,67 @@ static bool sculpt_no_multires_poll(bContext *C)
   return false;
 }
 
+static bool sculpt_only_bmesh_poll(bContext *C)
+{
+  Object *ob = CTX_data_active_object(C);
+  if (SCULPT_mode_poll(C) && ob->sculpt && ob->sculpt->pbvh) {
+    return BKE_pbvh_type(ob->sculpt->pbvh) == PBVH_BMESH;
+  }
+  return false;
+}
+
+static int sculpt_spatial_sort_exec(bContext *C, wmOperator *op)
+{
+  Main *bmain = CTX_data_main(C);
+  Object *ob = CTX_data_active_object(C);
+  const Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
+  SculptSession *ss = ob->sculpt;
+  PBVH *pbvh = ss->pbvh;
+
+  if (!pbvh) {
+    return OPERATOR_CANCELLED;
+  }
+
+  switch (BKE_pbvh_type(pbvh)) {
+    case PBVH_BMESH:
+      SCULPT_undo_push_begin(ob, "Dynamic topology symmetrize");
+      SCULPT_undo_push_node(ob, NULL, SCULPT_UNDO_GEOMETRY);
+
+      BKE_pbvh_reorder_bmesh(ss->pbvh);
+
+      BKE_pbvh_recalc_bmesh_boundary(ss->pbvh);
+      BM_log_full_mesh(ss->bm, ss->bm_log);
+
+      ss->act

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list