diff options
-rw-r--r-- | source/blender/blenkernel/intern/image.c | 8 | ||||
-rw-r--r-- | source/blender/gpu/GPU_draw.h | 2 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_draw.c | 73 | ||||
-rw-r--r-- | source/blender/windowmanager/intern/wm_draw.c | 2 | ||||
-rw-r--r-- | source/blender/windowmanager/intern/wm_init_exit.c | 2 |
5 files changed, 44 insertions, 43 deletions
diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index 24d175511c7..bb793b58a1d 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -360,13 +360,7 @@ void BKE_image_free_buffers_ex(Image *ima, bool do_lock) ima->rr = NULL; } - if (!G.background) { - /* Background mode doesn't use OpenGL, - * so we can avoid freeing GPU images and save some - * time by skipping mutex lock. - */ - GPU_free_image(ima); - } + GPU_free_image(ima); LISTBASE_FOREACH (ImageTile *, tile, &ima->tiles) { tile->ok = IMA_OK; diff --git a/source/blender/gpu/GPU_draw.h b/source/blender/gpu/GPU_draw.h index ab507d852e8..1cd5c4d519e 100644 --- a/source/blender/gpu/GPU_draw.h +++ b/source/blender/gpu/GPU_draw.h @@ -86,7 +86,7 @@ void GPU_create_smoke_coba_field(struct FluidModifierData *mmd); void GPU_create_smoke_velocity(struct FluidModifierData *mmd); /* Delayed free of OpenGL buffers by main thread */ -void GPU_free_unused_buffers(struct Main *bmain); +void GPU_free_unused_buffers(void); #ifdef __cplusplus } diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c index d768ce373b6..f07e3ed70d7 100644 --- a/source/blender/gpu/intern/gpu_draw.c +++ b/source/blender/gpu/intern/gpu_draw.c @@ -60,7 +60,8 @@ #include "PIL_time.h" -static void gpu_free_image_immediate(Image *ima); +static void gpu_free_image(Image *ima, const bool immediate); +static void gpu_free_unused_buffers(void); //* Checking powers of two for images since OpenGL ES requires it */ #ifdef WITH_DDS @@ -859,9 +860,13 @@ GPUTexture *GPU_texture_from_blender(Image *ima, ImageUser *iuser, ImBuf *ibuf, return NULL; } + /* Free any unused GPU textures, since we know we are in a thread with OpenGL + * context and might as well ensure we have as much space free as possible. */ + gpu_free_unused_buffers(); + /* currently, gpu refresh tagging is used by ima sequences */ if (ima->gpuflag & IMA_GPU_REFRESH) { - gpu_free_image_immediate(ima); + gpu_free_image(ima, true); ima->gpuflag &= ~IMA_GPU_REFRESH; } @@ -1338,47 +1343,47 @@ void GPU_paint_update_image(Image *ima, ImageUser *iuser, int x, int y, int w, i #endif } -static LinkNode *image_free_queue = NULL; -static ThreadMutex img_queue_mutex = BLI_MUTEX_INITIALIZER; +/* Delayed GPU texture free. Image datablocks can be deleted by any thread, + * but there may not be any active OpenGL context. In that case we push them + * into a queue and free the buffers later. */ +static LinkNode *gpu_texture_free_queue = NULL; +static ThreadMutex gpu_texture_queue_mutex = BLI_MUTEX_INITIALIZER; -static void gpu_queue_image_for_free(Image *ima) +static void gpu_free_unused_buffers() { - BLI_mutex_lock(&img_queue_mutex); - BLI_linklist_prepend(&image_free_queue, ima); - BLI_mutex_unlock(&img_queue_mutex); -} - -void GPU_free_unused_buffers(Main *bmain) -{ - if (!BLI_thread_is_main()) { + if (gpu_texture_free_queue == NULL) { return; } - BLI_mutex_lock(&img_queue_mutex); - - /* images */ - for (LinkNode *node = image_free_queue; node; node = node->next) { - Image *ima = node->link; + BLI_mutex_lock(&gpu_texture_queue_mutex); - /* check in case it was freed in the meantime */ - if (bmain && BLI_findindex(&bmain->images, ima) != -1) { - GPU_free_image(ima); + if (gpu_texture_free_queue != NULL) { + for (LinkNode *node = gpu_texture_free_queue; node; node = node->next) { + GPUTexture *tex = node->link; + GPU_texture_free(tex); } - } - BLI_linklist_free(image_free_queue, NULL); - image_free_queue = NULL; + BLI_linklist_free(gpu_texture_free_queue, NULL); + gpu_texture_free_queue = NULL; + } - BLI_mutex_unlock(&img_queue_mutex); + BLI_mutex_unlock(&gpu_texture_queue_mutex); } -static void gpu_free_image_immediate(Image *ima) +static void gpu_free_image(Image *ima, const bool immediate) { for (int eye = 0; eye < 2; eye++) { for (int i = 0; i < TEXTARGET_COUNT; i++) { - /* free glsl image binding */ if (ima->gputexture[i][eye] != NULL) { - GPU_texture_free(ima->gputexture[i][eye]); + if (immediate) { + GPU_texture_free(ima->gputexture[i][eye]); + } + else { + BLI_mutex_lock(&gpu_texture_queue_mutex); + BLI_linklist_prepend(&gpu_texture_free_queue, ima->gputexture[i][eye]); + BLI_mutex_unlock(&gpu_texture_queue_mutex); + } + ima->gputexture[i][eye] = NULL; } } @@ -1387,14 +1392,16 @@ static void gpu_free_image_immediate(Image *ima) ima->gpuflag &= ~IMA_GPU_MIPMAP_COMPLETE; } -void GPU_free_image(Image *ima) +void GPU_free_unused_buffers() { - if (!BLI_thread_is_main()) { - gpu_queue_image_for_free(ima); - return; + if (BLI_thread_is_main()) { + gpu_free_unused_buffers(); } +} - gpu_free_image_immediate(ima); +void GPU_free_image(Image *ima) +{ + gpu_free_image(ima, BLI_thread_is_main()); } void GPU_free_images(Main *bmain) diff --git a/source/blender/windowmanager/intern/wm_draw.c b/source/blender/windowmanager/intern/wm_draw.c index 6a19ce62f50..3c2bc14837d 100644 --- a/source/blender/windowmanager/intern/wm_draw.c +++ b/source/blender/windowmanager/intern/wm_draw.c @@ -1012,7 +1012,7 @@ void wm_draw_update(bContext *C) wmWindowManager *wm = CTX_wm_manager(C); wmWindow *win; - GPU_free_unused_buffers(bmain); + GPU_free_unused_buffers(); for (win = wm->windows.first; win; win = win->next) { #ifdef WIN32 diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c index e0d2127ba51..cb5a039765a 100644 --- a/source/blender/windowmanager/intern/wm_init_exit.c +++ b/source/blender/windowmanager/intern/wm_init_exit.c @@ -578,7 +578,7 @@ void WM_exit_ex(bContext *C, const bool do_python) BKE_subdiv_exit(); if (opengl_is_init) { - GPU_free_unused_buffers(G_MAIN); + GPU_free_unused_buffers(); } BKE_blender_free(); /* blender.c, does entire library and spacetypes */ |