Skip to content

iOS: Remove software renderer/headless fallback - #190590

Merged
cbracken merged 2 commits into
flutter:masterfrom
cbracken:cleanup-delete-sw-renderer-fallback
Aug 5, 2026
Merged

cbracken merged 2 commits into
flutter:masterfrom
cbracken:cleanup-delete-sw-renderer-fallback

Conversation

@cbracken

@cbracken cbracken commented Aug 5, 2026 •

Copy link
Copy Markdown
Member

iOS is Impeller-only and requires iOS 15, so there is no software renderer. The IOSRenderingAPI::kSoftware path doesn't actually render in software: on a simulator whose host exposed no Metal device it selects a no-op context and surface that draw nothing.

This removes that fallback and instead fails immediately when Metal is unavailable. This matches the existing runtime behaviour (which already FML_CHECKed) and the macOS embedder, which refuses to start without a Metal device.

The no-op path was added in flutter-team-archive/engine#54856 to stop Impeller-enabled simulators from exiting when no Metal context was available. That goes back way before we bumped the minimum supported iOS version to 15. Every device capable of running iOS 15 has a Metal-capable GPU, and a simulator requires a host with Metal support, so the fallback isn't necessary and a source of additional complexity and possibly bugs from misconfigured environments.

GPUSurfaceNoop is now unused and IOSRenderingAPI is down to just one enum value. I'll remove both in followups.

This also fixes a lint in IOSSurface::Create() that was revealed by removing IOSSurfaceNoop. IOSSurfaceMetalImpeller constructor takes a const std::shared_ptr<IOSContext>&, so in this code, the move was doing nothing.

std::unique_ptr<IOSSurface> IOSSurface::Create(std::shared_ptr<IOSContext> context,
return std::make_unique<IOSSurfaceMetalImpeller>(
    static_cast<CAMetalLayer*>(layer),  // Metal layer
    std::move(context)                  // context
);

The lint wasn't triggering before because in the same method, we were constructing a fallback IOSSurfaceNoop, whose ctor takes a std::shared_ptr<IOSContext> by value, not by const ref. That move WAS doing real work, but effectively covered prevented the lint from firing.

Issue: #190041
Issue: #112232

Pre-launch Checklist

If you need help, consider asking for advice on the #hackers-new channel on Discord.

If this change needs to override an active code freeze, provide a comment explaining why. The code freeze workflow can be overridden by code reviewers. See pinned issues for any active code freezes with guidance.

Note: The Flutter team is currently trialing the use of Gemini Code Assist for GitHub. Comments from the gemini-code-assist bot should not be taken as authoritative feedback from the Flutter team. If you find its comments useful you can update your code accordingly, but if you are unsure or disagree with the feedback, please feel free to wait for a Flutter team member's review for guidance on which automated comments should be addressed.

@flutter-dashboard flutter-dashboard Bot added the CICD Run CI/CD label Aug 5, 2026
@github-actions github-actions Bot added platform-ios iOS applications specifically engine flutter/engine related. See also e: labels. labels Aug 5, 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 removes the software rendering fallback and the associated no-op context and surface implementations (IOSContextNoop and IOSSurfaceNoop) for iOS, making Metal rendering mandatory. Feedback suggests caching the result of the Metal support check in GetRenderingAPIForProcess using a static local variable to avoid executing the expensive MTLCreateSystemDefaultDevice call repeatedly.

Comment thread engine/src/flutter/shell/platform/darwin/ios/rendering_api_selection.mm Outdated
@cbracken
cbracken force-pushed the cleanup-delete-sw-renderer-fallback branch 2 times, most recently from 78bc525 to c847293 Compare August 5, 2026 00:50
@cbracken

cbracken commented Aug 5, 2026

Copy link
Copy Markdown
Member Author

/gemini review

Ducks and runs for cover.

@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 removes the software rendering fallback (noop contexts and surfaces) for iOS, enforcing Metal rendering. The review feedback points out a minor formatting issue in a comment within ios_surface.mm and identifies a potential issue where ShouldUseMetalRenderer() always returns true on iOS 15+, which would bypass the helpful error message in rendering_api_selection.mm on simulators without Metal support.

Comment thread engine/src/flutter/shell/platform/darwin/ios/ios_surface.mm Outdated
Comment thread engine/src/flutter/shell/platform/darwin/ios/rendering_api_selection.mm Outdated
@cbracken
cbracken force-pushed the cleanup-delete-sw-renderer-fallback branch 2 times, most recently from 03fb353 to 7a91927 Compare August 5, 2026 01:13
@cbracken

cbracken commented Aug 5, 2026

Copy link
Copy Markdown
Member Author

Simplifying a tiny bit.

/gemini review

@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 removes the software rendering backend (including IOSContextNoop and IOSSurfaceNoop) and the kSoftware rendering API option for iOS, making Metal rendering mandatory. If Metal is unavailable, the engine will now fail with an assertion. Feedback on the changes suggests explicitly including flutter/fml/logging.h in ios_surface.mm to support the newly added FML_CHECK and FML_UNREACHABLE macros, adhering to the "Include What You Use" principle.

Comment thread engine/src/flutter/shell/platform/darwin/ios/ios_surface.mm
iOS is Impeller-only and requires iOS 15, so there is no software
renderer. The `IOSRenderingAPI::kSoftware` path doesn't actually render
in software: on a simulator whose host exposed no Metal device it
selects a no-op context and surface that draw nothing.

This removes that fallback and instead fails immediately when Metal is
unavailable. This matches the existing runtime behaviour (which already
`FML_CHECK`ed) and the macOS embedder, which refuses to start without a
Metal device.

The no-op path was added in flutter-team-archive/engine#54856 to stop
Impeller-enabled simulators from exiting when no Metal context was
available. That goes back way before we bumped the minimum supported iOS
version to 15. Every device capable of running iOS 15 has a
Metal-capable GPU, and a simulator requires a host with Metal support,
so the fallback isn't necessary and a source of additonal complexity and
possibly bugs from misconfigured environments.

`GPUSurfaceNoop` is now unused and `IOSRenderingAPI` is down to just one
enum value. I'l remove both in followups.

Issue: flutter#190041
@cbracken
cbracken force-pushed the cleanup-delete-sw-renderer-fallback branch from 7a91927 to ae308f5 Compare August 5, 2026 01:25
return std::make_unique<IOSSurfaceMetalImpeller>(
static_cast<CAMetalLayer*>(layer), // Metal layer
std::move(context) // context
context // context

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.

This fixes a lint.

See the PR description for why this move wasn't actually a move at all and was still triggering a copy before, and why changing the method param to a const ref fixes it.

@hellohuanlin hellohuanlin 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.

LGTM! Just a questions for sanity check & future references.

case IOSRenderingAPI::kSoftware:
[FlutterLogger logImportant:@"Software rendering is incompatible with Impeller.\n"
"Software rendering may have been automatically selected when "
"running on a simulator in an environment that does not support "

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.

just sanity check: is it correct to say this comment is outdated, because even on simulator, it doesn't use software rendering? What does simualtor use nowadays?

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.

Correct Impeller has no software rendering; we use Metal on simulator. That's been the case for years now, and that choice was locked in once we removed Skia.

return IOSRenderingAPI::kSoftware;
#endif // TARGET_OS_SIMULATOR
FML_CHECK(false) << "Metal is unavailable. On a simulator this means the host environment "
"does not expose a Metal device; enabling GPU passthrough may fix this.";

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.

Do you know what host doesn't expose a metal device? Are those intel chips?

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.

All macOS machines running Ventura or later require Metal. Years ago it was the case that some CI systems didn't support GPU passthrough, but we waited for the vast bulk of CI providers to support GPU paravirtualisation before we ripped OpenGL out of the macOS embedder back in 2022.

@cbracken
cbracken added this pull request to the merge queue Aug 5, 2026
Merged via the queue into flutter:master with commit 67cfcfb Aug 5, 2026
18 checks passed
@cbracken
cbracken deleted the cleanup-delete-sw-renderer-fallback branch August 5, 2026 08:39
cbracken added a commit to cbracken/flutter that referenced this pull request Aug 5, 2026
`GPUSurfaceNoop` was only ever used by the iOS `IOSSurfaceNoop`, which
was deleted when the iOS software-renderer fallback was removed in
flutter#190590. Since there are no remaining callers, this removes the class.

No behavioural change; the code was already unreachable. The compiler is
the test!

Issue: flutter#190041
@cbracken cbracken mentioned this pull request Aug 5, 2026
10 tasks done
pull Bot pushed a commit to Mattlk13/flutter that referenced this pull request Aug 5, 2026
`GPUSurfaceNoop` was only ever used by the iOS `IOSSurfaceNoop`, which
was deleted when the iOS software-renderer fallback was removed in
flutter#190590. Since there are no remaining callers, this removes the class.

No behavioural change; the code was already unreachable. The compiler is
the test!

Issue: flutter#190041


## Pre-launch Checklist

- [X] I read the [Contributor Guide] and followed the process outlined
there for submitting PRs.
- [X] I read the [AI contribution guidelines] and understand my
responsibilities, or I am not using AI tools.
- [X] I read the [Tree Hygiene] wiki page, which explains my
responsibilities.
- [X] I read and followed the [Flutter Style Guide], including [Features
we expect every widget to implement].
- [X] I signed the [CLA].
- [X] I listed at least one issue that this PR fixes in the description
above.
- [X] I updated/added relevant documentation (doc comments with `///`).
- [X] I added new tests to check the change I am making, or this PR is
[test-exempt].
- [X] I followed the [breaking change policy] and added [Data Driven
Fixes] where supported.
- [X] All existing and new tests are passing.

If you need help, consider asking for advice on the #hackers-new channel
on [Discord].

If this change needs to override an active code freeze, provide a
comment explaining why. The code freeze workflow can be overridden by
code reviewers. See pinned issues for any active code freezes with
guidance.

**Note**: The Flutter team is currently trialing the use of [Gemini Code
Assist for
GitHub](https://developers.google.com/gemini-code-assist/docs/review-github-code).
Comments from the `gemini-code-assist` bot should not be taken as
authoritative feedback from the Flutter team. If you find its comments
useful you can update your code accordingly, but if you are unsure or
disagree with the feedback, please feel free to wait for a Flutter team
member's review for guidance on which automated comments should be
addressed.

<!-- Links -->
[Contributor Guide]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview
[AI contribution guidelines]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#ai-contribution-guidelines
[Tree Hygiene]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md
[test-exempt]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests
[Flutter Style Guide]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md
[Features we expect every widget to implement]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement
[CLA]: https://cla.developers.google.com/
[flutter/tests]: https://github.com/flutter/tests
[breaking change policy]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes
[Discord]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md
[Data Driven Fixes]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md
cbracken added a commit to cbracken/flutter that referenced this pull request Aug 6, 2026
`GPUSurfaceNoop` was only ever used by the iOS `IOSSurfaceNoop`, which
was deleted when the iOS software-renderer fallback was removed in
flutter#190590. Since there are no remaining callers, this removes the class.

No behavioural change; the code was already unreachable. The compiler is
the test!

Issue: flutter#190041
cbracken added a commit to cbracken/flutter that referenced this pull request Aug 10, 2026
`FLTEnableIOSEmbedderAPI` is an existing (unused) switch for the iOS
embedder API migration, but we didn't document its expected behaviour
where we used it.

This documents its semantics in `FlutterDartProject`: it's opt-in while
the migration is in progress, a YES value currently only has the effect
of populating `FlutterEngine`'s `FlutterEngineProcTable`. Once the
embedder fully supports the embedder API and we've tested for a
sufficient period, this will become opt-out and eventually be removed.

This also replaces the `NSLog` banner we emitted when the flag is on
with `FlutterLogger`, so the message goes through the same logging path
as the rest of the embedder and respects the configured log level.

Also drops two `settings.enable_software_rendering = true` assignments
from `testCanEnableDisableEmbedderAPIThroughInfoPlist`. Those were the
last references to that setting anywhere in the iOS embedder; nothing
has read it on iOS since the software renderer fallback was removed in
flutter#190590.

Issue: flutter#112232
dayanruben pushed a commit to dayanruben/flutter that referenced this pull request Aug 11, 2026
`FLTEnableIOSEmbedderAPI` is an existing (unused) switch for the iOS
embedder API migration, but we didn't document its expected behaviour
where we used it.

This documents its semantics in `FlutterDartProject`: it's opt-in while
the migration is in progress, a YES value currently only has the effect
of populating `FlutterEngine`'s `FlutterEngineProcTable`. Once the
embedder fully supports the embedder API and we've tested for a
sufficient period, this will become opt-out and eventually be removed.

This also replaces the `NSLog` banner we emitted when the flag is on
with `FlutterLogger`, so the message goes through the same logging path
as the rest of the embedder and respects the configured log level.

Also drops two `settings.enable_software_rendering = true` assignments
from `testCanEnableDisableEmbedderAPIThroughInfoPlist`. Those were the
last references to that setting anywhere in the iOS embedder; nothing
has read it on iOS since the software renderer fallback was removed in
flutter#190590.

Issue: flutter#112232

<!--
Thanks for filing a pull request!
Reviewers are typically assigned within a week of filing a request.
To learn more about code review, see our documentation on Tree Hygiene:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md
-->

## Pre-launch Checklist

- [X] I read the [Contributor Guide] and followed the process outlined
there for submitting PRs.
- [X] I read the [AI contribution guidelines] and understand my
responsibilities, or I am not using AI tools.
- [X] I read the [Tree Hygiene] wiki page, which explains my
responsibilities.
- [X] I read and followed the [Flutter Style Guide], including [Features
we expect every widget to implement].
- [X] I signed the [CLA].
- [X] I listed at least one issue that this PR fixes in the description
above.
- [X] I updated/added relevant documentation (doc comments with `///`).
- [X] I added new tests to check the change I am making, or this PR is
[test-exempt].
- [X] I followed the [breaking change policy] and added [Data Driven
Fixes] where supported.
- [X] All existing and new tests are passing.

If you need help, consider asking for advice on the #hackers-new channel
on [Discord].

If this change needs to override an active code freeze, provide a
comment explaining why. The code freeze workflow can be overridden by
code reviewers. See pinned issues for any active code freezes with
guidance.

**Note**: The Flutter team is currently trialing the use of [Gemini Code
Assist for
GitHub](https://developers.google.com/gemini-code-assist/docs/review-github-code).
Comments from the `gemini-code-assist` bot should not be taken as
authoritative feedback from the Flutter team. If you find its comments
useful you can update your code accordingly, but if you are unsure or
disagree with the feedback, please feel free to wait for a Flutter team
member's review for guidance on which automated comments should be
addressed.

<!-- Links -->
[Contributor Guide]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview
[AI contribution guidelines]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#ai-contribution-guidelines
[Tree Hygiene]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md
[test-exempt]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests
[Flutter Style Guide]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md
[Features we expect every widget to implement]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement
[CLA]: https://cla.developers.google.com/
[flutter/tests]: https://github.com/flutter/tests
[breaking change policy]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes
[Discord]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md
[Data Driven Fixes]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CICD Run CI/CD engine flutter/engine related. See also e: labels. platform-ios iOS applications specifically

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants