[Bf-blender-cvs] [489260198e9] master: File Browser: Fix slowdown with non-existing ID previews in big files

Julian Eisel noreply at git.blender.org
Tue Oct 18 15:11:41 CEST 2022


Commit: 489260198e9654aaf5922e64fbe36b335bcb8e1b
Author: Julian Eisel
Date:   Tue Oct 18 15:05:53 2022 +0200
Branches: master
https://developer.blender.org/rB489260198e9654aaf5922e64fbe36b335bcb8e1b

File Browser: Fix slowdown with non-existing ID previews in big files

When the File (or Asset) Browser would display data-blocks without
previews in a heavy .blend file, there would be a drastic slowdown.

See patch for details and comparison videos.

Differential Revision: https://developer.blender.org/D16273

Reviewed by: Bastien Montagne

===================================================================

M	source/blender/blenloader/BLO_readfile.h
M	source/blender/blenloader/intern/readblenentry.cc
M	source/blender/editors/space_file/filelist.cc
M	source/blender/makesdna/DNA_space_types.h

===================================================================

diff --git a/source/blender/blenloader/BLO_readfile.h b/source/blender/blenloader/BLO_readfile.h
index 93040fa01ee..75a1956ce12 100644
--- a/source/blender/blenloader/BLO_readfile.h
+++ b/source/blender/blenloader/BLO_readfile.h
@@ -182,6 +182,11 @@ void BLO_blendfiledata_free(BlendFileData *bfd);
 typedef struct BLODataBlockInfo {
   char name[64]; /* MAX_NAME */
   struct AssetMetaData *asset_data;
+  /* Optimization: Tag data-blocks for which we know there is no preview.
+   * Knowing this can be used to skip the (potentially expensive) preview loading process. If this
+   * is set to true it means we looked for a preview and couldn't find one. False may mean that
+   * either no preview was found, or that it wasn't looked for in the first place. */
+  bool no_preview_found;
 } BLODataBlockInfo;
 
 /**
diff --git a/source/blender/blenloader/intern/readblenentry.cc b/source/blender/blenloader/intern/readblenentry.cc
index 55ac2d31277..ead796c0e28 100644
--- a/source/blender/blenloader/intern/readblenentry.cc
+++ b/source/blender/blenloader/intern/readblenentry.cc
@@ -138,11 +138,15 @@ LinkNode *BLO_blendhandle_get_datablock_info(BlendHandle *bh,
   BHead *bhead;
   int tot = 0;
 
+  const int sdna_nr_preview_image = DNA_struct_find_nr(fd->filesdna, "PreviewImage");
+
   for (bhead = blo_bhead_first(fd); bhead; bhead = blo_bhead_next(fd, bhead)) {
     if (bhead->code == ENDB) {
       break;
     }
     if (bhead->code == ofblocktype) {
+      BHead *id_bhead = bhead;
+
       const char *name = blo_bhead_id_name(fd, bhead) + 2;
       AssetMetaData *asset_meta_data = blo_bhead_id_asset_data_address(fd, bhead);
 
@@ -165,6 +169,17 @@ LinkNode *BLO_blendhandle_get_datablock_info(BlendHandle *bh,
       STRNCPY(info->name, name);
       info->asset_data = asset_meta_data;
 
+      bool has_preview = false;
+      /* See if we can find a preview in the data of this ID. */
+      for (BHead *data_bhead = blo_bhead_next(fd, id_bhead); data_bhead->code == DATA;
+           data_bhead = blo_bhead_next(fd, data_bhead)) {
+        if (data_bhead->SDNAnr == sdna_nr_preview_image) {
+          has_preview = true;
+          break;
+        }
+      }
+      info->no_preview_found = !has_preview;
+
       BLI_linklist_prepend(&infos, info);
       tot++;
     }
diff --git a/source/blender/editors/space_file/filelist.cc b/source/blender/editors/space_file/filelist.cc
index b6f6ab39438..f177eebf6f2 100644
--- a/source/blender/editors/space_file/filelist.cc
+++ b/source/blender/editors/space_file/filelist.cc
@@ -115,6 +115,9 @@ struct FileListInternEntry {
    * Owning pointer. */
   AssetMetaData *imported_asset_data;
 
+  /* See #FILE_ENTRY_BLENDERLIB_NO_PREVIEW. */
+  bool blenderlib_has_no_preview;
+
   /** Defined in BLI_fileops.h */
   eFileAttributes attributes;
   BLI_stat_t st;
@@ -1575,6 +1578,14 @@ static void filelist_cache_previews_push(FileList *filelist, FileDirEntry *entry
     return;
   }
 
+  /* If we know this is an external ID without a preview, skip loading the preview. Can save quite
+   * some time in heavy files, because otherwise for each missing preview and for each preview
+   * reload, we'd reopen the .blend to look for the preview. */
+  if ((entry->typeflag & FILE_TYPE_BLENDERLIB) &&
+      (entry->flags & FILE_ENTRY_BLENDERLIB_NO_PREVIEW)) {
+    return;
+  }
+
   FileListInternEntry *intern_entry = filelist->filelist_intern.filtered[index];
   PreviewImage *preview_in_memory = intern_entry->local_data.preview_image;
   if (preview_in_memory && !BKE_previewimg_is_finished(preview_in_memory, ICON_SIZE_PREVIEW)) {
@@ -2042,6 +2053,9 @@ static FileDirEntry *filelist_file_create_entry(FileList *filelist, const int in
       ret->preview_icon_id = BKE_icon_imbuf_create(ibuf);
     }
   }
+  if (entry->blenderlib_has_no_preview) {
+    ret->flags |= FILE_ENTRY_BLENDERLIB_NO_PREVIEW;
+  }
   BLI_addtail(&cache->cached_entries, ret);
   return ret;
 }
@@ -2995,10 +3009,15 @@ static void filelist_readjob_list_lib_add_datablock(ListBase *entries,
     entry->relpath = BLI_strdup(datablock_info->name);
   }
   entry->typeflag |= FILE_TYPE_BLENDERLIB;
-  if (datablock_info && datablock_info->asset_data) {
-    entry->typeflag |= FILE_TYPE_ASSET;
-    /* Moves ownership! */
-    entry->imported_asset_data = datablock_info->asset_data;
+
+  if (datablock_info) {
+    entry->blenderlib_has_no_preview = datablock_info->no_preview_found;
+
+    if (datablock_info->asset_data) {
+      entry->typeflag |= FILE_TYPE_ASSET;
+      /* Moves ownership! */
+      entry->imported_asset_data = datablock_info->asset_data;
+    }
   }
   entry->blentype = idcode;
   BLI_addtail(entries, entry);
diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h
index 809c8be7bc4..d2d20bcde78 100644
--- a/source/blender/makesdna/DNA_space_types.h
+++ b/source/blender/makesdna/DNA_space_types.h
@@ -1169,6 +1169,10 @@ enum {
   FILE_ENTRY_NAME_FREE = 1 << 1,
   /* The preview for this entry is being loaded on another thread. */
   FILE_ENTRY_PREVIEW_LOADING = 1 << 2,
+  /** For #FILE_TYPE_BLENDERLIB only: Denotes that the ID is known to not have a preview (none was
+   * found in the .blend). Stored so we don't keep trying to find non-existent previews every time
+   * we reload previews. When dealing with heavy files this can have quite an impact. */
+  FILE_ENTRY_BLENDERLIB_NO_PREVIEW = 1 << 3,
 };
 
 /** \} */



More information about the Bf-blender-cvs mailing list