[Bf-blender-cvs] [1695d38989f] master: LibOverride: Add partial resync.

Bastien Montagne noreply at git.blender.org
Fri Feb 11 15:19:05 CET 2022


Commit: 1695d38989fd482d3c010dc9ba4b0cb8e07a7139
Author: Bastien Montagne
Date:   Fri Feb 11 15:18:01 2022 +0100
Branches: master
https://developer.blender.org/rB1695d38989fd482d3c010dc9ba4b0cb8e07a7139

LibOverride: Add partial resync.

Reduce compute effort of liboverrides resync process by only re-syncing
the parts of the override hierarchy that actually need it.

The main change compared to existing code (which was systematically resyncing
a whole override hierarchy), is that resyncing now operates over several
sub-hierarchies at once, each defined by their own 'resync root' ID.
This ensures that we do not get several new overrides for the same data inside
of the same hierarchy.

Implements T95682.

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

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

M	source/blender/blenkernel/intern/lib_override.c

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

diff --git a/source/blender/blenkernel/intern/lib_override.c b/source/blender/blenkernel/intern/lib_override.c
index d65c0bb4e95..e42320fa2ca 100644
--- a/source/blender/blenkernel/intern/lib_override.c
+++ b/source/blender/blenkernel/intern/lib_override.c
@@ -724,7 +724,23 @@ static void lib_override_linked_group_tag(LibOverrideGroupTagData *data)
   /* For each object tagged for override, ensure we get at least one local or liboverride
    * collection to host it. Avoids getting a bunch of random object in the scene's master
    * collection when all objects' dependencies are not properly 'packed' into a single root
-   * collection. */
+   * collection.
+   *
+   * NOTE: In resync case, we do not handle this at all, since:
+   *         - In normal, valid cases nothing would be needed anyway (resync process takes care
+   *           of tagging needed 'owner' collection then).
+   *         - Partial resync makes it extremely difficult to properly handle such extra
+   *           collection 'tagging for override' (since one would need to know if the new object
+   *           is actually going to replace an already existing override [most common case], or
+   *           if it is actually a real new 'orphan' one).
+   *         - While not ideal, having objects dangling around is less critical than both points
+   *           above.
+   *        So if users add new objects to their library override hierarchy in an invalid way, so
+   *        be it. Trying to find a collection to override and host this new object would most
+   *        likely make existing override very unclean anyway. */
+  if (is_resync) {
+    return;
+  }
   LISTBASE_FOREACH (Object *, ob, &bmain->objects) {
     if (ID_IS_LINKED(ob) && (ob->id.tag & data->tag) != 0) {
       Collection *instantiating_collection = NULL;
@@ -738,17 +754,17 @@ static void lib_override_linked_group_tag(LibOverrideGroupTagData *data)
              instantiating_collection_linknode != NULL;
              instantiating_collection_linknode = instantiating_collection_linknode->next) {
           instantiating_collection = instantiating_collection_linknode->link;
-          /* In (recursive) resync case, if a collection of a 'parent' lib instantiates the
-           * linked object, it is also fine. */
-          if (!ID_IS_LINKED(instantiating_collection) ||
-              (is_resync && ID_IS_LINKED(id_root) &&
-               instantiating_collection->id.lib->temp_index < id_root->lib->temp_index)) {
+          if (!ID_IS_LINKED(instantiating_collection)) {
+            /* There is a local collection instantiating the linked object to override, nothing
+             * else to be done here. */
             break;
           }
-          if (ID_IS_LINKED(instantiating_collection) &&
-              (!is_resync || instantiating_collection->id.lib == id_root->lib)) {
-            instantiating_collection_override_candidate = instantiating_collection;
+          if (instantiating_collection->id.tag & data->tag) {
+            /* There is a linked collection instantiating the linked object to override,
+             * already tagged to be overridden, nothing else to be done here. */
+            break;
           }
+          instantiating_collection_override_candidate = instantiating_collection;
           instantiating_collection = NULL;
         }
       }
@@ -1293,6 +1309,8 @@ static bool lib_override_library_resync(Main *bmain,
                                         Scene *scene,
                                         ViewLayer *view_layer,
                                         ID *id_root,
+                                        LinkNode *id_resync_roots,
+                                        ListBase *no_main_ids_list,
                                         Collection *override_resync_residual_storage,
                                         const bool do_hierarchy_enforce,
                                         const bool do_post_process,
@@ -1301,6 +1319,7 @@ static bool lib_override_library_resync(Main *bmain,
   BLI_assert(ID_IS_OVERRIDE_LIBRARY_REAL(id_root));
 
   ID *id_root_reference = id_root->override_library->reference;
+  ID *id;
 
   if (id_root_reference->tag & LIB_TAG_MISSING) {
     BKE_reportf(reports != NULL ? reports->reports : NULL,
@@ -1321,94 +1340,145 @@ static bool lib_override_library_resync(Main *bmain,
                                   .is_override = true,
                                   .is_resync = true};
   lib_override_group_tag_data_object_to_collection_init(&data);
-  lib_override_overrides_group_tag(&data);
-
-  BKE_main_relations_tag_set(bmain, MAINIDRELATIONS_ENTRY_TAGS_PROCESSED, false);
-  data.id_root = id_root_reference;
-  data.is_override = false;
-  lib_override_linked_group_tag(&data);
-
-  BKE_main_relations_tag_set(bmain, MAINIDRELATIONS_ENTRY_TAGS_PROCESSED, false);
-  lib_override_hierarchy_dependencies_recursive_tag(&data);
 
-  /* Make a mapping 'linked reference IDs' -> 'Local override IDs' of existing overrides. */
+  /* Mapping 'linked reference IDs' -> 'Local override IDs' of existing overrides, populated from
+   * each sub-tree that actually needs to be resynced. */
   GHash *linkedref_to_old_override = BLI_ghash_new(
       BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, __func__);
-  ID *id;
-  FOREACH_MAIN_ID_BEGIN (bmain, id) {
-    /* IDs that get fully removed from linked data remain as local overrides (using place-holder
-     * linked IDs as reference), but they are often not reachable from any current valid local
-     * override hierarchy anymore. This will ensure they get properly deleted at the end of this
-     * function. */
-    if (!ID_IS_LINKED(id) && ID_IS_OVERRIDE_LIBRARY_REAL(id) &&
-        (id->override_library->reference->tag & LIB_TAG_MISSING) != 0 &&
-        /* Unfortunately deleting obdata means deleting their objects too. Since there is no
-         * guarantee that a valid override object using an obsolete override obdata gets properly
-         * updated, we ignore those here for now. In practice this should not be a big issue. */
-        !OB_DATA_SUPPORT_ID(GS(id->name))) {
-      id->tag |= LIB_TAG_MISSING;
-    }
-
-    if (id->tag & LIB_TAG_DOIT && (id->lib == id_root->lib) && ID_IS_OVERRIDE_LIBRARY(id)) {
-      /* While this should not happen in typical cases (and won't be properly supported here), user
-       * is free to do all kind of very bad things, including having different local overrides of a
-       * same linked ID in a same hierarchy. */
-      IDOverrideLibrary *id_override_library = lib_override_get(bmain, id);
-      ID *reference_id = id_override_library->reference;
-      if (GS(reference_id->name) != GS(id->name)) {
-        switch (GS(id->name)) {
-          case ID_KE:
-            reference_id = (ID *)BKE_key_from_id(reference_id);
-            break;
-          case ID_GR:
-            BLI_assert(GS(reference_id->name) == ID_SCE);
-            reference_id = (ID *)((Scene *)reference_id)->master_collection;
-            break;
-          case ID_NT:
-            reference_id = (ID *)ntreeFromID(id);
-            break;
-          default:
-            break;
-        }
+
+  /* Only tag linked IDs from related linked reference hierarchy that are actually part of
+   * the sub-trees of each detected sub-roots needing resync. */
+  for (LinkNode *resync_root_link = id_resync_roots; resync_root_link != NULL;
+       resync_root_link = resync_root_link->next) {
+    ID *id_resync_root = resync_root_link->link;
+    BLI_assert(ID_IS_OVERRIDE_LIBRARY_REAL(id_resync_root));
+
+    if ((id_resync_root->tag & LIB_TAG_NO_MAIN) != 0) {
+      CLOG_ERROR(&LOG,
+                 "While dealing with root '%s', resync root ID '%s' (%p) found to be alreaady "
+                 "resynced.\n",
+                 id_root->name,
+                 id_resync_root->name,
+                 id_resync_root);
+    }
+    //    if (no_main_ids_list && BLI_findindex(no_main_ids_list, id_resync_root) != -1) {
+    //      CLOG_ERROR(
+    //          &LOG,
+    //          "While dealing with root '%s', resync root ID '%s' found to be alreaady
+    //          resynced.\n", id_root->name, id_resync_root->name);
+    //    }
+
+    ID *id_resync_root_reference = id_resync_root->override_library->reference;
+
+    if (id_resync_root_reference->tag & LIB_TAG_MISSING) {
+      BKE_reportf(
+          reports != NULL ? reports->reports : NULL,
+          RPT_ERROR,
+          "Impossible to resync data-block %s and its dependencies, as its linked reference "
+          "is missing",
+          id_root->name + 2);
+      BLI_ghash_free(linkedref_to_old_override, NULL, NULL);
+      BKE_main_relations_free(bmain);
+      lib_override_group_tag_data_clear(&data);
+      return false;
+    }
+
+    /* Tag local overrides of the current resync sub-hierarchy. */
+    BKE_main_relations_tag_set(bmain, MAINIDRELATIONS_ENTRY_TAGS_PROCESSED, false);
+    data.id_root = id_resync_root;
+    data.is_override = true;
+    lib_override_overrides_group_tag(&data);
+
+    /* Tag reference data matching the current resync sub-hierarchy. */
+    BKE_main_relations_tag_set(bmain, MAINIDRELATIONS_ENTRY_TAGS_PROCESSED, false);
+    data.id_root = id_resync_root->override_library->reference;
+    data.is_override = false;
+    lib_override_linked_group_tag(&data);
+
+    BKE_main_relations_tag_set(bmain, MAINIDRELATIONS_ENTRY_TAGS_PROCESSED, false);
+    lib_override_hierarchy_dependencies_recursive_tag(&data);
+
+    FOREACH_MAIN_ID_BEGIN (bmain, id) {
+      /* IDs that get fully removed from linked data remain as local overrides (using place-holder
+       * linked IDs as reference), but they are often not reachable from any current valid local
+       * override hierarchy anymore. This will ensure they get properly deleted at the end of this
+       * function. */
+      if (!ID_IS_LINKED(id) && ID_IS_OVERRIDE_LIBRARY_REAL(id) &&
+          (id->override_library->reference->tag & LIB_TAG_MISSING) != 0 &&
+          /* Unfortunately deleting obdata means deleting their objects too. Since there is no
+           * guarantee that a valid override object using an obsolete override obdata gets properly
+           * upda

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list