[Bf-blender-cvs] [a71a513def2] master: Remap multiple items in referenced data.

Jeroen Bakker noreply at git.blender.org
Fri Feb 11 14:55:02 CET 2022


Commit: a71a513def202b119328035dbd68e86c2c47f7ac
Author: Jeroen Bakker
Date:   Fri Feb 11 14:53:08 2022 +0100
Branches: master
https://developer.blender.org/rBa71a513def202b119328035dbd68e86c2c47f7ac

Remap multiple items in referenced data.

This patch increases the performance when remapping data.
{D13615} introduced a mechanism to remap multiple items in a single go.
This patch uses the same mechanism when remapping data inside ID datablocks.

Benchmark results when loading the village scene of sprite fright on AMD Ryzen 7 3800X 8-Core Processor
Before this patch 115 seconds
When patch applied less than 43 seconds

There is still some room for improvement by porting relink code.

Reviewed By: mont29

Maniphest Tasks: T95279

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

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

M	source/blender/blenkernel/BKE_lib_id.h
M	source/blender/blenkernel/BKE_lib_remap.h
M	source/blender/blenkernel/intern/lib_id.c
M	source/blender/blenkernel/intern/lib_id_remapper.cc
M	source/blender/blenkernel/intern/lib_id_remapper_test.cc
M	source/blender/blenkernel/intern/lib_remap.c
M	source/blender/makesdna/DNA_ID.h

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

diff --git a/source/blender/blenkernel/BKE_lib_id.h b/source/blender/blenkernel/BKE_lib_id.h
index c4aa44706d5..c56cb616a9a 100644
--- a/source/blender/blenkernel/BKE_lib_id.h
+++ b/source/blender/blenkernel/BKE_lib_id.h
@@ -69,6 +69,11 @@ void *BKE_libblock_alloc(struct Main *bmain, short type, const char *name, int f
  */
 void BKE_libblock_init_empty(struct ID *id) ATTR_NONNULL(1);
 
+/**
+ * Reset the runtime counters used by ID remapping.
+ */
+void BKE_libblock_runtime_reset_remapping_status(struct ID *id) ATTR_NONNULL(1);
+
 /* *** ID's session_uuid management. *** */
 
 /**
diff --git a/source/blender/blenkernel/BKE_lib_remap.h b/source/blender/blenkernel/BKE_lib_remap.h
index f4136ed5cda..94b94303ec9 100644
--- a/source/blender/blenkernel/BKE_lib_remap.h
+++ b/source/blender/blenkernel/BKE_lib_remap.h
@@ -77,17 +77,25 @@ enum {
   ID_REMAP_FORCE_OBDATA_IN_EDITMODE = 1 << 9,
 };
 
+typedef enum eIDRemapType {
+  /** Remap an ID reference to a new reference. The new reference can also be null. */
+  ID_REMAP_TYPE_REMAP = 0,
+
+  /** Cleanup all IDs used by a specific one. */
+  ID_REMAP_TYPE_CLEANUP = 1,
+} eIDRemapType;
+
 /**
  * Replace all references in given Main using the given \a mappings
  *
  * \note Is preferred over BKE_libblock_remap_locked due to performance.
  */
 void BKE_libblock_remap_multiple_locked(struct Main *bmain,
-                                        const struct IDRemapper *mappings,
+                                        struct IDRemapper *mappings,
                                         const short remap_flags);
 
 void BKE_libblock_remap_multiple(struct Main *bmain,
-                                 const struct IDRemapper *mappings,
+                                 struct IDRemapper *mappings,
                                  const short remap_flags);
 
 /**
@@ -172,6 +180,13 @@ typedef enum IDRemapperApplyOptions {
    */
   ID_REMAP_APPLY_ENSURE_REAL = (1 << 1),
 
+  /**
+   * Unassign in stead of remap when the new ID datablock would become id_self.
+   *
+   * To use this option 'BKE_id_remapper_apply_ex' must be used with a not-null id_self parameter.
+   */
+  ID_REMAP_APPLY_UNMAP_WHEN_REMAPPING_TO_SELF = (1 << 2),
+
   ID_REMAP_APPLY_DEFAULT = 0,
 } IDRemapperApplyOptions;
 
@@ -199,7 +214,28 @@ void BKE_id_remapper_add(struct IDRemapper *id_remapper, struct ID *old_id, stru
 IDRemapperApplyResult BKE_id_remapper_apply(const struct IDRemapper *id_remapper,
                                             struct ID **r_id_ptr,
                                             IDRemapperApplyOptions options);
+/**
+ * Apply a remapping.
+ *
+ * Use this function when `ID_REMAP_APPLY_UNMAP_WHEN_REMAPPING_TO_SELF`. In this case
+ * the #id_self parameter is required. Otherwise the #BKE_id_remapper_apply can be used.
+ *
+ * \param id_self required for ID_REMAP_APPLY_UNMAP_WHEN_REMAPPING_TO_SELF.
+ *     When remapping to id_self it will then be remapped to NULL.
+ */
+IDRemapperApplyResult BKE_id_remapper_apply_ex(const struct IDRemapper *id_remapper,
+                                               struct ID **r_id_ptr,
+                                               IDRemapperApplyOptions options,
+                                               struct ID *id_self);
 bool BKE_id_remapper_has_mapping_for(const struct IDRemapper *id_remapper, uint64_t type_filter);
+
+/**
+ * Determine the mapping result, without applying the mapping.
+ */
+IDRemapperApplyResult BKE_id_remapper_get_mapping_result(const struct IDRemapper *id_remapper,
+                                                         struct ID *id,
+                                                         IDRemapperApplyOptions options,
+                                                         const struct ID *id_self);
 void BKE_id_remapper_iter(const struct IDRemapper *id_remapper,
                           IDRemapperIterFunction func,
                           void *user_data);
diff --git a/source/blender/blenkernel/intern/lib_id.c b/source/blender/blenkernel/intern/lib_id.c
index 2baecea51ff..7cd3204f3f1 100644
--- a/source/blender/blenkernel/intern/lib_id.c
+++ b/source/blender/blenkernel/intern/lib_id.c
@@ -1121,6 +1121,14 @@ void BKE_libblock_init_empty(ID *id)
   BLI_assert_msg(0, "IDType Missing IDTypeInfo");
 }
 
+void BKE_libblock_runtime_reset_remapping_status(ID *id)
+{
+  id->runtime.remap.status = 0;
+  id->runtime.remap.skipped_refcounted = 0;
+  id->runtime.remap.skipped_direct = 0;
+  id->runtime.remap.skipped_indirect = 0;
+}
+
 /* ********** ID session-wise UUID management. ********** */
 static uint global_session_uuid = 0;
 
diff --git a/source/blender/blenkernel/intern/lib_id_remapper.cc b/source/blender/blenkernel/intern/lib_id_remapper.cc
index 5af482ac088..7696386c87d 100644
--- a/source/blender/blenkernel/intern/lib_id_remapper.cc
+++ b/source/blender/blenkernel/intern/lib_id_remapper.cc
@@ -44,7 +44,25 @@ struct IDRemapper {
     return (source_types & filter) != 0;
   }
 
-  IDRemapperApplyResult apply(ID **r_id_ptr, IDRemapperApplyOptions options) const
+  IDRemapperApplyResult get_mapping_result(ID *id,
+                                           IDRemapperApplyOptions options,
+                                           const ID *id_self) const
+  {
+    if (!mappings.contains(id)) {
+      return ID_REMAP_RESULT_SOURCE_UNAVAILABLE;
+    }
+    const ID *new_id = mappings.lookup(id);
+    if ((options & ID_REMAP_APPLY_UNMAP_WHEN_REMAPPING_TO_SELF) != 0 && id_self == new_id) {
+      new_id = nullptr;
+    }
+    if (new_id == nullptr) {
+      return ID_REMAP_RESULT_SOURCE_UNASSIGNED;
+    }
+
+    return ID_REMAP_RESULT_SOURCE_REMAPPED;
+  }
+
+  IDRemapperApplyResult apply(ID **r_id_ptr, IDRemapperApplyOptions options, ID *id_self) const
   {
     BLI_assert(r_id_ptr != nullptr);
     if (*r_id_ptr == nullptr) {
@@ -60,6 +78,9 @@ struct IDRemapper {
     }
 
     *r_id_ptr = mappings.lookup(*r_id_ptr);
+    if (options & ID_REMAP_APPLY_UNMAP_WHEN_REMAPPING_TO_SELF && *r_id_ptr == id_self) {
+      *r_id_ptr = nullptr;
+    }
     if (*r_id_ptr == nullptr) {
       return ID_REMAP_RESULT_SOURCE_UNASSIGNED;
     }
@@ -142,12 +163,35 @@ bool BKE_id_remapper_has_mapping_for(const struct IDRemapper *id_remapper, uint6
   return remapper->contains_mappings_for_any(type_filter);
 }
 
+IDRemapperApplyResult BKE_id_remapper_get_mapping_result(const struct IDRemapper *id_remapper,
+                                                         struct ID *id,
+                                                         IDRemapperApplyOptions options,
+                                                         const struct ID *id_self)
+{
+  const blender::bke::id::remapper::IDRemapper *remapper = unwrap(id_remapper);
+  return remapper->get_mapping_result(id, options, id_self);
+}
+
+IDRemapperApplyResult BKE_id_remapper_apply_ex(const IDRemapper *id_remapper,
+                                               ID **r_id_ptr,
+                                               const IDRemapperApplyOptions options,
+                                               ID *id_self)
+{
+  BLI_assert_msg((options & ID_REMAP_APPLY_UNMAP_WHEN_REMAPPING_TO_SELF) == 0 ||
+                     id_self != nullptr,
+                 "ID_REMAP_APPLY_WHEN_REMAPPING_TO_SELF requires id_self parameter.");
+  const blender::bke::id::remapper::IDRemapper *remapper = unwrap(id_remapper);
+  return remapper->apply(r_id_ptr, options, id_self);
+}
+
 IDRemapperApplyResult BKE_id_remapper_apply(const IDRemapper *id_remapper,
                                             ID **r_id_ptr,
                                             const IDRemapperApplyOptions options)
 {
-  const blender::bke::id::remapper::IDRemapper *remapper = unwrap(id_remapper);
-  return remapper->apply(r_id_ptr, options);
+  BLI_assert_msg((options & ID_REMAP_APPLY_UNMAP_WHEN_REMAPPING_TO_SELF) == 0,
+                 "ID_REMAP_APPLY_UNMAP_WHEN_REMAPPING_TO_SELF requires id_self parameter. Use "
+                 "`BKE_id_remapper_apply_ex`.");
+  return BKE_id_remapper_apply_ex(id_remapper, r_id_ptr, options, nullptr);
 }
 
 void BKE_id_remapper_iter(const struct IDRemapper *id_remapper,
diff --git a/source/blender/blenkernel/intern/lib_id_remapper_test.cc b/source/blender/blenkernel/intern/lib_id_remapper_test.cc
index a6cfe60153d..73edc30d077 100644
--- a/source/blender/blenkernel/intern/lib_id_remapper_test.cc
+++ b/source/blender/blenkernel/intern/lib_id_remapper_test.cc
@@ -65,4 +65,44 @@ TEST(lib_id_remapper, unassigned)
   BKE_id_remapper_free(remapper);
 }
 
+TEST(lib_id_remapper, unassign_when_mapped_to_self)
+{
+  ID id_self;
+  ID id1;
+  ID id2;
+  ID *idp;
+
+  BLI_strncpy(id_self.name, "OBSelf", sizeof(id1.name));
+  BLI_strncpy(id1.name, "OB1", sizeof(id1.name));
+  BLI_strncpy(id2.name, "OB2", sizeof(id2.name));
+
+  /* Default mapping behavior. Should just remap to id2. */
+  idp = &id1;
+  IDRemapper *remapper = BKE_id_remapper_create();
+  BKE_id_remapper_add(remapper, &id1, &id2);
+  IDRemapperApplyResult result = BKE_id_remapper_apply_ex(
+      remapper, &idp, ID_REMAP_APPLY_UNMAP_WHEN_REMAPPING_TO_SELF, &id_self);
+  EXPECT_EQ(result, ID_REMAP_RESULT_SOURCE_REMAPPED);
+  EXPECT_EQ(idp, &id2);
+
+  /* Default mapping behavior. Should unassign. */
+  idp = &id1;
+  BKE_id_remapper_clear(remapper);
+  BKE_id_remapper_add(remapper, &id1, nullptr);
+  result = BKE_id_remapper_apply_ex(
+      remapper, &idp, ID_REMAP_APPLY_UNMAP_WHEN_REMAPPING_TO_SELF, &id_self);
+  EXPECT_EQ(result, ID_REMAP_RESULT_SOURCE_UNASSIGNED);
+  EXPECT_EQ(idp, nullptr);
+
+  /* Unmap when remapping to self behavior. Should unassign. */
+  idp = &id1;
+  BKE_id_remapper_clear(remapper);
+  BKE_id_remapper_add(remapper, &id1, &id_self);
+  result = BKE_id_remapper_apply_ex(
+      remapper, &idp, ID_REMAP_APPLY_UNMAP_WHEN_REMAPPING_TO_SELF, &id_self);
+  EXPECT_EQ(result, ID_REMAP_RESULT_SOURCE_UNASSIGNED);
+  EXPECT_EQ(idp, nullptr);
+  BKE_id_remapper_free(remapper);
+}
+
 }  // namespace blender::bke::id::remapper::tests
diff --git a/source/blender/blenkernel/intern/lib_remap.c b/source/blender/blenkernel/intern/lib_remap.c
index a05067e16f6..9329a09f1b6 100644
--- a/source/blender/blenkernel/intern/lib_re

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list