Fix T101836: Blender crashes upon render finish when clearing unused data during a render.

Imgaes which are render results and the like should not be considered as
unused, even if they do not have actual users.

NOTE: this does not apply to 'regular' images, which should be purged by
the recursive purge code, even if they are currently shown in an Image
Editor (this is not actual data usage).
This commit is contained in:
Bastien Montagne 2022-11-16 14:51:44 +01:00
parent 3b35d9d667
commit 59641042a7
Notes: blender-bot 2023-02-14 06:42:54 +01:00
Referenced by issue #101836, Blender crashes upon render finish when clearing unused data during a render
1 changed files with 14 additions and 7 deletions

View File

@ -684,6 +684,15 @@ static void lib_query_unused_ids_tag_recurse(Main *bmain,
return;
}
if (ELEM(GS(id->name), ID_IM)) {
/* Images which have a 'viewer' source (e.g. render results) should not be considered as
* orphaned/unused data. */
Image *image = (Image *)id;
if (image->source == IMA_SRC_VIEWER) {
return;
}
}
/* An ID user is 'valid' (i.e. may affect the 'used'/'not used' status of the ID it uses) if it
* does not match `ignored_usages`, and does match `required_usages`. */
const int ignored_usages = (IDWALK_CB_LOOPBACK | IDWALK_CB_EMBEDDED);
@ -696,11 +705,10 @@ static void lib_query_unused_ids_tag_recurse(Main *bmain,
bool has_valid_from_users = false;
/* Preemptively consider this ID as unused. That way if there is a loop of dependency leading
* back to it, it won't create a fake 'valid user' detection.
* NOTE: This can only be done for a subset of IDs, some types are never 'indirectly unused',
* same for IDs with a fake user. */
if ((id->flag & LIB_FAKEUSER) == 0 && !ELEM(GS(id->name), ID_SCE, ID_WM, ID_SCR, ID_WS, ID_LI)) {
id->tag |= tag;
}
* NOTE: there are some cases (like when fake user is set, or some ID types) which are never
* 'indirectly unused'. However, these have already been checked and early-returned above, so any
* ID reaching this point of the function can be tagged. */
id->tag |= tag;
for (MainIDRelationsEntryItem *id_from_item = id_relations->from_ids; id_from_item != NULL;
id_from_item = id_from_item->next) {
if ((id_from_item->usage_flag & ignored_usages) != 0 ||
@ -727,8 +735,7 @@ static void lib_query_unused_ids_tag_recurse(Main *bmain,
id->tag &= ~tag;
}
else {
/* This ID has no 'valid' users, tag it as unused. */
id->tag |= tag;
/* This ID has no 'valid' users, its 'unused' tag preemptively set above can be kept. */
if (r_num_tagged != NULL) {
r_num_tagged[INDEX_ID_NULL]++;
r_num_tagged[BKE_idtype_idcode_to_index(GS(id->name))]++;