[Bf-blender-cvs] [b852db57ba2] master: Add experimental global undo speedup.

Bastien Montagne noreply at git.blender.org
Tue Mar 17 15:07:26 CET 2020


Commit: b852db57ba24adfcfaa0ada7e9ff513a79a399a2
Author: Bastien Montagne
Date:   Tue Mar 17 12:29:36 2020 +0100
Branches: master
https://developer.blender.org/rBb852db57ba24adfcfaa0ada7e9ff513a79a399a2

Add experimental global undo speedup.

The feature is hidden behind an experimental option, you'll have to
enable it in the preferences to try it.

This feature is not yet considered fully stable, crashes may happen, as
well as .blend file corruptions (very unlikely, but still possible).

In a nutshell, the ideas behind this code are to:
* Detect unchanged IDs across an undo step.
* Reuse as much as possible existing IDs memory, even when its content
  did change.
* Re-use existing depsgraphs instead of building new ones from scratch.
* Store accumulated recalc flags, to avoid needless re-compute of things
  that did not change, when the ID itself is detected as modified.

See T60695 and D6580 for more technical details.

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

M	release/scripts/startup/bl_ui/space_userpref.py
M	source/blender/blenkernel/BKE_blender_undo.h
M	source/blender/blenkernel/BKE_main.h
M	source/blender/blenkernel/BKE_undo_system.h
M	source/blender/blenkernel/intern/blender_undo.c
M	source/blender/blenkernel/intern/blendfile.c
M	source/blender/blenloader/BLO_readfile.h
M	source/blender/blenloader/BLO_undofile.h
M	source/blender/blenloader/intern/readblenentry.c
M	source/blender/blenloader/intern/readfile.c
M	source/blender/blenloader/intern/readfile.h
M	source/blender/blenloader/intern/undofile.c
M	source/blender/blenloader/intern/writefile.c
M	source/blender/editors/undo/memfile_undo.c
M	source/blender/makesdna/DNA_ID.h
M	source/blender/makesdna/DNA_userdef_types.h
M	source/blender/makesrna/intern/rna_userdef.c

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

diff --git a/release/scripts/startup/bl_ui/space_userpref.py b/release/scripts/startup/bl_ui/space_userpref.py
index 6aa0f51c55c..2ca0e73bd74 100644
--- a/release/scripts/startup/bl_ui/space_userpref.py
+++ b/release/scripts/startup/bl_ui/space_userpref.py
@@ -2133,6 +2133,25 @@ class USERPREF_PT_experimental_virtual_reality(ExperimentalPanel, Panel):
 """
 
 
+class USERPREF_PT_experimental_system(ExperimentalPanel, Panel):
+    bl_label = "System"
+
+    def draw(self, context):
+        prefs = context.preferences
+        experimental = prefs.experimental
+
+        layout = self.layout
+        layout.use_property_split = True
+        layout.use_property_decorate = False
+
+        task = "T60695"
+        split = layout.split(factor=0.66)
+        col = split.split()
+        col.prop(experimental, "use_undo_speedup")
+        col = split.split()
+        col.operator("wm.url_open", text=task, icon='URL').url = self.url_prefix + task
+
+
 # -----------------------------------------------------------------------------
 # Class Registration
 
@@ -2222,6 +2241,8 @@ classes = (
     # Popovers.
     USERPREF_PT_ndof_settings,
 
+    USERPREF_PT_experimental_system,
+
     # Add dynamically generated editor theme panels last,
     # so they show up last in the theme section.
     *ThemeGenericClassGenerator.generate_panel_classes_from_theme_areas(),
diff --git a/source/blender/blenkernel/BKE_blender_undo.h b/source/blender/blenkernel/BKE_blender_undo.h
index 7392d3947a2..4ecedbbfc1e 100644
--- a/source/blender/blenkernel/BKE_blender_undo.h
+++ b/source/blender/blenkernel/BKE_blender_undo.h
@@ -32,7 +32,10 @@ struct bContext;
 
 struct MemFileUndoData *BKE_memfile_undo_encode(struct Main *bmain,
                                                 struct MemFileUndoData *mfu_prev);
-bool BKE_memfile_undo_decode(struct MemFileUndoData *mfu, struct bContext *C);
+bool BKE_memfile_undo_decode(struct MemFileUndoData *mfu,
+                             const int undo_direction,
+                             const bool use_old_bmain_data,
+                             struct bContext *C);
 void BKE_memfile_undo_free(struct MemFileUndoData *mfu);
 
 #ifdef __cplusplus
diff --git a/source/blender/blenkernel/BKE_main.h b/source/blender/blenkernel/BKE_main.h
index a263162e013..8aac09d8738 100644
--- a/source/blender/blenkernel/BKE_main.h
+++ b/source/blender/blenkernel/BKE_main.h
@@ -99,6 +99,11 @@ typedef struct Main {
    * use "needs_flush_to_id" in edit data to flag data which needs updating.
    */
   char is_memfile_undo_flush_needed;
+  /**
+   * Indicates that next memfile undo step should not allow to re-use old bmain when re-read, but
+   * instead do a complete full re-read/update from stored memfile.
+   */
+  char use_memfile_full_barrier;
 
   BlendThumbnail *blen_thumb;
 
diff --git a/source/blender/blenkernel/BKE_undo_system.h b/source/blender/blenkernel/BKE_undo_system.h
index c503215be1f..4870b19fe1d 100644
--- a/source/blender/blenkernel/BKE_undo_system.h
+++ b/source/blender/blenkernel/BKE_undo_system.h
@@ -83,6 +83,9 @@ typedef struct UndoStep {
   bool skip;
   /** Some situations require the global state to be stored, edge cases when exiting modes. */
   bool use_memfile_step;
+  /** When this is true, undo/memfile read code is allowed to re-use old data-blocks for unchanged
+   * IDs, and existing depsgraphes. This has to be forbidden in some cases (like renamed IDs). */
+  bool use_old_bmain_data;
   /** For use by undo systems that accumulate changes (text editor, painting). */
   bool is_applied;
   /* Over alloc 'type->struct_size'. */
diff --git a/source/blender/blenkernel/intern/blender_undo.c b/source/blender/blenkernel/intern/blender_undo.c
index 9ccc53b6318..bb705e2295c 100644
--- a/source/blender/blenkernel/intern/blender_undo.c
+++ b/source/blender/blenkernel/intern/blender_undo.c
@@ -61,7 +61,10 @@
 
 #define UNDO_DISK 0
 
-bool BKE_memfile_undo_decode(MemFileUndoData *mfu, bContext *C)
+bool BKE_memfile_undo_decode(MemFileUndoData *mfu,
+                             const int undo_direction,
+                             const bool use_old_bmain_data,
+                             bContext *C)
 {
   Main *bmain = CTX_data_main(C);
   char mainstr[sizeof(bmain->name)];
@@ -76,8 +79,12 @@ bool BKE_memfile_undo_decode(MemFileUndoData *mfu, bContext *C)
     success = BKE_blendfile_read(C, mfu->filename, &(const struct BlendFileReadParams){0}, NULL);
   }
   else {
-    success = BKE_blendfile_read_from_memfile(
-        C, &mfu->memfile, &(const struct BlendFileReadParams){0}, NULL);
+    struct BlendFileReadParams params = {0};
+    params.undo_direction = undo_direction > 0 ? 1 : -1;
+    if (!use_old_bmain_data) {
+      params.skip_flags |= BLO_READ_SKIP_UNDO_OLD_MAIN;
+    }
+    success = BKE_blendfile_read_from_memfile(C, &mfu->memfile, &params, NULL);
   }
 
   /* Restore, bmain has been re-allocated. */
diff --git a/source/blender/blenkernel/intern/blendfile.c b/source/blender/blenkernel/intern/blendfile.c
index efab2039dc3..3890bf4e7f8 100644
--- a/source/blender/blenkernel/intern/blendfile.c
+++ b/source/blender/blenkernel/intern/blendfile.c
@@ -134,26 +134,29 @@ static void setup_app_userdef(BlendFileData *bfd)
 static void setup_app_data(bContext *C,
                            BlendFileData *bfd,
                            const char *filepath,
-                           const bool is_startup,
+                           const struct BlendFileReadParams *params,
                            ReportList *reports)
 {
   Main *bmain = G_MAIN;
   Scene *curscene = NULL;
   const bool recover = (G.fileflags & G_FILE_RECOVER) != 0;
+  const bool is_startup = params->is_startup;
   enum {
     LOAD_UI = 1,
     LOAD_UI_OFF,
     LOAD_UNDO,
   } mode;
 
-  /* may happen with library files - UNDO file should never have NULL cursccene... */
-  if (ELEM(NULL, bfd->curscreen, bfd->curscene)) {
+  if (params->undo_direction != 0) {
+    BLI_assert(bfd->curscene != NULL);
+    mode = LOAD_UNDO;
+  }
+  /* may happen with library files - UNDO file should never have NULL curscene (but may have a
+   * NULL curscreen)... */
+  else if (ELEM(NULL, bfd->curscreen, bfd->curscene)) {
     BKE_report(reports, RPT_WARNING, "Library file, loading empty scene");
     mode = LOAD_UI_OFF;
   }
-  else if (BLI_listbase_is_empty(&bfd->main->screens)) {
-    mode = LOAD_UNDO;
-  }
   else if (G.fileflags & G_FILE_NO_UI) {
     mode = LOAD_UI_OFF;
   }
@@ -371,7 +374,9 @@ static void setup_app_data(bContext *C,
      * means that we do not reset their user count, however we do increase that one when doing
      * lib_link on local IDs using linked ones.
      * There is no real way to predict amount of changes here, so we have to fully redo
-     * refcounting . */
+     * refcounting.
+     * Now that we re-use (and do not liblink in readfile.c) most local datablocks as well, we have
+     * to recompute refcount for all local IDs too. */
     BKE_main_id_refcount_recompute(bmain, false);
   }
 }
@@ -386,7 +391,7 @@ static void setup_app_blend_file_data(bContext *C,
     setup_app_userdef(bfd);
   }
   if ((params->skip_flags & BLO_READ_SKIP_DATA) == 0) {
-    setup_app_data(C, bfd, filepath, params->is_startup, reports);
+    setup_app_data(C, bfd, filepath, params, reports);
   }
 }
 
@@ -473,16 +478,15 @@ bool BKE_blendfile_read_from_memfile(bContext *C,
   Main *bmain = CTX_data_main(C);
   BlendFileData *bfd;
 
-  bfd = BLO_read_from_memfile(
-      bmain, BKE_main_blendfile_path(bmain), memfile, params->skip_flags, reports);
+  bfd = BLO_read_from_memfile(bmain, BKE_main_blendfile_path(bmain), memfile, params, reports);
   if (bfd) {
-    /* remove the unused screens and wm */
-    while (bfd->main->wm.first) {
-      BKE_id_free(bfd->main, bfd->main->wm.first);
-    }
-    while (bfd->main->screens.first) {
-      BKE_id_free(bfd->main, bfd->main->screens.first);
-    }
+    /* Removing the unused workspaces, screens and wm is useless here, setup_app_data will switch
+     * those lists with the ones from old bmain, which freeing is much more efficient than
+     * individual calls to `BKE_id_free()`.
+     * Further more, those are expected to be empty anyway with new memfile reading code. */
+    BLI_assert(BLI_listbase_is_empty(&bfd->main->wm));
+    BLI_assert(BLI_listbase_is_empty(&bfd->main->workspaces));
+    BLI_assert(BLI_listbase_is_empty(&bfd->main->screens));
 
     setup_app_blend_file_data(C, bfd, "<memory1>", params, reports);
     BLO_blendfiledata_free(bfd);
diff --git a/source/blender/blenloader/BLO_readfile.h b/source/blender/blenloader/BLO_readfile.h
index 00dbe334356..8495caa91b5 100644
--- a/source/blender/blenloader/BLO_readfile.h
+++ b/source/blender/blenloader/BLO_readfile.h
@@ -76,8 +76,11 @@ typedef struct WorkspaceConfigFileData {
 } WorkspaceConfigFileData;
 
 struct BlendFileReadParams {
-  uint skip_flags : 2; /* eBLOReadSkip */
+  uint skip_flags : 3; /* eBLOReadSkip */
   uint is_startup : 1;
+
+  /** Whether we are reading the memfile for an undo (< 0) or a redo (> 0). */
+  int undo_direction : 2;
 };
 
 /* skip reading some data-block types (may want to skip screen data too). */
@@ -85,6 +88,8 @@ typedef enum eBLOReadSkip {
   BLO_READ_SKIP_NONE = 0,
   BLO_READ_SKIP_USERDEF = (1 << 0),
   BLO_READ_SKIP_DATA = (1 << 1),
+  /** Do not attempt to re-use IDs from old bmain for unchanged ones in case of undo. */
+  BLO_READ_SKIP_UNDO_OLD_MAIN = (1 << 2),
 } eBLOReadSkip;
 #define BLO_READ_SKIP_ALL (BLO_READ_SKIP_USERDEF | BLO_READ_SKIP_DATA)
 
@@ -98,7 +103,7 @@ BlendFileData *BLO_read_from_memory(const void *mem,
 BlendFileData *BLO_read_from_memfile(struct Main *oldmain,
                                      const char *filename,
                                      struct MemFile *memfile,
-                                     eBLOReadSkip skip_flags,
+                                     const struct BlendFileReadParams *params,
                                      struct ReportList *reports);
 
 void BLO_blendfiledata_free(BlendFileData *bfd);
diff --git a/source/blender/blenloader/BLO_undofile.h b/source/blender/blenloader/BLO_undofile.h
index 0388b3f3520..5f1142cc20e 100644
--- a/source/blend

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list