[Bf-blender-cvs] [d9697bc] master: Fix T38024 crash when rebuilding sculpt mode buffers.

Antony Riakiotakis noreply at git.blender.org
Sun Jan 5 03:58:31 CET 2014


Commit: d9697bc1455dc556fd233aae9d45b523af62669b
Author: Antony Riakiotakis
Date:   Sun Jan 5 04:58:27 2014 +0200
https://developer.blender.org/rBd9697bc1455dc556fd233aae9d45b523af62669b

Fix T38024 crash when rebuilding sculpt mode buffers.

Main issue here is that glBuf* calls were invoked from threads different than
main thread. This caused a crash (since those do not have a GL context active).

Fix here is twofold:
* add an ID buffer in buffer pool that handles pbvh buffers and is freed
from main thread when gpu_buffer_pool_free_unused is called.

* do not create glbuffers in derivedmesh creation routine, rather tag nodes
for update and create those in the draw function
(guaranteed to be called from main thread)

Reviewed By: brecht

Differential Revision: https://developer.blender.org/D169

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

M	source/blender/blenkernel/intern/pbvh.c
M	source/blender/blenkernel/intern/pbvh_bmesh.c
M	source/blender/gpu/intern/gpu_buffers.c

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

diff --git a/source/blender/blenkernel/intern/pbvh.c b/source/blender/blenkernel/intern/pbvh.c
index 90447db..59bc9f9 100644
--- a/source/blender/blenkernel/intern/pbvh.c
+++ b/source/blender/blenkernel/intern/pbvh.c
@@ -330,15 +330,7 @@ static void build_mesh_leaf_node(PBVH *bvh, PBVHNode *node)
 		}
 	}
 
-	if (!G.background) {
-		node->draw_buffers =
-				GPU_build_pbvh_mesh_buffers(node->face_vert_indices,
-		                               bvh->faces, bvh->verts,
-		                               node->prim_indices,
-		                               node->totprim);
-	}
-
-	node->flag |= PBVH_UpdateDrawBuffers;
+	BKE_pbvh_node_mark_rebuild_draw(node);
 
 	BLI_ghash_free(map, NULL, NULL);
 }
diff --git a/source/blender/blenkernel/intern/pbvh_bmesh.c b/source/blender/blenkernel/intern/pbvh_bmesh.c
index 4bd2114..bfde9a9 100644
--- a/source/blender/blenkernel/intern/pbvh_bmesh.c
+++ b/source/blender/blenkernel/intern/pbvh_bmesh.c
@@ -91,12 +91,9 @@ static void pbvh_bmesh_node_finalize(PBVH *bvh, int node_index)
 
 	n->orig_vb = n->vb;
 
-	/* Build GPU buffers */
-	if (!G.background) {
-		int smooth = bvh->flags & PBVH_DYNTOPO_SMOOTH_SHADING;
-		n->draw_buffers = GPU_build_bmesh_pbvh_buffers(smooth);
-		n->flag |= PBVH_UpdateDrawBuffers | PBVH_UpdateNormals;
-	}
+	/* Build GPU buffers for new node and update vertex normals */
+	BKE_pbvh_node_mark_rebuild_draw(n);
+	n->flag |= PBVH_UpdateNormals;
 }
 
 /* Recursively split the node if it exceeds the leaf_limit */
diff --git a/source/blender/gpu/intern/gpu_buffers.c b/source/blender/gpu/intern/gpu_buffers.c
index 4a509b7..f6919e3 100644
--- a/source/blender/gpu/intern/gpu_buffers.c
+++ b/source/blender/gpu/intern/gpu_buffers.c
@@ -93,11 +93,15 @@ static ThreadMutex buffer_mutex = BLI_MUTEX_INITIALIZER;
 typedef struct GPUBufferPool {
 	/* number of allocated buffers stored */
 	int totbuf;
-	/* actual allocated length of the array */
+	int totpbvhbufids;
+	/* actual allocated length of the arrays */
 	int maxsize;
+	int maxpbvhsize;
 	GPUBuffer **buffers;
+	GLuint *pbvhbufids;
 } GPUBufferPool;
 #define MAX_FREE_GPU_BUFFERS 8
+#define MAX_FREE_GPU_BUFF_IDS 100
 
 /* create a new GPUBufferPool */
 static GPUBufferPool *gpu_buffer_pool_new(void)
@@ -111,9 +115,11 @@ static GPUBufferPool *gpu_buffer_pool_new(void)
 	pool = MEM_callocN(sizeof(GPUBufferPool), "GPUBuffer_Pool");
 
 	pool->maxsize = MAX_FREE_GPU_BUFFERS;
-	pool->buffers = MEM_callocN(sizeof(GPUBuffer *) * pool->maxsize,
-	                            "GPUBuffer.buffers");
-
+	pool->maxpbvhsize = MAX_FREE_GPU_BUFF_IDS;
+	pool->buffers = MEM_callocN(sizeof(*pool->buffers) * pool->maxsize,
+								"GPUBufferPool.buffers");
+	pool->pbvhbufids = MEM_callocN(sizeof(*pool->pbvhbufids) * pool->maxpbvhsize,
+								"GPUBufferPool.pbvhbuffers");
 	return pool;
 }
 
@@ -171,6 +177,7 @@ static void gpu_buffer_pool_free(GPUBufferPool *pool)
 		gpu_buffer_pool_delete_last(pool);
 
 	MEM_freeN(pool->buffers);
+	MEM_freeN(pool->pbvhbufids);
 	MEM_freeN(pool);
 }
 
@@ -181,6 +188,9 @@ static void gpu_buffer_pool_free_unused(GPUBufferPool *pool)
 	
 	while (pool->totbuf)
 		gpu_buffer_pool_delete_last(pool);
+
+	glDeleteBuffersARB(pool->totpbvhbufids, pool->pbvhbufids);
+	pool->totpbvhbufids = 0;
 }
 
 static GPUBufferPool *gpu_buffer_pool = NULL;
@@ -2492,13 +2502,50 @@ int GPU_pbvh_buffers_diffuse_changed(GPU_PBVH_Buffers *buffers, int show_diffuse
 	       diffuse_color[2] != buffers->diffuse_color[2];
 }
 
+/* release a GPU_PBVH_Buffers id;
+ *
+ * Thread-unsafe version for internal usage only.
+ */
+static void gpu_pbvh_buffer_free_intern(GLuint id)
+{
+	GPUBufferPool *pool;
+
+	/* zero id is vertex buffers off */
+	if (!id)
+		return;
+
+	pool = gpu_get_global_buffer_pool();
+
+	/* free the buffers immediately if we are on main thread */
+	if (BLI_thread_is_main()) {
+		glDeleteBuffersARB(1, &id);
+
+		if (pool->totpbvhbufids > 0) {
+			glDeleteBuffersARB(pool->totpbvhbufids, pool->pbvhbufids);
+			pool->totpbvhbufids = 0;
+		}
+		return;
+	}
+	/* outside of main thread, can't safely delete the
+	 * buffer, so increase pool size */
+	if (pool->maxpbvhsize == pool->totpbvhbufids) {
+		pool->maxpbvhsize += MAX_FREE_GPU_BUFF_IDS;
+		pool->pbvhbufids = MEM_reallocN(pool->pbvhbufids,
+										sizeof(*pool->pbvhbufids) * pool->maxpbvhsize);
+	}
+
+	/* insert the buffer into the beginning of the pool */
+	pool->pbvhbufids[pool->totpbvhbufids++] = id;
+}
+
+
 void GPU_free_pbvh_buffers(GPU_PBVH_Buffers *buffers)
 {
 	if (buffers) {
 		if (buffers->vert_buf)
-			glDeleteBuffersARB(1, &buffers->vert_buf);
+			gpu_pbvh_buffer_free_intern(buffers->vert_buf);
 		if (buffers->index_buf && (buffers->tot_tri || buffers->has_hidden))
-			glDeleteBuffersARB(1, &buffers->index_buf);
+			gpu_pbvh_buffer_free_intern(buffers->index_buf);
 
 		MEM_freeN(buffers);
 	}




More information about the Bf-blender-cvs mailing list