Fix T58251: Cycles ignores linked meshes when rendering

The idea is to share a mesh data-block as a result across all objects
which are sharing same original mesh and have no effective modifiers.
This mesh is owned by an original copy-on-written version of object data.

Tricky part is to make sure it is only initialized once, and currently a
silly mutex lock is used. In practice it only locks if the mesh is not
already there.

As an extra bonus, even viewport memory is also lower after this change.

Reviewers: brecht, mont29

Reviewed By: brecht, mont29

Differential Revision: https://developer.blender.org/D4954
This commit is contained in:
2019-05-27 11:45:33 +02:00
parent da7e5e861f
commit 2f7711962a
6 changed files with 126 additions and 40 deletions

View File

@@ -361,6 +361,13 @@ static void object_update_from_subsurf_ccg(Object *object)
if (object->type != OB_MESH) {
return;
}
/* If object does not own evaluated mesh we can not access it since it might be freed already
* (happens on dependency graph free where order of CoW-ed IDs free is undefined).
*
* Good news is: such mesh does not have modifiers applied, so no need to worry about CCG. */
if (!object->runtime.is_mesh_eval_owned) {
return;
}
/* Object was never evaluated, so can not have CCG subdivision surface. */
Mesh *mesh_eval = object->runtime.mesh_eval;
if (mesh_eval == NULL) {
@@ -448,12 +455,13 @@ void BKE_object_free_derived_caches(Object *ob)
object_update_from_subsurf_ccg(ob);
BKE_object_free_derived_mesh_caches(ob);
if (ob->runtime.mesh_eval != NULL) {
/* Restore initial pointer. */
if (ob->runtime.mesh_orig != NULL) {
ob->data = ob->runtime.mesh_orig;
}
if ((ob->runtime.mesh_eval != NULL && ob->runtime.is_mesh_eval_owned)) {
Mesh *mesh_eval = ob->runtime.mesh_eval;
/* Restore initial pointer. */
if (ob->data == mesh_eval) {
ob->data = ob->runtime.mesh_orig;
}
/* Evaluated mesh points to edit mesh, but does not own it. */
mesh_eval->edit_mesh = NULL;
BKE_mesh_free(mesh_eval);