From 878fc88dd0e954e98641016c522159cf22b43276 Mon Sep 17 00:00:00 2001 From: Chinmay Garde Date: Thu, 11 Aug 2022 14:58:16 -0700 Subject: [PATCH 1/2] [Impeller] Add implementations for concurrent work-queues. These workers are owned by Impeller and not shared with the IO pool because we don't want long running tasks such as image decompression getting in the way of these Impeller render tasks. Impeller will still use the work pool provided by the shell for image decompression as before. This patch just adds the queues but doesn't use them. --- impeller/base/BUILD.gn | 11 +++++ .../base/platform/darwin/work_queue_darwin.cc | 38 +++++++++++++++++ .../base/platform/darwin/work_queue_darwin.h | 36 ++++++++++++++++ impeller/base/work_queue.cc | 13 ++++++ impeller/base/work_queue.h | 27 ++++++++++++ impeller/base/work_queue_common.cc | 25 +++++++++++ impeller/base/work_queue_common.h | 33 +++++++++++++++ .../renderer/backend/gles/context_gles.cc | 22 +++++++++- impeller/renderer/backend/gles/context_gles.h | 4 ++ impeller/renderer/backend/metal/context_mtl.h | 4 ++ .../renderer/backend/metal/context_mtl.mm | 41 +++++++++++++++---- .../renderer/backend/vulkan/context_vk.cc | 14 +++++++ impeller/renderer/backend/vulkan/context_vk.h | 4 ++ impeller/renderer/context.h | 3 ++ 14 files changed, 265 insertions(+), 10 deletions(-) create mode 100644 impeller/base/platform/darwin/work_queue_darwin.cc create mode 100644 impeller/base/platform/darwin/work_queue_darwin.h create mode 100644 impeller/base/work_queue.cc create mode 100644 impeller/base/work_queue.h create mode 100644 impeller/base/work_queue_common.cc create mode 100644 impeller/base/work_queue_common.h diff --git a/impeller/base/BUILD.gn b/impeller/base/BUILD.gn index 577d34d78f2b7..4edd4e1a154f9 100644 --- a/impeller/base/BUILD.gn +++ b/impeller/base/BUILD.gn @@ -24,8 +24,19 @@ impeller_component("base") { "validation.h", "version.cc", "version.h", + "work_queue.cc", + "work_queue.h", + "work_queue_common.cc", + "work_queue_common.h", ] + if (is_ios || is_mac) { + sources += [ + "platform/darwin/work_queue_darwin.cc", + "platform/darwin/work_queue_darwin.h", + ] + } + deps = [ "//flutter/fml" ] } diff --git a/impeller/base/platform/darwin/work_queue_darwin.cc b/impeller/base/platform/darwin/work_queue_darwin.cc new file mode 100644 index 0000000000000..6ac76520530ed --- /dev/null +++ b/impeller/base/platform/darwin/work_queue_darwin.cc @@ -0,0 +1,38 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "impeller/base/platform/darwin/work_queue_darwin.h" + +namespace impeller { + +std::shared_ptr WorkQueueDarwin::Create() { + auto queue = std::shared_ptr(new WorkQueueDarwin()); + if (!queue->IsValid()) { + return nullptr; + } + return queue; +} + +WorkQueueDarwin::WorkQueueDarwin() + : queue_(::dispatch_queue_create( + "io.flutter.impeller.wq", + ::dispatch_queue_attr_make_with_qos_class( + DISPATCH_QUEUE_CONCURRENT_WITH_AUTORELEASE_POOL, + QOS_CLASS_USER_INITIATED, + -1))) {} + +WorkQueueDarwin::~WorkQueueDarwin() = default; + +bool WorkQueueDarwin::IsValid() const { + return queue_ != NULL; +} + +// |WorkQueue| +void WorkQueueDarwin::PostTask(fml::closure task) { + dispatch_async(queue_, ^() { + task(); + }); +} + +} // namespace impeller diff --git a/impeller/base/platform/darwin/work_queue_darwin.h b/impeller/base/platform/darwin/work_queue_darwin.h new file mode 100644 index 0000000000000..c82aca9eb285f --- /dev/null +++ b/impeller/base/platform/darwin/work_queue_darwin.h @@ -0,0 +1,36 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#pragma once + +#include + +#include + +#include "flutter/fml/macros.h" +#include "impeller/base/work_queue.h" + +namespace impeller { + +class WorkQueueDarwin final : public WorkQueue { + public: + static std::shared_ptr Create(); + + // |WorkQueue| + ~WorkQueueDarwin(); + + bool IsValid() const; + + private: + dispatch_queue_t queue_ = NULL; + + WorkQueueDarwin(); + + // |WorkQueue| + void PostTask(fml::closure task) override; + + FML_DISALLOW_COPY_AND_ASSIGN(WorkQueueDarwin); +}; + +} // namespace impeller diff --git a/impeller/base/work_queue.cc b/impeller/base/work_queue.cc new file mode 100644 index 0000000000000..f4a375496207a --- /dev/null +++ b/impeller/base/work_queue.cc @@ -0,0 +1,13 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "flutter/impeller/base/work_queue.h" + +namespace impeller { + +WorkQueue::WorkQueue() = default; + +WorkQueue::~WorkQueue() = default; + +} // namespace impeller diff --git a/impeller/base/work_queue.h b/impeller/base/work_queue.h new file mode 100644 index 0000000000000..afd31c7acd53c --- /dev/null +++ b/impeller/base/work_queue.h @@ -0,0 +1,27 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#pragma once + +#include + +#include "flutter/fml/closure.h" +#include "flutter/fml/macros.h" + +namespace impeller { + +class WorkQueue : public std::enable_shared_from_this { + public: + virtual ~WorkQueue(); + + virtual void PostTask(fml::closure task) = 0; + + protected: + WorkQueue(); + + private: + FML_DISALLOW_COPY_AND_ASSIGN(WorkQueue); +}; + +} // namespace impeller diff --git a/impeller/base/work_queue_common.cc b/impeller/base/work_queue_common.cc new file mode 100644 index 0000000000000..9a1f0620148ec --- /dev/null +++ b/impeller/base/work_queue_common.cc @@ -0,0 +1,25 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "impeller/base/work_queue_common.h" + +namespace impeller { + +std::shared_ptr WorkQueueCommon::Create() { + return std::shared_ptr(new WorkQueueCommon()); +} + +WorkQueueCommon::WorkQueueCommon() + : loop_(fml::ConcurrentMessageLoop::Create(2u)) {} + +WorkQueueCommon::~WorkQueueCommon() { + loop_->Terminate(); +} + +// |WorkQueue| +void WorkQueueCommon::PostTask(fml::closure task) { + loop_->GetTaskRunner()->PostTask(std::move(task)); +} + +} // namespace impeller diff --git a/impeller/base/work_queue_common.h b/impeller/base/work_queue_common.h new file mode 100644 index 0000000000000..952f6ecbadacd --- /dev/null +++ b/impeller/base/work_queue_common.h @@ -0,0 +1,33 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#pragma once + +#include + +#include "flutter/fml/concurrent_message_loop.h" +#include "flutter/fml/macros.h" +#include "impeller/base/work_queue.h" + +namespace impeller { + +class WorkQueueCommon : public WorkQueue { + public: + static std::shared_ptr Create(); + + // |WorkQueue| + ~WorkQueueCommon(); + + private: + std::shared_ptr loop_; + + WorkQueueCommon(); + + // |WorkQueue| + void PostTask(fml::closure task) override; + + FML_DISALLOW_COPY_AND_ASSIGN(WorkQueueCommon); +}; + +} // namespace impeller diff --git a/impeller/renderer/backend/gles/context_gles.cc b/impeller/renderer/backend/gles/context_gles.cc index a7522b412d7bf..7ff2339498613 100644 --- a/impeller/renderer/backend/gles/context_gles.cc +++ b/impeller/renderer/backend/gles/context_gles.cc @@ -6,6 +6,7 @@ #include "impeller/base/config.h" #include "impeller/base/validation.h" +#include "impeller/base/work_queue_common.h" namespace impeller { @@ -52,12 +53,21 @@ ContextGLES::ContextGLES( } } - // Create the sampler library + // Create the sampler library. { sampler_library_ = std::shared_ptr(new SamplerLibraryGLES()); } + // Create the work queue. + { + work_queue_ = WorkQueueCommon::Create(); + if (!work_queue_) { + VALIDATION_LOG << "Could not create work queue."; + return; + } + } + is_valid_ = true; } @@ -86,27 +96,37 @@ bool ContextGLES::IsValid() const { return is_valid_; } +// |Context| std::shared_ptr ContextGLES::GetResourceAllocator() const { return resource_allocator_; } +// |Context| std::shared_ptr ContextGLES::GetShaderLibrary() const { return shader_library_; } +// |Context| std::shared_ptr ContextGLES::GetSamplerLibrary() const { return sampler_library_; } +// |Context| std::shared_ptr ContextGLES::GetPipelineLibrary() const { return pipeline_library_; } +// |Context| std::shared_ptr ContextGLES::CreateCommandBuffer() const { return std::shared_ptr( new CommandBufferGLES(weak_from_this(), reactor_)); } +// |Context| +std::shared_ptr ContextGLES::GetWorkQueue() const { + return work_queue_; +} + // |Context| bool ContextGLES::HasThreadingRestrictions() const { return true; diff --git a/impeller/renderer/backend/gles/context_gles.h b/impeller/renderer/backend/gles/context_gles.h index f96efd2098760..7c7246dc796b6 100644 --- a/impeller/renderer/backend/gles/context_gles.h +++ b/impeller/renderer/backend/gles/context_gles.h @@ -38,6 +38,7 @@ class ContextGLES final : public Context, std::shared_ptr shader_library_; std::shared_ptr pipeline_library_; std::shared_ptr sampler_library_; + std::shared_ptr work_queue_; std::shared_ptr resource_allocator_; bool is_valid_ = false; @@ -62,6 +63,9 @@ class ContextGLES final : public Context, // |Context| std::shared_ptr CreateCommandBuffer() const override; + // |Context| + std::shared_ptr GetWorkQueue() const override; + // |Context| bool HasThreadingRestrictions() const override; diff --git a/impeller/renderer/backend/metal/context_mtl.h b/impeller/renderer/backend/metal/context_mtl.h index a08a9b252071c..45368a26ac737 100644 --- a/impeller/renderer/backend/metal/context_mtl.h +++ b/impeller/renderer/backend/metal/context_mtl.h @@ -42,6 +42,7 @@ class ContextMTL final : public Context, std::shared_ptr pipeline_library_; std::shared_ptr sampler_library_; std::shared_ptr resource_allocator_; + std::shared_ptr work_queue_; bool is_valid_ = false; ContextMTL(id device, NSArray>* shader_libraries); @@ -64,6 +65,9 @@ class ContextMTL final : public Context, // |Context| std::shared_ptr CreateCommandBuffer() const override; + // |Context| + std::shared_ptr GetWorkQueue() const override; + 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 c19f3888e6d18..b3a8d7ea5c805 100644 --- a/impeller/renderer/backend/metal/context_mtl.mm +++ b/impeller/renderer/backend/metal/context_mtl.mm @@ -9,6 +9,7 @@ #include "flutter/fml/file.h" #include "flutter/fml/logging.h" #include "flutter/fml/paths.h" +#include "impeller/base/platform/darwin/work_queue_darwin.h" #include "impeller/renderer/backend/metal/sampler_library_mtl.h" #include "impeller/renderer/sampler_descriptor.h" @@ -40,31 +41,43 @@ shader_library_ = std::move(library); } - // Setup command queues. - command_queue_ = device_.newCommandQueue; - - if (!command_queue_) { - return; + // Setup command queue. + { + command_queue_ = device_.newCommandQueue; + if (!command_queue_) { + VALIDATION_LOG << "Could not setup the command queue."; + return; + } + command_queue_.label = @"Impeller Command Queue"; } - command_queue_.label = @"Impeller Command Queue"; - // Setup the pipeline library. - { // + { pipeline_library_ = std::shared_ptr(new PipelineLibraryMTL(device_)); } // Setup the sampler library. - { // + { sampler_library_ = std::shared_ptr(new SamplerLibraryMTL(device_)); } + // Setup the resource allocator. { resource_allocator_ = std::shared_ptr( new AllocatorMTL(device_, "Impeller Permanents Allocator")); if (!resource_allocator_) { + VALIDATION_LOG << "Could not setup the resource allocator."; + return; + } + } + + // Setup the work queue. + { + work_queue_ = WorkQueueDarwin::Create(); + if (!work_queue_) { + VALIDATION_LOG << "Could not setup the work queue."; return; } } @@ -167,26 +180,36 @@ ContextMTL::~ContextMTL() = default; +// |Context| bool ContextMTL::IsValid() const { return is_valid_; } +// |Context| std::shared_ptr ContextMTL::GetShaderLibrary() const { return shader_library_; } +// |Context| std::shared_ptr ContextMTL::GetPipelineLibrary() const { return pipeline_library_; } +// |Context| std::shared_ptr ContextMTL::GetSamplerLibrary() const { return sampler_library_; } +// |Context| std::shared_ptr ContextMTL::CreateCommandBuffer() const { return CreateCommandBufferInQueue(command_queue_); } +// |Context| +std::shared_ptr ContextMTL::GetWorkQueue() const { + return work_queue_; +} + std::shared_ptr ContextMTL::CreateCommandBufferInQueue( id queue) const { if (!IsValid()) { diff --git a/impeller/renderer/backend/vulkan/context_vk.cc b/impeller/renderer/backend/vulkan/context_vk.cc index 52329dd833071..27a15e293222e 100644 --- a/impeller/renderer/backend/vulkan/context_vk.cc +++ b/impeller/renderer/backend/vulkan/context_vk.cc @@ -12,6 +12,7 @@ #include "flutter/fml/build_config.h" #include "flutter/fml/trace_event.h" #include "impeller/base/validation.h" +#include "impeller/base/work_queue_common.h" #include "impeller/renderer/backend/vulkan/allocator_vk.h" #include "impeller/renderer/backend/vulkan/capabilities_vk.h" #include "impeller/renderer/backend/vulkan/surface_producer_vk.h" @@ -407,6 +408,13 @@ ContextVK::ContextVK( return; } + auto work_queue = WorkQueueCommon::Create(); + + if (!work_queue) { + VALIDATION_LOG << "Could not create workqueue."; + return; + } + instance_ = std::move(instance.value); debug_messenger_ = std::move(debug_messenger); device_ = std::move(device.value); @@ -414,6 +422,7 @@ ContextVK::ContextVK( shader_library_ = std::move(shader_library); sampler_library_ = std::move(sampler_library); pipeline_library_ = std::move(pipeline_library); + work_queue_ = std::move(work_queue); graphics_queue_ = device_->getQueue(graphics_queue->family, graphics_queue->index); compute_queue_ = @@ -447,6 +456,11 @@ std::shared_ptr ContextVK::GetPipelineLibrary() const { return pipeline_library_; } +// |Context| +std::shared_ptr ContextVK::GetWorkQueue() const { + return work_queue_; +} + std::shared_ptr ContextVK::CreateCommandBuffer() const { FML_UNREACHABLE(); } diff --git a/impeller/renderer/backend/vulkan/context_vk.h b/impeller/renderer/backend/vulkan/context_vk.h index a83bd2d0a14b7..eadc810d44d36 100644 --- a/impeller/renderer/backend/vulkan/context_vk.h +++ b/impeller/renderer/backend/vulkan/context_vk.h @@ -78,6 +78,7 @@ class ContextVK final : public Context, public BackendCast { std::unique_ptr swapchain_; std::unique_ptr graphics_command_pool_; std::unique_ptr surface_producer_; + std::shared_ptr work_queue_; bool is_valid_ = false; ContextVK( @@ -102,6 +103,9 @@ class ContextVK final : public Context, public BackendCast { // |Context| std::shared_ptr CreateCommandBuffer() const override; + // |Context| + std::shared_ptr GetWorkQueue() const override; + FML_DISALLOW_COPY_AND_ASSIGN(ContextVK); }; diff --git a/impeller/renderer/context.h b/impeller/renderer/context.h index dad614f5051eb..7f13fce9ac684 100644 --- a/impeller/renderer/context.h +++ b/impeller/renderer/context.h @@ -16,6 +16,7 @@ class SamplerLibrary; class CommandBuffer; class PipelineLibrary; class Allocator; +class WorkQueue; class Context : public std::enable_shared_from_this { public: @@ -36,6 +37,8 @@ class Context : public std::enable_shared_from_this { virtual std::shared_ptr CreateCommandBuffer() const = 0; + virtual std::shared_ptr GetWorkQueue() const = 0; + virtual bool HasThreadingRestrictions() const; protected: From 6fbe5116ff273f6adec24175b4337e74459b4690 Mon Sep 17 00:00:00 2001 From: Chinmay Garde Date: Thu, 11 Aug 2022 15:16:53 -0700 Subject: [PATCH 2/2] Licenses. --- ci/licenses_golden/licenses_flutter | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter index 450968be91055..a051333848cc4 100644 --- a/ci/licenses_golden/licenses_flutter +++ b/ci/licenses_golden/licenses_flutter @@ -450,6 +450,8 @@ FILE: ../../../flutter/impeller/base/base_unittests.cc FILE: ../../../flutter/impeller/base/comparable.cc FILE: ../../../flutter/impeller/base/comparable.h FILE: ../../../flutter/impeller/base/config.h +FILE: ../../../flutter/impeller/base/platform/darwin/work_queue_darwin.cc +FILE: ../../../flutter/impeller/base/platform/darwin/work_queue_darwin.h FILE: ../../../flutter/impeller/base/promise.cc FILE: ../../../flutter/impeller/base/promise.h FILE: ../../../flutter/impeller/base/strings.cc @@ -462,6 +464,10 @@ FILE: ../../../flutter/impeller/base/validation.cc FILE: ../../../flutter/impeller/base/validation.h FILE: ../../../flutter/impeller/base/version.cc FILE: ../../../flutter/impeller/base/version.h +FILE: ../../../flutter/impeller/base/work_queue.cc +FILE: ../../../flutter/impeller/base/work_queue.h +FILE: ../../../flutter/impeller/base/work_queue_common.cc +FILE: ../../../flutter/impeller/base/work_queue_common.h FILE: ../../../flutter/impeller/blobcat/blob.cc FILE: ../../../flutter/impeller/blobcat/blob.h FILE: ../../../flutter/impeller/blobcat/blob_library.cc