Repository navigation
Avoid most vulkan initialization for known bad vulkan drivers - #193875
Conversation
There was a problem hiding this comment.
Code Review
This pull request introduces an optional should_reject_device policy hook in ContextVK::Settings to allow early rejection of Vulkan physical devices (such as known bad drivers on Android) before performing expensive setup operations. It also defers the initialization of worker threads and the pipeline library. Feedback was provided on a unit test where std::string_view::copy is used without explicit null-termination, which could leave trailing garbage characters in the device name buffer.
gaaclarke
left a comment
There was a problem hiding this comment.
Looking good, let's just refactor to avoid the indirection.
| /// An optional policy hook consulted as soon as a physical device has been | ||
| /// selected, before the logical device, allocator, pipeline cache, shader | ||
| /// modules, or worker threads are created. Returning true aborts setup and | ||
| /// leaves the context invalid. | ||
| std::function<bool(const DriverInfoVK&)> should_reject_device; | ||
|
|
There was a problem hiding this comment.
Instead of making this a callback, let's split up ContextVK::Setup. Then we'll have a method to do the work up until the point where we have the DriverInfoVK. That method is already super big already.
There was a problem hiding this comment.
Aye aye, captain. Added a method SelectDevice() that returns an object which the caller can use to reject the device or call CreateContext() on to finish initialization.
| /// Initialize the Vulkan instance and select a physical device, returning its | ||
| /// `DriverInfoVK` so the caller can inspect or reject the device before the | ||
| /// remainder of context setup runs. | ||
| static std::optional<DeviceSelection> SelectDevice(Settings settings); |
There was a problem hiding this comment.
nit: this should be absl::StatusOr<DeviceSelection>
…r#193875) Adds a short-circuit in vulkan initialization for known bad devices (e.g., IsKnownBadDriver()==True). Adds a callback `should_reject_device` to the Vulkan context initialization to allow callers to specify a fast fail during context creation before the bulk of the Vulkan context creation operations are kicked off. This is only used on Android at the moment. Fixes flutter#193502 ## 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 in-code documentation (doc comments with `///`). - [x] If this PR introduces a new feature or capability, I created and linked a website documentation issue or PR in [flutter/website] (or verified none is needed). - [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.
Impeller's Android autoselect falls back to OpenGLES for several reasons. Some were silent: emulators, Huawei devices, and MediaTek vendor SDKs below 32. Known bad SoCs and known bad Vulkan drivers were logged only at INFO, which is hidden by default, with the same text for both. A profile or release log therefore shows only `Using the Impeller rendering backend (OpenGLES).`, and app developers and triagers cannot tell why Vulkan was not used. This PR logs every fallback branch at `FML_LOG(INFO)`, visible with `--verbose-system-logs`, one line each and with the values that triggered it. All lines are in `GetActualRenderingAPIForImpeller` (`android_context_dynamic_impeller.cc`) unless noted: | branch | message | |---|---| | emulator | `Emulator detected, falling back to OpenGLES.` | | Huawei | `Huawei device detected (ro.com.google.clientidbase=android-huawei), falling back to OpenGLES.` | | MediaTek vendor SDK | `MediaTek vendor API level <n> is below 32 (ro.vendor.mediatek.platform=<value>), falling back to OpenGLES.` | | known bad SoC | `Known bad SoC encountered (ro.product.board=<board>), falling back to OpenGLES.` | | Vulkan probe invalid | `Could not create a Vulkan context, falling back to OpenGLES.` | In `android_context_vk_impeller.cc` (`CreateImpellerContext`), the failing step is logged just before the probe line: | step | message | |---|---| | device selection | `Could not select a Vulkan device: <absl status message>` | | known bad driver | `Known bad Vulkan driver encountered.` followed by `DriverInfoVK::DumpToLog()` (name, API version, driver version, vendor, device type) | | context setup | `Could not set up the Vulkan context on the selected device.` | The vk messages do not say "falling back", because forced Vulkan (`ImpellerBackend=vulkan`) uses the same function and aborts instead. The `Using the Impeller rendering backend (Vulkan)` banner keeps the structure from flutter#193875: it only prints for a non-null context. No new log line contains the phrase "Using the Impeller rendering backend". devicelab `hello_world_impeller.dart` counts logcat lines with that phrase, so its backend count is unchanged. ### Observed on device moto g54 5G (MediaTek MT6855, PowerVR BXM-8-256, Android 15, Vulkan driver 1.15@6133110), profile build of master plus this PR, default backend selection, `--verbose-system-logs`, logcat from process start: ``` I flutter : [INFO:flutter/shell/platform/android/android_context_dynamic_impeller.cc(116)] MediaTek vendor API level 31 is below 32 (ro.vendor.mediatek.platform=MT6855), falling back to OpenGLES. I flutter : [IMPORTANT:flutter/shell/platform/android/android_context_gl_impeller.cc(105)] Using the Impeller rendering backend (OpenGLES). ``` Before this PR, only the second line was printed. With Vulkan forced (and the PowerVR denylist disabled locally for the experiment), no fallback line appears and the only Impeller line is the `(Vulkan)` banner. Only the MediaTek branch fired on hardware. The emulator, Huawei, bad SoC and bad driver branches and the three Vulkan setup-failure steps were not exercised on a device; each is a log-only addition next to an existing `return nullptr`. ### Tests None added. The change is log-only and the tree has no tests asserting these messages: `shell/` has no other matches for "Known bad Vulkan" or "falling back", and `android_context_dynamic_impeller_unittests.cc` has no log checks. I'd like to request a test exemption, since behavior is unchanged beyond logging. ### Related issues - flutter#192467: the engine ignores `ImpellerBackend` in release builds, and the maintainer answer asked for device properties in order to denylist. With this PR, the fallback reason and the triggering property values are in the default log. - flutter#193502 (fixed by flutter#193875): skip full Vulkan setup on denylisted drivers. This PR adds the reason line on that early-reject path, and on the device-selection and context-setup failures. - flutter#193148: the MediaTek vendor-SDK gate from flutter#186405. A build with this PR is how the gate was confirmed as the cause on a second device: flutter#193148 (comment) ## 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 in-code documentation (doc comments with `///`). - [x] If this PR introduces a new feature or capability, I created and linked a website documentation issue or PR in [flutter/website] (or verified none is needed). - [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/CONTRIBUTING.ai.md [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 [flutter/website]: https://github.com/flutter/website [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
Impeller's Android autoselect falls back to OpenGLES for several reasons. Some were silent: emulators, Huawei devices, and MediaTek vendor SDKs below 32. Known bad SoCs and known bad Vulkan drivers were logged only at INFO, which is hidden by default, with the same text for both. A profile or release log therefore shows only `Using the Impeller rendering backend (OpenGLES).`, and app developers and triagers cannot tell why Vulkan was not used. This PR logs every fallback branch at `FML_LOG(INFO)`, visible with `--verbose-system-logs`, one line each and with the values that triggered it. All lines are in `GetActualRenderingAPIForImpeller` (`android_context_dynamic_impeller.cc`) unless noted: | branch | message | |---|---| | emulator | `Emulator detected, falling back to OpenGLES.` | | Huawei | `Huawei device detected (ro.com.google.clientidbase=android-huawei), falling back to OpenGLES.` | | MediaTek vendor SDK | `MediaTek vendor API level <n> is below 32 (ro.vendor.mediatek.platform=<value>), falling back to OpenGLES.` | | known bad SoC | `Known bad SoC encountered (ro.product.board=<board>), falling back to OpenGLES.` | | Vulkan probe invalid | `Could not create a Vulkan context, falling back to OpenGLES.` | In `android_context_vk_impeller.cc` (`CreateImpellerContext`), the failing step is logged just before the probe line: | step | message | |---|---| | device selection | `Could not select a Vulkan device: <absl status message>` | | known bad driver | `Known bad Vulkan driver encountered.` followed by `DriverInfoVK::DumpToLog()` (name, API version, driver version, vendor, device type) | | context setup | `Could not set up the Vulkan context on the selected device.` | The vk messages do not say "falling back", because forced Vulkan (`ImpellerBackend=vulkan`) uses the same function and aborts instead. The `Using the Impeller rendering backend (Vulkan)` banner keeps the structure from flutter#193875: it only prints for a non-null context. No new log line contains the phrase "Using the Impeller rendering backend". devicelab `hello_world_impeller.dart` counts logcat lines with that phrase, so its backend count is unchanged. ### Observed on device moto g54 5G (MediaTek MT6855, PowerVR BXM-8-256, Android 15, Vulkan driver 1.15@6133110), profile build of master plus this PR, default backend selection, `--verbose-system-logs`, logcat from process start: ``` I flutter : [INFO:flutter/shell/platform/android/android_context_dynamic_impeller.cc(116)] MediaTek vendor API level 31 is below 32 (ro.vendor.mediatek.platform=MT6855), falling back to OpenGLES. I flutter : [IMPORTANT:flutter/shell/platform/android/android_context_gl_impeller.cc(105)] Using the Impeller rendering backend (OpenGLES). ``` Before this PR, only the second line was printed. With Vulkan forced (and the PowerVR denylist disabled locally for the experiment), no fallback line appears and the only Impeller line is the `(Vulkan)` banner. Only the MediaTek branch fired on hardware. The emulator, Huawei, bad SoC and bad driver branches and the three Vulkan setup-failure steps were not exercised on a device; each is a log-only addition next to an existing `return nullptr`. ### Tests None added. The change is log-only and the tree has no tests asserting these messages: `shell/` has no other matches for "Known bad Vulkan" or "falling back", and `android_context_dynamic_impeller_unittests.cc` has no log checks. I'd like to request a test exemption, since behavior is unchanged beyond logging. ### Related issues - flutter#192467: the engine ignores `ImpellerBackend` in release builds, and the maintainer answer asked for device properties in order to denylist. With this PR, the fallback reason and the triggering property values are in the default log. - flutter#193502 (fixed by flutter#193875): skip full Vulkan setup on denylisted drivers. This PR adds the reason line on that early-reject path, and on the device-selection and context-setup failures. - flutter#193148: the MediaTek vendor-SDK gate from flutter#186405. A build with this PR is how the gate was confirmed as the cause on a second device: flutter#193148 (comment) ## 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 in-code documentation (doc comments with `///`). - [x] If this PR introduces a new feature or capability, I created and linked a website documentation issue or PR in [flutter/website] (or verified none is needed). - [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/CONTRIBUTING.ai.md [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 [flutter/website]: https://github.com/flutter/website [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
Adds a short-circuit in vulkan initialization for known bad devices (e.g., IsKnownBadDriver()==True).
Adds a callback
should_reject_deviceto the Vulkan context initialization to allow callers to specify a fast fail during context creation before the bulk of the Vulkan context creation operations are kicked off. This is only used on Android at the moment.Fixes #193502
Pre-launch Checklist
///).