Draw: Avoid hang when depsgraph update happens during draw
This should not happen and any failure here should be considered a bug. But for end users better not to hang Blender, and to have a better diagnostic for developers in bug reports. Ref #82483 Pull Request: https://projects.blender.org/blender/blender/pulls/123023
This commit is contained in:
parent
4f593b5710
commit
27f467e028
@ -144,6 +144,7 @@ typedef struct TicketMutex TicketMutex;
|
||||
TicketMutex *BLI_ticket_mutex_alloc(void);
|
||||
void BLI_ticket_mutex_free(TicketMutex *ticket);
|
||||
void BLI_ticket_mutex_lock(TicketMutex *ticket);
|
||||
bool BLI_ticket_mutex_lock_check_recursive(TicketMutex *ticket);
|
||||
void BLI_ticket_mutex_unlock(TicketMutex *ticket);
|
||||
|
||||
/* Condition */
|
||||
|
@ -504,6 +504,8 @@ struct TicketMutex {
|
||||
pthread_cond_t cond;
|
||||
pthread_mutex_t mutex;
|
||||
uint queue_head, queue_tail;
|
||||
pthread_t owner;
|
||||
bool has_owner;
|
||||
};
|
||||
|
||||
TicketMutex *BLI_ticket_mutex_alloc()
|
||||
@ -524,24 +526,46 @@ void BLI_ticket_mutex_free(TicketMutex *ticket)
|
||||
MEM_freeN(ticket);
|
||||
}
|
||||
|
||||
void BLI_ticket_mutex_lock(TicketMutex *ticket)
|
||||
static bool ticket_mutex_lock(TicketMutex *ticket, const bool check_recursive)
|
||||
{
|
||||
uint queue_me;
|
||||
|
||||
pthread_mutex_lock(&ticket->mutex);
|
||||
|
||||
/* Check for recursive locks, for debugging only. */
|
||||
if (check_recursive && ticket->has_owner && pthread_equal(pthread_self(), ticket->owner)) {
|
||||
pthread_mutex_unlock(&ticket->mutex);
|
||||
return false;
|
||||
}
|
||||
|
||||
queue_me = ticket->queue_tail++;
|
||||
|
||||
while (queue_me != ticket->queue_head) {
|
||||
pthread_cond_wait(&ticket->cond, &ticket->mutex);
|
||||
}
|
||||
|
||||
ticket->owner = pthread_self();
|
||||
ticket->has_owner = true;
|
||||
|
||||
pthread_mutex_unlock(&ticket->mutex);
|
||||
return true;
|
||||
}
|
||||
|
||||
void BLI_ticket_mutex_lock(TicketMutex *ticket)
|
||||
{
|
||||
ticket_mutex_lock(ticket, false);
|
||||
}
|
||||
|
||||
bool BLI_ticket_mutex_lock_check_recursive(TicketMutex *ticket)
|
||||
{
|
||||
return ticket_mutex_lock(ticket, true);
|
||||
}
|
||||
|
||||
void BLI_ticket_mutex_unlock(TicketMutex *ticket)
|
||||
{
|
||||
pthread_mutex_lock(&ticket->mutex);
|
||||
ticket->queue_head++;
|
||||
ticket->has_owner = false;
|
||||
pthread_cond_broadcast(&ticket->cond);
|
||||
pthread_mutex_unlock(&ticket->mutex);
|
||||
}
|
||||
|
@ -8,6 +8,8 @@
|
||||
|
||||
#include <cstdio>
|
||||
|
||||
#include "CLG_log.h"
|
||||
|
||||
#include "BLI_alloca.h"
|
||||
#include "BLI_listbase.h"
|
||||
#include "BLI_memblock.h"
|
||||
@ -103,6 +105,8 @@
|
||||
|
||||
#include "DRW_select_buffer.hh"
|
||||
|
||||
static CLG_LogRef LOG = {"draw.manager"};
|
||||
|
||||
/** Render State: No persistent data between draw calls. */
|
||||
DRWManager DST = {nullptr};
|
||||
|
||||
@ -1327,10 +1331,17 @@ void DRW_notify_view_update(const DRWUpdateContext *update_ctx)
|
||||
|
||||
const bool gpencil_engine_needed = drw_gpencil_engine_needed(depsgraph, v3d);
|
||||
|
||||
/* XXX Really nasty locking. But else this could
|
||||
* be executed by the material previews thread
|
||||
* while rendering a viewport. */
|
||||
BLI_ticket_mutex_lock(DST.system_gpu_context_mutex);
|
||||
/* XXX Really nasty locking. But else this could be executed by the
|
||||
* material previews thread while rendering a viewport.
|
||||
*
|
||||
* Check for recursive lock which can deadlock. This should not
|
||||
* happen, but in case there is a bug where depsgraph update is called
|
||||
* during drawing we try not to hang Blender. */
|
||||
if (!BLI_ticket_mutex_lock_check_recursive(DST.system_gpu_context_mutex)) {
|
||||
CLOG_ERROR(&LOG, "GPU context already bound");
|
||||
BLI_assert_unreachable();
|
||||
return;
|
||||
}
|
||||
|
||||
/* Reset before using it. */
|
||||
drw_state_prepare_clean_for_draw(&DST);
|
||||
|
Loading…
Reference in New Issue
Block a user