Commit: dc02d5439bdb32fffce519030f34816938320252 Author: Joseph Eagar Date: Thu Sep 24 22:06:43 2020 -0700 Branches: temp-trimesh-sculpt https://developer.blender.org/rBdc02d5439bdb32fffce519030f34816938320252
add trimesh and thread safe mempool code =================================================================== A source/blender/blenlib/BLI_threadsafe_mempool.h A source/blender/blenlib/BLI_trimesh.h M source/blender/blenlib/CMakeLists.txt A source/blender/blenlib/intern/BLI_threadsafe_mempool.c A source/blender/blenlib/intern/BLI_trimesh.c =================================================================== diff --git a/source/blender/blenlib/BLI_threadsafe_mempool.h b/source/blender/blenlib/BLI_threadsafe_mempool.h new file mode 100644 index 00000000000..e900651856b --- /dev/null +++ b/source/blender/blenlib/BLI_threadsafe_mempool.h @@ -0,0 +1,47 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2008 Blender Foundation. + * All rights reserved. + */ +#ifndef _BLI_THREADSAFE_MEMPOOL_H +#define _BLI_THREADSAFE_MEMPOOL_H + +struct BLI_ThreadSafePool; +typedef struct BLI_ThreadSafePool BLI_ThreadSafePool; + +struct BLI_ThreadSafePool* BLI_safepool_create(int elemsize, int chunksize, int maxthread); +void* BLI_safepool_alloc(struct BLI_ThreadSafePool *pool, int threadnr); + +void BLI_safepool_free(struct BLI_ThreadSafePool*pool, void *elem); +bool BLI_safepool_is_dead(struct BLI_ThreadSafePool *pool, void *elem); + +void BLI_safepool_threaded_free(struct BLI_ThreadSafePool*pool, void *elem, int threadnr); +int BLI_safepool_length(struct BLI_ThreadSafePool*pool); +void BLI_safepool_destroy(struct BLI_ThreadSafePool* pool); + +typedef struct ThreadSafePoolIter { + struct BLI_ThreadSafePool* pool; + int thread; + void *chunk; + int i; +} ThreadSafePoolIter; + +void BLI_safepool_iternew(struct BLI_ThreadSafePool* pool, ThreadSafePoolIter* iter); +void BLI_safepool_iterfree(ThreadSafePoolIter* iter); +void* BLI_safepool_iterstep(ThreadSafePoolIter* iter); +void BLI_safepool_threaded_free(struct BLI_ThreadSafePool* pool, void* elem, int thread); + +#endif /* _BLI_THREADSAFE_MEMPOOL_H */ diff --git a/source/blender/blenlib/BLI_trimesh.h b/source/blender/blenlib/BLI_trimesh.h new file mode 100644 index 00000000000..9c84155e8a7 --- /dev/null +++ b/source/blender/blenlib/BLI_trimesh.h @@ -0,0 +1,107 @@ +//optimized thread-safe triangle mesh library with topological info + +#include "BLI_threads.h" +#include "BLI_threadsafe_mempool.h" + + +struct OptTriVert; +struct OptTriEdge; +struct OptTri; + +#define OPTELEM_HEAD(type) struct type *next, *prev; int threadtag; + +typedef struct OptElem { + OPTELEM_HEAD(OptElem) +} OptElem; + +typedef struct optmesh_simplelist { + void **items; + int _size, length; + bool is_pool_allocd; +} optmesh_simplelist; + +typedef struct OptTriVert { + OPTELEM_HEAD(OptTriVert) + float co[3]; + float no[3]; + + optmesh_simplelist edges; +} OptTriVert; + +typedef struct OptTriEdge { + OPTELEM_HEAD(OptTriEdge) + OptTriVert *v1, *v2; + optmesh_simplelist tris; +} OptTriEdge; + +typedef struct OptTri { + OPTELEM_HEAD(OptTri) + + OptTriVert *v1, *v2, *v3; + OptTriEdge *e1, *e2, *e3; + + float no[3]; +} OptTri; + +typedef struct OptTriIsland { + OptTri **tris; + int tottri; + OptTriVert **verts; + int totvert; + int tag; +} OptTriIsland; + +struct BLI_ThreadSafePool; + +#define MAX_TRIMESH_POOLS 5 + +typedef struct OptTriMesh { + struct BLI_ThreadSafePool* pools[MAX_TRIMESH_POOLS]; + + int totvert, tottri, totedge; + int maxthread; + SpinLock global_lock; +} OptTriMesh; + +typedef struct OptTriMeshIter { + int pool; + ThreadSafePoolIter iter; +} OptTriMeshIter; + +#define TRIMESH_NEED_TAG -1 +#define TRIMESH_BOUNDARY -2 +#define TRIMESH_BOUNDARY_TEMP -3 +#define TRIMESH_TAG_CLEAR -4 + +#define TRIMESH_VERT 1 +#define TRIMESH_EDGE 2 +#define TRIMESH_TRI 4 + +OptTriMesh* BLI_trimesh_new(int maxthread); +void BLI_trimesh_free(OptTriMesh *tm); +void BLI_trimesh_vert_iternew(OptTriMesh *tm, OptTriMeshIter* iter); +void BLI_trimesh_edge_iternew(OptTriMesh *tm, OptTriMeshIter* iter); +void BLI_trimesh_tri_iternew(OptTriMesh *tm, OptTriMeshIter* iter); +void BLI_trimesh_iterstep(OptTriMeshIter* iter); +void BLI_trimesh_add(OptTriMesh *tm, float* vertCos, float* vertNos, int totvert, int* triIndices, int tottri, int threadnr); + +void BLI_trimesh_kill_edge(OptTriMesh *tm, OptTriEdge *e, int threadnr, bool kill_verts); +void BLI_trimesh_kill_vert(OptTriMesh *tm, OptTriVert *v, int threadnr); +void BLI_trimesh_kill_tri(OptTriMesh *tm, OptTri *tri, int threadnr, bool kill_edges, bool kill_verts); + +//primary interface to run threaded jobs +typedef void (*OptTriMeshJob)(OptTriMesh *tm, void **elements, int totelem, int threadnr, void *userdata); +void BLI_trimesh_foreach_tris(OptTriMesh *tm, OptTri **tris, int tottri, OptTriMeshJob job, int maxthread, void *userdata); + +//yes, the input is an array of triangles, even though the jobs are fed vertices. +void BLI_trimesh_foreach_verts(OptTriMesh *tm, OptTri **tris, int tottri, OptTriMeshJob job, int maxthread, void *userdata); + +//low-level api functions used by BLI_trimesh_foreach_XXX +//if tottris is -1 then all triangles will be tagged +void BLI_trimesh_thread_tag(OptTriMesh *tm, OptTri** tris, int tottri); +void BLI_trimesh_clear_threadtags(OptTriMesh *tm); +void BLI_trimesh_tag_thread_boundaries(OptTriMesh *tm, OptTri **tris, int tottri); + +//called after BLI_trimesh_thread_tag +//last island is always boundary triangles +void BLI_trimesh_build_islands(OptTriMesh *tm, OptTri **tris, int tottri, OptTriIsland** r_islands, int *r_totisland); diff --git a/source/blender/blenlib/CMakeLists.txt b/source/blender/blenlib/CMakeLists.txt index 5f5145cab70..61cfd78f966 100644 --- a/source/blender/blenlib/CMakeLists.txt +++ b/source/blender/blenlib/CMakeLists.txt @@ -40,6 +40,7 @@ set(SRC intern/BLI_dial_2d.c intern/BLI_dynstr.c intern/BLI_filelist.c + intern/BLI_trimesh.c intern/BLI_ghash.c intern/BLI_ghash_utils.c intern/BLI_heap.c @@ -50,6 +51,7 @@ set(SRC intern/BLI_linklist_lockfree.c intern/BLI_memarena.c intern/BLI_memblock.c + intern/BLI_threadsafe_mempool.c intern/BLI_memiter.c intern/BLI_mempool.c intern/BLI_timer.c diff --git a/source/blender/blenlib/intern/BLI_threadsafe_mempool.c b/source/blender/blenlib/intern/BLI_threadsafe_mempool.c new file mode 100644 index 00000000000..88787cf12d8 --- /dev/null +++ b/source/blender/blenlib/intern/BLI_threadsafe_mempool.c @@ -0,0 +1,313 @@ +#include <stdio.h> +#include <string.h> +#include <stdint.h> + +#include "BLI_threadsafe_mempool.h" +#include "BLI_threads.h" +#include "BLI_utildefines.h" +#include "MEM_guardedalloc.h" +#include "atomic_ops.h" +#include "BLI_listbase.h" + +#define POOL_CHUNK_MAGIC ('p' | ('o' << 8) | ('o' << 16) | ('l' || 24)) +#define DEAD_MAGIC ('d' | ('e' << 8) | ('a' << 16) | ('d' || 24)) + +//#define BLI_SAFEPOOL_HAVE_LENGTH + +//keep eight-byte aligned! +typedef struct poolchunk { + struct poolchunk* next, * prev; + unsigned int threadnr, magic; +} poolchunk; + +typedef struct deadelem { + struct deadelem *next; + int dead_magic; +} deadelem; + +typedef struct pool_thread_data { + ListBase chunks; + void* freehead; + SpinLock lock; + unsigned int used; +} pool_thread_data; + +typedef struct BLI_ThreadSafePool { + pool_thread_data* threadchunks; + int maxthread; + SpinLock global_lock; + +#ifdef BLI_SAFEPOOL_HAVE_LENGTH + unsigned int length; +#endif + size_t esize, csize; +} BLI_ThreadSafePool; + +static int getalign(int size) { + if (size & 15) { + return size + (16 - (size & 15)); + } + + return size; +} + +static size_t get_chunk_size(BLI_ThreadSafePool* pool) { + return getalign(sizeof(pool_thread_data) + pool->esize*pool->csize); +} + +static poolchunk* get_chunk_from_elem(BLI_ThreadSafePool *pool, void* elem) { + uintptr_t addr = (uintptr_t) elem; + uintptr_t size = get_chunk_size(pool); + + if (!elem) { + return NULL; + } + + addr = addr - (addr % size); + + poolchunk *chunk = (poolchunk*)addr; + + if (chunk->magic != POOL_CHUNK_MAGIC) { + return NULL; + } + + return chunk; +} + +static poolchunk *new_chunk(BLI_ThreadSafePool *pool, pool_thread_data* thread_data) { + size_t size = get_chunk_size(pool); + size_t esize = pool->esize; + + //align size? + /* + if (size & 7) { + size += 8 - (size & 7); + };*/ + + poolchunk* chunk = MEM_mallocN_aligned(size, getalign(size), "safepool chunk"); + + chunk->magic = POOL_CHUNK_MAGIC; + chunk->threadnr = thread_data - pool->threadchunks; + + BLI_addtail(&thread_data->chunks, chunk); + deadelem *first = NULL; + + for (size_t i = 0; i < pool->csize-1; i++) { + deadelem *de = (deadelem*)(((char*)chunk) + sizeof(poolchunk) + esize*i); + + if (i == 0) { + first = de; + } + + de->next = de + 1; + de->dead_magic = DEAD_MAGIC; + } + + deadelem *de = (deadelem*)(((char*)chunk) + sizeof(poolchunk) + esize*(pool->csize-1)); + de->next = thread_data->freehead; + de->dead_magic = DEAD_MAGIC; + + thread_data->freehead = first; + + return chunk; +} + +BLI_ThreadSafePool* BLI_safepool_create(int elemsize, int chunksize, int maxthread) { + BLI_ThreadSafePool* pool = MEM_callocN(sizeof(*pool), "BLI_ThreadSafePool"); + + elemsize = MAX2(elemsize, sizeof(void*)*2); + + pool->maxthread = maxthread; + pool->threadchunks = MEM_callocN(sizeof(pool_thread_data) * maxthread, "pool->threadchunks"); + pool->esize = elemsize; + pool->csize = chunksize; + + BLI_spin_init(&pool->global_lock); + + for (int i = 0; i < maxthread; i++) { + BLI_spin_init(&pool->threadchunks[i].lock); + new_chunk(pool, pool->threadchunks); + } + + return pool; +} + +bool BLI_safepool_elem_is_dead(BLI_ThreadSafePool *pool, void *elem) { + deadelem *de = (deadelem*)elem; + + return de->dead_magic == DEAD_MAGIC; +} + +void BLI_safepool_destroy(BLI_ThreadSafePool* pool) { + poolchunk* chunk; + int i; + + //wait for all threads to end? + //BLI_spin_lock(&pool->global_lock); + //BLI_spin_unlock(&pool->global_lock); + + for (i = 0; i < pool->maxthread; i++) { + B @@ Diff output truncated at 10240 characters. @@ _______________________________________________ Bf-blender-cvs mailing list Bf-blender-cvs@blender.org https://lists.blender.org/mailman/listinfo/bf-blender-cvs