Fix T52149: LoopTriArray computation was not correctly protected against concurrency.

Note: this commit seems to work as expected (also with transform
snapping etc.). However, it is rather unsafe - not enough for 2.79 at
least, unless we get much more testing on it. It also depends on three
previous ones.

Note that using a global lock here is far from ideal, we should rather
have a lock per DM, but that will do for now, whole DM thing is doomed
to oblivion anyway in 2.8.

Also, we may need a `DM_DIRTY_LOOPTRIS` dirty flag at some point. Looks
like we can survive without it for now though... Probably because cached
looptris are never copied accross DM's?
This commit is contained in:
Bastien Montagne 2017-08-11 16:51:19 +02:00
parent c034193821
commit 00cb352790
Notes: blender-bot 2023-02-14 06:46:23 +01:00
Referenced by issue #52149, Crash on entering Edit Mode of high poly mesh used by Shrink Wrap
3 changed files with 14 additions and 5 deletions

View File

@ -220,7 +220,7 @@ struct DerivedMesh {
/** Recalculates mesh tessellation */
void (*recalcTessellation)(DerivedMesh *dm);
/** Loop tessellation cache */
/** Loop tessellation cache (WARNING! Only call inside threading-protected code!) */
void (*recalcLoopTri)(DerivedMesh *dm);
/** accessor functions */
const struct MLoopTri *(*getLoopTriArray)(DerivedMesh * dm);

View File

@ -93,6 +93,10 @@ static DerivedMesh *navmesh_dm_createNavMeshForVisualization(DerivedMesh *dm);
# define ASSERT_IS_VALID_DM(dm)
#endif
static ThreadMutex loops_cache_lock = BLI_MUTEX_INITIALIZER;
static void add_shapekey_layers(DerivedMesh *dm, Mesh *me, Object *ob);
static void shapekey_layers_to_keyblocks(DerivedMesh *dm, Mesh *me, int actshape_uid);
@ -241,7 +245,13 @@ static const MLoopTri *dm_getLoopTriArray(DerivedMesh *dm)
BLI_assert(dm->getNumLoopTri(dm) == dm->looptris.num);
}
else {
dm->recalcLoopTri(dm);
BLI_mutex_lock(&loops_cache_lock);
/* We need to ensure array is still NULL inside mutex-protected code, some other thread might have already
* recomputed those looptris. */
if (dm->looptris.array == NULL) {
dm->recalcLoopTri(dm);
}
BLI_mutex_unlock(&loops_cache_lock);
}
return dm->looptris.array;
}

View File

@ -4474,10 +4474,10 @@ static void ccgDM_recalcTessellation(DerivedMesh *UNUSED(dm))
/* Nothing to do: CCG handles creating its own tessfaces */
}
/* WARNING! *MUST* be called in an 'loops_cache_rwlock' protected thread context! */
static void ccgDM_recalcLoopTri(DerivedMesh *dm)
{
BLI_rw_mutex_lock(&loops_cache_rwlock, THREAD_LOCK_WRITE);
MLoopTri *mlooptri;
MLoopTri *mlooptri = dm->looptris.array;
const int tottri = dm->numPolyData * 2;
int i, poly_index;
@ -4502,7 +4502,6 @@ static void ccgDM_recalcLoopTri(DerivedMesh *dm)
lt->tri[2] = (poly_index * 4) + 2;
lt->poly = poly_index;
}
BLI_rw_mutex_unlock(&loops_cache_rwlock);
}
static void ccgDM_calcNormals(DerivedMesh *dm)