diff options
author | Joseph Eagar <joeedh@gmail.com> | 2010-04-13 16:51:03 +0400 |
---|---|---|
committer | Joseph Eagar <joeedh@gmail.com> | 2010-04-13 16:51:03 +0400 |
commit | 86aa4e5c3d7e0b95d9e55bab027f968b42a3eda6 (patch) | |
tree | 9208dfc29a7f163ea7af988ad663cfc7c78d2ae1 | |
parent | e50f7986476a2fe5604d78db6dea784384d3e38f (diff) |
prevent images from freeing gpu buffers if not run within the main thread, instead they are queued to be freed the next time GPU_image_free() is run from the main thread.
-rw-r--r-- | source/blender/blenlib/BLI_threads.h | 4 | ||||
-rw-r--r-- | source/blender/blenlib/intern/threads.c | 15 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_draw.c | 37 | ||||
-rw-r--r-- | source/creator/creator.c | 3 |
4 files changed, 58 insertions, 1 deletions
diff --git a/source/blender/blenlib/BLI_threads.h b/source/blender/blenlib/BLI_threads.h index eda0e830736..e3290873dc3 100644 --- a/source/blender/blenlib/BLI_threads.h +++ b/source/blender/blenlib/BLI_threads.h @@ -40,6 +40,9 @@ struct ListBase; /* Threading API */ +/*this is run once at startup*/ +void BLI_threadapi_init(void); + void BLI_init_threads (struct ListBase *threadbase, void *(*do_thread)(void *), int tot); int BLI_available_threads(struct ListBase *threadbase); int BLI_available_thread_index(struct ListBase *threadbase); @@ -48,6 +51,7 @@ void BLI_remove_thread (struct ListBase *threadbase, void *callerdata); void BLI_remove_thread_index(struct ListBase *threadbase, int index); void BLI_remove_threads(struct ListBase *threadbase); void BLI_end_threads (struct ListBase *threadbase); +int BLI_thread_is_main(void); /* System Information */ diff --git a/source/blender/blenlib/intern/threads.c b/source/blender/blenlib/intern/threads.c index 351e0be1102..6e2eff6f97a 100644 --- a/source/blender/blenlib/intern/threads.c +++ b/source/blender/blenlib/intern/threads.c @@ -106,6 +106,7 @@ static pthread_mutex_t _image_lock = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t _preview_lock = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t _viewer_lock = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t _custom1_lock = PTHREAD_MUTEX_INITIALIZER; +static pthread_t mainid; static int thread_levels= 0; /* threads can be invoked inside threads */ /* just a max for security reasons */ @@ -129,6 +130,11 @@ static void BLI_unlock_malloc_thread(void) pthread_mutex_unlock(&_malloc_lock); } +void BLI_threadapi_init(void) +{ + mainid = pthread_self(); +} + /* tot = 0 only initializes malloc mutex in a safe way (see sequence.c) problem otherwise: scene render will kill of the mutex! */ @@ -136,7 +142,7 @@ static void BLI_unlock_malloc_thread(void) void BLI_init_threads(ListBase *threadbase, void *(*do_thread)(void *), int tot) { int a; - + if(threadbase != NULL && tot > 0) { threadbase->first= threadbase->last= NULL; @@ -204,6 +210,13 @@ static void *tslot_thread_start(void *tslot_p) return tslot->do_thread(tslot->callerdata); } +int BLI_thread_is_main(void) { + pthread_t tid; + tid = pthread_self(); + + return !memcmp(&tid, &mainid, sizeof(pthread_t)); +} + void BLI_insert_thread(ListBase *threadbase, void *callerdata) { ThreadSlot *tslot; diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c index d3a4621c793..652902e3035 100644 --- a/source/blender/gpu/intern/gpu_draw.c +++ b/source/blender/gpu/intern/gpu_draw.c @@ -62,6 +62,9 @@ #include "BKE_object.h" #include "BKE_utildefines.h" +#include "BLI_threads.h" +#include "BLI_blenlib.h" + #include "GPU_extensions.h" #include "GPU_material.h" #include "GPU_draw.h" @@ -781,8 +784,42 @@ void GPU_create_smoke(SmokeModifierData *smd, int highres) smd->domain->tex_shadow = GPU_texture_create_3D(smd->domain->res[0], smd->domain->res[1], smd->domain->res[2], smd->domain->shadow); } +ListBase image_free_queue = {NULL, NULL}; +static void flush_queued_free(void) +{ + Image *ima, *imanext; + + BLI_lock_thread(LOCK_IMAGE); + + ima = image_free_queue.first; + image_free_queue.first = image_free_queue.last = NULL; + for (; ima; ima=imanext) { + imanext = (Image*)ima->id.next; + GPU_free_image(ima); + MEM_freeN(ima); + } + + BLI_unlock_thread(LOCK_IMAGE); +} + +static void queue_image_for_free(Image *ima) +{ + Image *cpy = MEM_dupallocN(ima); + + BLI_lock_thread(LOCK_IMAGE); + BLI_addtail(&image_free_queue, cpy); + BLI_unlock_thread(LOCK_IMAGE); +} + void GPU_free_image(Image *ima) { + if (!BLI_thread_is_main()) { + queue_image_for_free(ima); + return; + } else if (image_free_queue.first) { + flush_queued_free(); + } + /* free regular image binding */ if(ima->bindcode) { glDeleteTextures(1, (GLuint *)&ima->bindcode); diff --git a/source/creator/creator.c b/source/creator/creator.c index 46c0376c02a..68b99b20d01 100644 --- a/source/creator/creator.c +++ b/source/creator/creator.c @@ -50,6 +50,7 @@ #endif #include "BLI_args.h" +#include "BLI_threads.h" #include "GEN_messaging.h" @@ -964,6 +965,8 @@ int main(int argc, char **argv) strip_quotes(build_type); #endif + BLI_threadapi_init(); + RNA_init(); RE_engines_init(); |