Sitelet https://github.com/flutter/flutter/pull/190684
Skip to content

[Flutter GPU] Add a project-level Flutter GPU setting to the Linux and Windows embedders - #190684

Merged
auto-submit[bot] merged 6 commits into
flutter:masterfrom
bdero:bdero/desktop-flutter-gpu
Aug 7, 2026
Merged

auto-submit[bot] merged 6 commits into
flutter:masterfrom
bdero:bdero/desktop-flutter-gpu

Conversation

@bdero

@bdero bdero commented Aug 6, 2026

Copy link
Copy Markdown
Member

Adds fl_dart_project_set_enable_flutter_gpu (Linux) and DartProject::set_enable_flutter_gpu (Windows), forwarding --enable-flutter-gpu to 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 (FLTEnableFlutterGPU in Info.plist on iOS and macOS, the EnableFlutterGPU manifest flag on Android).

Pre-launch Checklist

…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.
@bdero
bdero marked this pull request as ready for review August 6, 2026 23:09
@bdero
bdero requested review from a team as code owners August 6, 2026 23:09
@bdero bdero added this to Flutter GPU Aug 6, 2026
@github-project-automation github-project-automation Bot moved this to 🤔 Needs Triage in Flutter GPU Aug 6, 2026
@bdero bdero moved this from 🤔 Needs Triage to ⚙️ In Progress in Flutter GPU Aug 6, 2026
@bdero bdero added the CICD Run CI/CD label Aug 6, 2026

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment on lines +841 to +854
// 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"));
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

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"));
    }
  }

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in 7ef4ea9.

Comment thread engine/src/flutter/shell/platform/windows/flutter_windows_engine.cc
@jtmcdole

jtmcdole commented Aug 6, 2026

Copy link
Copy Markdown
Member

@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;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

@loic-sharma

Copy link
Copy Markdown
Member

cc @robert-ancell as this adds a new config to Flutter Linux's runner APIs

loic-sharma
loic-sharma previously approved these changes Aug 6, 2026

@loic-sharma loic-sharma left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@github-actions github-actions Bot added engine flutter/engine related. See also e: labels. platform-windows Building on or for Windows specifically platform-linux Building on or for Linux specifically a: desktop Running on desktop team-windows Owned by the Windows platform team team-linux Owned by the Linux platform team labels Aug 7, 2026
b-luk
b-luk previously approved these changes Aug 7, 2026
// The Impeller enablement switch.
ImpellerSwitch impeller_switch_ = ImpellerSwitch::Default;
// Whether the Flutter GPU API is enabled.
bool enable_flutter_gpu_ = false;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment on lines +841 to +854
// 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"));
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

@bdero

bdero commented Aug 7, 2026

Copy link
Copy Markdown
Member Author

Google testing has failed 3 times on this

@b-luk

b-luk commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

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.

@bdero
bdero dismissed stale reviews from b-luk and loic-sharma via e1ca1b9 August 7, 2026 19:14
@bdero

bdero commented Aug 7, 2026 •

Copy link
Copy Markdown
Member Author

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!

@loic-sharma loic-sharma left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-LGTM

@loic-sharma loic-sharma added the autosubmit Merge PR when tree becomes green via auto submit App label Aug 7, 2026
@auto-submit
auto-submit Bot added this pull request to the merge queue Aug 7, 2026
Merged via the queue into flutter:master with commit 4ff86d4 Aug 7, 2026
22 checks passed
@github-project-automation github-project-automation Bot moved this from ⚙️ In Progress to ✅ Done in Flutter GPU Aug 7, 2026
@flutter-dashboard flutter-dashboard Bot removed the autosubmit Merge PR when tree becomes green via auto submit App label Aug 7, 2026
auto-submit Bot pushed a commit that referenced this pull request Aug 18, 2026
… 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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

a: desktop Running on desktop CICD Run CI/CD engine flutter/engine related. See also e: labels. platform-linux Building on or for Linux specifically platform-windows Building on or for Windows specifically team-linux Owned by the Linux platform team team-windows Owned by the Windows platform team

Projects

Status: ✅ Done

Development

Successfully merging this pull request may close these issues.

4 participants