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
diff options
context:
space:
mode:
authorBrecht Van Lommel <brecht@blender.org>2020-04-04 20:30:42 +0300
committerBrecht Van Lommel <brecht@blender.org>2020-04-07 18:14:19 +0300
commitc5ed2eb95e3d75121b93b0271abf6cdec69d5a66 (patch)
treee9e86e18ff8ee030ea2824df2d70f7ae15cdd8a4 /source/blender/editors/undo
parent02598e629eb3a3291784b297528c8596c964cd37 (diff)
Undo: change depsgraph recalc flags handling to improve performance
These changes only have an effect when the experimental Undo Speedup preference is enabled. * For DEG_id_tag_update, accumulate recalc flags immediately before the undo push happens instead of afterwards. Otherwise the undo state does not contain enough flags, and the current state may contain too many flags. This also means we call DEG_id_tag_update after undo with the accumulated flags to ensure they are flushed to other datablocks. * For undo, accumulate recalc flags in id->recalc and clear accumulated flags immediately. Not clearing would cause circular behavior where accumulated flags may never end up being cleared. This matches what happens after an undo push where these are also cleared, indicating that the undo state and current in-memory state match exactly. * Don't change id->recalc of identical datablocks, it should not be needed. There is one exception for armatures where pointers across datablocks exist which otherwise would cause problems. There may be a better solution to this but it seems to work in agent 327 production files. * This contains a change in undofile.c to avoid detecting all datablocks as changed for the first of the two undo steps, where we restore to the state of the last undo push before going to the one before. Without this the whole system is much less efficient. However this is unsafe in the sense that if an app handler or operators edits a datablock after an undo push, that change will not be undone. It can be argued that this is acceptable behavior, since a following undo push will include that change and this may already have unexpected side effects. Ref T60695 Differential Revision: https://developer.blender.org/D7339
Diffstat (limited to 'source/blender/editors/undo')
-rw-r--r--source/blender/editors/undo/memfile_undo.c34
1 files changed, 29 insertions, 5 deletions
diff --git a/source/blender/editors/undo/memfile_undo.c b/source/blender/editors/undo/memfile_undo.c
index 086aa6c4c9d..a5c503fec90 100644
--- a/source/blender/editors/undo/memfile_undo.c
+++ b/source/blender/editors/undo/memfile_undo.c
@@ -25,14 +25,17 @@
#include "BLI_ghash.h"
+#include "DNA_node_types.h"
#include "DNA_object_enums.h"
#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
#include "BKE_blender_undo.h"
#include "BKE_context.h"
#include "BKE_lib_id.h"
#include "BKE_lib_query.h"
#include "BKE_main.h"
+#include "BKE_node.h"
#include "BKE_scene.h"
#include "BKE_undo_system.h"
@@ -106,7 +109,6 @@ static int memfile_undosys_step_id_reused_cb(LibraryIDLinkCallbackData *cb_data)
ID *id_self = cb_data->id_self;
ID **id_pointer = cb_data->id_pointer;
BLI_assert((id_self->tag & LIB_TAG_UNDO_OLD_ID_REUSED) != 0);
- Main *bmain = cb_data->user_data;
ID *id = *id_pointer;
if (id != NULL && id->lib == NULL && (id->tag & LIB_TAG_UNDO_OLD_ID_REUSED) == 0) {
@@ -129,9 +131,6 @@ static int memfile_undosys_step_id_reused_cb(LibraryIDLinkCallbackData *cb_data)
}
}
- /* In case an old, re-used ID is using a newly read data-block (i.e. one of its ID pointers got
- * updated), we have to tell the depsgraph about it. */
- DEG_id_tag_update_ex(bmain, id_self, ID_RECALC_COPY_ON_WRITE);
return do_stop_iter ? IDWALK_RET_STOP_ITER : IDWALK_RET_NOP;
}
@@ -219,10 +218,35 @@ static void memfile_undosys_step_decode(struct bContext *C,
BKE_library_foreach_ID_link(
bmain, id, memfile_undosys_step_id_reused_cb, bmain, IDWALK_READONLY);
}
+
+ /* Tag depsgraph to update datablock for changes that happend between the
+ * current and the target state, see direct_link_id_restore_recalc(). */
+ if (id->recalc) {
+ DEG_id_tag_update_ex(bmain, id, id->recalc);
+ }
}
FOREACH_MAIN_ID_END;
- BKE_main_id_tag_all(bmain, LIB_TAG_UNDO_OLD_ID_REUSED, false);
+ FOREACH_MAIN_ID_BEGIN (bmain, id) {
+ /* Clear temporary tag. */
+ id->tag &= ~LIB_TAG_UNDO_OLD_ID_REUSED;
+
+ /* We only start accumulating from this point, any tags set up to here
+ * are already part of the current undo state. This is done in a second
+ * loop because DEG_id_tag_update may set tags on other datablocks. */
+ id->recalc_undo_accumulated = 0;
+ bNodeTree *nodetree = ntreeFromID(id);
+ if (nodetree != NULL) {
+ nodetree->id.recalc_undo_accumulated = 0;
+ }
+ if (GS(id->name) == ID_SCE) {
+ Scene *scene = (Scene *)id;
+ if (scene->master_collection != NULL) {
+ scene->master_collection->id.recalc_undo_accumulated = 0;
+ }
+ }
+ }
+ FOREACH_MAIN_ID_END;
}
WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, CTX_data_scene(C));