| // 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 <Metal/Metal.h> |
| |
| #include <deque> |
| #include <string> |
| |
| #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" |
| #include "impeller/renderer/backend/metal/command_buffer_mtl.h" |
| #include "impeller/renderer/backend/metal/gpu_tracer_mtl.h" |
| #include "impeller/renderer/backend/metal/pipeline_library_mtl.h" |
| #include "impeller/renderer/backend/metal/shader_library_mtl.h" |
| #include "impeller/renderer/capabilities.h" |
| #include "impeller/renderer/context.h" |
| |
| #if TARGET_OS_SIMULATOR |
| #define IMPELLER_CA_METAL_LAYER_AVAILABLE API_AVAILABLE(macos(10.11), ios(13.0)) |
| #else // TARGET_OS_SIMULATOR |
| #define IMPELLER_CA_METAL_LAYER_AVAILABLE API_AVAILABLE(macos(10.11), ios(8.0)) |
| #endif // TARGET_OS_SIMULATOR |
| |
| namespace impeller { |
| |
| class ContextMTL final : public Context, |
| public BackendCast<ContextMTL, Context>, |
| public std::enable_shared_from_this<ContextMTL> { |
| public: |
| static std::shared_ptr<ContextMTL> Create( |
| const std::vector<std::string>& shader_library_paths, |
| std::shared_ptr<const fml::SyncSwitch> is_gpu_disabled_sync_switch); |
| |
| static std::shared_ptr<ContextMTL> Create( |
| const std::vector<std::shared_ptr<fml::Mapping>>& shader_libraries_data, |
| std::shared_ptr<const fml::SyncSwitch> is_gpu_disabled_sync_switch, |
| const std::string& label); |
| |
| static std::shared_ptr<ContextMTL> Create( |
| id<MTLDevice> device, |
| id<MTLCommandQueue> command_queue, |
| const std::vector<std::shared_ptr<fml::Mapping>>& shader_libraries_data, |
| std::shared_ptr<const fml::SyncSwitch> is_gpu_disabled_sync_switch, |
| const std::string& label); |
| |
| // |Context| |
| ~ContextMTL() override; |
| |
| // |Context| |
| BackendType GetBackendType() const override; |
| |
| id<MTLDevice> GetMTLDevice() const; |
| |
| // |Context| |
| std::string DescribeGpuModel() const override; |
| |
| // |Context| |
| bool IsValid() const override; |
| |
| // |Context| |
| std::shared_ptr<Allocator> GetResourceAllocator() const override; |
| |
| // |Context| |
| std::shared_ptr<ShaderLibrary> GetShaderLibrary() const override; |
| |
| // |Context| |
| std::shared_ptr<SamplerLibrary> GetSamplerLibrary() const override; |
| |
| // |Context| |
| std::shared_ptr<PipelineLibrary> GetPipelineLibrary() const override; |
| |
| // |Context| |
| std::shared_ptr<CommandBuffer> CreateCommandBuffer() const override; |
| |
| // |Context| |
| const std::shared_ptr<const Capabilities>& GetCapabilities() const override; |
| |
| // |Context| |
| bool UpdateOffscreenLayerPixelFormat(PixelFormat format) override; |
| |
| // |Context| |
| void Shutdown() override; |
| |
| id<MTLCommandBuffer> CreateMTLCommandBuffer(const std::string& label) const; |
| |
| const std::shared_ptr<fml::ConcurrentTaskRunner> GetWorkerTaskRunner() const; |
| |
| std::shared_ptr<const fml::SyncSwitch> GetIsGpuDisabledSyncSwitch() const; |
| |
| #ifdef IMPELLER_DEBUG |
| std::shared_ptr<GPUTracerMTL> GetGPUTracer() const; |
| #endif // IMPELLER_DEBUG |
| |
| // |Context| |
| void StoreTaskForGPU(const std::function<void()>& task) override; |
| |
| private: |
| class SyncSwitchObserver : public fml::SyncSwitch::Observer { |
| public: |
| explicit SyncSwitchObserver(ContextMTL& parent); |
| virtual ~SyncSwitchObserver() = default; |
| void OnSyncSwitchUpdate(bool new_value) override; |
| |
| private: |
| ContextMTL& parent_; |
| }; |
| |
| id<MTLDevice> device_ = nullptr; |
| id<MTLCommandQueue> command_queue_ = nullptr; |
| std::shared_ptr<ShaderLibraryMTL> shader_library_; |
| std::shared_ptr<PipelineLibraryMTL> pipeline_library_; |
| std::shared_ptr<SamplerLibrary> sampler_library_; |
| std::shared_ptr<AllocatorMTL> resource_allocator_; |
| std::shared_ptr<const Capabilities> device_capabilities_; |
| std::shared_ptr<fml::ConcurrentMessageLoop> raster_message_loop_; |
| std::shared_ptr<const fml::SyncSwitch> is_gpu_disabled_sync_switch_; |
| #ifdef IMPELLER_DEBUG |
| std::shared_ptr<GPUTracerMTL> gpu_tracer_; |
| #endif // IMPELLER_DEBUG |
| std::deque<std::function<void()>> tasks_awaiting_gpu_; |
| std::unique_ptr<SyncSwitchObserver> sync_switch_observer_; |
| bool is_valid_ = false; |
| |
| ContextMTL( |
| id<MTLDevice> device, |
| id<MTLCommandQueue> command_queue, |
| NSArray<id<MTLLibrary>>* shader_libraries, |
| std::shared_ptr<const fml::SyncSwitch> is_gpu_disabled_sync_switch); |
| |
| std::shared_ptr<CommandBuffer> CreateCommandBufferInQueue( |
| id<MTLCommandQueue> queue) const; |
| |
| void FlushTasksAwaitingGPU(); |
| |
| ContextMTL(const ContextMTL&) = delete; |
| |
| ContextMTL& operator=(const ContextMTL&) = delete; |
| }; |
| |
| } // namespace impeller |