| // 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. |
| |
| #ifndef FLUTTER_IMPELLER_RENDERER_CONTEXT_H_ |
| #define FLUTTER_IMPELLER_RENDERER_CONTEXT_H_ |
| |
| #include <memory> |
| #include <string> |
| |
| #include "impeller/core/allocator.h" |
| #include "impeller/core/capture.h" |
| #include "impeller/core/formats.h" |
| #include "impeller/renderer/capabilities.h" |
| #include "impeller/renderer/command_queue.h" |
| #include "impeller/renderer/sampler_library.h" |
| |
| namespace impeller { |
| |
| class ShaderLibrary; |
| class CommandBuffer; |
| class PipelineLibrary; |
| |
| //------------------------------------------------------------------------------ |
| /// @brief To do anything rendering related with Impeller, you need a |
| /// context. |
| /// |
| /// Contexts are expensive to construct and typically you only need |
| /// one in the process. The context represents a connection to a |
| /// graphics or compute accelerator on the device. |
| /// |
| /// If there are multiple context in a process, it would typically |
| /// be for separation of concerns (say, use with multiple engines in |
| /// Flutter), talking to multiple accelerators, or talking to the |
| /// same accelerator using different client APIs (Metal, Vulkan, |
| /// OpenGL ES, etc..). |
| /// |
| /// Contexts are thread-safe. They may be created, used, and |
| /// collected (though not from a thread used by an internal pool) on |
| /// any thread. They may also be accessed simultaneously from |
| /// multiple threads. |
| /// |
| /// Contexts are abstract and a concrete instance must be created |
| /// using one of the subclasses of `Context` in |
| /// `//impeller/renderer/backend`. |
| class Context { |
| public: |
| enum class BackendType { |
| kMetal, |
| kOpenGLES, |
| kVulkan, |
| }; |
| |
| /// The maximum number of tasks that should ever be stored for |
| /// `StoreTaskForGPU`. |
| /// |
| /// This number was arbitrarily chosen. The idea is that this is a somewhat |
| /// rare situation where tasks happen to get executed in that tiny amount of |
| /// time while an app is being backgrounded but still executing. |
| static constexpr int32_t kMaxTasksAwaitingGPU = 10; |
| |
| //---------------------------------------------------------------------------- |
| /// @brief Destroys an Impeller context. |
| /// |
| virtual ~Context(); |
| |
| //---------------------------------------------------------------------------- |
| /// @brief Get the graphics backend of an Impeller context. |
| /// |
| /// This is useful for cases where a renderer needs to track and |
| /// lookup backend-specific resources, like shaders or uniform |
| /// layout information. |
| /// |
| /// It's not recommended to use this as a substitute for |
| /// per-backend capability checking. Instead, check for specific |
| /// capabilities via `GetCapabilities()`. |
| /// |
| /// @return The graphics backend of the `Context`. |
| /// |
| virtual BackendType GetBackendType() const = 0; |
| |
| // TODO(129920): Refactor and move to capabilities. |
| virtual std::string DescribeGpuModel() const = 0; |
| |
| //---------------------------------------------------------------------------- |
| /// @brief Determines if a context is valid. If the caller ever receives |
| /// an invalid context, they must discard it and construct a new |
| /// context. There is no recovery mechanism to repair a bad |
| /// context. |
| /// |
| /// It is convention in Impeller to never return an invalid |
| /// context from a call that returns an pointer to a context. The |
| /// call implementation performs validity checks itself and return |
| /// a null context instead of a pointer to an invalid context. |
| /// |
| /// How a context goes invalid is backend specific. It could |
| /// happen due to device loss, or any other unrecoverable error. |
| /// |
| /// @return If the context is valid. |
| /// |
| virtual bool IsValid() const = 0; |
| |
| //---------------------------------------------------------------------------- |
| /// @brief Get the capabilities of Impeller context. All optionally |
| /// supported feature of the platform, client-rendering API, and |
| /// device can be queried using the `Capabilities`. |
| /// |
| /// @return The capabilities. Can never be `nullptr` for a valid context. |
| /// |
| virtual const std::shared_ptr<const Capabilities>& GetCapabilities() |
| const = 0; |
| |
| // TODO(129920): Refactor and move to capabilities. |
| virtual bool UpdateOffscreenLayerPixelFormat(PixelFormat format); |
| |
| //---------------------------------------------------------------------------- |
| /// @brief Returns the allocator used to create textures and buffers on |
| /// the device. |
| /// |
| /// @return The resource allocator. Can never be `nullptr` for a valid |
| /// context. |
| /// |
| virtual std::shared_ptr<Allocator> GetResourceAllocator() const = 0; |
| |
| //---------------------------------------------------------------------------- |
| /// @brief Returns the library of shaders used to specify the |
| /// programmable stages of a pipeline. |
| /// |
| /// @return The shader library. Can never be `nullptr` for a valid |
| /// context. |
| /// |
| virtual std::shared_ptr<ShaderLibrary> GetShaderLibrary() const = 0; |
| |
| //---------------------------------------------------------------------------- |
| /// @brief Returns the library of combined image samplers used in |
| /// shaders. |
| /// |
| /// @return The sampler library. Can never be `nullptr` for a valid |
| /// context. |
| /// |
| virtual std::shared_ptr<SamplerLibrary> GetSamplerLibrary() const = 0; |
| |
| //---------------------------------------------------------------------------- |
| /// @brief Returns the library of pipelines used by render or compute |
| /// commands. |
| /// |
| /// @return The pipeline library. Can never be `nullptr` for a valid |
| /// context. |
| /// |
| virtual std::shared_ptr<PipelineLibrary> GetPipelineLibrary() const = 0; |
| |
| //---------------------------------------------------------------------------- |
| /// @brief Create a new command buffer. Command buffers can be used to |
| /// encode graphics, blit, or compute commands to be submitted to |
| /// the device. |
| /// |
| /// A command buffer can only be used on a single thread. |
| /// Multi-threaded render, blit, or compute passes must create a |
| /// new command buffer on each thread. |
| /// |
| /// @return A new command buffer. |
| /// |
| virtual std::shared_ptr<CommandBuffer> CreateCommandBuffer() const = 0; |
| |
| /// @brief Return the graphics queue for submitting command buffers. |
| virtual std::shared_ptr<CommandQueue> GetCommandQueue() const = 0; |
| |
| //---------------------------------------------------------------------------- |
| /// @brief Force all pending asynchronous work to finish. This is |
| /// achieved by deleting all owned concurrent message loops. |
| /// |
| virtual void Shutdown() = 0; |
| |
| CaptureContext capture; |
| |
| /// Stores a task on the `ContextMTL` that is awaiting access for the GPU. |
| /// |
| /// The task will be executed in the event that the GPU access has changed to |
| /// being available or that the task has been canceled. The task should |
| /// operate with the `SyncSwitch` to make sure the GPU is accessible. |
| /// |
| /// Threadsafe. |
| /// |
| /// `task` will be executed on the platform thread. |
| virtual void StoreTaskForGPU(const std::function<void()>& task) { |
| FML_CHECK(false && "not supported in this context"); |
| } |
| |
| /// Run backend specific additional setup and create common shader variants. |
| /// |
| /// This bootstrap is intended to improve the performance of several |
| /// first frame benchmarks that are tracked in the flutter device lab. |
| /// The workload includes initializing commonly used but not default |
| /// shader variants, as well as forcing driver initialization. |
| virtual void InitializeCommonlyUsedShadersIfNeeded() const {} |
| |
| protected: |
| Context(); |
| |
| std::vector<std::function<void()>> per_frame_task_; |
| |
| private: |
| Context(const Context&) = delete; |
| |
| Context& operator=(const Context&) = delete; |
| }; |
| |
| } // namespace impeller |
| |
| #endif // FLUTTER_IMPELLER_RENDERER_CONTEXT_H_ |