[Bf-blender-cvs] [8346bcf] bmesh-boolean-experiment: Use memarena to avoid too many stack allocations

Campbell Barton noreply at git.blender.org
Thu Dec 10 11:06:55 CET 2015


Commit: 8346bcfaf4e257797a45a13cf2707ff63240cca0
Author: Campbell Barton
Date:   Thu Dec 10 20:49:55 2015 +1100
Branches: bmesh-boolean-experiment
https://developer.blender.org/rB8346bcfaf4e257797a45a13cf2707ff63240cca0

Use memarena to avoid too many stack allocations

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

M	source/blender/bmesh/intern/bmesh_polygon_edgenet.c
M	source/blender/bmesh/intern/bmesh_polygon_edgenet.h
M	source/blender/bmesh/tools/bmesh_intersect.c

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

diff --git a/source/blender/bmesh/intern/bmesh_polygon_edgenet.c b/source/blender/bmesh/intern/bmesh_polygon_edgenet.c
index 30110ab..38127fb 100644
--- a/source/blender/bmesh/intern/bmesh_polygon_edgenet.c
+++ b/source/blender/bmesh/intern/bmesh_polygon_edgenet.c
@@ -29,6 +29,7 @@
 #include "MEM_guardedalloc.h"
 
 #include "BLI_math.h"
+#include "BLI_memarena.h"
 #include "BLI_array.h"
 #include "BLI_alloca.h"
 #include "BLI_stackdefines.h"
@@ -934,10 +935,14 @@ static int bm_face_split_edgenet_find_connection(
 
 /**
  * For when the edge-net has holes in it-this connects them.
+ *
+ * \param mem_arena: Avoids many small allocs & should be cleared after each use.
+ * take care since \a r_edge_net_new is stored in \a r_edge_net_new.
  */
 bool BM_face_split_edgenet_connect_islands(
         BMesh *bm,
         BMFace *f, BMEdge **edge_net_init, const unsigned int edge_net_init_len,
+        MemArena *mem_arena,
         BMEdge ***r_edge_net_new, unsigned int *r_edge_net_new_len)
 {
 	/* -------------------------------------------------------------------- */
@@ -947,6 +952,9 @@ bool BM_face_split_edgenet_connect_islands(
 	 * - Connect the holes with edges (if any are found).
 	 *
 	 * Keep the first part fast since it will run very often for edge-nets that have no holes.
+	 *
+	 * \note Don't use the mem_arena unless he have holes to fill.
+	 * (avoid thrashing the area when the initial check isn't so intensive on the stack).
 	 */
 
 	const unsigned int edge_arr_len = (unsigned int)edge_net_init_len + (unsigned int)f->len;
@@ -1050,7 +1058,7 @@ bool BM_face_split_edgenet_connect_islands(
 
 #define VERT_IN_ARRAY BM_ELEM_INTERNAL_TAG
 
-	struct EdgeGroupIsland **group_arr = BLI_array_alloca(group_arr, group_arr_len);
+	struct EdgeGroupIsland **group_arr = BLI_memarena_alloc(mem_arena, sizeof(*group_arr) * group_arr_len);
 	unsigned int vert_arr_len = 0;
 	/* sort groups by lowest value vertex */
 	{
@@ -1093,11 +1101,11 @@ bool BM_face_split_edgenet_connect_islands(
 	qsort(group_arr, group_arr_len, sizeof(*group_arr), group_min_cmp_fn);
 
 	/* we don't know how many unique verts there are connecting the edges, so over-alloc */
-	BMVert **vert_arr = BLI_array_alloca(vert_arr, vert_arr_len);
+	BMVert **vert_arr = BLI_memarena_alloc(mem_arena, sizeof(*vert_arr) * vert_arr_len);
 	/* map vertex -> group index */
-	unsigned int *verts_group_table = BLI_array_alloca(verts_group_table, vert_arr_len);
+	unsigned int *verts_group_table = BLI_memarena_alloc(mem_arena, sizeof(*verts_group_table) * vert_arr_len);
 
-	float (*vert_coords_backup)[3] = BLI_array_alloca(vert_coords_backup, vert_arr_len);
+	float (*vert_coords_backup)[3] = BLI_memarena_alloc(mem_arena, sizeof(*vert_coords_backup) * vert_arr_len);
 
 	{
 		float axis_mat[3][3];
@@ -1157,7 +1165,7 @@ bool BM_face_split_edgenet_connect_islands(
 
 	/* may be an over-alloc, but not by much */
 	unsigned int edge_net_new_len = (unsigned int)edge_net_init_len + ((group_arr_len - 1) * 2);
-	BMEdge **edge_net_new = MEM_mallocN(sizeof(*edge_net_new) * edge_net_new_len, __func__);
+	BMEdge **edge_net_new = BLI_memarena_alloc(mem_arena, sizeof(*edge_net_new) * edge_net_new_len);
 	memcpy(edge_net_new, edge_net_init, sizeof(*edge_net_new) * (size_t)edge_net_init_len);
 
 	{
diff --git a/source/blender/bmesh/intern/bmesh_polygon_edgenet.h b/source/blender/bmesh/intern/bmesh_polygon_edgenet.h
index a1ea1cb..b664231 100644
--- a/source/blender/bmesh/intern/bmesh_polygon_edgenet.h
+++ b/source/blender/bmesh/intern/bmesh_polygon_edgenet.h
@@ -33,6 +33,8 @@ bool BM_face_split_edgenet(
 bool BM_face_split_edgenet_connect_islands(
         BMesh *bm,
         BMFace *f, BMEdge **edge_net_init, const unsigned int edge_net_init_len,
-        BMEdge ***r_edge_net_new, unsigned int *r_edge_net_new_len);
+        struct MemArena *arena,
+        BMEdge ***r_edge_net_new, unsigned int *r_edge_net_new_len)
+ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2, 3, 5, 6, 7);
 
 #endif  /* __BMESH_POLYGON_EDGENET_H__ */
diff --git a/source/blender/bmesh/tools/bmesh_intersect.c b/source/blender/bmesh/tools/bmesh_intersect.c
index 486c425..6930c48 100644
--- a/source/blender/bmesh/tools/bmesh_intersect.c
+++ b/source/blender/bmesh/tools/bmesh_intersect.c
@@ -255,14 +255,12 @@ static void face_edges_add(
 static void face_edges_split(
         BMesh *bm,
         BMFace *f,
-        struct LinkBase *e_ls_base)
+        struct LinkBase *e_ls_base,
+        MemArena *mem_arena_edgenet)
 {
 	unsigned int i;
 	unsigned int edge_arr_len = e_ls_base->list_len;
 	BMEdge **edge_arr = BLI_array_alloca(edge_arr, edge_arr_len);
-#ifdef USE_HOLE_FILL
-	bool edge_arr_free = false;
-#endif
 	LinkNode *node;
 	BLI_assert(f->head.htype == BM_FACE);
 
@@ -282,22 +280,16 @@ static void face_edges_split(
 		if (BM_face_split_edgenet_connect_islands(
 		        bm, f,
 		        edge_arr, edge_arr_len,
+		        mem_arena_edgenet,
 		        &edge_arr_holes, &edge_arr_holes_len))
 		{
 			edge_arr_len = edge_arr_holes_len;
-			edge_arr = edge_arr_holes;
-			edge_arr_free = true;
+			edge_arr = edge_arr_holes;  /* owned by the arena */
 		}
 	}
 #endif
 
 	BM_face_split_edgenet(bm, f, edge_arr, (int)edge_arr_len, NULL, NULL);
-
-#ifdef USE_HOLE_FILL
-	if (edge_arr_free) {
-		MEM_freeN(edge_arr);
-	}
-#endif
 }
 #endif
 
@@ -1563,6 +1555,8 @@ bool BM_mesh_intersect(
 		GHashIterator gh_iter;
 		BMFace **faces;
 
+		MemArena *mem_arena_edgenet = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
+
 		faces = bm->ftable;
 
 		GHASH_ITER (gh_iter, s.face_edges) {
@@ -1579,8 +1573,12 @@ bool BM_mesh_intersect(
 
 			BLI_assert(BM_elem_index_get(f) == f_index);
 
-			face_edges_split(bm, f, e_ls_base);
+			face_edges_split(bm, f, e_ls_base, mem_arena_edgenet);
+
+			BLI_memarena_clear(mem_arena_edgenet);
 		}
+
+		BLI_memarena_free(mem_arena_edgenet);
 	}
 #endif  /* USE_NET */
 	(void)totface_orig;




More information about the Bf-blender-cvs mailing list