Fix T38403: Laplacian smooth on instanced objects leads to crash.

The laplacian modifiers (smooth and deform) use the OpenNL library,
which is not threadsafe due to the use of a global context variable.
Ideally this would be changed so that an explicit context can be
created for every caller of the OpenNL functions, but since OpenNL's
most recent version is from 2010 this is unlikely to happen.

As a workaround for now just use a mutex to prevent conflicting OpenNL
calls. Eventually OpenNL can be replaced by eigen or ceres.
This commit is contained in:
Lukas Tönne 2014-01-30 13:06:48 +01:00
parent 810c6d1880
commit 2b55d7895c
Notes: blender-bot 2023-02-14 11:16:52 +01:00
Referenced by issue #38409, Snapping Bug
Referenced by issue #38403, Laplacian smooth on instanced objects leads to crash
4 changed files with 59 additions and 5 deletions

View File

@ -452,6 +452,10 @@ static void laplacianDeformPreview(LaplacianSystem *sys, float (*vertexCos)[3])
n = sys->total_verts;
na = sys->total_anchors;
#ifdef OPENNL_THREADING_HACK
modifier_opennl_lock();
#endif
if (!sys->is_matrix_computed) {
nlNewContext();
sys->context = nlGetCurrent();
@ -530,12 +534,9 @@ static void laplacianDeformPreview(LaplacianSystem *sys, float (*vertexCos)[3])
sys->has_solution = false;
}
sys->is_matrix_computed = true;
}
else {
if (!sys->has_solution) {
return;
}
}
else if (sys->has_solution) {
nlBegin(NL_SYSTEM);
nlBegin(NL_MATRIX);
@ -589,6 +590,10 @@ static void laplacianDeformPreview(LaplacianSystem *sys, float (*vertexCos)[3])
sys->has_solution = false;
}
}
#ifdef OPENNL_THREADING_HACK
modifier_opennl_unlock();
#endif
}
static bool isValidVertexGroup(LaplacianDeformModifierData *lmd, Object *ob, DerivedMesh *dm)

View File

@ -534,6 +534,11 @@ static void laplaciansmoothModifier_do(
sys->vert_centroid[1] = 0.0f;
sys->vert_centroid[2] = 0.0f;
memset_laplacian_system(sys, 0);
#ifdef OPENNL_THREADING_HACK
modifier_opennl_lock();
#endif
nlNewContext();
sys->context = nlGetCurrent();
nlSolverParameteri(NL_NB_VARIABLES, numVerts);
@ -618,6 +623,11 @@ static void laplaciansmoothModifier_do(
}
nlDeleteContext(sys->context);
sys->context = NULL;
#ifdef OPENNL_THREADING_HACK
modifier_opennl_unlock();
#endif
delete_laplacian_system(sys);
}

View File

@ -61,6 +61,10 @@
#include "RE_shader_ext.h"
#ifdef OPENNL_THREADING_HACK
#include "BLI_threads.h"
#endif
void modifier_init_texture(Scene *scene, Tex *tex)
{
if (!tex)
@ -235,6 +239,24 @@ void modifier_get_vgroup(Object *ob, DerivedMesh *dm, const char *name, MDeformV
}
}
#ifdef OPENNL_THREADING_HACK
static ThreadMutex opennl_context_mutex = BLI_MUTEX_INITIALIZER;
void modifier_opennl_lock(void)
{
BLI_mutex_lock(&opennl_context_mutex);
}
void modifier_opennl_unlock(void)
{
BLI_mutex_unlock(&opennl_context_mutex);
}
#endif
/* only called by BKE_modifier.h/modifier.c */
void modifier_type_init(ModifierTypeInfo *types[])
{

View File

@ -52,4 +52,21 @@ struct DerivedMesh *get_dm_for_modifier(struct Object *ob, ModifierApplyFlag fla
void modifier_get_vgroup(struct Object *ob, struct DerivedMesh *dm,
const char *name, struct MDeformVert **dvert, int *defgrp_index);
/* XXX workaround for non-threadsafe context in OpenNL (T38403)
* OpenNL uses global pointer for "current context", which causes
* conflict when multiple modifiers get evaluated in threaded depgraph.
* This is just a stupid hack to prevent assert failure / crash,
* otherwise we'd have to modify OpenNL on a large scale.
* OpenNL should be replaced eventually, there are other options (eigen, ceres).
* - lukas_t
*/
#ifdef WITH_OPENNL
#define OPENNL_THREADING_HACK
#endif
#ifdef OPENNL_THREADING_HACK
void modifier_opennl_lock(void);
void modifier_opennl_unlock(void);
#endif
#endif /* __MOD_UTIL_H__ */