Repository navigation
iOS: Remove software renderer/headless fallback - #190590
Conversation
There was a problem hiding this comment.
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.
78bc525 to
c847293
Compare
|
/gemini review Ducks and runs for cover. |
There was a problem hiding this comment.
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.
03fb353 to
7a91927
Compare
|
Simplifying a tiny bit. /gemini review |
There was a problem hiding this comment.
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.
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
7a91927 to
ae308f5
Compare
| return std::make_unique<IOSSurfaceMetalImpeller>( | ||
| static_cast<CAMetalLayer*>(layer), // Metal layer | ||
| std::move(context) // context | ||
| context // context |
There was a problem hiding this comment.
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
left a comment
There was a problem hiding this comment.
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 " |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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."; |
There was a problem hiding this comment.
Do you know what host doesn't expose a metal device? Are those intel chips?
There was a problem hiding this comment.
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.
`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
`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
`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
`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
`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
iOS is Impeller-only and requires iOS 15, so there is no software renderer. The
IOSRenderingAPI::kSoftwarepath 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.
GPUSurfaceNoopis now unused andIOSRenderingAPIis down to just one enum value. I'll remove both in followups.This also fixes a lint in
IOSSurface::Create()that was revealed by removingIOSSurfaceNoop.IOSSurfaceMetalImpellerconstructor takes aconst std::shared_ptr<IOSContext>&, so in this code, the move was doing nothing.The lint wasn't triggering before because in the same method, we were constructing a fallback
IOSSurfaceNoop, whose ctor takes astd::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-assistbot 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.