diff --git a/engine/src/flutter/impeller/renderer/backend/metal/context_mtl.h b/engine/src/flutter/impeller/renderer/backend/metal/context_mtl.h index dbc3806939..15bb2fd46e 100644 --- a/engine/src/flutter/impeller/renderer/backend/metal/context_mtl.h +++ b/engine/src/flutter/impeller/renderer/backend/metal/context_mtl.h @@ -164,7 +164,9 @@ class ContextMTL final : public Context, std::shared_ptr resource_allocator_; std::shared_ptr device_capabilities_; std::shared_ptr is_gpu_disabled_sync_switch_; - std::deque tasks_awaiting_gpu_; + Mutex tasks_awaiting_gpu_mutex_; + std::deque tasks_awaiting_gpu_ IPLR_GUARDED_BY( + tasks_awaiting_gpu_mutex_); std::unique_ptr sync_switch_observer_; std::shared_ptr command_queue_ip_; #ifdef IMPELLER_DEBUG diff --git a/engine/src/flutter/impeller/renderer/backend/metal/context_mtl.mm b/engine/src/flutter/impeller/renderer/backend/metal/context_mtl.mm index 2d6c432e1b..0a66c82146 100644 --- a/engine/src/flutter/impeller/renderer/backend/metal/context_mtl.mm +++ b/engine/src/flutter/impeller/renderer/backend/metal/context_mtl.mm @@ -381,21 +381,39 @@ id ContextMTL::CreateMTLCommandBuffer( void ContextMTL::StoreTaskForGPU(const fml::closure& task, const fml::closure& failure) { - tasks_awaiting_gpu_.push_back(PendingTasks{task, failure}); - while (tasks_awaiting_gpu_.size() > kMaxTasksAwaitingGPU) { - const PendingTasks& front = tasks_awaiting_gpu_.front(); - if (front.failure) { - front.failure(); + std::vector failed_tasks; + { + Lock lock(tasks_awaiting_gpu_mutex_); + tasks_awaiting_gpu_.push_back(PendingTasks{task, failure}); + int32_t failed_task_count = + tasks_awaiting_gpu_.size() - kMaxTasksAwaitingGPU; + if (failed_task_count > 0) { + failed_tasks.reserve(failed_task_count); + failed_tasks.insert(failed_tasks.end(), + std::make_move_iterator(tasks_awaiting_gpu_.begin()), + std::make_move_iterator(tasks_awaiting_gpu_.begin() + + failed_task_count)); + tasks_awaiting_gpu_.erase( + tasks_awaiting_gpu_.begin(), + tasks_awaiting_gpu_.begin() + failed_task_count); + } + } + for (const PendingTasks& task : failed_tasks) { + if (task.failure) { + task.failure(); } - tasks_awaiting_gpu_.pop_front(); } } void ContextMTL::FlushTasksAwaitingGPU() { - for (const auto& task : tasks_awaiting_gpu_) { + std::deque tasks_awaiting_gpu; + { + Lock lock(tasks_awaiting_gpu_mutex_); + std::swap(tasks_awaiting_gpu, tasks_awaiting_gpu_); + } + for (const auto& task : tasks_awaiting_gpu) { task.task(); } - tasks_awaiting_gpu_.clear(); } ContextMTL::SyncSwitchObserver::SyncSwitchObserver(ContextMTL& parent)