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
path: root/source
diff options
context:
space:
mode:
authorBrecht Van Lommel <brecht@blender.org>2020-07-01 15:55:43 +0300
committerJeroen Bakker <j.bakker@atmind.nl>2020-07-13 18:13:17 +0300
commit9949b5098ae80ed5bc47b01e1d644d8eadaac3bc (patch)
tree022b0b75b968cb8040051da4f6e6d3c0ca475438 /source
parent52be97a91b38d1f93a366382e876cfe9a329be58 (diff)
Fix missing GPU image free in background mode
This is legacy code from before Eevee and Workbench rendering in background mode was supported. Avoid memory leak by only queueing GPU textures to be freed when we know they have been allocated. Differential Revision: https://developer.blender.org/D8172
Diffstat (limited to 'source')
-rw-r--r--source/blender/blenkernel/intern/image.c8
-rw-r--r--source/blender/gpu/GPU_draw.h2
-rw-r--r--source/blender/gpu/intern/gpu_draw.c73
-rw-r--r--source/blender/windowmanager/intern/wm_draw.c2
-rw-r--r--source/blender/windowmanager/intern/wm_init_exit.c2
5 files changed, 44 insertions, 43 deletions
diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c
index 906d76dfed8..9ce0bf90984 100644
--- a/source/blender/blenkernel/intern/image.c
+++ b/source/blender/blenkernel/intern/image.c
@@ -359,13 +359,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 f521fa3c702..232ec43b306 100644
--- a/source/blender/gpu/GPU_draw.h
+++ b/source/blender/gpu/GPU_draw.h
@@ -93,7 +93,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 5f3822c794e..63700dcfe9e 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
@@ -867,9 +868,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;
}
@@ -1364,47 +1369,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;
}
}
@@ -1413,14 +1418,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 bf30d7a3328..e1df2cbc039 100644
--- a/source/blender/windowmanager/intern/wm_draw.c
+++ b/source/blender/windowmanager/intern/wm_draw.c
@@ -987,7 +987,7 @@ void wm_draw_update(bContext *C)
BKE_subsurf_free_unused_buffers();
#endif
- 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 17d697840a0..66317770722 100644
--- a/source/blender/windowmanager/intern/wm_init_exit.c
+++ b/source/blender/windowmanager/intern/wm_init_exit.c
@@ -580,7 +580,7 @@ void WM_exit_ex(bContext *C, const bool do_python)
BKE_subsurf_osd_cleanup();
#endif
- GPU_free_unused_buffers(G_MAIN);
+ GPU_free_unused_buffers();
}
BKE_blender_free(); /* blender.c, does entire library and spacetypes */