[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