diff --git a/impeller/entity/contents/content_context.cc b/impeller/entity/contents/content_context.cc index 6010452a0232f..55aa880923ceb 100644 --- a/impeller/entity/contents/content_context.cc +++ b/impeller/entity/contents/content_context.cc @@ -375,11 +375,7 @@ std::shared_ptr ContentContext::MakeSubpass( return nullptr; } - if (!sub_renderpass->EncodeCommands()) { - return nullptr; - } - - if (!sub_command_buffer->SubmitCommands()) { + if (!sub_command_buffer->SubmitCommandsAsync(std::move(sub_renderpass))) { return nullptr; } diff --git a/impeller/entity/inline_pass_context.cc b/impeller/entity/inline_pass_context.cc index fd3afd2d8040d..b04bf025c7dc4 100644 --- a/impeller/entity/inline_pass_context.cc +++ b/impeller/entity/inline_pass_context.cc @@ -54,15 +54,9 @@ bool InlinePassContext::EndPass() { return true; } - if (!pass_->EncodeCommands()) { - VALIDATION_LOG - << "Failed to encode commands while ending the current render pass."; - return false; - } - - if (!command_buffer_->SubmitCommands()) { - VALIDATION_LOG - << "Failed to submit command buffer while ending render pass."; + if (!command_buffer_->SubmitCommandsAsync(std::move(pass_))) { + VALIDATION_LOG << "Failed to encode and submit command buffer while ending " + "render pass."; return false; } diff --git a/impeller/playground/backend/metal/playground_impl_mtl.h b/impeller/playground/backend/metal/playground_impl_mtl.h index d1b1aebd80edb..71e2c6607a72b 100644 --- a/impeller/playground/backend/metal/playground_impl_mtl.h +++ b/impeller/playground/backend/metal/playground_impl_mtl.h @@ -6,7 +6,9 @@ #include +#include "flutter/fml/concurrent_message_loop.h" #include "flutter/fml/macros.h" +#include "flutter/fml/synchronization/sync_switch.h" #include "impeller/playground/playground_impl.h" namespace impeller { @@ -27,6 +29,8 @@ class PlaygroundImplMTL final : public PlaygroundImpl { // To ensure that ObjC stuff doesn't leak into C++ TUs. std::unique_ptr data_; std::shared_ptr context_; + std::shared_ptr concurrent_loop_; + std::shared_ptr is_gpu_disabled_sync_switch_; // |PlaygroundImpl| std::shared_ptr GetContext() const override; diff --git a/impeller/playground/backend/metal/playground_impl_mtl.mm b/impeller/playground/backend/metal/playground_impl_mtl.mm index 033824b11383b..25f108666ebe0 100644 --- a/impeller/playground/backend/metal/playground_impl_mtl.mm +++ b/impeller/playground/backend/metal/playground_impl_mtl.mm @@ -63,7 +63,9 @@ PlaygroundImplMTL::PlaygroundImplMTL(PlaygroundSwitches switches) : PlaygroundImpl(switches), handle_(nullptr, &DestroyWindowHandle), - data_(std::make_unique()) { + data_(std::make_unique()), + concurrent_loop_(fml::ConcurrentMessageLoop::Create()), + is_gpu_disabled_sync_switch_(new fml::SyncSwitch(false)) { ::glfwDefaultWindowHints(); ::glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); ::glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE); @@ -71,8 +73,10 @@ if (!window) { return; } - auto context = ContextMTL::Create(ShaderLibraryMappingsForPlayground(), - "Playground Library"); + auto worker_task_runner = concurrent_loop_->GetTaskRunner(); + auto context = ContextMTL::Create( + ShaderLibraryMappingsForPlayground(), worker_task_runner, + is_gpu_disabled_sync_switch_, "Playground Library"); if (!context) { return; } diff --git a/impeller/renderer/backend/metal/command_buffer_mtl.h b/impeller/renderer/backend/metal/command_buffer_mtl.h index f6e4f0eb9cb9d..7fb49d1882450 100644 --- a/impeller/renderer/backend/metal/command_buffer_mtl.h +++ b/impeller/renderer/backend/metal/command_buffer_mtl.h @@ -36,6 +36,9 @@ class CommandBufferMTL final : public CommandBuffer { // |CommandBuffer| void OnWaitUntilScheduled() override; + // |CommandBuffer| + bool SubmitCommandsAsync(std::shared_ptr render_pass) override; + // |CommandBuffer| std::shared_ptr OnCreateRenderPass(RenderTarget target) override; diff --git a/impeller/renderer/backend/metal/command_buffer_mtl.mm b/impeller/renderer/backend/metal/command_buffer_mtl.mm index bd1b71f64c03e..58aa6b5478148 100644 --- a/impeller/renderer/backend/metal/command_buffer_mtl.mm +++ b/impeller/renderer/backend/metal/command_buffer_mtl.mm @@ -4,8 +4,13 @@ #include "impeller/renderer/backend/metal/command_buffer_mtl.h" +#include "flutter/fml/make_copyable.h" +#include "flutter/fml/synchronization/semaphore.h" +#include "flutter/fml/trace_event.h" + #include "impeller/renderer/backend/metal/blit_pass_mtl.h" #include "impeller/renderer/backend/metal/compute_pass_mtl.h" +#include "impeller/renderer/backend/metal/context_mtl.h" #include "impeller/renderer/backend/metal/render_pass_mtl.h" namespace impeller { @@ -171,6 +176,62 @@ static bool LogMTLCommandBufferErrorIfPresent(id buffer) { return true; } +bool CommandBufferMTL::SubmitCommandsAsync( + std::shared_ptr render_pass) { + TRACE_EVENT0("impeller", "CommandBufferMTL::SubmitCommandsAsync"); + if (!IsValid() || !render_pass->IsValid()) { + return false; + } + auto context = context_.lock(); + if (!context) { + return false; + } + [buffer_ enqueue]; + auto buffer = buffer_; + buffer_ = nil; + + auto worker_task_runner = ContextMTL::Cast(*context).GetWorkerTaskRunner(); + auto mtl_render_pass = static_cast(render_pass.get()); + + // Render command encoder creation has been observed to exceed the stack size + // limit for worker threads, and therefore is intentionally constructed on the + // raster thread. + auto render_command_encoder = + [buffer renderCommandEncoderWithDescriptor:mtl_render_pass->desc_]; + if (!render_command_encoder) { + return false; + } + + auto task = fml::MakeCopyable([render_pass, buffer, render_command_encoder, + weak_context = context_]() { + auto context = weak_context.lock(); + if (!context) { + return; + } + auto is_gpu_disabled_sync_switch = + ContextMTL::Cast(*context).GetIsGpuDisabledSyncSwitch(); + is_gpu_disabled_sync_switch->Execute(fml::SyncSwitch::Handlers().SetIfFalse( + [&render_pass, &render_command_encoder, &buffer, &context] { + auto mtl_render_pass = static_cast(render_pass.get()); + if (!mtl_render_pass->label_.empty()) { + [render_command_encoder + setLabel:@(mtl_render_pass->label_.c_str())]; + } + + auto result = mtl_render_pass->EncodeCommands( + context->GetResourceAllocator(), render_command_encoder); + [render_command_encoder endEncoding]; + if (result) { + [buffer commit]; + } else { + VALIDATION_LOG << "Failed to encode command buffer"; + } + })); + }); + worker_task_runner->PostTask(task); + return true; +} + void CommandBufferMTL::OnWaitUntilScheduled() {} std::shared_ptr CommandBufferMTL::OnCreateRenderPass( diff --git a/impeller/renderer/backend/metal/context_mtl.h b/impeller/renderer/backend/metal/context_mtl.h index f6a5bfd25232e..fe461601daf06 100644 --- a/impeller/renderer/backend/metal/context_mtl.h +++ b/impeller/renderer/backend/metal/context_mtl.h @@ -9,7 +9,9 @@ #include #include +#include "flutter/fml/concurrent_message_loop.h" #include "flutter/fml/macros.h" +#include "flutter/fml/synchronization/sync_switch.h" #include "impeller/base/backend_cast.h" #include "impeller/core/sampler.h" #include "impeller/renderer/backend/metal/allocator_mtl.h" @@ -26,10 +28,14 @@ class ContextMTL final : public Context, public std::enable_shared_from_this { public: static std::shared_ptr Create( - const std::vector& shader_library_paths); + const std::vector& shader_library_paths, + std::shared_ptr worker_task_runner, + std::shared_ptr is_gpu_disabled_sync_switch); static std::shared_ptr Create( const std::vector>& shader_libraries_data, + std::shared_ptr worker_task_runner, + std::shared_ptr is_gpu_disabled_sync_switch, const std::string& label); // |Context| @@ -66,6 +72,10 @@ class ContextMTL final : public Context, id CreateMTLCommandBuffer() const; + const std::shared_ptr& GetWorkerTaskRunner() const; + + std::shared_ptr GetIsGpuDisabledSyncSwitch() const; + private: id device_ = nullptr; id command_queue_ = nullptr; @@ -74,9 +84,15 @@ class ContextMTL final : public Context, std::shared_ptr sampler_library_; std::shared_ptr resource_allocator_; std::shared_ptr device_capabilities_; + std::shared_ptr worker_task_runner_; + std::shared_ptr is_gpu_disabled_sync_switch_; bool is_valid_ = false; - ContextMTL(id device, NSArray>* shader_libraries); + ContextMTL( + id device, + NSArray>* shader_libraries, + std::shared_ptr worker_task_runner, + std::shared_ptr is_gpu_disabled_sync_switch); std::shared_ptr CreateCommandBufferInQueue( id queue) const; diff --git a/impeller/renderer/backend/metal/context_mtl.mm b/impeller/renderer/backend/metal/context_mtl.mm index c83f5b7075c47..20af3b87c7141 100644 --- a/impeller/renderer/backend/metal/context_mtl.mm +++ b/impeller/renderer/backend/metal/context_mtl.mm @@ -65,9 +65,14 @@ static bool DeviceSupportsComputeSubgroups(id device) { .Build(); } -ContextMTL::ContextMTL(id device, - NSArray>* shader_libraries) - : device_(device) { +ContextMTL::ContextMTL( + id device, + NSArray>* shader_libraries, + std::shared_ptr worker_task_runner, + std::shared_ptr is_gpu_disabled_sync_switch) + : device_(device), + worker_task_runner_(std::move(worker_task_runner)), + is_gpu_disabled_sync_switch_(std::move(is_gpu_disabled_sync_switch)) { // Validate device. if (!device_) { VALIDATION_LOG << "Could not setup valid Metal device."; @@ -200,10 +205,13 @@ static bool DeviceSupportsComputeSubgroups(id device) { } std::shared_ptr ContextMTL::Create( - const std::vector& shader_library_paths) { + const std::vector& shader_library_paths, + std::shared_ptr worker_task_runner, + std::shared_ptr is_gpu_disabled_sync_switch) { auto device = CreateMetalDevice(); auto context = std::shared_ptr(new ContextMTL( - device, MTLShaderLibraryFromFilePaths(device, shader_library_paths))); + device, MTLShaderLibraryFromFilePaths(device, shader_library_paths), + std::move(worker_task_runner), std::move(is_gpu_disabled_sync_switch))); if (!context->IsValid()) { FML_LOG(ERROR) << "Could not create Metal context."; return nullptr; @@ -213,11 +221,14 @@ static bool DeviceSupportsComputeSubgroups(id device) { std::shared_ptr ContextMTL::Create( const std::vector>& shader_libraries_data, + std::shared_ptr worker_task_runner, + std::shared_ptr is_gpu_disabled_sync_switch, const std::string& label) { auto device = CreateMetalDevice(); auto context = std::shared_ptr(new ContextMTL( device, - MTLShaderLibraryFromFileData(device, shader_libraries_data, label))); + MTLShaderLibraryFromFileData(device, shader_libraries_data, label), + worker_task_runner, std::move(is_gpu_disabled_sync_switch))); if (!context->IsValid()) { FML_LOG(ERROR) << "Could not create Metal context."; return nullptr; @@ -257,6 +268,16 @@ static bool DeviceSupportsComputeSubgroups(id device) { return CreateCommandBufferInQueue(command_queue_); } +const std::shared_ptr& +ContextMTL::GetWorkerTaskRunner() const { + return worker_task_runner_; +} + +std::shared_ptr ContextMTL::GetIsGpuDisabledSyncSwitch() + const { + return is_gpu_disabled_sync_switch_; +} + std::shared_ptr ContextMTL::CreateCommandBufferInQueue( id queue) const { if (!IsValid()) { diff --git a/impeller/renderer/backend/metal/render_pass_mtl.mm b/impeller/renderer/backend/metal/render_pass_mtl.mm index 1eb63299b23fb..317e46b98ca64 100644 --- a/impeller/renderer/backend/metal/render_pass_mtl.mm +++ b/impeller/renderer/backend/metal/render_pass_mtl.mm @@ -6,11 +6,13 @@ #include "flutter/fml/closure.h" #include "flutter/fml/logging.h" +#include "flutter/fml/make_copyable.h" #include "flutter/fml/trace_event.h" #include "impeller/base/backend_cast.h" #include "impeller/core/formats.h" #include "impeller/core/host_buffer.h" #include "impeller/core/shader_types.h" +#include "impeller/renderer/backend/metal/context_mtl.h" #include "impeller/renderer/backend/metal/device_buffer_mtl.h" #include "impeller/renderer/backend/metal/formats_mtl.h" #include "impeller/renderer/backend/metal/pipeline_mtl.h" diff --git a/impeller/renderer/command_buffer.cc b/impeller/renderer/command_buffer.cc index 99e6be8ef5cbe..0ffad01ff9857 100644 --- a/impeller/renderer/command_buffer.cc +++ b/impeller/renderer/command_buffer.cc @@ -36,6 +36,21 @@ void CommandBuffer::WaitUntilScheduled() { return OnWaitUntilScheduled(); } +bool CommandBuffer::SubmitCommandsAsync( + std::shared_ptr + render_pass // NOLINT(performance-unnecessary-value-param) +) { + TRACE_EVENT0("impeller", "CommandBuffer::SubmitCommandsAsync"); + if (!render_pass->IsValid() || !IsValid()) { + return false; + } + if (!render_pass->EncodeCommands()) { + return false; + } + + return SubmitCommands(nullptr); +} + std::shared_ptr CommandBuffer::CreateRenderPass( const RenderTarget& render_target) { auto pass = OnCreateRenderPass(render_target); diff --git a/impeller/renderer/command_buffer.h b/impeller/renderer/command_buffer.h index 71703bb40f41a..3a6abacbb2556 100644 --- a/impeller/renderer/command_buffer.h +++ b/impeller/renderer/command_buffer.h @@ -55,7 +55,8 @@ class CommandBuffer { //---------------------------------------------------------------------------- /// @brief Schedule the command encoded by render passes within this - /// command buffer on the GPU. + /// command buffer on the GPU. The encoding of these commnands is + /// performed immediately on the calling thread. /// /// A command buffer may only be committed once. /// @@ -65,6 +66,17 @@ class CommandBuffer { [[nodiscard]] bool SubmitCommands(); + //---------------------------------------------------------------------------- + /// @brief Schedule the command encoded by render passes within this + /// command buffer on the GPU. The enqueing of this buffer is + /// performed immediately but encoding is pushed to a worker + /// thread if possible. + /// + /// A command buffer may only be committed once. + /// + [[nodiscard]] virtual bool SubmitCommandsAsync( + std::shared_ptr render_pass); + //---------------------------------------------------------------------------- /// @brief Force execution of pending GPU commands. /// diff --git a/impeller/renderer/render_pass.h b/impeller/renderer/render_pass.h index a75b59b279c54..a5fac32292f8c 100644 --- a/impeller/renderer/render_pass.h +++ b/impeller/renderer/render_pass.h @@ -7,6 +7,7 @@ #include #include "impeller/renderer/command.h" +#include "impeller/renderer/command_buffer.h" #include "impeller/renderer/render_target.h" namespace impeller { diff --git a/shell/common/animator_unittests.cc b/shell/common/animator_unittests.cc index a3d814e298daa..cf20635b14203 100644 --- a/shell/common/animator_unittests.cc +++ b/shell/common/animator_unittests.cc @@ -81,7 +81,9 @@ TEST_F(ShellTest, VSyncTargetTime) { [vsync_clock, &create_vsync_waiter](Shell& shell) { return ShellTestPlatformView::Create( shell, shell.GetTaskRunners(), vsync_clock, create_vsync_waiter, - ShellTestPlatformView::BackendType::kDefaultBackend, nullptr); + ShellTestPlatformView::BackendType::kDefaultBackend, nullptr, + shell.GetConcurrentWorkerTaskRunner(), + shell.GetIsGpuDisabledSyncSwitch()); }, [](Shell& shell) { return std::make_unique(shell); }); ASSERT_TRUE(DartVMRef::IsInstanceRunning()); diff --git a/shell/common/shell_test.cc b/shell/common/shell_test.cc index a85a58e15b7f5..8be076930b11b 100644 --- a/shell/common/shell_test.cc +++ b/shell/common/shell_test.cc @@ -352,12 +352,15 @@ std::unique_ptr ShellTest::CreateShell( shell_test_external_view_embedder, // rendering_backend // ](Shell& shell) { - return ShellTestPlatformView::Create(shell, // - shell.GetTaskRunners(), // - vsync_clock, // - create_vsync_waiter, // - rendering_backend, // - shell_test_external_view_embedder // + return ShellTestPlatformView::Create( + shell, // + shell.GetTaskRunners(), // + vsync_clock, // + create_vsync_waiter, // + rendering_backend, // + shell_test_external_view_embedder, // + shell.GetConcurrentWorkerTaskRunner(), // + shell.GetIsGpuDisabledSyncSwitch() // ); }; } diff --git a/shell/common/shell_test_platform_view.cc b/shell/common/shell_test_platform_view.cc index 7653b75a4d96a..a683d372d8d0a 100644 --- a/shell/common/shell_test_platform_view.cc +++ b/shell/common/shell_test_platform_view.cc @@ -24,7 +24,9 @@ std::unique_ptr ShellTestPlatformView::Create( const CreateVsyncWaiter& create_vsync_waiter, BackendType backend, const std::shared_ptr& - shell_test_external_view_embedder) { + shell_test_external_view_embedder, + const std::shared_ptr& worker_task_runner, + const std::shared_ptr& is_gpu_disabled_sync_switch) { // TODO(gw280): https://github.com/flutter/flutter/issues/50298 // Make this fully runtime configurable switch (backend) { @@ -45,7 +47,8 @@ std::unique_ptr ShellTestPlatformView::Create( case BackendType::kMetalBackend: return std::make_unique( delegate, task_runners, vsync_clock, create_vsync_waiter, - shell_test_external_view_embedder); + shell_test_external_view_embedder, worker_task_runner, + is_gpu_disabled_sync_switch); #endif // SHELL_ENABLE_METAL default: diff --git a/shell/common/shell_test_platform_view.h b/shell/common/shell_test_platform_view.h index 08a8baf3b43d6..ebb96c87dd23e 100644 --- a/shell/common/shell_test_platform_view.h +++ b/shell/common/shell_test_platform_view.h @@ -28,7 +28,10 @@ class ShellTestPlatformView : public PlatformView { const CreateVsyncWaiter& create_vsync_waiter, BackendType backend, const std::shared_ptr& - shell_test_external_view_embedder); + shell_test_external_view_embedder, + const std::shared_ptr& worker_task_runner, + const std::shared_ptr& + is_gpu_disabled_sync_switch); virtual void SimulateVSync() = 0; diff --git a/shell/common/shell_test_platform_view_metal.h b/shell/common/shell_test_platform_view_metal.h index 8dd015cd2408d..a20b9c5f3f929 100644 --- a/shell/common/shell_test_platform_view_metal.h +++ b/shell/common/shell_test_platform_view_metal.h @@ -17,12 +17,16 @@ class DarwinContextMetal; class ShellTestPlatformViewMetal final : public ShellTestPlatformView, public GPUSurfaceMetalDelegate { public: - ShellTestPlatformViewMetal(PlatformView::Delegate& delegate, - const TaskRunners& task_runners, - std::shared_ptr vsync_clock, - CreateVsyncWaiter create_vsync_waiter, - std::shared_ptr - shell_test_external_view_embedder); + ShellTestPlatformViewMetal( + PlatformView::Delegate& delegate, + const TaskRunners& task_runners, + std::shared_ptr vsync_clock, + CreateVsyncWaiter create_vsync_waiter, + std::shared_ptr + shell_test_external_view_embedder, + const std::shared_ptr& worker_task_runner, + const std::shared_ptr& + is_gpu_disabled_sync_switch); // |ShellTestPlatformView| virtual ~ShellTestPlatformViewMetal() override; diff --git a/shell/common/shell_test_platform_view_metal.mm b/shell/common/shell_test_platform_view_metal.mm index 701bba7737a22..598ecd5f87557 100644 --- a/shell/common/shell_test_platform_view_metal.mm +++ b/shell/common/shell_test_platform_view_metal.mm @@ -31,9 +31,15 @@ // non-Objective-C TUs. class DarwinContextMetal { public: - explicit DarwinContextMetal(bool impeller) + explicit DarwinContextMetal(bool impeller, + std::shared_ptr worker_task_runner, + std::shared_ptr is_gpu_disabled_sync_switch) : context_(impeller ? nil : [[FlutterDarwinContextMetalSkia alloc] initWithDefaultMTLDevice]), - impeller_context_(impeller ? [[FlutterDarwinContextMetalImpeller alloc] init] : nil), + impeller_context_( + impeller ? [[FlutterDarwinContextMetalImpeller alloc] + initWithTaskRunner:std::move(worker_task_runner) + is_gpu_disabled_sync_switch:std::move(is_gpu_disabled_sync_switch)] + : nil), offscreen_texture_(CreateOffscreenTexture( impeller ? [impeller_context_ context]->GetMTLDevice() : [context_ device])) {} @@ -67,10 +73,14 @@ GPUMTLTextureInfo offscreen_texture_info() const { const TaskRunners& task_runners, std::shared_ptr vsync_clock, CreateVsyncWaiter create_vsync_waiter, - std::shared_ptr shell_test_external_view_embedder) + std::shared_ptr shell_test_external_view_embedder, + const std::shared_ptr& worker_task_runner, + const std::shared_ptr& is_gpu_disabled_sync_switch) : ShellTestPlatformView(delegate, task_runners), GPUSurfaceMetalDelegate(MTLRenderTargetType::kMTLTexture), - metal_context_(std::make_unique(GetSettings().enable_impeller)), + metal_context_(std::make_unique(GetSettings().enable_impeller, + worker_task_runner, + is_gpu_disabled_sync_switch)), create_vsync_waiter_(std::move(create_vsync_waiter)), vsync_clock_(std::move(vsync_clock)), shell_test_external_view_embedder_(std::move(shell_test_external_view_embedder)) { diff --git a/shell/common/shell_unittests.cc b/shell/common/shell_unittests.cc index 2584e6cff0e12..2edc3b173d82b 100644 --- a/shell/common/shell_unittests.cc +++ b/shell/common/shell_unittests.cc @@ -409,7 +409,9 @@ TEST_F(ShellTest, return static_cast>( std::make_unique(task_runners)); }, - ShellTestPlatformView::BackendType::kDefaultBackend, nullptr); + ShellTestPlatformView::BackendType::kDefaultBackend, nullptr, + shell.GetConcurrentWorkerTaskRunner(), + shell.GetIsGpuDisabledSyncSwitch()); }, [](Shell& shell) { return std::make_unique(shell); }); ASSERT_TRUE(ValidateShell(shell.get())); diff --git a/shell/platform/darwin/graphics/FlutterDarwinContextMetalImpeller.h b/shell/platform/darwin/graphics/FlutterDarwinContextMetalImpeller.h index 55fc5ac9b79c3..4a09c6d50e0d6 100644 --- a/shell/platform/darwin/graphics/FlutterDarwinContextMetalImpeller.h +++ b/shell/platform/darwin/graphics/FlutterDarwinContextMetalImpeller.h @@ -9,6 +9,7 @@ #import #import +#include "flutter/fml/concurrent_message_loop.h" #include "flutter/fml/platform/darwin/cf_utils.h" #import "flutter/shell/platform/darwin/common/framework/Headers/FlutterTexture.h" #import "flutter/shell/platform/darwin/graphics/FlutterDarwinExternalTextureMetal.h" @@ -24,7 +25,9 @@ NS_ASSUME_NONNULL_BEGIN /** * Initializes a FlutterDarwinContextMetalImpeller. */ -- (instancetype)init; +- (instancetype)initWithTaskRunner:(std::shared_ptr)task_runner + is_gpu_disabled_sync_switch: + (std::shared_ptr)is_gpu_disabled_sync_switch; /** * Creates an external texture with the specified ID and contents. @@ -34,7 +37,7 @@ NS_ASSUME_NONNULL_BEGIN texture:(NSObject*)texture; /** - * Impeller context; + * Impeller context. */ @property(nonatomic, readonly) std::shared_ptr context; diff --git a/shell/platform/darwin/graphics/FlutterDarwinContextMetalImpeller.mm b/shell/platform/darwin/graphics/FlutterDarwinContextMetalImpeller.mm index e84a2e29cb30f..34cc332233cd0 100644 --- a/shell/platform/darwin/graphics/FlutterDarwinContextMetalImpeller.mm +++ b/shell/platform/darwin/graphics/FlutterDarwinContextMetalImpeller.mm @@ -16,7 +16,9 @@ FLUTTER_ASSERT_ARC -static std::shared_ptr CreateImpellerContext() { +static std::shared_ptr CreateImpellerContext( + std::shared_ptr worker_task_runner, + std::shared_ptr is_gpu_disabled_sync_switch) { std::vector> shader_mappings = { std::make_shared(impeller_entity_shaders_data, impeller_entity_shaders_length), @@ -27,7 +29,9 @@ std::make_shared(impeller_framebuffer_blend_shaders_data, impeller_framebuffer_blend_shaders_length), }; - auto context = impeller::ContextMTL::Create(shader_mappings, "Impeller Library"); + auto context = + impeller::ContextMTL::Create(shader_mappings, std::move(worker_task_runner), + std::move(is_gpu_disabled_sync_switch), "Impeller Library"); if (!context) { FML_LOG(ERROR) << "Could not create Metal Impeller Context."; return nullptr; @@ -39,10 +43,13 @@ @implementation FlutterDarwinContextMetalImpeller -- (instancetype)init { +- (instancetype)initWithTaskRunner:(std::shared_ptr)task_runner + is_gpu_disabled_sync_switch: + (std::shared_ptr)is_gpu_disabled_sync_switch { self = [super init]; if (self != nil) { - _context = CreateImpellerContext(); + _context = + CreateImpellerContext(std::move(task_runner), std::move(is_gpu_disabled_sync_switch)); id device = _context->GetMTLDevice(); if (!device) { FML_DLOG(ERROR) << "Could not acquire Metal device."; diff --git a/shell/platform/darwin/ios/framework/Source/FlutterEngine.mm b/shell/platform/darwin/ios/framework/Source/FlutterEngine.mm index a124d2b0296a4..d8adc04c78abd 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterEngine.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterEngine.mm @@ -836,7 +836,8 @@ - (BOOL)createShell:(NSString*)entrypoint [self](flutter::Shell& shell) { [self recreatePlatformViewController]; return std::make_unique( - shell, self->_renderingApi, self->_platformViewsController, shell.GetTaskRunners()); + shell, self->_renderingApi, self->_platformViewsController, shell.GetTaskRunners(), + shell.GetConcurrentWorkerTaskRunner(), shell.GetIsGpuDisabledSyncSwitch()); }; flutter::Shell::CreateCallback on_create_rasterizer = diff --git a/shell/platform/darwin/ios/framework/Source/FlutterEnginePlatformViewTest.mm b/shell/platform/darwin/ios/framework/Source/FlutterEnginePlatformViewTest.mm index e34a4ffc05af4..e4341a065c2af 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterEnginePlatformViewTest.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterEnginePlatformViewTest.mm @@ -74,7 +74,9 @@ - (void)setUp { /*delegate=*/fake_delegate, /*rendering_api=*/flutter::IOSRenderingAPI::kSoftware, /*platform_views_controller=*/nil, - /*task_runners=*/runners); + /*task_runners=*/runners, + /*worker_task_runner=*/nil, + /*is_gpu_disabled_sync_switch=*/nil); weak_factory = std::make_unique>(platform_view.get()); } @@ -105,7 +107,9 @@ - (void)testMsaaSampleCount { /*delegate=*/fake_delegate, /*rendering_api=*/flutter::IOSRenderingAPI::kMetal, /*platform_views_controller=*/nil, - /*task_runners=*/runners); + /*task_runners=*/runners, + /*worker_task_runner=*/nil, + /*is_gpu_disabled_sync_switch=*/nil); XCTAssertEqual(msaa_4x_platform_view->GetIosContext()->GetMsaaSampleCount(), MsaaSampleCount::kFour); diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViewsTest.mm b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViewsTest.mm index fd656a9d1767f..75f62214897d9 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViewsTest.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViewsTest.mm @@ -150,7 +150,9 @@ - (void)testFlutterViewOnlyCreateOnceInOneFrame { /*delegate=*/mock_delegate, /*rendering_api=*/flutter::IOSRenderingAPI::kSoftware, /*platform_views_controller=*/flutterPlatformViewsController, - /*task_runners=*/runners); + /*task_runners=*/runners, + /*worker_task_runner=*/nil, + /*is_gpu_disabled_sync_switch=*/nil); FlutterPlatformViewsTestMockFlutterPlatformFactory* factory = [[FlutterPlatformViewsTestMockFlutterPlatformFactory new] autorelease]; @@ -204,7 +206,9 @@ - (void)testCanCreatePlatformViewWithoutFlutterView { /*delegate=*/mock_delegate, /*rendering_api=*/flutter::IOSRenderingAPI::kSoftware, /*platform_views_controller=*/flutterPlatformViewsController, - /*task_runners=*/runners); + /*task_runners=*/runners, + /*worker_task_runner=*/nil, + /*is_gpu_disabled_sync_switch=*/nil); FlutterPlatformViewsTestMockFlutterPlatformFactory* factory = [[FlutterPlatformViewsTestMockFlutterPlatformFactory new] autorelease]; @@ -256,7 +260,9 @@ - (void)testApplyBackdropFilter { /*delegate=*/mock_delegate, /*rendering_api=*/flutter::IOSRenderingAPI::kSoftware, /*platform_views_controller=*/flutterPlatformViewsController, - /*task_runners=*/runners); + /*task_runners=*/runners, + /*worker_task_runner=*/nil, + /*is_gpu_disabled_sync_switch=*/nil); FlutterPlatformViewsTestMockFlutterPlatformFactory* factory = [[FlutterPlatformViewsTestMockFlutterPlatformFactory new] autorelease]; @@ -326,7 +332,9 @@ - (void)testApplyBackdropFilterWithCorrectFrame { /*delegate=*/mock_delegate, /*rendering_api=*/flutter::IOSRenderingAPI::kSoftware, /*platform_views_controller=*/flutterPlatformViewsController, - /*task_runners=*/runners); + /*task_runners=*/runners, + /*worker_task_runner=*/nil, + /*is_gpu_disabled_sync_switch=*/nil); FlutterPlatformViewsTestMockFlutterPlatformFactory* factory = [[FlutterPlatformViewsTestMockFlutterPlatformFactory new] autorelease]; @@ -396,7 +404,9 @@ - (void)testApplyMultipleBackdropFilters { /*delegate=*/mock_delegate, /*rendering_api=*/flutter::IOSRenderingAPI::kSoftware, /*platform_views_controller=*/flutterPlatformViewsController, - /*task_runners=*/runners); + /*task_runners=*/runners, + /*worker_task_runner=*/nil, + /*is_gpu_disabled_sync_switch=*/nil); FlutterPlatformViewsTestMockFlutterPlatformFactory* factory = [[FlutterPlatformViewsTestMockFlutterPlatformFactory new] autorelease]; @@ -467,7 +477,9 @@ - (void)testAddBackdropFilters { /*delegate=*/mock_delegate, /*rendering_api=*/flutter::IOSRenderingAPI::kSoftware, /*platform_views_controller=*/flutterPlatformViewsController, - /*task_runners=*/runners); + /*task_runners=*/runners, + /*worker_task_runner=*/nil, + /*is_gpu_disabled_sync_switch=*/nil); FlutterPlatformViewsTestMockFlutterPlatformFactory* factory = [[FlutterPlatformViewsTestMockFlutterPlatformFactory new] autorelease]; @@ -578,7 +590,9 @@ - (void)testRemoveBackdropFilters { /*delegate=*/mock_delegate, /*rendering_api=*/flutter::IOSRenderingAPI::kSoftware, /*platform_views_controller=*/flutterPlatformViewsController, - /*task_runners=*/runners); + /*task_runners=*/runners, + /*worker_task_runner=*/nil, + /*is_gpu_disabled_sync_switch=*/nil); FlutterPlatformViewsTestMockFlutterPlatformFactory* factory = [[FlutterPlatformViewsTestMockFlutterPlatformFactory new] autorelease]; @@ -713,7 +727,9 @@ - (void)testEditBackdropFilters { /*delegate=*/mock_delegate, /*rendering_api=*/flutter::IOSRenderingAPI::kSoftware, /*platform_views_controller=*/flutterPlatformViewsController, - /*task_runners=*/runners); + /*task_runners=*/runners, + /*worker_task_runner=*/nil, + /*is_gpu_disabled_sync_switch=*/nil); FlutterPlatformViewsTestMockFlutterPlatformFactory* factory = [[FlutterPlatformViewsTestMockFlutterPlatformFactory new] autorelease]; @@ -988,7 +1004,9 @@ - (void)testApplyBackdropFilterNotDlBlurImageFilter { /*delegate=*/mock_delegate, /*rendering_api=*/flutter::IOSRenderingAPI::kSoftware, /*platform_views_controller=*/flutterPlatformViewsController, - /*task_runners=*/runners); + /*task_runners=*/runners, + /*worker_task_runner=*/nil, + /*is_gpu_disabled_sync_switch=*/nil); FlutterPlatformViewsTestMockFlutterPlatformFactory* factory = [[FlutterPlatformViewsTestMockFlutterPlatformFactory new] autorelease]; @@ -1286,7 +1304,9 @@ - (void)testCompositePlatformView { /*delegate=*/mock_delegate, /*rendering_api=*/flutter::IOSRenderingAPI::kSoftware, /*platform_views_controller=*/flutterPlatformViewsController, - /*task_runners=*/runners); + /*task_runners=*/runners, + /*worker_task_runner=*/nil, + /*is_gpu_disabled_sync_switch=*/nil); FlutterPlatformViewsTestMockFlutterPlatformFactory* factory = [[FlutterPlatformViewsTestMockFlutterPlatformFactory new] autorelease]; @@ -1340,7 +1360,9 @@ - (void)testBackdropFilterCorrectlyPushedAndReset { /*delegate=*/mock_delegate, /*rendering_api=*/flutter::IOSRenderingAPI::kSoftware, /*platform_views_controller=*/flutterPlatformViewsController, - /*task_runners=*/runners); + /*task_runners=*/runners, + /*worker_task_runner=*/nil, + /*is_gpu_disabled_sync_switch=*/nil); FlutterPlatformViewsTestMockFlutterPlatformFactory* factory = [[FlutterPlatformViewsTestMockFlutterPlatformFactory new] autorelease]; @@ -1432,7 +1454,9 @@ - (void)testChildClippingViewShouldBeTheBoundingRectOfPlatformView { /*delegate=*/mock_delegate, /*rendering_api=*/flutter::IOSRenderingAPI::kSoftware, /*platform_views_controller=*/flutterPlatformViewsController, - /*task_runners=*/runners); + /*task_runners=*/runners, + /*worker_task_runner=*/nil, + /*is_gpu_disabled_sync_switch=*/nil); FlutterPlatformViewsTestMockFlutterPlatformFactory* factory = [[FlutterPlatformViewsTestMockFlutterPlatformFactory new] autorelease]; @@ -1501,7 +1525,9 @@ - (void)testClipsDoNotInterceptWithPlatformViewShouldNotAddMaskView { /*delegate=*/mock_delegate, /*rendering_api=*/flutter::IOSRenderingAPI::kSoftware, /*platform_views_controller=*/flutterPlatformViewsController, - /*task_runners=*/runners); + /*task_runners=*/runners, + /*worker_task_runner=*/nil, + /*is_gpu_disabled_sync_switch=*/nil); FlutterPlatformViewsTestMockFlutterPlatformFactory* factory = [[FlutterPlatformViewsTestMockFlutterPlatformFactory new] autorelease]; @@ -1566,7 +1592,9 @@ - (void)testClipRRectOnlyHasCornersInterceptWithPlatformViewShouldAddMaskView { /*delegate=*/mock_delegate, /*rendering_api=*/flutter::IOSRenderingAPI::kSoftware, /*platform_views_controller=*/flutterPlatformViewsController, - /*task_runners=*/runners); + /*task_runners=*/runners, + /*worker_task_runner=*/nil, + /*is_gpu_disabled_sync_switch=*/nil); FlutterPlatformViewsTestMockFlutterPlatformFactory* factory = [[FlutterPlatformViewsTestMockFlutterPlatformFactory new] autorelease]; @@ -1630,7 +1658,9 @@ - (void)testClipRect { /*delegate=*/mock_delegate, /*rendering_api=*/flutter::IOSRenderingAPI::kSoftware, /*platform_views_controller=*/flutterPlatformViewsController, - /*task_runners=*/runners); + /*task_runners=*/runners, + /*worker_task_runner=*/nil, + /*is_gpu_disabled_sync_switch=*/nil); FlutterPlatformViewsTestMockFlutterPlatformFactory* factory = [[FlutterPlatformViewsTestMockFlutterPlatformFactory new] autorelease]; @@ -1701,7 +1731,9 @@ - (void)testClipRRect { /*delegate=*/mock_delegate, /*rendering_api=*/flutter::IOSRenderingAPI::kSoftware, /*platform_views_controller=*/flutterPlatformViewsController, - /*task_runners=*/runners); + /*task_runners=*/runners, + /*worker_task_runner=*/nil, + /*is_gpu_disabled_sync_switch=*/nil); FlutterPlatformViewsTestMockFlutterPlatformFactory* factory = [[FlutterPlatformViewsTestMockFlutterPlatformFactory new] autorelease]; @@ -1772,7 +1804,9 @@ - (void)testClipPath { /*delegate=*/mock_delegate, /*rendering_api=*/flutter::IOSRenderingAPI::kSoftware, /*platform_views_controller=*/flutterPlatformViewsController, - /*task_runners=*/runners); + /*task_runners=*/runners, + /*worker_task_runner=*/nil, + /*is_gpu_disabled_sync_switch=*/nil); FlutterPlatformViewsTestMockFlutterPlatformFactory* factory = [[FlutterPlatformViewsTestMockFlutterPlatformFactory new] autorelease]; @@ -1844,7 +1878,9 @@ - (void)testSetFlutterViewControllerAfterCreateCanStillDispatchTouchEvents { /*delegate=*/mock_delegate, /*rendering_api=*/flutter::IOSRenderingAPI::kSoftware, /*platform_views_controller=*/flutterPlatformViewsController, - /*task_runners=*/runners); + /*task_runners=*/runners, + /*worker_task_runner=*/nil, + /*is_gpu_disabled_sync_switch=*/nil); FlutterPlatformViewsTestMockFlutterPlatformFactory* factory = [[FlutterPlatformViewsTestMockFlutterPlatformFactory new] autorelease]; @@ -1906,7 +1942,9 @@ - (void)testSetFlutterViewControllerInTheMiddleOfTouchEventShouldStillAllowGestu /*delegate=*/mock_delegate, /*rendering_api=*/flutter::IOSRenderingAPI::kSoftware, /*platform_views_controller=*/flutterPlatformViewsController, - /*task_runners=*/runners); + /*task_runners=*/runners, + /*worker_task_runner=*/nil, + /*is_gpu_disabled_sync_switch=*/nil); FlutterPlatformViewsTestMockFlutterPlatformFactory* factory = [[FlutterPlatformViewsTestMockFlutterPlatformFactory new] autorelease]; @@ -2025,7 +2063,9 @@ - (void)testSetFlutterViewControllerInTheMiddleOfTouchEventShouldStillAllowGestu /*delegate=*/mock_delegate, /*rendering_api=*/flutter::IOSRenderingAPI::kSoftware, /*platform_views_controller=*/flutterPlatformViewsController, - /*task_runners=*/runners); + /*task_runners=*/runners, + /*worker_task_runner=*/nil, + /*is_gpu_disabled_sync_switch=*/nil); FlutterPlatformViewsTestMockFlutterPlatformFactory* factory = [[FlutterPlatformViewsTestMockFlutterPlatformFactory new] autorelease]; @@ -2134,7 +2174,9 @@ - (void)testFlutterPlatformViewTouchesCancelledEventAreForcedToBeCancelled { /*delegate=*/mock_delegate, /*rendering_api=*/flutter::IOSRenderingAPI::kSoftware, /*platform_views_controller=*/flutterPlatformViewsController, - /*task_runners=*/runners); + /*task_runners=*/runners, + /*worker_task_runner=*/nil, + /*is_gpu_disabled_sync_switch=*/nil); FlutterPlatformViewsTestMockFlutterPlatformFactory* factory = [[FlutterPlatformViewsTestMockFlutterPlatformFactory new] autorelease]; @@ -2194,7 +2236,9 @@ - (void)testFlutterPlatformViewControllerSubmitFrameWithoutFlutterViewNotCrashin /*delegate=*/mock_delegate, /*rendering_api=*/flutter::IOSRenderingAPI::kSoftware, /*platform_views_controller=*/flutterPlatformViewsController, - /*task_runners=*/runners); + /*task_runners=*/runners, + /*worker_task_runner=*/nil, + /*is_gpu_disabled_sync_switch=*/nil); FlutterPlatformViewsTestMockFlutterPlatformFactory* factory = [[FlutterPlatformViewsTestMockFlutterPlatformFactory new] autorelease]; @@ -2254,7 +2298,9 @@ - (void)testFlutterPlatformViewControllerSubmitFrameWithoutFlutterViewNotCrashin /*delegate=*/mock_delegate, /*rendering_api=*/flutter::IOSRenderingAPI::kSoftware, /*platform_views_controller=*/flutterPlatformViewsController, - /*task_runners=*/runners); + /*task_runners=*/runners, + /*worker_task_runner=*/nil, + /*is_gpu_disabled_sync_switch=*/nil); UIView* mockFlutterView = [[[UIView alloc] initWithFrame:CGRectMake(0, 0, 500, 500)] autorelease]; flutterPlatformViewsController->SetFlutterView(mockFlutterView); @@ -2302,7 +2348,9 @@ - (void)testFlutterPlatformViewControllerBeginFrameShouldResetCompisitionOrder { /*delegate=*/mock_delegate, /*rendering_api=*/flutter::IOSRenderingAPI::kSoftware, /*platform_views_controller=*/flutterPlatformViewsController, - /*task_runners=*/runners); + /*task_runners=*/runners, + /*worker_task_runner=*/nil, + /*is_gpu_disabled_sync_switch=*/nil); UIView* mockFlutterView = [[[UIView alloc] initWithFrame:CGRectMake(0, 0, 500, 500)] autorelease]; flutterPlatformViewsController->SetFlutterView(mockFlutterView); @@ -2356,7 +2404,9 @@ - (void)testFlutterPlatformViewControllerBeginFrameShouldResetCompisitionOrder { /*delegate=*/mock_delegate, /*rendering_api=*/flutter::IOSRenderingAPI::kSoftware, /*platform_views_controller=*/flutterPlatformViewsController, - /*task_runners=*/runners); + /*task_runners=*/runners, + /*worker_task_runner=*/nil, + /*is_gpu_disabled_sync_switch=*/nil); UIView* mockFlutterView = [[[UIView alloc] initWithFrame:CGRectMake(0, 0, 500, 500)] autorelease]; flutterPlatformViewsController->SetFlutterView(mockFlutterView); @@ -2452,7 +2502,9 @@ - (void)testFlutterPlatformViewControllerBeginFrameShouldResetCompisitionOrder { /*delegate=*/mock_delegate, /*rendering_api=*/flutter::IOSRenderingAPI::kSoftware, /*platform_views_controller=*/flutterPlatformViewsController, - /*task_runners=*/runners); + /*task_runners=*/runners, + /*worker_task_runner=*/nil, + /*is_gpu_disabled_sync_switch=*/nil); UIView* mockFlutterView = [[[UIView alloc] initWithFrame:CGRectMake(0, 0, 500, 500)] autorelease]; flutterPlatformViewsController->SetFlutterView(mockFlutterView); @@ -2548,7 +2600,9 @@ - (void)testThreadMergeAtEndFrame { /*delegate=*/mock_delegate, /*rendering_api=*/flutter::IOSRenderingAPI::kSoftware, /*platform_views_controller=*/flutterPlatformViewsController, - /*task_runners=*/runners); + /*task_runners=*/runners, + /*worker_task_runner=*/nil, + /*is_gpu_disabled_sync_switch=*/nil); UIView* mockFlutterView = [[[UIView alloc] initWithFrame:CGRectMake(0, 0, 500, 500)] autorelease]; flutterPlatformViewsController->SetFlutterView(mockFlutterView); @@ -2696,7 +2750,9 @@ - (void)testClipMaskViewIsReused { /*delegate=*/mock_delegate, /*rendering_api=*/flutter::IOSRenderingAPI::kSoftware, /*platform_views_controller=*/flutterPlatformViewsController, - /*task_runners=*/runners); + /*task_runners=*/runners, + /*worker_task_runner=*/nil, + /*is_gpu_disabled_sync_switch=*/nil); FlutterPlatformViewsTestMockFlutterPlatformFactory* factory = [[FlutterPlatformViewsTestMockFlutterPlatformFactory new] autorelease]; @@ -2803,7 +2859,9 @@ - (void)testDisposingViewInCompositionOrderDoNotCrash { /*delegate=*/mock_delegate, /*rendering_api=*/flutter::IOSRenderingAPI::kSoftware, /*platform_views_controller=*/flutterPlatformViewsController, - /*task_runners=*/runners); + /*task_runners=*/runners, + /*worker_task_runner=*/nil, + /*is_gpu_disabled_sync_switch=*/nil); UIView* mockFlutterView = [[[UIView alloc] initWithFrame:CGRectMake(0, 0, 500, 500)] autorelease]; flutterPlatformViewsController->SetFlutterView(mockFlutterView); @@ -2909,7 +2967,9 @@ - (void)testOnlyPlatformViewsAreRemovedWhenReset { /*delegate=*/mock_delegate, /*rendering_api=*/flutter::IOSRenderingAPI::kSoftware, /*platform_views_controller=*/flutterPlatformViewsController, - /*task_runners=*/runners); + /*task_runners=*/runners, + /*worker_task_runner=*/nil, + /*is_gpu_disabled_sync_switch=*/nil); FlutterPlatformViewsTestMockFlutterPlatformFactory* factory = [[FlutterPlatformViewsTestMockFlutterPlatformFactory new] autorelease]; diff --git a/shell/platform/darwin/ios/framework/Source/accessibility_bridge_test.mm b/shell/platform/darwin/ios/framework/Source/accessibility_bridge_test.mm index 1965d89ac705c..c617284489e73 100644 --- a/shell/platform/darwin/ios/framework/Source/accessibility_bridge_test.mm +++ b/shell/platform/darwin/ios/framework/Source/accessibility_bridge_test.mm @@ -149,7 +149,9 @@ - (void)testCreate { /*delegate=*/mock_delegate, /*rendering_api=*/flutter::IOSRenderingAPI::kSoftware, /*platform_views_controller=*/nil, - /*task_runners=*/runners); + /*task_runners=*/runners, + /*worker_task_runner=*/nil, + /*is_gpu_disabled_sync_switch=*/nil); auto bridge = std::make_unique(/*view=*/nil, /*platform_view=*/platform_view.get(), @@ -169,7 +171,9 @@ - (void)testUpdateSemanticsEmpty { /*delegate=*/mock_delegate, /*rendering_api=*/flutter::IOSRenderingAPI::kSoftware, /*platform_views_controller=*/nil, - /*task_runners=*/runners); + /*task_runners=*/runners, + /*worker_task_runner=*/nil, + /*is_gpu_disabled_sync_switch=*/nil); id mockFlutterView = OCMClassMock([FlutterView class]); id mockFlutterViewController = OCMClassMock([FlutterViewController class]); OCMStub([mockFlutterViewController viewIfLoaded]).andReturn(mockFlutterView); @@ -196,7 +200,9 @@ - (void)testUpdateSemanticsOneNode { /*delegate=*/mock_delegate, /*rendering_api=*/flutter::IOSRenderingAPI::kSoftware, /*platform_views_controller=*/nil, - /*task_runners=*/runners); + /*task_runners=*/runners, + /*worker_task_runner=*/nil, + /*is_gpu_disabled_sync_switch=*/nil); id mockFlutterView = OCMClassMock([FlutterView class]); id mockFlutterViewController = OCMClassMock([FlutterViewController class]); OCMStub([mockFlutterViewController view]).andReturn(mockFlutterView); @@ -241,7 +247,9 @@ - (void)testIsVoiceOverRunning { /*delegate=*/mock_delegate, /*rendering_api=*/flutter::IOSRenderingAPI::kSoftware, /*platform_views_controller=*/nil, - /*task_runners=*/runners); + /*task_runners=*/runners, + /*worker_task_runner=*/nil, + /*is_gpu_disabled_sync_switch=*/nil); id mockFlutterView = OCMClassMock([FlutterView class]); id mockFlutterViewController = OCMClassMock([FlutterViewController class]); OCMStub([mockFlutterViewController view]).andReturn(mockFlutterView); @@ -271,7 +279,9 @@ - (void)testSemanticsDeallocated { /*delegate=*/mock_delegate, /*rendering_api=*/flutter::IOSRenderingAPI::kSoftware, /*platform_views_controller=*/flutterPlatformViewsController, - /*task_runners=*/runners); + /*task_runners=*/runners, + /*worker_task_runner=*/nil, + /*is_gpu_disabled_sync_switch=*/nil); id mockFlutterView = OCMClassMock([FlutterView class]); id mockFlutterViewController = OCMClassMock([FlutterViewController class]); OCMStub([mockFlutterViewController view]).andReturn(mockFlutterView); @@ -328,7 +338,9 @@ - (void)testSemanticsDeallocatedWithoutLoadingView { /*delegate=*/mock_delegate, /*rendering_api=*/flutter::IOSRenderingAPI::kSoftware, /*platform_views_controller=*/flutterPlatformViewsController, - /*task_runners=*/runners); + /*task_runners=*/runners, + /*worker_task_runner=*/nil, + /*is_gpu_disabled_sync_switch=*/nil); MockFlutterPlatformFactory* factory = [[MockFlutterPlatformFactory new] autorelease]; flutterPlatformViewsController->RegisterViewFactory( @@ -371,7 +383,9 @@ - (void)testReplacedSemanticsDoesNotCleanupChildren { /*delegate=*/mock_delegate, /*rendering_api=*/flutter::IOSRenderingAPI::kSoftware, /*platform_views_controller=*/flutterPlatformViewsController, - /*task_runners=*/runners); + /*task_runners=*/runners, + /*worker_task_runner=*/nil, + /*is_gpu_disabled_sync_switch=*/nil); id engine = OCMClassMock([FlutterEngine class]); id mockFlutterViewController = OCMClassMock([FlutterViewController class]); FlutterView* flutterView = [[FlutterView alloc] initWithDelegate:engine @@ -463,7 +477,9 @@ - (void)testScrollableSemanticsDeallocated { /*delegate=*/mock_delegate, /*rendering_api=*/flutter::IOSRenderingAPI::kSoftware, /*platform_views_controller=*/flutterPlatformViewsController, - /*task_runners=*/runners); + /*task_runners=*/runners, + /*worker_task_runner=*/nil, + /*is_gpu_disabled_sync_switch=*/nil); id engine = OCMClassMock([FlutterEngine class]); id mockFlutterViewController = OCMClassMock([FlutterViewController class]); FlutterView* flutterView = [[FlutterView alloc] initWithDelegate:engine @@ -533,7 +549,9 @@ - (void)testBridgeReplacesSemanticsNode { /*delegate=*/mock_delegate, /*rendering_api=*/flutter::IOSRenderingAPI::kSoftware, /*platform_views_controller=*/flutterPlatformViewsController, - /*task_runners=*/runners); + /*task_runners=*/runners, + /*worker_task_runner=*/nil, + /*is_gpu_disabled_sync_switch=*/nil); id engine = OCMClassMock([FlutterEngine class]); id mockFlutterViewController = OCMClassMock([FlutterViewController class]); FlutterView* flutterView = [[FlutterView alloc] initWithDelegate:engine @@ -603,7 +621,9 @@ - (void)testAnnouncesRouteChanges { /*delegate=*/mock_delegate, /*rendering_api=*/flutter::IOSRenderingAPI::kSoftware, /*platform_views_controller=*/nil, - /*task_runners=*/runners); + /*task_runners=*/runners, + /*worker_task_runner=*/nil, + /*is_gpu_disabled_sync_switch=*/nil); id mockFlutterView = OCMClassMock([FlutterView class]); id mockFlutterViewController = OCMClassMock([FlutterViewController class]); OCMStub([mockFlutterViewController view]).andReturn(mockFlutterView); @@ -669,7 +689,9 @@ - (void)testRadioButtonIsNotSwitchButton { /*delegate=*/mock_delegate, /*rendering_api=*/flutter::IOSRenderingAPI::kSoftware, /*platform_views_controller=*/nil, - /*task_runners=*/runners); + /*task_runners=*/runners, + /*worker_task_runner=*/nil, + /*is_gpu_disabled_sync_switch=*/nil); id engine = OCMClassMock([FlutterEngine class]); id mockFlutterViewController = OCMClassMock([FlutterViewController class]); FlutterView* flutterView = [[FlutterView alloc] initWithDelegate:engine @@ -714,7 +736,9 @@ - (void)testLayoutChangeWithNonAccessibilityElement { /*delegate=*/mock_delegate, /*rendering_api=*/flutter::IOSRenderingAPI::kSoftware, /*platform_views_controller=*/nil, - /*task_runners=*/runners); + /*task_runners=*/runners, + /*worker_task_runner=*/nil, + /*is_gpu_disabled_sync_switch=*/nil); id mockFlutterView = OCMClassMock([FlutterView class]); id mockFlutterViewController = OCMClassMock([FlutterViewController class]); OCMStub([mockFlutterViewController view]).andReturn(mockFlutterView); @@ -796,7 +820,9 @@ - (void)testLayoutChangeDoesCallNativeAccessibility { /*delegate=*/mock_delegate, /*rendering_api=*/flutter::IOSRenderingAPI::kSoftware, /*platform_views_controller=*/nil, - /*task_runners=*/runners); + /*task_runners=*/runners, + /*worker_task_runner=*/nil, + /*is_gpu_disabled_sync_switch=*/nil); id mockFlutterView = OCMClassMock([FlutterView class]); id mockFlutterViewController = OCMClassMock([FlutterViewController class]); OCMStub([mockFlutterViewController view]).andReturn(mockFlutterView); @@ -869,7 +895,9 @@ - (void)testLayoutChangeDoesCallNativeAccessibilityWhenFocusChanged { /*delegate=*/mock_delegate, /*rendering_api=*/flutter::IOSRenderingAPI::kSoftware, /*platform_views_controller=*/nil, - /*task_runners=*/runners); + /*task_runners=*/runners, + /*worker_task_runner=*/nil, + /*is_gpu_disabled_sync_switch=*/nil); id mockFlutterView = OCMClassMock([FlutterView class]); id mockFlutterViewController = OCMClassMock([FlutterViewController class]); OCMStub([mockFlutterViewController view]).andReturn(mockFlutterView); @@ -941,7 +969,9 @@ - (void)testScrollableSemanticsContainerReturnsCorrectChildren { /*delegate=*/mock_delegate, /*rendering_api=*/flutter::IOSRenderingAPI::kSoftware, /*platform_views_controller=*/nil, - /*task_runners=*/runners); + /*task_runners=*/runners, + /*worker_task_runner=*/nil, + /*is_gpu_disabled_sync_switch=*/nil); id mockFlutterView = OCMClassMock([FlutterView class]); id mockFlutterViewController = OCMClassMock([FlutterViewController class]); OCMStub([mockFlutterViewController view]).andReturn(mockFlutterView); @@ -996,7 +1026,9 @@ - (void)testAnnouncesRouteChangesAndLayoutChangeInOneUpdate { /*delegate=*/mock_delegate, /*rendering_api=*/flutter::IOSRenderingAPI::kSoftware, /*platform_views_controller=*/nil, - /*task_runners=*/runners); + /*task_runners=*/runners, + /*worker_task_runner=*/nil, + /*is_gpu_disabled_sync_switch=*/nil); id mockFlutterView = OCMClassMock([FlutterView class]); id mockFlutterViewController = OCMClassMock([FlutterViewController class]); OCMStub([mockFlutterViewController view]).andReturn(mockFlutterView); @@ -1091,7 +1123,9 @@ - (void)testAnnouncesRouteChangesWhenAddAdditionalRoute { /*delegate=*/mock_delegate, /*rendering_api=*/flutter::IOSRenderingAPI::kSoftware, /*platform_views_controller=*/nil, - /*task_runners=*/runners); + /*task_runners=*/runners, + /*worker_task_runner=*/nil, + /*is_gpu_disabled_sync_switch=*/nil); id mockFlutterView = OCMClassMock([FlutterView class]); id mockFlutterViewController = OCMClassMock([FlutterViewController class]); OCMStub([mockFlutterViewController view]).andReturn(mockFlutterView); @@ -1175,7 +1209,9 @@ - (void)testAnnouncesRouteChangesRemoveRouteInMiddle { /*delegate=*/mock_delegate, /*rendering_api=*/flutter::IOSRenderingAPI::kSoftware, /*platform_views_controller=*/nil, - /*task_runners=*/runners); + /*task_runners=*/runners, + /*worker_task_runner=*/nil, + /*is_gpu_disabled_sync_switch=*/nil); id mockFlutterView = OCMClassMock([FlutterView class]); id mockFlutterViewController = OCMClassMock([FlutterViewController class]); OCMStub([mockFlutterViewController view]).andReturn(mockFlutterView); @@ -1265,7 +1301,9 @@ - (void)testAnnouncesRouteChangesWhenNoNamesRoute { /*delegate=*/mock_delegate, /*rendering_api=*/flutter::IOSRenderingAPI::kSoftware, /*platform_views_controller=*/nil, - /*task_runners=*/runners); + /*task_runners=*/runners, + /*worker_task_runner=*/nil, + /*is_gpu_disabled_sync_switch=*/nil); id mockFlutterView = OCMClassMock([FlutterView class]); id mockFlutterViewController = OCMClassMock([FlutterViewController class]); OCMStub([mockFlutterViewController view]).andReturn(mockFlutterView); @@ -1333,7 +1371,9 @@ - (void)testAnnouncesLayoutChangeWithNilIfLastFocusIsRemoved { /*delegate=*/mock_delegate, /*rendering_api=*/flutter::IOSRenderingAPI::kSoftware, /*platform_views_controller=*/nil, - /*task_runners=*/runners); + /*task_runners=*/runners, + /*worker_task_runner=*/nil, + /*is_gpu_disabled_sync_switch=*/nil); id mockFlutterViewController = OCMClassMock([FlutterViewController class]); id mockFlutterView = OCMClassMock([FlutterView class]); OCMStub([mockFlutterViewController view]).andReturn(mockFlutterView); @@ -1400,7 +1440,9 @@ - (void)testAnnouncesLayoutChangeWithTheSameItemFocused { /*delegate=*/mock_delegate, /*rendering_api=*/flutter::IOSRenderingAPI::kSoftware, /*platform_views_controller=*/nil, - /*task_runners=*/runners); + /*task_runners=*/runners, + /*worker_task_runner=*/nil, + /*is_gpu_disabled_sync_switch=*/nil); id mockFlutterViewController = OCMClassMock([FlutterViewController class]); id mockFlutterView = OCMClassMock([FlutterView class]); OCMStub([mockFlutterViewController view]).andReturn(mockFlutterView); @@ -1473,7 +1515,9 @@ - (void)testAnnouncesLayoutChangeWhenFocusMovedOutside { /*delegate=*/mock_delegate, /*rendering_api=*/flutter::IOSRenderingAPI::kSoftware, /*platform_views_controller=*/nil, - /*task_runners=*/runners); + /*task_runners=*/runners, + /*worker_task_runner=*/nil, + /*is_gpu_disabled_sync_switch=*/nil); id mockFlutterViewController = OCMClassMock([FlutterViewController class]); id mockFlutterView = OCMClassMock([FlutterView class]); OCMStub([mockFlutterViewController view]).andReturn(mockFlutterView); @@ -1548,7 +1592,9 @@ - (void)testAnnouncesScrollChangeWithLastFocused { /*delegate=*/mock_delegate, /*rendering_api=*/flutter::IOSRenderingAPI::kSoftware, /*platform_views_controller=*/nil, - /*task_runners=*/runners); + /*task_runners=*/runners, + /*worker_task_runner=*/nil, + /*is_gpu_disabled_sync_switch=*/nil); id mockFlutterViewController = OCMClassMock([FlutterViewController class]); id mockFlutterView = OCMClassMock([FlutterView class]); OCMStub([mockFlutterViewController view]).andReturn(mockFlutterView); @@ -1619,7 +1665,9 @@ - (void)testAnnouncesScrollChangeDoesCallNativeAccessibility { /*delegate=*/mock_delegate, /*rendering_api=*/flutter::IOSRenderingAPI::kSoftware, /*platform_views_controller=*/nil, - /*task_runners=*/runners); + /*task_runners=*/runners, + /*worker_task_runner=*/nil, + /*is_gpu_disabled_sync_switch=*/nil); id mockFlutterViewController = OCMClassMock([FlutterViewController class]); id mockFlutterView = OCMClassMock([FlutterView class]); OCMStub([mockFlutterViewController view]).andReturn(mockFlutterView); @@ -1692,7 +1740,9 @@ - (void)testAnnouncesIgnoresRouteChangesWhenModal { /*delegate=*/mock_delegate, /*rendering_api=*/flutter::IOSRenderingAPI::kSoftware, /*platform_views_controller=*/nil, - /*task_runners=*/runners); + /*task_runners=*/runners, + /*worker_task_runner=*/nil, + /*is_gpu_disabled_sync_switch=*/nil); id mockFlutterView = OCMClassMock([FlutterView class]); id mockFlutterViewController = OCMClassMock([FlutterViewController class]); OCMStub([mockFlutterViewController view]).andReturn(mockFlutterView); @@ -1747,7 +1797,9 @@ - (void)testAnnouncesIgnoresLayoutChangeWhenModal { /*delegate=*/mock_delegate, /*rendering_api=*/flutter::IOSRenderingAPI::kSoftware, /*platform_views_controller=*/nil, - /*task_runners=*/runners); + /*task_runners=*/runners, + /*worker_task_runner=*/nil, + /*is_gpu_disabled_sync_switch=*/nil); id mockFlutterView = OCMClassMock([FlutterView class]); id mockFlutterViewController = OCMClassMock([FlutterViewController class]); OCMStub([mockFlutterViewController view]).andReturn(mockFlutterView); @@ -1807,7 +1859,9 @@ - (void)testAnnouncesIgnoresScrollChangeWhenModal { /*delegate=*/mock_delegate, /*rendering_api=*/flutter::IOSRenderingAPI::kSoftware, /*platform_views_controller=*/nil, - /*task_runners=*/runners); + /*task_runners=*/runners, + /*worker_task_runner=*/nil, + /*is_gpu_disabled_sync_switch=*/nil); id mockFlutterView = OCMClassMock([FlutterView class]); id mockFlutterViewController = OCMClassMock([FlutterViewController class]); OCMStub([mockFlutterViewController view]).andReturn(mockFlutterView); @@ -1875,7 +1929,9 @@ - (void)testAccessibilityMessageAfterDeletion { /*delegate=*/mock_delegate, /*rendering_api=*/flutter::IOSRenderingAPI::kSoftware, /*platform_views_controller=*/nil, - /*task_runners=*/runners); + /*task_runners=*/runners, + /*worker_task_runner=*/nil, + /*is_gpu_disabled_sync_switch=*/nil); fml::AutoResetWaitableEvent latch; thread_task_runner->PostTask([&] { auto weakFactory = @@ -1908,7 +1964,9 @@ - (void)testFlutterSemanticsScrollViewManagedObjectLifecycleCorrectly { /*delegate=*/mock_delegate, /*rendering_api=*/flutter::IOSRenderingAPI::kSoftware, /*platform_views_controller=*/nil, - /*task_runners=*/runners); + /*task_runners=*/runners, + /*worker_task_runner=*/nil, + /*is_gpu_disabled_sync_switch=*/nil); id mockFlutterView = OCMClassMock([FlutterView class]); id mockFlutterViewController = OCMClassMock([FlutterViewController class]); OCMStub([mockFlutterViewController view]).andReturn(mockFlutterView); @@ -1956,7 +2014,9 @@ - (void)testPlatformViewDestructorDoesNotCallSemanticsAPIs { /*delegate=*/test_delegate, /*rendering_api=*/flutter::IOSRenderingAPI::kSoftware, /*platform_views_controller=*/nil, - /*task_runners=*/runners); + /*task_runners=*/runners, + /*worker_task_runner=*/nil, + /*is_gpu_disabled_sync_switch=*/nil); id mockFlutterViewController = OCMClassMock([FlutterViewController class]); auto flutterPlatformViewsController = diff --git a/shell/platform/darwin/ios/ios_context.h b/shell/platform/darwin/ios/ios_context.h index db14fd37e23de..35065675750b3 100644 --- a/shell/platform/darwin/ios/ios_context.h +++ b/shell/platform/darwin/ios/ios_context.h @@ -10,8 +10,10 @@ #include "flutter/common/graphics/gl_context_switch.h" #include "flutter/common/graphics/msaa_sample_count.h" #include "flutter/common/graphics/texture.h" +#include "flutter/fml/concurrent_message_loop.h" #include "flutter/fml/macros.h" #include "flutter/fml/platform/darwin/scoped_nsobject.h" +#include "flutter/fml/synchronization/sync_switch.h" #import "flutter/shell/platform/darwin/common/framework/Headers/FlutterTexture.h" #import "flutter/shell/platform/darwin/ios/rendering_api_selection.h" #include "third_party/skia/include/gpu/GrDirectContext.h" @@ -51,12 +53,17 @@ class IOSContext { /// @param[in] msaa_samples /// The number of MSAA samples to use. Only supplied to /// Skia, must be either 0, 1, 2, 4, or 8. + /// @param[in] task_runner + /// The engine concurrent task runner. /// /// @return A valid context on success. `nullptr` on failure. /// - static std::unique_ptr Create(IOSRenderingAPI api, - IOSRenderingBackend backend, - MsaaSampleCount msaa_samples); + static std::unique_ptr Create( + IOSRenderingAPI api, + IOSRenderingBackend backend, + MsaaSampleCount msaa_samples, + std::shared_ptr task_runner, + std::shared_ptr is_gpu_disabled_sync_switch); //---------------------------------------------------------------------------- /// @brief Collects the context object. This must happen on the thread on diff --git a/shell/platform/darwin/ios/ios_context.mm b/shell/platform/darwin/ios/ios_context.mm index f861e10e3ff6b..fba7071f6d65f 100644 --- a/shell/platform/darwin/ios/ios_context.mm +++ b/shell/platform/darwin/ios/ios_context.mm @@ -18,9 +18,12 @@ IOSContext::~IOSContext() = default; -std::unique_ptr IOSContext::Create(IOSRenderingAPI api, - IOSRenderingBackend backend, - MsaaSampleCount msaa_samples) { +std::unique_ptr IOSContext::Create( + IOSRenderingAPI api, + IOSRenderingBackend backend, + MsaaSampleCount msaa_samples, + std::shared_ptr task_runner, + std::shared_ptr is_gpu_disabled_sync_switch) { switch (api) { case IOSRenderingAPI::kSoftware: return std::make_unique(); @@ -30,7 +33,8 @@ case IOSRenderingBackend::kSkia: return std::make_unique(msaa_samples); case IOSRenderingBackend::kImpeller: - return std::make_unique(); + return std::make_unique(std::move(task_runner), + std::move(is_gpu_disabled_sync_switch)); } #endif // SHELL_ENABLE_METAL default: diff --git a/shell/platform/darwin/ios/ios_context_metal_impeller.h b/shell/platform/darwin/ios/ios_context_metal_impeller.h index a46dc81cfed9c..10136218291fd 100644 --- a/shell/platform/darwin/ios/ios_context_metal_impeller.h +++ b/shell/platform/darwin/ios/ios_context_metal_impeller.h @@ -20,7 +20,8 @@ namespace flutter { class IOSContextMetalImpeller final : public IOSContext { public: - IOSContextMetalImpeller(); + IOSContextMetalImpeller(std::shared_ptr task_runner, + std::shared_ptr is_gpu_disabled_sync_switch); ~IOSContextMetalImpeller(); diff --git a/shell/platform/darwin/ios/ios_context_metal_impeller.mm b/shell/platform/darwin/ios/ios_context_metal_impeller.mm index fc011f652c4cf..75f3a531fcd69 100644 --- a/shell/platform/darwin/ios/ios_context_metal_impeller.mm +++ b/shell/platform/darwin/ios/ios_context_metal_impeller.mm @@ -8,10 +8,14 @@ namespace flutter { -IOSContextMetalImpeller::IOSContextMetalImpeller() +IOSContextMetalImpeller::IOSContextMetalImpeller( + std::shared_ptr task_runner, + std::shared_ptr is_gpu_disabled_sync_switch) : IOSContext(MsaaSampleCount::kFour), darwin_context_metal_impeller_(fml::scoped_nsobject{ - [[FlutterDarwinContextMetalImpeller alloc] init]}) {} + [[FlutterDarwinContextMetalImpeller alloc] + initWithTaskRunner:std::move(task_runner) + is_gpu_disabled_sync_switch:std::move(is_gpu_disabled_sync_switch)]}) {} IOSContextMetalImpeller::~IOSContextMetalImpeller() = default; diff --git a/shell/platform/darwin/ios/platform_view_ios.h b/shell/platform/darwin/ios/platform_view_ios.h index e9129350a4277..fa48ce8ee309b 100644 --- a/shell/platform/darwin/ios/platform_view_ios.h +++ b/shell/platform/darwin/ios/platform_view_ios.h @@ -49,7 +49,9 @@ class PlatformViewIOS final : public PlatformView { PlatformView::Delegate& delegate, IOSRenderingAPI rendering_api, const std::shared_ptr& platform_views_controller, - const flutter::TaskRunners& task_runners); + const flutter::TaskRunners& task_runners, + const std::shared_ptr& worker_task_runner, + std::shared_ptr is_gpu_disabled_sync_switch); ~PlatformViewIOS() override; diff --git a/shell/platform/darwin/ios/platform_view_ios.mm b/shell/platform/darwin/ios/platform_view_ios.mm index 219dab4ec9c98..61095c81d71a9 100644 --- a/shell/platform/darwin/ios/platform_view_ios.mm +++ b/shell/platform/darwin/ios/platform_view_ios.mm @@ -55,14 +55,18 @@ new PlatformMessageHandlerIos(task_runners.GetPlatformTaskRunner())) {} PlatformView::Delegate& delegate, IOSRenderingAPI rendering_api, const std::shared_ptr& platform_views_controller, - const flutter::TaskRunners& task_runners) + const flutter::TaskRunners& task_runners, + const std::shared_ptr& worker_task_runner, + std::shared_ptr is_gpu_disabled_sync_switch) : PlatformViewIOS( delegate, IOSContext::Create( rendering_api, delegate.OnPlatformViewGetSettings().enable_impeller ? IOSRenderingBackend::kImpeller : IOSRenderingBackend::kSkia, - static_cast(delegate.OnPlatformViewGetSettings().msaa_samples)), + static_cast(delegate.OnPlatformViewGetSettings().msaa_samples), + worker_task_runner, + std::move(is_gpu_disabled_sync_switch)), platform_views_controller, task_runners) {}