Repository navigation
[Flutter GPU] Add a project-level Flutter GPU setting to the Linux and Windows embedders - #190684
Conversation
…d Windows embedders Flutter GPU requires the enable-flutter-gpu engine switch, which desktop embedders only read from FLUTTER_ENGINE_SWITCH_* environment variables, a path compiled out of release builds. Every other platform has a permanent project-level opt-in (FLTEnableFlutterGPU in Info.plist on iOS and macOS, the EnableFlutterGPU manifest flag on Android), so a released desktop app had no way to enable Flutter GPU at all. Adds fl_dart_project_set_enable_flutter_gpu to the GTK embedder and DartProject::set_enable_flutter_gpu (via a new FlutterDesktopEngineProperties field) to the Windows embedder, forwarding the switch to the engine the same way the existing Impeller project settings do.
There was a problem hiding this comment.
Code Review
This pull request adds programmatic support for enabling the Flutter GPU API on Linux and Windows desktop platforms by introducing configuration properties, forwarding the --enable-flutter-gpu command-line switch to the engine, and adding corresponding unit tests. The review feedback suggests optimizing the command-line switch checks on both platforms: on Linux, by deferring the environment switch lookup until programmatic enablement is confirmed, and on Windows, by consolidating multiple vector searches into a single pass.
| // Forward the project's Flutter GPU setting unless an environment switch | ||
| // already carries it (the switch is presence based, so it is only ever | ||
| // added, never negated). | ||
| gboolean has_enable_flutter_gpu = FALSE; | ||
| for (const auto& env_switch : flutter::GetSwitchesFromEnvironment()) { | ||
| if (env_switch == "--enable-flutter-gpu" || | ||
| env_switch == "--enable-flutter-gpu=true") { | ||
| has_enable_flutter_gpu = TRUE; | ||
| } | ||
| } | ||
| if (fl_dart_project_get_enable_flutter_gpu(self->project) && | ||
| !has_enable_flutter_gpu) { | ||
| g_ptr_array_add(command_line_args, g_strdup("--enable-flutter-gpu")); | ||
| } |
There was a problem hiding this comment.
Checking the environment switches by calling flutter::GetSwitchesFromEnvironment() is an expensive operation (involving system calls and memory allocations) and is unnecessary when the programmatic Flutter GPU setting is disabled (which is the default case).
We can optimize this by wrapping the entire check inside if (fl_dart_project_get_enable_flutter_gpu(self->project)). Additionally, we can break out of the loop early once the switch is found.
// Forward the project's Flutter GPU setting unless an environment switch
// already carries it (the switch is presence based, so it is only ever
// added, never negated).
if (fl_dart_project_get_enable_flutter_gpu(self->project)) {
gboolean has_enable_flutter_gpu = FALSE;
for (const auto& env_switch : flutter::GetSwitchesFromEnvironment()) {
if (env_switch == "--enable-flutter-gpu" ||
env_switch == "--enable-flutter-gpu=true") {
has_enable_flutter_gpu = TRUE;
break;
}
}
if (!has_enable_flutter_gpu) {
g_ptr_array_add(command_line_args, g_strdup("--enable-flutter-gpu"));
}
}There was a problem hiding this comment.
If flutter::GetSwitchesFromEnvironment() really is an expensive operation that we want to minimize, then we should just call it once and store it in a variable rather than calling it multiple times in this function.
Not directly related to the code changes in this PR, so I'm not blocking this PR on this and I'll leave it up to you if you want to make this change.
|
@b-luk - could you take a peek look at this tomorrow? |
| // The Impeller enablement switch. | ||
| ImpellerSwitch impeller_switch_ = ImpellerSwitch::Default; | ||
| // Whether the Flutter GPU API is enabled. | ||
| bool enable_flutter_gpu_ = false; |
There was a problem hiding this comment.
FYI for Windows we've historically used an enum with a Default value if the runner app doesn't have an opinion. I personally don't have a strong preference though.
There was a problem hiding this comment.
I also don't have a strong preference. I do think it would be nice to be consistent with the other switches. But this particular one is just a bool with a clear default that we don't anticipate will change, so it may not be worth the extra boilerplate to make it like the others. I'm fine either way.
There was a problem hiding this comment.
Keeping the bool. The switch is presence based with an off default on every platform, so an enum's Disabled and Default would be the same state, and a bool matches the Info.plist and manifest booleans the other platforms use for this setting.
|
cc @robert-ancell as this adds a new config to Flutter Linux's runner APIs |
| // The Impeller enablement switch. | ||
| ImpellerSwitch impeller_switch_ = ImpellerSwitch::Default; | ||
| // Whether the Flutter GPU API is enabled. | ||
| bool enable_flutter_gpu_ = false; |
There was a problem hiding this comment.
I also don't have a strong preference. I do think it would be nice to be consistent with the other switches. But this particular one is just a bool with a clear default that we don't anticipate will change, so it may not be worth the extra boilerplate to make it like the others. I'm fine either way.
| // Forward the project's Flutter GPU setting unless an environment switch | ||
| // already carries it (the switch is presence based, so it is only ever | ||
| // added, never negated). | ||
| gboolean has_enable_flutter_gpu = FALSE; | ||
| for (const auto& env_switch : flutter::GetSwitchesFromEnvironment()) { | ||
| if (env_switch == "--enable-flutter-gpu" || | ||
| env_switch == "--enable-flutter-gpu=true") { | ||
| has_enable_flutter_gpu = TRUE; | ||
| } | ||
| } | ||
| if (fl_dart_project_get_enable_flutter_gpu(self->project) && | ||
| !has_enable_flutter_gpu) { | ||
| g_ptr_array_add(command_line_args, g_strdup("--enable-flutter-gpu")); | ||
| } |
There was a problem hiding this comment.
If flutter::GetSwitchesFromEnvironment() really is an expensive operation that we want to minimize, then we should just call it once and store it in a variable rather than calling it multiple times in this function.
Not directly related to the code changes in this PR, so I'm not blocking this PR on this and I'll leave it up to you if you want to make this change.
|
Google testing has failed 3 times on this |
Google testing failed due to "Engine artifacts not found". I think this is because the Dashboard Checks which output the engine artifacts did not complete successfully. In the Dashboard Checks, "Linux linux_fuchsia" failed. I think the failure is just a flake. I'll rerun it, and if it succeeds I'll retry the Google testing. |
|
Network failures downloading gradle have blocked the last few runs. I have a long dentist appointment I'm heading to right now, but if anyone wants to keep hitting retry on the tests to get this merged for the CP, please feel free! |
… Linux and Windows embedders (#190872) Cherry-pick of #190684 (`4ff86d444fb94c39c38111f4b9be649bb716dff7`) onto `flutter-3.47-candidate.0`. It applies cleanly with no conflicts. The 3.47.0 cherry-pick window is already closed, so this is a request to reopen the conversation rather than a routine cherry-pick. The reasoning is under "Why this is requested after the window closed" below, and I am happy to take a no. ### Issue Link: #190871 ### Why this is requested after the window closed: This is an API addition rather than a regression fix, so it does not meet the usual bar. Three things make it worth asking about anyway. Flutter GPU already has a permanent, project-level opt-in on every other platform (`FLTEnableFlutterGPU` in `Info.plist` on iOS and macOS, the `EnableFlutterGPU` manifest key on Android). Linux and Windows are the only platforms with no equivalent, so this closes a parity gap rather than adding new capability. Release-mode desktop builds compile out `GetSwitchesFromEnvironment` (`engine_switches.cc` guards it with `#ifndef FLUTTER_RELEASE`), so `--enable-flutter-gpu` reaches the engine only under `flutter run`. Without a project-level setter there is no way at all to ship a released Linux or Windows app that uses `package:flutter_gpu`. It landed on master on August 7, two days after `flutter-3.48-candidate.0` branched on August 5, so it missed both this branch and the next beta branch. If it is not picked up here, the first beta carrying it is 3.49 and the first stable is roughly a quarter out. ### Impacted Users: Developers shipping Flutter desktop apps on Linux and Windows that use `package:flutter_gpu`, either directly or through a package built on top of it. Issue #167734 has been open since April 2025 with users repeatedly asking how to enable Flutter GPU on Windows, and the most recent comment describes exactly this case, that the command line flag works under `flutter run` but a packaged executable has no way to set it. ### Impact Description: Production apps on Linux and Windows cannot ship Flutter GPU at all. A release build throws on the first Flutter GPU call with "Flutter GPU must be enabled via the Flutter GPU manifest setting", and that message names only the iOS and Android opt-ins because the desktop ones did not exist. This does not affect development, since `flutter run --enable-flutter-gpu` works, which is what makes it easy to discover the problem only at packaging time. ### Changelog Description: [flutter/190871] Flutter GPU could not be enabled in release builds on Linux and Windows, since those embedders had no project-level opt-in and release builds ignore engine switches from the environment. ### Workaround: No practical one. Shipping the app in debug or profile mode is the only way to get the environment switches honored, and neither is shippable. The alternative is patching the embedder and building a custom engine. ### Risk: What is the risk level of this cherry-pick? The change is additive and defaults to off. Both embedders append `--enable-flutter-gpu` only when the project setting is true, and skip it when an environment switch already carries it, so an app that does not opt in produces a byte-identical switch list. Nothing in the engine, Impeller, or the rendering path changes. The Linux side also hoists a repeated `GetSwitchesFromEnvironment()` call into a local, which is behavior neutral. One caveat worth naming. A `bool enable_flutter_gpu` field is appended to `FlutterDesktopEngineProperties` in the public `flutter_windows.h`, which changes that struct's layout. The header and `flutter_windows.dll` ship together in the SDK artifact cache so they stay consistent, but it is a public C struct change, and once it ships in a stable the shape of the API is locked in. ### Test Coverage: Are you confident that your fix is well-tested by automated tests? Unit tests cover both embedders. On Linux, `fl_dart_project_test.cc` covers the getter, setter, and default, and `fl_engine_test.cc` covers switch forwarding and the environment switch deduplication. On Windows, `dart_project_unittests.cc`, `flutter_project_bundle_unittests.cc`, and `flutter_windows_engine_unittests.cc` cover the client wrapper, the project bundle, and the engine switch assembly. ### Validation Steps: 1. Create a Flutter app that calls into `package:flutter_gpu` and run it in release mode on Linux or Windows without the new setting. Confirm it throws "Flutter GPU must be enabled via the Flutter GPU manifest setting". 2. On Linux, add `fl_dart_project_set_enable_flutter_gpu(project, TRUE);` in `linux/runner/my_application.cc`. On Windows, add `project.set_enable_flutter_gpu(true);` in `windows/runner/main.cpp`. 3. Build in release mode and launch the packaged binary directly rather than through `flutter run`. Confirm Flutter GPU initializes and renders. 4. Confirm an app that does not set the flag behaves exactly as before. 5. Run the Linux and Windows embedder unit tests.
Adds
fl_dart_project_set_enable_flutter_gpu(Linux) andDartProject::set_enable_flutter_gpu(Windows), forwarding--enable-flutter-gputo the engine the same way the existing project-level Impeller settings do. Release desktop builds ignore engine switches from the environment, so this is the only way a released app on these platforms can enable Flutter GPU, matching the permanent opt-ins the other platforms already have (FLTEnableFlutterGPUin Info.plist on iOS and macOS, theEnableFlutterGPUmanifest flag on Android).Pre-launch Checklist
///).