engine/src/flutter/impeller/README.md
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
----------------- ___ _ _ --------------------
----------------- |_ _|_ __ ___ _ __ ___| | | ___ _ __ --------------------
----------------- | || '_ ` _ \| '_ \ / _ \ | |/ _ \ '__| --------------------
----------------- | || | | | | | |_) | __/ | | __/ | --------------------
----------------- |___|_| |_| |_| .__/ \___|_|_|\___|_| --------------------
----------------- |_| --------------------
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
Impeller is a rendering runtime for Flutter with the following objectives:
Impeller is a meta-framework. While a user of Impeller may choose to include the
whole enchilada (in //impeller/:impeller), the various sub-frameworks have
clearly defined responsibilities and adhere to a strict hierarchy.
Impeller itself may not depend on anything in //flutter except //flutter/fml
and flutter/display_list. FML is a base library for C++ projects and Impeller
implements the display list dispatcher interface to make it easy for Flutter to
swap the renderer with Impeller. Impeller is meant to be used by the Flow
(//flutter/flow) subsystem. Hence the name. The tessellator and geometry
libraries are exceptions - they unconditionally may not depend on anything from
//flutter.
An overview of the major sub-frameworks, their responsibilities, and, relative states of completion:
//impeller/compiler: The offline shader compiler. Takes GLSL 4.60 shader
source code and converts it into a backend specific shader representation
(like Metal Shading Language). It also generates C++ bindings that callers can
include as a GN source_sets so there is no runtime shader reflection either.
The target is an executable called impellerc which is never shipped into the
binary or as an artifact.//impeller/renderer: The very lowest level of the renderer that is still
backend agnostic. Allows users to build a renderer from scratch with few
restrictions. Has utilities for creating allocators, generating pipeline state
objects from bindings generated by //impeller/compiler, setting up render
passes, managing jumbo uniform-buffers, tessellators, etc..
//impeller/renderer/backend: Contains all the implementation details
for a specific client rendering API. The interfaces in these targets are
meant to be private for non-WSI user targets. No Impeller sub-frameworks
may depend on these targets.//impeller/geometry: All (or, most of) the math! This C++ mathematics
library is used extensively by Impeller and its clients. The reasonably
interesting bit about this library is that all types can be used
interchangeably in device and host memory. Various Impeller subsystems
understand these types and can take care of packing and alignment concerns
w.r.t these types.//impeller/playground: When working with graphics APIs, it is often
necessary to visually verify rendering results as a specific feature is being
worked upon. Moreover, it is useful to attach frame debuggers or profilers to
specific test cases. The playground framework provides Google Test fixtures
that open the current state of various rendering related objects in a window
in which rendering results can be visualized, or, to which frame debuggers can
be attached. Most Impeller sub-frameworks that have a test harness also have a
custom playground subclass. This sub-framework is only meant to provide
utilities for tests and will not be compiled into any shipping binary.//impeller/entity: Sits one level above //impeller/renderer and
provides a framework for building 2D renderers. Most of the pipeline state
objects generated from shaders authored at build time reside in this
framework. The render-pass optimization and pass-rewriting framework also
resides there. This allows authoring composable 2D rendering optimizations
(like collapsing passes, or, eliding them completely).//impeller/display_list: The replacement for //impeller/aiks to serve
in the integration of Impeller in //flutter/flow. This is pending graphics
package agnosticism in the Impeller interface. This sub-framework primarily
provides a custom implementation of the flutter::DisplayListDispatcher that
forwards Flutter rendering intent to Impeller.//impeller/typographer: Contains a backend agnostic interface for
rendering typefaces. While Impeller does not do any text layout or
shaping, it does render shaped glyph runs. The application specifies these
glyph runs to Impeller using the Typographer subsystem.
//impeller/typographer/backend: Contains code that interfaces with an
underlying (usually platform-specific) library or toolkit to render glyphs
in typefaces into texture atlases. Impeller will then reference these glyphs
when rendering shaped glyph runs. No Impeller sub-frameworks may depend on
these targets. There may be multiple typographer backends.//impeller/base: Contains C++ utilities that are used throughout the
Impeller family of frameworks. Ideally, these should go in //flutter/fml but
their use is probably not widespread enough to at this time.//fixtures: Contains test fixtures used by the various test harnesses.
This depends on //flutter/testing.//impeller/tools: Contains all GN rules and python scripts for working
with Impeller. These include GN rules processing GLSL shaders, including
reflected shader information as source set targets, and, including compiled
shader intermediate representations into the final executable as binary blobs
for easier packaging.//impeller/toolkit: Contains Impeller agnostic toolkits that provide
more ergonomic wrappers around certain APIs like EGL. Toolkits must be
dependency free so that an external component using a toolkit doesn't have to
pull in a significant portion of Impeller itself.//impeller/shader_archive: Create a persistent library of shader blobs.
This is primarily used by rendering backends that don't have the notion of a
shader library. In Impeller, all shaders are packaged into a single library
that contains a manifest of the shaders in the library along with the
pre-compiled shaders themselves. Unlike Metal, backends like OpenGL ES and
Vulkan don't have such a concept. For these backends, //impeller/blobcat is
used to create a single shader library to be packaged with the engine.impellerc) converts the GLSL
into SPIRV. No optimizations are performed on the generated SPIRV at this
stage. This is to preserve all debugging and instrumentation information.impellerc.xxd.py) into a C source file with a
generated GN target. Executable targets that want to include the compiled code
in their binaries just need to depend on the generated GN target. This eases
any shader packaging concerns.flowchart TD
glsl_460[GLSL ES 4.60] -- Stage 1 Compiler --> spirv[SPIRV]
spirv -- SPIRV Optimizer --> optimized_spirv[Optimized SPIRV]
optimized_spirv -- Metal Stage 2 Compiler --> metal_sources[Metal Shader Sources]
metal_sources -- Metal Linker --> metal_library[Metal Library]
optimized_spirv -- Vulkan Stage 2 Compiler --> vulkan_spirv[Vulkan SPIRV]
vulkan_spirv -- Shader Archiver --> vulkan_shader_archive[Vulkan Shader Archive]
optimized_spirv -- GLSL ES Stage 2 Compiler --> glsl_es_100[GLSL ES 1.00]
glsl_es_100 -- Shader Archiver --> gles_shader_archive[OpenGL ES Shader Archive]
spirv -- Reflector --> cxx_sources[C++ Sources]
cxx_sources -- Ninja Build --> cxx_library[C++ Library]
Impeller is available under the --enable-impeller flag on iOS, Android, and
macOS Desktop. This flag can be specified to flutter run.
If the application needs to be launched with Impeller enabled without using the Flutter tool, follow the platform specific steps below.
Impeller is the only rendering engine available on iOS. The legacy renderer has been removed.
Impeller is the default on Android. Impeller will attempt to use Vulkan first and then fall back to OpenGL rendering depending on device capabilities.
To explicitly opt out of using Impeller, add the following to your AndroidManifest.xml
under the <application> tag.
[!CAUTION] The ability to disable Impeller is going to go away in a future release. Please file an issue if you need to do this in your application.
<meta-data
android:name="io.flutter.embedding.android.EnableImpeller"
android:value="false" />
During development, to try Impeller with OpenGL in your application, add the following
to your AndroidManifest.xml file under the <application> tag:
[!Warning] Selecting the Impeller backend this way will only work in
debugandprofileruntime modes.
<meta-data
android:name="io.flutter.embedding.android.ImpellerBackend"
android:value="opengles" />
Impeller is in preview on macOS Desktop.
To your Info.plist file, add under the top-level <dict> tag:
<key>FLTEnableImpeller</key>
<true/>
Impeller is in preview on custom embedders. It is not enabled by default.
To enable it Impeller in your application, pass the --enable-impeller=true command line
argument to FlutterProjectArgs.command_line_argv
during application initialization.
Impeller does not require any other modifications in the embedder.
Impeller is designed to work best when used by Flutter. Most of the teams efforts go into being great at that use-case. But, standalone Impeller can be used to perform accelerated rendering in most environments without any Flutter dependencies.
Impeller provides a standalone SDK. The SDK exposes a single-header C API with no platform dependencies. Prebuilts for major platforms, documentation, examples, are available.