[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [30268] trunk/blender/source/blender/gpu: Fix #20461: deleting VBO's from threads used for rendering or baking would

Brecht Van Lommel brecht at blender.org
Tue Jul 13 15:31:44 CEST 2010


Revision: 30268
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=30268
Author:   blendix
Date:     2010-07-13 15:31:43 +0200 (Tue, 13 Jul 2010)

Log Message:
-----------
Fix #20461: deleting VBO's from threads used for rendering or baking would
crash, as OpenGL can't be called from these. Now deleting VBO's is delayed
until the next redraw in the main thread.

Modified Paths:
--------------
    trunk/blender/source/blender/gpu/gpu_buffers.h
    trunk/blender/source/blender/gpu/intern/gpu_buffers.c
    trunk/blender/source/blender/gpu/intern/gpu_draw.c

Modified: trunk/blender/source/blender/gpu/gpu_buffers.h
===================================================================
--- trunk/blender/source/blender/gpu/gpu_buffers.h	2010-07-13 12:54:25 UTC (rev 30267)
+++ trunk/blender/source/blender/gpu/gpu_buffers.h	2010-07-13 13:31:43 UTC (rev 30268)
@@ -69,8 +69,9 @@
 
 typedef struct GPUBufferPool
 {
-	int size;	/* number of allocated buffers stored */
-	GPUBuffer* buffers[MAX_FREE_GPU_BUFFERS];
+	int size;		/* number of allocated buffers stored */
+	int maxsize;	/* size of the array */
+	GPUBuffer **buffers;
 } GPUBufferPool;
 
 typedef struct GPUBufferMaterial
@@ -119,7 +120,8 @@
 } GPUAttrib;
 
 GPUBufferPool *GPU_buffer_pool_new();
-void GPU_buffer_pool_free( GPUBufferPool *pool );	/* TODO: Find a place where to call this function on exit */
+void GPU_buffer_pool_free( GPUBufferPool *pool );
+void GPU_buffer_pool_free_unused( GPUBufferPool *pool );
 
 GPUBuffer *GPU_buffer_alloc( int size, GPUBufferPool *pool );
 void GPU_buffer_free( GPUBuffer *buffer, GPUBufferPool *pool );

Modified: trunk/blender/source/blender/gpu/intern/gpu_buffers.c
===================================================================
--- trunk/blender/source/blender/gpu/intern/gpu_buffers.c	2010-07-13 12:54:25 UTC (rev 30267)
+++ trunk/blender/source/blender/gpu/intern/gpu_buffers.c	2010-07-13 13:31:43 UTC (rev 30268)
@@ -38,8 +38,9 @@
 
 #include "MEM_guardedalloc.h"
 
+#include "BLI_ghash.h"
 #include "BLI_math.h"
-#include "BLI_ghash.h"
+#include "BLI_threads.h"
 
 #include "DNA_meshdata_types.h"
 
@@ -82,37 +83,12 @@
 	}
 
 	pool = MEM_callocN(sizeof(GPUBufferPool), "GPU_buffer_pool_new");
+	pool->maxsize = MAX_FREE_GPU_BUFFERS;
+	pool->buffers = MEM_callocN(sizeof(GPUBuffer*)*pool->maxsize, "GPU_buffer_pool_new buffers");
 
 	return pool;
 }
 
-void GPU_buffer_pool_free(GPUBufferPool *pool)
-{
-	int i;
-
-	DEBUG_VBO("GPU_buffer_pool_free\n");
-
-	if( pool == 0 )
-		pool = globalPool;
-	if( pool == 0 )
-		return;
-
-	for( i = 0; i < pool->size; i++ ) {
-		if( pool->buffers[i] != 0 ) {
-			if( useVBOs ) {
-				glDeleteBuffersARB( 1, &pool->buffers[i]->id );
-			}
-			else {
-				MEM_freeN( pool->buffers[i]->pointer );
-			}
-			MEM_freeN(pool->buffers[i]);
-		} else {
-			ERROR_VBO("Why are we accessing a null buffer in GPU_buffer_pool_free?\n");
-		}
-	}
-	MEM_freeN(pool);
-}
-
 void GPU_buffer_pool_remove( int index, GPUBufferPool *pool )
 {
 	int i;
@@ -159,6 +135,35 @@
 	pool->size--;
 }
 
+void GPU_buffer_pool_free(GPUBufferPool *pool)
+{
+	DEBUG_VBO("GPU_buffer_pool_free\n");
+
+	if( pool == 0 )
+		pool = globalPool;
+	if( pool == 0 )
+		return;
+	
+	while( pool->size )
+		GPU_buffer_pool_delete_last(pool);
+
+	MEM_freeN(pool->buffers);
+	MEM_freeN(pool);
+}
+
+void GPU_buffer_pool_free_unused(GPUBufferPool *pool)
+{
+	DEBUG_VBO("GPU_buffer_pool_free_unused\n");
+
+	if( pool == 0 )
+		pool = globalPool;
+	if( pool == 0 )
+		return;
+	
+	while( pool->size > MAX_FREE_GPU_BUFFERS )
+		GPU_buffer_pool_delete_last(pool);
+}
+
 GPUBuffer *GPU_buffer_alloc( int size, GPUBufferPool *pool )
 {
 	char buffer[60];
@@ -226,6 +231,7 @@
 void GPU_buffer_free( GPUBuffer *buffer, GPUBufferPool *pool )
 {
 	int i;
+
 	DEBUG_VBO("GPU_buffer_free\n");
 
 	if( buffer == 0 )
@@ -235,10 +241,20 @@
 	if( pool == 0 )
 		globalPool = GPU_buffer_pool_new();
 
-	/* free the last used buffer in the queue if no more space */
-	if( pool->size == MAX_FREE_GPU_BUFFERS ) {
-		GPU_buffer_pool_delete_last( pool );
+	/* free the last used buffer in the queue if no more space, but only
+	   if we are in the main thread. for e.g. rendering or baking it can
+	   happen that we are in other thread and can't call OpenGL, in that
+	   case cleanup will be done GPU_buffer_pool_free_unused */
+	if( BLI_thread_is_main() ) {
+		while( pool->size >= MAX_FREE_GPU_BUFFERS )
+			GPU_buffer_pool_delete_last( pool );
 	}
+	else {
+		if( pool->maxsize == pool->size ) {
+			pool->maxsize += MAX_FREE_GPU_BUFFERS;
+			pool->buffers = MEM_reallocN(pool->buffers, sizeof(GPUBuffer*)*pool->maxsize);
+		}
+	}
 
 	for( i =pool->size; i > 0; i-- ) {
 		pool->buffers[i] = pool->buffers[i-1];

Modified: trunk/blender/source/blender/gpu/intern/gpu_draw.c
===================================================================
--- trunk/blender/source/blender/gpu/intern/gpu_draw.c	2010-07-13 12:54:25 UTC (rev 30267)
+++ trunk/blender/source/blender/gpu/intern/gpu_draw.c	2010-07-13 13:31:43 UTC (rev 30268)
@@ -804,11 +804,15 @@
 
 	BLI_lock_thread(LOCK_OPENGL);
 
+	/* images */
 	for(ima=image_free_queue.first; ima; ima=ima->id.next)
 		GPU_free_image(ima);
 
 	BLI_freelistN(&image_free_queue);
 
+	/* vbo buffers */
+	GPU_buffer_pool_free_unused(0);
+
 	BLI_unlock_thread(LOCK_OPENGL);
 }
 





More information about the Bf-blender-cvs mailing list