From e43b6e2f9725edd8cbe1ca8538c8a2bbdf1b45cd Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Tue, 3 Nov 2015 21:16:58 +0100 Subject: Fix T46672: Concurrent access to source DM in datatransfer modifier. There is no real elegant solution here, ideally a modifier shall never *modify* a source DM, but that would imply much better ways to ensure required data is available in that source DM, which we do not have currently. So instead, let's use brute force solution for now and always create a local copy of our source DM, that we can modify to our heart content! --- source/blender/blenkernel/intern/data_transfer.c | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) (limited to 'source/blender/blenkernel/intern/data_transfer.c') diff --git a/source/blender/blenkernel/intern/data_transfer.c b/source/blender/blenkernel/intern/data_transfer.c index 43d23e92901..d22a8451c01 100644 --- a/source/blender/blenkernel/intern/data_transfer.c +++ b/source/blender/blenkernel/intern/data_transfer.c @@ -42,6 +42,7 @@ #include "BLI_blenlib.h" #include "BLI_utildefines.h" +#include "BKE_cdderivedmesh.h" #include "BKE_context.h" #include "BKE_customdata.h" #include "BKE_data_transfer.h" @@ -1136,11 +1137,15 @@ bool BKE_object_data_transfer_dm( /* XXX Hack! In case this is being evaluated from dm stack, we cannot compute final dm, * can lead to infinite recursion in case of dependency cycles of DataTransfer modifiers... * Issue is, this means we cannot be sure to have requested cd layers in source. + * + * Also, we need to make a local copy of dm_src, otherwise we may end with concurrent creation + * of data in it (multi-threaded evaluation of the modifier stack, see T46672). */ dm_src = dm_dst ? ob_src->derivedFinal : mesh_get_derived_final(scene, ob_src, dm_src_mask); if (!dm_src) { return changed; } + dm_src = CDDM_copy(dm_src); if (auto_transform) { MVert *verts_dst = dm_dst ? dm_dst->getVertArray(dm_dst) : me_dst->mvert; @@ -1190,12 +1195,12 @@ bool BKE_object_data_transfer_dm( BKE_report(reports, RPT_ERROR, "Source and destination meshes do not have the same amount of vertices, " "'Topology' mapping cannot be used in this case"); - return changed; + continue; } if (ELEM(0, num_verts_dst, num_verts_src)) { BKE_report(reports, RPT_ERROR, "Source or destination meshes do not have any vertices, cannot transfer vertex data"); - return changed; + continue; } BKE_mesh_remap_calc_verts_from_dm( @@ -1238,12 +1243,12 @@ bool BKE_object_data_transfer_dm( BKE_report(reports, RPT_ERROR, "Source and destination meshes do not have the same amount of edges, " "'Topology' mapping cannot be used in this case"); - return changed; + continue; } if (ELEM(0, num_edges_dst, num_edges_src)) { BKE_report(reports, RPT_ERROR, "Source or destination meshes do not have any edges, cannot transfer edge data"); - return changed; + continue; } BKE_mesh_remap_calc_edges_from_dm( @@ -1297,12 +1302,12 @@ bool BKE_object_data_transfer_dm( BKE_report(reports, RPT_ERROR, "Source and destination meshes do not have the same amount of face corners, " "'Topology' mapping cannot be used in this case"); - return changed; + continue; } if (ELEM(0, num_loops_dst, num_loops_src)) { BKE_report(reports, RPT_ERROR, "Source or destination meshes do not have any polygons, cannot transfer loop data"); - return changed; + continue; } BKE_mesh_remap_calc_loops_from_dm( @@ -1355,12 +1360,12 @@ bool BKE_object_data_transfer_dm( BKE_report(reports, RPT_ERROR, "Source and destination meshes do not have the same amount of faces, " "'Topology' mapping cannot be used in this case"); - return changed; + continue; } if (ELEM(0, num_polys_dst, num_polys_src)) { BKE_report(reports, RPT_ERROR, "Source or destination meshes do not have any polygons, cannot transfer poly data"); - return changed; + continue; } BKE_mesh_remap_calc_polys_from_dm( @@ -1402,6 +1407,7 @@ bool BKE_object_data_transfer_dm( BKE_mesh_remap_free(&geom_map[i]); MEM_SAFE_FREE(weights[i]); } + dm_src->release(dm_src); return changed; -- cgit v1.2.3