mirror of
https://github.com/godotengine/godot
synced 2024-10-02 23:48:45 +00:00
Merge pull request #91725 from RandomShaper/cmd_queue_avoid_skip
`CommandQueueMT`: Fix sync command awaiters missing the chance
This commit is contained in:
commit
c4279fe3e0
|
@ -327,7 +327,6 @@ class CommandQueueMT {
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
DEFAULT_COMMAND_MEM_SIZE_KB = 256,
|
DEFAULT_COMMAND_MEM_SIZE_KB = 256,
|
||||||
SYNC_SEMAPHORES = 8
|
|
||||||
};
|
};
|
||||||
|
|
||||||
BinaryMutex mutex;
|
BinaryMutex mutex;
|
||||||
|
@ -335,6 +334,7 @@ class CommandQueueMT {
|
||||||
ConditionVariable sync_cond_var;
|
ConditionVariable sync_cond_var;
|
||||||
uint32_t sync_head = 0;
|
uint32_t sync_head = 0;
|
||||||
uint32_t sync_tail = 0;
|
uint32_t sync_tail = 0;
|
||||||
|
uint32_t sync_awaiters = 0;
|
||||||
WorkerThreadPool::TaskID pump_task_id = WorkerThreadPool::INVALID_TASK_ID;
|
WorkerThreadPool::TaskID pump_task_id = WorkerThreadPool::INVALID_TASK_ID;
|
||||||
uint64_t flush_read_ptr = 0;
|
uint64_t flush_read_ptr = 0;
|
||||||
|
|
||||||
|
@ -349,6 +349,15 @@ class CommandQueueMT {
|
||||||
return cmd;
|
return cmd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_FORCE_INLINE_ void _prevent_sync_wraparound() {
|
||||||
|
bool safe_to_reset = !sync_awaiters;
|
||||||
|
bool already_sync_to_latest = sync_head == sync_tail;
|
||||||
|
if (safe_to_reset && already_sync_to_latest) {
|
||||||
|
sync_head = 0;
|
||||||
|
sync_tail = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void _flush() {
|
void _flush() {
|
||||||
if (unlikely(flush_read_ptr)) {
|
if (unlikely(flush_read_ptr)) {
|
||||||
// Re-entrant call.
|
// Re-entrant call.
|
||||||
|
@ -365,7 +374,9 @@ class CommandQueueMT {
|
||||||
cmd->call();
|
cmd->call();
|
||||||
if (unlikely(cmd->sync)) {
|
if (unlikely(cmd->sync)) {
|
||||||
sync_head++;
|
sync_head++;
|
||||||
|
unlock(); // Give an opportunity to awaiters right away.
|
||||||
sync_cond_var.notify_all();
|
sync_cond_var.notify_all();
|
||||||
|
lock();
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the command involved reallocating the buffer, the address may have changed.
|
// If the command involved reallocating the buffer, the address may have changed.
|
||||||
|
@ -378,14 +389,20 @@ class CommandQueueMT {
|
||||||
|
|
||||||
command_mem.clear();
|
command_mem.clear();
|
||||||
flush_read_ptr = 0;
|
flush_read_ptr = 0;
|
||||||
|
|
||||||
|
_prevent_sync_wraparound();
|
||||||
|
|
||||||
unlock();
|
unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
_FORCE_INLINE_ void _wait_for_sync(MutexLock<BinaryMutex> &p_lock) {
|
_FORCE_INLINE_ void _wait_for_sync(MutexLock<BinaryMutex> &p_lock) {
|
||||||
|
sync_awaiters++;
|
||||||
uint32_t sync_head_goal = sync_tail;
|
uint32_t sync_head_goal = sync_tail;
|
||||||
do {
|
do {
|
||||||
sync_cond_var.wait(p_lock);
|
sync_cond_var.wait(p_lock);
|
||||||
} while (sync_head != sync_head_goal); // Can't use lower-than because of wraparound.
|
} while (sync_head < sync_head_goal);
|
||||||
|
sync_awaiters--;
|
||||||
|
_prevent_sync_wraparound();
|
||||||
}
|
}
|
||||||
|
|
||||||
void _no_op() {}
|
void _no_op() {}
|
||||||
|
|
Loading…
Reference in a new issue