[Bf-blender-cvs] [9111ea78acf] master: Localize image mutex lock into runtime field of Image datablock
Sergey Sharybin
noreply at git.blender.org
Mon Nov 1 12:47:49 CET 2021
Commit: 9111ea78acf457c27655dbdd7e7fd9d221db67e0
Author: Sergey Sharybin
Date: Fri Oct 29 12:23:36 2021 +0200
Branches: master
https://developer.blender.org/rB9111ea78acf457c27655dbdd7e7fd9d221db67e0
Localize image mutex lock into runtime field of Image datablock
Allows to avoid a global lock being held while reading files from disk,
solving performance issues when Cycles needs to read a lot of packed
images.
Simple test file F11597666
Differential Revision: https://developer.blender.org/D13032
===================================================================
M source/blender/blenkernel/BKE_image.h
M source/blender/blenkernel/intern/blender.c
M source/blender/blenkernel/intern/image.c
M source/blender/blenloader/tests/blendfile_loading_base_test.cc
M source/blender/makesdna/DNA_image_types.h
M source/blender/windowmanager/intern/wm_playanim.c
M source/creator/creator.c
===================================================================
diff --git a/source/blender/blenkernel/BKE_image.h b/source/blender/blenkernel/BKE_image.h
index 82d1f299b4b..2d590ec668b 100644
--- a/source/blender/blenkernel/BKE_image.h
+++ b/source/blender/blenkernel/BKE_image.h
@@ -47,9 +47,6 @@ struct anim;
#define IMA_MAX_SPACE 64
#define IMA_UDIM_MAX 2000
-void BKE_images_init(void);
-void BKE_images_exit(void);
-
void BKE_image_free_packedfiles(struct Image *image);
void BKE_image_free_views(struct Image *image);
void BKE_image_free_buffers(struct Image *image);
diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c
index 97f8bddc043..fb65a9bec7e 100644
--- a/source/blender/blenkernel/intern/blender.c
+++ b/source/blender/blenkernel/intern/blender.c
@@ -90,7 +90,6 @@ void BKE_blender_free(void)
IMB_exit();
BKE_cachefiles_exit();
- BKE_images_exit();
DEG_free_node_types();
BKE_brush_system_exit();
diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c
index 3800cbec94b..cdc8b15f744 100644
--- a/source/blender/blenkernel/intern/image.c
+++ b/source/blender/blenkernel/intern/image.c
@@ -112,12 +112,26 @@
#include "DNA_view3d_types.h"
static CLG_LogRef LOG = {"bke.image"};
-static ThreadMutex *image_mutex;
static void image_init(Image *ima, short source, short type);
static void image_free_packedfiles(Image *ima);
static void copy_image_packedfiles(ListBase *lb_dst, const ListBase *lb_src);
+/* Reset runtime image fields when datablock is being initialized. */
+static void image_runtime_reset(struct Image *image)
+{
+ memset(&image->runtime, 0, sizeof(image->runtime));
+ image->runtime.cache_mutex = MEM_mallocN(sizeof(ThreadMutex), "image runtime cache_mutex");
+ BLI_mutex_init(image->runtime.cache_mutex);
+}
+
+/* Reset runtime image fields when datablock is being copied. */
+static void image_runtime_reset_on_copy(struct Image *image)
+{
+ image->runtime.cache_mutex = MEM_mallocN(sizeof(ThreadMutex), "image runtime cache_mutex");
+ BLI_mutex_init(image->runtime.cache_mutex);
+}
+
static void image_init_data(ID *id)
{
Image *image = (Image *)id;
@@ -167,6 +181,8 @@ static void image_copy_data(Main *UNUSED(bmain), ID *id_dst, const ID *id_src, c
else {
image_dst->preview = NULL;
}
+
+ image_runtime_reset_on_copy(image_dst);
}
static void image_free_data(ID *id)
@@ -194,6 +210,9 @@ static void image_free_data(ID *id)
BLI_freelistN(&image->tiles);
BLI_freelistN(&image->gpu_refresh_areas);
+
+ BLI_mutex_end(image->runtime.cache_mutex);
+ MEM_freeN(image->runtime.cache_mutex);
}
static void image_foreach_cache(ID *id,
@@ -327,6 +346,8 @@ static void image_blend_read_data(BlendDataReader *reader, ID *id)
ima->lastused = 0;
ima->gpuflag = 0;
BLI_listbase_clear(&ima->gpu_refresh_areas);
+
+ image_runtime_reset(ima);
}
static void image_blend_read_lib(BlendLibReader *UNUSED(reader), ID *id)
@@ -454,16 +475,6 @@ static struct ImBuf *imagecache_get(Image *image, int index)
return NULL;
}
-void BKE_images_init(void)
-{
- image_mutex = BLI_mutex_alloc();
-}
-
-void BKE_images_exit(void)
-{
- BLI_mutex_free(image_mutex);
-}
-
/* ***************** ALLOC & FREE, DATA MANAGING *************** */
static void image_free_cached_frames(Image *image)
@@ -516,7 +527,7 @@ static void image_free_anims(Image *ima)
void BKE_image_free_buffers_ex(Image *ima, bool do_lock)
{
if (do_lock) {
- BLI_mutex_lock(image_mutex);
+ BLI_mutex_lock(ima->runtime.cache_mutex);
}
image_free_cached_frames(ima);
@@ -534,7 +545,7 @@ void BKE_image_free_buffers_ex(Image *ima, bool do_lock)
}
if (do_lock) {
- BLI_mutex_unlock(image_mutex);
+ BLI_mutex_unlock(ima->runtime.cache_mutex);
}
}
@@ -574,6 +585,8 @@ static void image_init(Image *ima, short source, short type)
}
}
+ image_runtime_reset(ima);
+
BKE_color_managed_colorspace_settings_init(&ima->colorspace_settings);
ima->stereo3d_format = MEM_callocN(sizeof(Stereo3dFormat), "Image Stereo Format");
}
@@ -647,7 +660,9 @@ void BKE_image_merge(Main *bmain, Image *dest, Image *source)
{
/* sanity check */
if (dest && source && dest != source) {
- BLI_mutex_lock(image_mutex);
+ BLI_mutex_lock(source->runtime.cache_mutex);
+ BLI_mutex_lock(dest->runtime.cache_mutex);
+
if (source->cache != NULL) {
struct MovieCacheIter *iter;
iter = IMB_moviecacheIter_new(source->cache);
@@ -659,7 +674,9 @@ void BKE_image_merge(Main *bmain, Image *dest, Image *source)
}
IMB_moviecacheIter_free(iter);
}
- BLI_mutex_unlock(image_mutex);
+
+ BLI_mutex_unlock(dest->runtime.cache_mutex);
+ BLI_mutex_unlock(source->runtime.cache_mutex);
BKE_id_free(bmain, source);
}
@@ -1260,7 +1277,8 @@ static uintptr_t image_mem_size(Image *image)
return 0;
}
- BLI_mutex_lock(image_mutex);
+ BLI_mutex_lock(image->runtime.cache_mutex);
+
if (image->cache != NULL) {
struct MovieCacheIter *iter = IMB_moviecacheIter_new(image->cache);
@@ -1292,7 +1310,8 @@ static uintptr_t image_mem_size(Image *image)
}
IMB_moviecacheIter_free(iter);
}
- BLI_mutex_unlock(image_mutex);
+
+ BLI_mutex_unlock(image->runtime.cache_mutex);
return size;
}
@@ -1370,11 +1389,11 @@ static bool imagecache_check_free_anim(ImBuf *ibuf, void *UNUSED(userkey), void
/* except_frame is weak, only works for seqs without offset... */
void BKE_image_free_anim_ibufs(Image *ima, int except_frame)
{
- BLI_mutex_lock(image_mutex);
+ BLI_mutex_lock(ima->runtime.cache_mutex);
if (ima->cache != NULL) {
IMB_moviecache_cleanup(ima->cache, imagecache_check_free_anim, &except_frame);
}
- BLI_mutex_unlock(image_mutex);
+ BLI_mutex_unlock(ima->runtime.cache_mutex);
}
void BKE_image_all_free_anim_ibufs(Main *bmain, int cfra)
@@ -3293,7 +3312,7 @@ void BKE_image_ensure_viewer_views(const RenderData *rd, Image *ima, ImageUser *
}
if (do_reset) {
- BLI_mutex_lock(image_mutex);
+ BLI_mutex_lock(ima->runtime.cache_mutex);
image_free_cached_frames(ima);
BKE_image_free_views(ima);
@@ -3301,7 +3320,7 @@ void BKE_image_ensure_viewer_views(const RenderData *rd, Image *ima, ImageUser *
/* add new views */
image_viewer_create_views(rd, ima);
- BLI_mutex_unlock(image_mutex);
+ BLI_mutex_unlock(ima->runtime.cache_mutex);
}
BLI_thread_unlock(LOCK_DRAW_IMAGE);
@@ -3568,7 +3587,7 @@ void BKE_image_signal(Main *bmain, Image *ima, ImageUser *iuser, int signal)
return;
}
- BLI_mutex_lock(image_mutex);
+ BLI_mutex_lock(ima->runtime.cache_mutex);
switch (signal) {
case IMA_SIGNAL_FREE:
@@ -3703,7 +3722,7 @@ void BKE_image_signal(Main *bmain, Image *ima, ImageUser *iuser, int signal)
break;
}
- BLI_mutex_unlock(image_mutex);
+ BLI_mutex_unlock(ima->runtime.cache_mutex);
/* don't use notifiers because they are not 100% sure to succeeded
* this also makes sure all scenes are accounted for. */
@@ -5230,11 +5249,11 @@ ImBuf *BKE_image_acquire_ibuf(Image *ima, ImageUser *iuser, void **r_lock)
{
ImBuf *ibuf;
- BLI_mutex_lock(image_mutex);
+ BLI_mutex_lock(ima->runtime.cache_mutex);
ibuf = image_acquire_ibuf(ima, iuser, r_lock);
- BLI_mutex_unlock(image_mutex);
+ BLI_mutex_unlock(ima->runtime.cache_mutex);
return ibuf;
}
@@ -5253,9 +5272,9 @@ void BKE_image_release_ibuf(Image *ima, ImBuf *ibuf, void *lock)
}
if (ibuf) {
- BLI_mutex_lock(image_mutex);
+ BLI_mutex_lock(ima->runtime.cache_mutex);
IMB_freeImBuf(ibuf);
- BLI_mutex_unlock(image_mutex);
+ BLI_mutex_unlock(ima->runtime.cache_mutex);
}
}
@@ -5269,7 +5288,7 @@ bool BKE_image_has_ibuf(Image *ima, ImageUser *iuser)
return false;
}
- BLI_mutex_lock(image_mutex);
+ BLI_mutex_lock(ima->runtime.cache_mutex);
ibuf = image_get_cached_ibuf(ima, iuser, NULL, NULL);
@@ -5277,7 +5296,7 @@ bool BKE_image_has_ibuf(Image *ima, ImageUser *iuser)
ibuf = image_acquire_ibuf(ima, iuser, NULL);
}
- BLI_mutex_unlock(image_mutex);
+ BLI_mutex_unlock(ima->runtime.cache_mutex);
IMB_freeImBuf(ibuf);
@@ -5297,6 +5316,7 @@ typedef struct ImagePoolItem {
typedef struct ImagePool {
ListBase image_buffers;
BLI_mempool *memory_pool;
+ ThreadMutex mutex;
} ImagePool;
ImagePool *BKE_image_pool_new(void)
@@ -5304,22 +5324,28 @@ ImagePool *BKE_image_pool_new(void)
ImagePool *pool = MEM_callocN(sizeof(ImagePool), "Image Pool");
pool->memory_pool = BLI_mempool_create(sizeof(ImagePoolItem), 0, 128, BLI_MEMPOOL_NOP);
+ BLI_mutex_init(&pool->mutex);
+
return pool;
}
void BKE_image_pool_free(ImagePool *pool)
{
/* Use single lock to dereference all the image buffers. */
- BLI_mutex_lock(image_mutex);
+ BLI_mutex_lock(&pool->mutex);
for (ImagePoolItem *item = pool->image_buffers.first; item != NULL; item = item->next) {
if (item->ibuf != NULL) {
+ BLI_mutex_lock(item->image->runtime.cache_mutex);
IMB_freeImBuf(item->ibuf);
+ BLI_mutex_unlock(item->image->runtime.cache_mutex);
}
}
- BLI_mutex_unlock(image_mutex);
+ BLI_mutex_unlock(&pool->mutex);
BLI_mempool_destroy(pool->memory_pool);
MEM_freeN(pool);
+
+ BLI_mutex_end(&pool->mutex);
}
BLI_INLINE ImBuf *image_pool_find_item(
@@ -5350,28 +5376,34 @@ ImBuf *BKE_image_pool_acquire_ibuf(Image *ima, ImageUser *iuser, ImagePool *pool
}
if (pool == NULL) {
- /* pool could be NULL, in this case use general acquire function */
+ /* Pool could be NULL, in this case use general acquire function. */
return BKE_image_acquire_ibuf(ima, iuser, NULL);
}
image_get_entry_and_index(ima, iuser, &entry, &index);
+ /* Use double-checked locking, to avoid locking when the requested image buffer is already in the
+ * pool. */
+
ibuf = image_pool_find_item(pool, ima, entry, index, &found);
if (found) {
return ibuf;
}
- BLI_mutex_lock(image_mutex);
+ /* Lock the pool, to allow thread-safe modification of the content of the pool. */
+ BLI_mutex_lock(&pool->mutex);
ibuf = image_pool_find_item(pool, ima, entry, index, &found);
- /* will also create item even in cases image buffer failed t
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list