Repository navigation
Description
Steps to reproduce
- Build the attached code sample (3 overlapping large-sigma blurs) in release mode and run it on a device with a PowerVR B-Series BXM GPU. I'm using a moto g64y 5G (MediaTek Dimensity 7025 / MT6855, PowerVR B-Series BXM-8-256, driver build 1.15@6133110, Android 15).
- Watch GPU memory via
adb shell dumpsys meminfo com.example.bug(theGL mtrackrow) and system events viaadb logcat -b events | grep -E "am_low_memory|am_proc_died".
Expected results
GPU memory in the same ballpark as Skia rendering the identical widget tree on the identical device (76 MB GL mtrack, 171 MB total PSS).
Actual results
Immediately after the first frame, GL mtrack jumps to ~1.42 GB (1,424,194 kB) in a single step — not a leak, it stays flat afterwards. Total PSS is ~1.5 GB for an app that draws a colored box, a FlutterLogo and three blurs. The device (8 GB RAM) immediately enters an am_low_memory cascade and starts killing other processes (Google Photos, Google app, launcher widgets, …) while the sample app is idle in the foreground.
All numbers below are release builds of the same code sample on the same device, Flutter 3.41.6 stable:
| Configuration | GL mtrack | Total PSS | Outcome |
|---|---|---|---|
| Impeller Vulkan (default backend selection) | 1,424,194 kB (~1.42 GB) | 1,541 MB | am_low_memory cascade, background apps killed |
Skia (EnableImpeller=false manifest entry) |
76,456 kB (76 MB) | 171 MB | stable, renders identically |
In our production app (where this was originally discovered) the effect is the same — GL mtrack 18 MB → ~1.05 GB right when a screen with 3 blurs appears, and there the app process itself is killed by the kernel OOM killer after ~40–60 s idle (fromBinderDied=true, isKilledByAm=false, no tombstone), i.e. the app just disappears for the user. Temporarily removing just the 3 blurs from that screen drops it to 319 MB and the OOM disappears, which is how the blur/savelayer offscreen render targets were identified as the dominant contributor.
For comparison, identical code on a Pixel 8 Pro (Mali / Tensor G3) runs at 62 MB (Vulkan) / 112–154 MB (GLES), both stable — this is specific to the PowerVR Vulkan driver.
Analysis: why this device is not caught by the PowerVR denylist
Backend selection was confirmed from logcat:
[IMPORTANT:flutter/shell/platform/android/android_context_vk_impeller.cc(62)] Using the Impeller rendering backend (Vulkan).
impeller/renderer/backend/vulkan/driver_info_vk.cc:
if (powervr_gpu_.has_value() && powervr_gpu_.value() < PowerVRGPU::kBXE) {
return true;
}kBXM sorts above kBXE in the PowerVRGPU enum, so IsKnownBadDriver() returns false and the device gets kImpellerVulkan. #191351 recently reported glyph atlas corruption on the same GPU (BXM-8-256) with the same denylist analysis — this issue adds an independent failure mode (GPU memory blow-up → system-wide low-memory kills / kernel OOM kill of the app) on that GPU, as further evidence that the B-Series cutoff from #173561 is too permissive.
The per-blur cost looks consistent with #144617: on drivers without lazily-allocated memory support, MSAA/offscreen buffers are fully allocated — and on this PowerVR driver each blur/savelayer offscreen render target appears to be allocated at an enormous size.
Two more observations:
- The
ImpellerBackend=openglesescape hatch does not work in release builds. I verified the meta-data is present in the merged manifest of the release APK (aapt2 dump xmltree), but logcat still shows Vulkan being selected. (Same observation as in [Impeller] Glyph atlas corruption on PowerVR BXM (Vulkan) — B-Series denylist cutoff from #173561 is too permissive #191351's report.) So an affected production app cannot even opt into Impeller GLES; the only working escape hatch in release is opting out of Impeller entirely (EnableImpeller=false), which is deprecated as Skia is on the way out. - In debug builds, forcing Impeller GLES on this device works fine (our production app: 292–317 MB
GL mtrack, stable, renders correctly). So falling back to GLES for BXM — extending the denylist, or a driver-version-gated entry like the existing Pixel 10 / PowerVR one — would fix this class of device.
Related issues:
- [Impeller] Glyph atlas corruption on PowerVR BXM (Vulkan) — B-Series denylist cutoff from #173561 is too permissive #191351 — glyph atlas corruption on the same GPU (PowerVR BXM-8-256), same denylist gap
- [Impeller]: Switch PowerVR block from allowlist to denylist #173589 — switch PowerVR block from allowlist to denylist
- [Impeller] Re-enable PowerVR GPU support. #162033 — history of the PowerVR Vulkan re-enablement / current cutoff
- [Impeller] Improve Impeller performance on Vulkan devices without lazily allocated memory support. #144617 — MSAA buffers fully allocated on drivers without lazily-allocated memory
- [Impeller][Vulkan] Unhandled
VK_ERROR_COMPRESSION_EXHAUSTED_EXTrender-target allocation failure crashes the raster thread on PowerVR (Pixel 10) #187564 — PowerVR (Pixel 10) render-target allocation failure
Code sample
Code sample
// Minimal repro: show several large-sigma blurs at once and watch
// `adb shell dumpsys meminfo <package>` (GL mtrack row).
import 'dart:ui';
import 'package:flutter/material.dart';
void main() => runApp(const MaterialApp(home: BlurOomPage()));
class BlurOomPage extends StatelessWidget {
const BlurOomPage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
fit: StackFit.expand,
children: [
// 1. Full-screen blurred background (sigma 30)
ImageFiltered(
imageFilter: ImageFilter.blur(sigmaX: 30, sigmaY: 30),
child: const ColoredBox(color: Colors.indigo),
),
// 2. Blurred content (sigma 40)
Center(
child: ImageFiltered(
imageFilter: ImageFilter.blur(sigmaX: 40, sigmaY: 40),
child: const FlutterLogo(size: 300),
),
),
// 3. BackdropFilter overlay (sigma 32)
Positioned.fill(
child: BackdropFilter(
filter: ImageFilter.blur(sigmaX: 32, sigmaY: 32),
child: const ColoredBox(color: Colors.black26),
),
),
],
),
);
}
}Screenshots or Video
Screenshots / Video demonstration
N/A — the failure is memory exhaustion and silent process kills; the dumpsys meminfo / event-log output below is the observable signal. The screen itself renders correctly.
Logs
Logs
$ adb logcat | grep Impeller
08-21 08:36:xx I flutter : [IMPORTANT:flutter/shell/platform/android/android_context_vk_impeller.cc(62)] Using the Impeller rendering backend (Vulkan).
$ adb shell dumpsys meminfo com.example.bug # Impeller Vulkan, ~8 s after launch
EGL mtrack 71468 71468 0 0 71468
GL mtrack 1424194 1424194 0 0 1424194
TOTAL PSS: 1541375 TOTAL RSS: 1578046 TOTAL SWAP PSS: 10337
# Same APK with <meta-data android:name="io.flutter.embedding.android.EnableImpeller" android:value="false" /> (Skia):
GL mtrack 76456 76456 0 0 76456
TOTAL PSS: 171008 TOTAL RSS: 252060 TOTAL SWAP PSS: 839
$ adb logcat -b events | grep -E "am_low_memory|am_proc_died" # while the Vulkan build sits idle in foreground
08-21 08:31:58.837 I am_proc_died: [0,11197,com.motorola.carriersettingsext,500,10]
08-21 08:31:58.839 I am_proc_died: [0,20275,com.google.android.apps.photos,900,19]
08-21 08:31:58.939 I am_proc_died: [0,19919,com.google.android.googlequicksearchbox:googleapp,915,17]
08-21 08:31:58.949 I am_low_memory: 32
08-21 08:31:59.134 I am_proc_died: [0,22028,com.motorola.timeweatherwidget,915,19]
08-21 08:31:59.363 I am_proc_died: [0,22029,com.motorola.msimsettings,915,19]
08-21 08:31:59.364 I am_low_memory: 33
...(cascade continues; am_low_memory reached 39)
$ adb shell dumpsys SurfaceFlinger | grep GLES
GLES: Imagination Technologies, PowerVR B-Series BXM-8-256, OpenGL ES 3.2 build 1.15@6133110Flutter Doctor output
Doctor output
[✓] Flutter (Channel stable, 3.41.6, on macOS 26.6 25G72 darwin-arm64, locale en-JP)
• Flutter version 3.41.6 on channel stable at /Users/tatsuhama/fvm/versions/3.41.6
• Upstream repository https://github.com/flutter/flutter.git
• Framework revision db50e20168 (2026-03-25 16:21:00 -0700)
• Engine revision 425cfb54d0
• Dart version 3.11.4
• DevTools version 2.54.2
[✓] Android toolchain - develop for Android devices (Android SDK version 36.0.0)
• Android SDK at /Users/tatsuhama/Library/Android/sdk
[✓] Xcode - develop for iOS and macOS (Xcode 26.2)
[✓] Connected device (5 available)
• moto g64y 5G (mobile) • ZY22L4QFVH • android-arm64 • Android 15 (API 35)
Activity
mbcorona commentedon Aug 21, 2026
HI @tatsuhama , thanks for the detailed report. Routing to the engine team.
gaaclarke commentedon Aug 24, 2026
@mbcorona were you able to reproduce this? the OP seemed to suggest it was device specific. I would be interested to know if that is the case.
mbcorona commentedon Aug 24, 2026
Hi @gaaclarke , no I did not reproduced it, @suryaKommana2662 could you take a look into check if you are able to reproduce on Linux?
suryaKommana2662 commentedon Aug 25, 2026
@mbcorona I checked the reproduction environment, but I don't currently have access to a PowerVR BXM-8-256 Android device. Since the issue appears to be GPU/driver-specific, testing it in the Debian Linux container alone would not provide a meaningful reproduction result.
gaaclarke commentedon Aug 25, 2026
The
moto g64y 5Gcame out in 2024. I'm hesitant to denylist it.Can you try updating the operating system of your phone to get the latest drivers?
tatsuhama commentedon Aug 25, 2026
The latest update had been applied to my phone.
Also, it was not possible to update to Android 16.
Denylists b-series powervr from vulkan (flutter#191808)
[CP-beta]Denylists b-series powervr from vulkan (#191904)
[CP-stable]Denylists b-series powervr from vulkan (#191903)
github-actions commentedon Sep 10, 2026
This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug, including the output of
flutter doctor -vand a minimal reproduction of the issue.