diff --git a/engine/src/flutter/impeller/renderer/backend/gles/reactor_gles.cc b/engine/src/flutter/impeller/renderer/backend/gles/reactor_gles.cc index 82266bfd998..c72f0d4af83 100644 --- a/engine/src/flutter/impeller/renderer/backend/gles/reactor_gles.cc +++ b/engine/src/flutter/impeller/renderer/backend/gles/reactor_gles.cc @@ -203,7 +203,6 @@ HandleGLES ReactorGLES::CreateHandle(HandleType type, GLuint external_handle) { if (new_handle.IsDead()) { return HandleGLES::DeadHandle(); } - WriterLock handles_lock(handles_mutex_); std::optional gl_handle; if (external_handle != GL_NONE) { @@ -211,6 +210,8 @@ HandleGLES ReactorGLES::CreateHandle(HandleType type, GLuint external_handle) { } else if (CanReactOnCurrentThread()) { gl_handle = CreateGLHandle(GetProcTable(), type); } + + WriterLock handles_lock(handles_mutex_); handles_[new_handle] = LiveHandle{gl_handle}; return new_handle; } @@ -266,41 +267,56 @@ bool ReactorGLES::ReactOnce() { bool ReactorGLES::ConsolidateHandles() { TRACE_EVENT0("impeller", __FUNCTION__); const auto& gl = GetProcTable(); - WriterLock handles_lock(handles_mutex_); - std::vector handles_to_delete; - for (auto& handle : handles_) { - // Collect dead handles. - if (handle.second.pending_collection) { - // This could be false if the handle was created and collected without - // use. We still need to get rid of map entry. - if (handle.second.name.has_value()) { - CollectGLHandle(gl, handle.first.type, handle.second.name.value()); + std::vector>> + handles_to_delete; + std::vector> + handles_to_name; + { + WriterLock handles_lock(handles_mutex_); + for (auto& handle : handles_) { + // Collect dead handles. + if (handle.second.pending_collection) { + handles_to_delete.push_back( + std::make_tuple(handle.first, handle.second.name)); + continue; } - handles_to_delete.push_back(handle.first); - continue; - } - // Create live handles. - if (!handle.second.name.has_value()) { - auto gl_handle = CreateGLHandle(gl, handle.first.type); - if (!gl_handle) { - VALIDATION_LOG << "Could not create GL handle."; - return false; + // Create live handles. + if (!handle.second.name.has_value()) { + auto gl_handle = CreateGLHandle(gl, handle.first.type); + if (!gl_handle) { + VALIDATION_LOG << "Could not create GL handle."; + return false; + } + handle.second.name = gl_handle; } - handle.second.name = gl_handle; - } - // Set pending debug labels. - if (handle.second.pending_debug_label.has_value() && - handle.first.type != HandleType::kFence) { - if (gl.SetDebugLabel(ToDebugResourceType(handle.first.type), - handle.second.name.value().handle, - handle.second.pending_debug_label.value())) { + // Set pending debug labels. + if (handle.second.pending_debug_label.has_value() && + handle.first.type != HandleType::kFence) { + handles_to_name.push_back(std::make_tuple( + ToDebugResourceType(handle.first.type), + handle.second.name.value().handle, + std::move(handle.second.pending_debug_label.value()))); handle.second.pending_debug_label = std::nullopt; } } + for (const auto& handle_to_delete : handles_to_delete) { + handles_.erase(std::get<0>(handle_to_delete)); + } } - for (const auto& handle_to_delete : handles_to_delete) { - handles_.erase(handle_to_delete); + + for (const auto& handle : handles_to_name) { + gl.SetDebugLabel(std::get<0>(handle), std::get<1>(handle), + std::get<2>(handle)); } + for (const auto& handle : handles_to_delete) { + const std::optional& storage = std::get<1>(handle); + // This could be false if the handle was created and collected without + // use. We still need to get rid of map entry. + if (storage.has_value()) { + CollectGLHandle(gl, std::get<0>(handle).type, storage.value()); + } + } + return true; }