diff --git a/core/templates/command_queue_mt.h b/core/templates/command_queue_mt.h index bcec23f1db8..80566ced20b 100644 --- a/core/templates/command_queue_mt.h +++ b/core/templates/command_queue_mt.h @@ -107,7 +107,8 @@ class CommandQueueMT { static const uint32_t DEFAULT_COMMAND_MEM_SIZE_KB = 64; - bool unique_flusher = false; + inline static thread_local bool flushing = false; + BinaryMutex mutex; LocalVector command_mem; ConditionVariable sync_cond_var; @@ -157,10 +158,20 @@ class CommandQueueMT { } void _flush() { + // Safeguard against trying to re-lock the binary mutex. + if (flushing) { + return; + } + + flushing = true; + MutexLock lock(mutex); if (unlikely(flush_read_ptr)) { - // Re-entrant call. + // Another thread is flushing. + lock.temp_unlock(); // Not really temp. + sync(); + flushing = false; return; } @@ -177,17 +188,9 @@ class CommandQueueMT { CommandBase *cmd_local = reinterpret_cast(cmd_local_mem); memcpy(cmd_local_mem, (char *)cmd_original, size); - if (unique_flusher) { - // A single thread will pump; the lock is only needed for the command queue itself. - lock.temp_unlock(); - cmd_local->call(); - lock.temp_relock(); - } else { - // At least we can unlock during WTP operations. - uint32_t allowance_id = WorkerThreadPool::thread_enter_unlock_allowance_zone(lock); - cmd_local->call(); - WorkerThreadPool::thread_exit_unlock_allowance_zone(allowance_id); - } + lock.temp_unlock(); + cmd_local->call(); + lock.temp_relock(); if (unlikely(cmd_local->sync)) { sync_head++; @@ -206,6 +209,8 @@ class CommandQueueMT { flush_read_ptr = 0; _prevent_sync_wraparound(); + + flushing = false; } _FORCE_INLINE_ void _wait_for_sync(MutexLock &p_lock) { @@ -270,8 +275,7 @@ public: pump_task_id = p_task_id; } - CommandQueueMT(bool p_unique_flusher = false) : - unique_flusher(p_unique_flusher) { + CommandQueueMT() { command_mem.reserve(DEFAULT_COMMAND_MEM_SIZE_KB * 1024); } }; diff --git a/modules/betsy/image_compress_betsy.h b/modules/betsy/image_compress_betsy.h index 78352a12947..15b58894970 100644 --- a/modules/betsy/image_compress_betsy.h +++ b/modules/betsy/image_compress_betsy.h @@ -103,7 +103,7 @@ Error _betsy_compress_s3tc(Image *r_img, Image::UsedChannels p_channels); class BetsyCompressor : public Object { GDSOFTCLASS(BetsyCompressor, Object); - mutable CommandQueueMT command_queue = CommandQueueMT(true); + mutable CommandQueueMT command_queue; bool exit = false; WorkerThreadPool::TaskID task_id = WorkerThreadPool::INVALID_TASK_ID; diff --git a/servers/rendering/rendering_server_default.h b/servers/rendering/rendering_server_default.h index 6fdc1917e80..5ddde49c114 100644 --- a/servers/rendering/rendering_server_default.h +++ b/servers/rendering/rendering_server_default.h @@ -74,7 +74,7 @@ class RenderingServerDefault : public RenderingServer { uint64_t print_frame_profile_ticks_from = 0; uint32_t print_frame_profile_frame_count = 0; - mutable CommandQueueMT command_queue = CommandQueueMT(true); + mutable CommandQueueMT command_queue; Thread::ID server_thread = Thread::MAIN_ID; WorkerThreadPool::TaskID server_task_id = WorkerThreadPool::INVALID_TASK_ID;