Fix T57571: Blender crashes on UV transformation

That was caused by a thread safety issue on gpu_batch_presets_unregister()
which was not designed to be used for this kind of situation (managing 3D
meshes batches).
This commit is contained in:
Clément Foucault 2018-11-12 18:06:32 +01:00
parent 7f2401532e
commit d941f40c21
Notes: blender-bot 2023-02-14 08:59:10 +01:00
Referenced by issue #57571, Blender crashes on UV transformation.
2 changed files with 31 additions and 6 deletions

View File

@ -2195,12 +2195,24 @@ static void mesh_batch_cache_discard_uvedit(MeshBatchCache *cache)
GPU_INDEXBUF_DISCARD_SAFE(cache->edituv_visible_faces);
GPU_INDEXBUF_DISCARD_SAFE(cache->edituv_visible_edges);
gpu_batch_presets_unregister(cache->edituv_faces_strech_area);
gpu_batch_presets_unregister(cache->edituv_faces_strech_angle);
gpu_batch_presets_unregister(cache->edituv_faces);
gpu_batch_presets_unregister(cache->edituv_edges);
gpu_batch_presets_unregister(cache->edituv_verts);
gpu_batch_presets_unregister(cache->edituv_facedots);
if (cache->edituv_faces_strech_area) {
gpu_batch_presets_unregister(cache->edituv_faces_strech_area);
}
if (cache->edituv_faces_strech_angle) {
gpu_batch_presets_unregister(cache->edituv_faces_strech_angle);
}
if (cache->edituv_faces) {
gpu_batch_presets_unregister(cache->edituv_faces);
}
if (cache->edituv_edges) {
gpu_batch_presets_unregister(cache->edituv_edges);
}
if (cache->edituv_verts) {
gpu_batch_presets_unregister(cache->edituv_verts);
}
if (cache->edituv_facedots) {
gpu_batch_presets_unregister(cache->edituv_facedots);
}
GPU_BATCH_DISCARD_SAFE(cache->edituv_faces_strech_area);
GPU_BATCH_DISCARD_SAFE(cache->edituv_faces_strech_angle);

View File

@ -57,6 +57,8 @@ static struct {
struct {
uint pos, nor;
} attr_id;
ThreadMutex mutex;
} g_presets_3d = {{0}};
static ListBase presets_list = {NULL, NULL};
@ -214,33 +216,42 @@ void gpu_batch_presets_init(void)
g_presets_3d.batch.sphere_wire_med = batch_sphere_wire(8, 16);
gpu_batch_presets_register(g_presets_3d.batch.sphere_wire_med);
BLI_mutex_init(&g_presets_3d.mutex);
}
void gpu_batch_presets_register(GPUBatch *preset_batch)
{
BLI_mutex_lock(&g_presets_3d.mutex);
BLI_addtail(&presets_list, BLI_genericNodeN(preset_batch));
BLI_mutex_unlock(&g_presets_3d.mutex);
}
bool gpu_batch_presets_unregister(GPUBatch *preset_batch)
{
BLI_mutex_lock(&g_presets_3d.mutex);
for (LinkData *link = presets_list.last; link; link = link->prev) {
if (preset_batch == link->data) {
BLI_remlink(&presets_list, link);
BLI_mutex_unlock(&g_presets_3d.mutex);
MEM_freeN(link);
return true;
}
}
BLI_mutex_unlock(&g_presets_3d.mutex);
return false;
}
void gpu_batch_presets_reset(void)
{
BLI_mutex_lock(&g_presets_3d.mutex);
/* Reset vao caches for these every time we switch opengl context.
* This way they will draw correctly for each window. */
for (LinkData *link = presets_list.first; link; link = link->next) {
GPUBatch *preset = link->data;
GPU_batch_vao_cache_clear(preset);
}
BLI_mutex_unlock(&g_presets_3d.mutex);
}
void gpu_batch_presets_exit(void)
@ -251,4 +262,6 @@ void gpu_batch_presets_exit(void)
GPU_batch_discard(preset);
MEM_freeN(link);
}
BLI_mutex_end(&g_presets_3d.mutex);
}