Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrecht Van Lommel <brechtvanlommel@pandora.be>2010-07-13 17:31:43 +0400
committerBrecht Van Lommel <brechtvanlommel@pandora.be>2010-07-13 17:31:43 +0400
commitee03a99695a2eaff6dbc323dcabb44e759f64099 (patch)
treeab2affce3c6ee9f00bec7c9396daf55d4df615cb /source/blender/gpu
parentf533a70a4b80e0e347dc8284382c0d13359f4bb8 (diff)
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.
Diffstat (limited to 'source/blender/gpu')
-rw-r--r--source/blender/gpu/gpu_buffers.h8
-rw-r--r--source/blender/gpu/intern/gpu_buffers.c78
-rw-r--r--source/blender/gpu/intern/gpu_draw.c4
3 files changed, 56 insertions, 34 deletions
diff --git a/source/blender/gpu/gpu_buffers.h b/source/blender/gpu/gpu_buffers.h
index 98cefa7a696..983133a6d4b 100644
--- a/source/blender/gpu/gpu_buffers.h
+++ b/source/blender/gpu/gpu_buffers.h
@@ -69,8 +69,9 @@ typedef struct GPUBuffer
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 @@ typedef struct GPUAttrib
} 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 );
diff --git a/source/blender/gpu/intern/gpu_buffers.c b/source/blender/gpu/intern/gpu_buffers.c
index 1d615c8e67b..e0a47c0c5bc 100644
--- a/source/blender/gpu/intern/gpu_buffers.c
+++ b/source/blender/gpu/intern/gpu_buffers.c
@@ -38,8 +38,9 @@
#include "MEM_guardedalloc.h"
-#include "BLI_math.h"
#include "BLI_ghash.h"
+#include "BLI_math.h"
+#include "BLI_threads.h"
#include "DNA_meshdata_types.h"
@@ -82,37 +83,12 @@ GPUBufferPool *GPU_buffer_pool_new()
}
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 @@ void GPU_buffer_pool_delete_last( GPUBufferPool *pool )
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 @@ GPUBuffer *GPU_buffer_alloc( int size, GPUBufferPool *pool )
void GPU_buffer_free( GPUBuffer *buffer, GPUBufferPool *pool )
{
int i;
+
DEBUG_VBO("GPU_buffer_free\n");
if( buffer == 0 )
@@ -235,9 +241,19 @@ void GPU_buffer_free( GPUBuffer *buffer, GPUBufferPool *pool )
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-- ) {
diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c
index 9a5a6704428..506ce94b763 100644
--- a/source/blender/gpu/intern/gpu_draw.c
+++ b/source/blender/gpu/intern/gpu_draw.c
@@ -804,11 +804,15 @@ void GPU_free_unused_buffers(void)
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);
}