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.
This commit is contained in:
parent
f533a70a4b
commit
ee03a99695
@ -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 );
|
||||
|
@ -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-- ) {
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user