[Bf-blender-cvs] [131a758b6f8] master: Refactor BMain relations temp data.
Bastien Montagne
noreply at git.blender.org
Fri Jan 22 16:06:53 CET 2021
Commit: 131a758b6f88a2be816e9351d216bcfb9c965c4b
Author: Bastien Montagne
Date: Thu Jan 21 14:52:40 2021 +0100
Branches: master
https://developer.blender.org/rB131a758b6f88a2be816e9351d216bcfb9c965c4b
Refactor BMain relations temp data.
`bmain.relations` is used to store temp data of relations between IDs,
to speed-up some complex processes heavily relying on such information.
Previous implementation was failry unclear/confusing, and required a
not-so-nice hack to 'tag' some ID as processed.
New code changes as such:
* Using `from`/`to` naming (instead of `user`/`used`).
* More clear separation between `to` `id_pointer` and `from` one,
using an union instead of hacking around difference between `ID *` and
`ID **` pointers.
* Adds storage of `session_uuid` informations (mainly useful as
debug/ensuring proper consistency of data currently).
* Adds a structure per ID in the mapping. This enables possibility of
storing tags (and potentially more data in the future) per-ID,
without polluting the IDs themselves with very short-life info.
Differential Revision: https://developer.blender.org/D10164
===================================================================
M source/blender/blenkernel/BKE_main.h
M source/blender/blenkernel/intern/lib_id.c
M source/blender/blenkernel/intern/lib_override.c
M source/blender/blenkernel/intern/lib_query.c
M source/blender/blenkernel/intern/main.c
===================================================================
diff --git a/source/blender/blenkernel/BKE_main.h b/source/blender/blenkernel/BKE_main.h
index 8106607572b..0768423fc5f 100644
--- a/source/blender/blenkernel/BKE_main.h
+++ b/source/blender/blenkernel/BKE_main.h
@@ -60,22 +60,52 @@ typedef struct BlendThumbnail {
} BlendThumbnail;
/* Structs caching relations between data-blocks in a given Main. */
+typedef struct MainIDRelationsEntryItem {
+ struct MainIDRelationsEntryItem *next;
+
+ union {
+ /* For `from_ids` list, a user of the hashed ID. */
+ struct ID *from;
+ /* For `to_ids` list, an ID used by the hashed ID. */
+ struct ID **to;
+ } id_pointer;
+ /* Session uuid of the `id_pointer`. */
+ uint session_uuid;
+
+ int usage_flag; /* Using IDWALK_ enums, defined in BKE_lib_query.h */
+} MainIDRelationsEntryItem;
+
typedef struct MainIDRelationsEntry {
- struct MainIDRelationsEntry *next;
- /* WARNING! for user_to_used,
- * that pointer is really an ID** one, but for used_to_user, it’s only an ID* one! */
- struct ID **id_pointer;
- int usage_flag; /* Using IDWALK_ enums, in BKE_lib_query.h */
+ /* Linked list of IDs using that ID. */
+ struct MainIDRelationsEntryItem *from_ids;
+ /* Linked list of IDs used by that ID. */
+ struct MainIDRelationsEntryItem *to_ids;
+
+ /* Session uuid of the ID matching that entry. */
+ uint session_uuid;
+
+ /* Runtime tags, users should ensure those are reset after usage. */
+ uint tags;
} MainIDRelationsEntry;
+/* MainIDRelationsEntry.tags */
+typedef enum MainIDRelationsEntryTags {
+ /* Generic tag marking the entry as to be processed. */
+ MAINIDRELATIONS_ENTRY_TAGS_DOIT = 1 << 0,
+ /* Generic tag marking the entry as processed. */
+ MAINIDRELATIONS_ENTRY_TAGS_PROCESSED = 1 << 1,
+} MainIDRelationsEntryTags;
+
typedef struct MainIDRelations {
- struct GHash *id_user_to_used;
- struct GHash *id_used_to_user;
+ /* Mapping from an ID pointer to all of its parents (IDs using it) and children (IDs it uses).
+ * Values are `MainIDRelationsEntry` pointers. */
+ struct GHash *relations_from_pointers;
+ /* Note: we could add more mappings when needed (e.g. from session uuid?). */
short flag;
/* Private... */
- struct BLI_mempool *entry_pool;
+ struct BLI_mempool *entry_items_pool;
} MainIDRelations;
enum {
@@ -172,7 +202,6 @@ void BKE_main_unlock(struct Main *bmain);
void BKE_main_relations_create(struct Main *bmain, const short flag);
void BKE_main_relations_free(struct Main *bmain);
-void BKE_main_relations_ID_remove(struct Main *bmain, struct ID *id);
struct GSet *BKE_main_gset_create(struct Main *bmain, struct GSet *gset);
diff --git a/source/blender/blenkernel/intern/lib_id.c b/source/blender/blenkernel/intern/lib_id.c
index 838f3046ed0..54c2f5f5565 100644
--- a/source/blender/blenkernel/intern/lib_id.c
+++ b/source/blender/blenkernel/intern/lib_id.c
@@ -1795,32 +1795,31 @@ static void library_make_local_copying_check(ID *id,
return; /* Already checked, nothing else to do. */
}
- MainIDRelationsEntry *entry = BLI_ghash_lookup(id_relations->id_used_to_user, id);
+ MainIDRelationsEntry *entry = BLI_ghash_lookup(id_relations->relations_from_pointers, id);
BLI_gset_insert(loop_tags, id);
- for (; entry != NULL; entry = entry->next) {
-
- /* Used_to_user stores ID pointer, not pointer to ID pointer. */
- ID *par_id = (ID *)entry->id_pointer;
-
+ for (MainIDRelationsEntryItem *from_id_entry = entry->from_ids; from_id_entry != NULL;
+ from_id_entry = from_id_entry->next) {
/* Our oh-so-beloved 'from' pointers... Those should always be ignored here, since the actual
* relation we want to check is in the other way around. */
- if (entry->usage_flag & IDWALK_CB_LOOPBACK) {
+ if (from_id_entry->usage_flag & IDWALK_CB_LOOPBACK) {
continue;
}
+ ID *from_id = from_id_entry->id_pointer.from;
+
/* Shape-keys are considered 'private' to their owner ID here, and never tagged
* (since they cannot be linked), so we have to switch effective parent to their owner.
*/
- if (GS(par_id->name) == ID_KE) {
- par_id = ((Key *)par_id)->from;
+ if (GS(from_id->name) == ID_KE) {
+ from_id = ((Key *)from_id)->from;
}
- if (par_id->lib == NULL) {
+ if (from_id->lib == NULL) {
/* Local user, early out to avoid some gset querying... */
continue;
}
- if (!BLI_gset_haskey(done_ids, par_id)) {
- if (BLI_gset_haskey(loop_tags, par_id)) {
+ if (!BLI_gset_haskey(done_ids, from_id)) {
+ if (BLI_gset_haskey(loop_tags, from_id)) {
/* We are in a 'dependency loop' of IDs, this does not say us anything, skip it.
* Note that this is the situation that can lead to archipelagoes of linked data-blocks
* (since all of them have non-local users, they would all be duplicated,
@@ -1829,10 +1828,10 @@ static void library_make_local_copying_check(ID *id,
continue;
}
/* Else, recursively check that user ID. */
- library_make_local_copying_check(par_id, loop_tags, id_relations, done_ids);
+ library_make_local_copying_check(from_id, loop_tags, id_relations, done_ids);
}
- if (par_id->tag & LIB_TAG_DOIT) {
+ if (from_id->tag & LIB_TAG_DOIT) {
/* This user will be fully local in future, so far so good,
* nothing to do here but check next user. */
}
diff --git a/source/blender/blenkernel/intern/lib_override.c b/source/blender/blenkernel/intern/lib_override.c
index a7e2394e7ad..388f50e12cf 100644
--- a/source/blender/blenkernel/intern/lib_override.c
+++ b/source/blender/blenkernel/intern/lib_override.c
@@ -374,9 +374,15 @@ static bool lib_override_hierarchy_recursive_tag(Main *bmain,
const uint missing_tag,
Library *override_group_lib_reference)
{
- void **entry_vp = BLI_ghash_lookup_p(bmain->relations->id_user_to_used, id);
+ void **entry_vp = BLI_ghash_lookup_p(bmain->relations->relations_from_pointers, id);
if (entry_vp == NULL) {
- /* Already processed. */
+ /* This ID is not used by nor using any other ID. */
+ return (id->tag & tag) != 0;
+ }
+
+ MainIDRelationsEntry *entry = *entry_vp;
+ if (entry->tags & MAINIDRELATIONS_ENTRY_TAGS_PROCESSED) {
+ /* This ID has already been processed. */
return (id->tag & tag) != 0;
}
@@ -393,22 +399,21 @@ static bool lib_override_hierarchy_recursive_tag(Main *bmain,
}
/* This way we won't process again that ID, should we encounter it again through another
- * relationship hierarchy.
- * Note that this does not free any memory from relations, so we can still use the entries.
- */
- BKE_main_relations_ID_remove(bmain, id);
+ * relationship hierarchy. */
+ entry->tags |= MAINIDRELATIONS_ENTRY_TAGS_PROCESSED;
- for (MainIDRelationsEntry *entry = *entry_vp; entry != NULL; entry = entry->next) {
- if ((entry->usage_flag & IDWALK_CB_LOOPBACK) != 0) {
+ for (MainIDRelationsEntryItem *to_id_entry = entry->to_ids; to_id_entry != NULL;
+ to_id_entry = to_id_entry->next) {
+ if ((to_id_entry->usage_flag & IDWALK_CB_LOOPBACK) != 0) {
/* Never consider 'loop back' relationships ('from', 'parents', 'owner' etc. pointers) as
* actual dependencies. */
continue;
}
/* We only consider IDs from the same library. */
- if (entry->id_pointer != NULL && (*entry->id_pointer)->lib == id->lib) {
- if (lib_override_hierarchy_recursive_tag(
- bmain, *entry->id_pointer, tag, missing_tag, override_group_lib_reference) &&
- override_group_lib_reference == NULL) {
+ if (*to_id_entry->id_pointer.to != NULL && (*to_id_entry->id_pointer.to)->lib == id->lib) {
+ const bool needs_tag = lib_override_hierarchy_recursive_tag(
+ bmain, *to_id_entry->id_pointer.to, tag, missing_tag, override_group_lib_reference);
+ if (needs_tag && override_group_lib_reference == NULL) {
id->tag |= tag;
}
}
@@ -1619,31 +1624,37 @@ static void lib_override_library_id_hierarchy_recursive_reset(Main *bmain, ID *i
return;
}
- void **entry_pp = BLI_ghash_lookup(bmain->relations->id_user_to_used, id_root);
- if (entry_pp == NULL) {
- /* Already processed. */
+ void **entry_vp = BLI_ghash_lookup_p(bmain->relations->relations_from_pointers, id_root);
+ if (entry_vp == NULL) {
+ /* This ID is not used by nor using any other ID. */
+ lib_override_library_id_reset_do(bmain, id_root);
+ return;
+ }
+
+ MainIDRelationsEntry *entry = *entry_vp;
+ if (entry->tags & MAINIDRELATIONS_ENTRY_TAGS_PROCESSED) {
+ /* This ID has already been processed. */
return;
}
lib_override_library_id_reset_do(bmain, id_root);
/* This way we won't process again that ID, should we encounter it again through another
- * relationship hierarchy.
- * Note that this does not free any memory from relations, so we can still use the entries.
- */
- BKE_main_relations_ID_remove(bmain, id_root);
+ * relationship hierarchy. */
+ entry->tags |= MAINIDRELATIONS_ENTRY_TAGS_PROCESSED;
- for (MainIDRelationsEntry *entry = *entry_pp; entry != NULL; entry = entry->next) {
- if ((entry->usage_flag & IDWALK_CB_LOOPBACK) != 0) {
+ for (MainIDRelationsEntryItem *to_id_entry = entry->to_ids; to_id_entry != NULL;
+ to_id_entry = to_id_entry->next) {
+ if ((to_id_entry->usage_flag & IDWALK_CB_LOOPBACK) != 0) {
/* Never consider 'loop back' relationships ('from', 'parents', 'owner' etc. pointers) as
* actual dependencies. */
continue;
}
/* We only consider IDs from the same library. */
- if (entry->id_pointer != NULL) {
- ID *id_entry = *entry->id_pointer;
- if (id_entry->override_library != NULL) {
- lib_override_library_id_hierarchy_recursive_reset(bmain, id_entry);
+ if (*to_id_entry->id_pointer.to != NULL) {
+ ID *to_id = *to_id_entry->id_pointer.to;
+ if (to_id->override_library != NULL) {
+ lib_override_library_id_hierarchy_recursive_reset(bmain, to_id);
}
}
}
diff --git a/source/blender/blenkernel/intern/lib_query.c b/source/blender/blenkernel/intern/lib_q
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list