forked from bartvdbraak/blender
Fix T39209: Localizing materials could cause heisenbug with concurrent
depsgraph updates. Material datablocks were localized by first making a regular datablock copy, which always gets inserted into the bmain list, and then removing it again from bmain. Problem is that this localization happens in preview threads, which can run while the depsgraph is also updating GPU materials. In case the copying of materials takes any amount of time, this can cause the depsgraph call to material_changed to use an invalid, localized material and access invalid GPUMaterial lists which have already been freed for the actual material. Solution is to not add localized datablocks to the bmain lists in the first place. bmain should be totally immutable during preview or render threads.
This commit is contained in:
parent
7148c97796
commit
c626462c0f
@ -49,6 +49,7 @@ struct PropertyRNA;
|
||||
|
||||
void *BKE_libblock_alloc(struct Main *bmain, short type, const char *name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
|
||||
void *BKE_libblock_copy_ex(struct Main *bmain, struct ID *id) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
|
||||
void *BKE_libblock_copy_nolib(struct ID *id) ATTR_NONNULL();
|
||||
void *BKE_libblock_copy(struct ID *id) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
|
||||
void BKE_libblock_copy_data(struct ID *id, const struct ID *id_from, const bool do_action);
|
||||
|
||||
|
@ -808,6 +808,32 @@ void *BKE_libblock_copy_ex(Main *bmain, ID *id)
|
||||
return idn;
|
||||
}
|
||||
|
||||
void *BKE_libblock_copy_nolib(ID *id)
|
||||
{
|
||||
ID *idn;
|
||||
size_t idn_len;
|
||||
|
||||
idn = alloc_libblock_notest(GS(id->name));
|
||||
assert(idn != NULL);
|
||||
|
||||
BLI_strncpy(idn->name, id->name, sizeof(idn->name));
|
||||
|
||||
idn_len = MEM_allocN_len(idn);
|
||||
if ((int)idn_len - (int)sizeof(ID) > 0) { /* signed to allow neg result */
|
||||
const char *cp = (const char *)id;
|
||||
char *cpn = (char *)idn;
|
||||
|
||||
memcpy(cpn + sizeof(ID), cp + sizeof(ID), idn_len - sizeof(ID));
|
||||
}
|
||||
|
||||
id->newid = idn;
|
||||
idn->flag |= LIB_NEW;
|
||||
|
||||
BKE_libblock_copy_data(idn, id, false);
|
||||
|
||||
return idn;
|
||||
}
|
||||
|
||||
void *BKE_libblock_copy(ID *id)
|
||||
{
|
||||
return BKE_libblock_copy_ex(G.main, id);
|
||||
|
@ -734,6 +734,7 @@ Mask *BKE_mask_new(Main *bmain, const char *name)
|
||||
return mask;
|
||||
}
|
||||
|
||||
/* TODO(sergey): Use generic BKE_libblock_copy_nolib() instead. */
|
||||
Mask *BKE_mask_copy_nolib(Mask *mask)
|
||||
{
|
||||
Mask *mask_new;
|
||||
|
@ -256,8 +256,7 @@ Material *localize_material(Material *ma)
|
||||
Material *man;
|
||||
int a;
|
||||
|
||||
man = BKE_libblock_copy(&ma->id);
|
||||
BLI_remlink(&G.main->mat, man);
|
||||
man = BKE_libblock_copy_nolib(&ma->id);
|
||||
|
||||
/* no increment for texture ID users, in previewrender.c it prevents decrement */
|
||||
for (a = 0; a < MAX_MTEX; a++) {
|
||||
|
Loading…
Reference in New Issue
Block a user