[Impeller] Retry uncompressed when fixed-rate compression is exhausted#187586
Conversation
|
Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA). View this failed invocation of the CLA check for more information. For the most up to date status, view the checks section at the bottom of the pull request. |
On the Pixel 10 (Imagination PowerVR GPU), vmaCreateImage can return VK_ERROR_COMPRESSION_EXHAUSTED_EXT when the driver's fixed-rate image-compression resources are depleted. Impeller requests fixed-rate compression for lossy render targets but did not handle this failure: it returned an invalid texture, producing a render target with no color attachment, which then crashed the raster thread (FML_CHECK(back_texture) / null deref on canvas.cc). Per the Vulkan spec this error is only returned for fixed-rate compression requests, so this retries the image allocation once with VkImageCompressionControlEXT unlinked (uncompressed) -- a valid recovery. Regression first observed between Flutter 3.41.9 and 3.44; stable with --no-enable-impeller. Adds an allocator_vk_unittests case that injects the error via the Vulkan mock (advertising fixed-rate compression support) and verifies the allocator retries and returns a valid texture.
65d411f to
b37f7f7
Compare
There was a problem hiding this comment.
Code Review
This pull request implements a fallback mechanism in the Vulkan allocator to retry image allocation without compression if the initial attempt fails with VK_ERROR_COMPRESSION_EXHAUSTED_EXT. It also updates the mock Vulkan implementation to simulate this error and adds a unit test to verify that the allocator successfully falls back to an uncompressed allocation. There are no review comments, and I have no feedback to provide.
|
CI had a failure that stopped further tests from running. We need to investigate to determine the root cause. SHA at time of execution: b37f7f7. Possible causes:
A blank commit, or merging to head, will be required to resume running CI for this PR. Error Details: Stack trace: |
gaaclarke
left a comment
There was a problem hiding this comment.
This code looks good to me. The tests are sufficient and the logic seems reasonable considering the runtime error we are getting. I just have a few minor comments on the code. Thanks!
- mock_vulkan: move compression_requested into the while condition - allocator_vk: use explicit types (vk::ImageCreateInfo::NativeType, vk::Result) instead of auto type deduction
|
Thanks @gaaclarke. Both of those have been addressed. |
|
@jason-simmons want to be a second reviewer on this? |
|
autosubmit label was removed for flutter/flutter/187586, because - The status or check suite Linux linux_unopt has failed. Please fix the issues identified (or deflake) before re-applying this label.
|
|
The CI failures are apropos: |
Per review: when the device doesn't support fixed-rate compression the ImageCompressionControlEXT struct is already unlinked above, so having try_create_image unlink it again on the uncompressed path asserted. Drop the use_compression argument; the lambda now allocates with the current create-info chain. Unlink the compression-control struct once, in the retry path, before the uncompressed second attempt.
|
An existing Git SHA, To re-trigger presubmits after closing or re-opeing a PR, or pushing a HEAD commit (i.e. with |
|
Re-adding the CICD label broke the system. I merged master and re-added the label |
flutter/flutter@66aaa9a...c0a1129 2026-06-10 137456488+flutter-pub-roller-bot@users.noreply.github.com Roll pub packages (flutter/flutter#187740) 2026-06-09 burak.karahan@mail.ru Remove Material import from view chrome style test (flutter/flutter#186994) 2026-06-09 jason-simmons@users.noreply.github.com [Impeller] Remove unused DeviceHolderVK reference from CommandBufferVK (flutter/flutter#187705) 2026-06-09 engine-flutter-autoroll@skia.org Roll Fuchsia Linux SDK from KNe93cf5wU4xG2d-m... to 8azSyvz57mKcPqTwk... (flutter/flutter#187745) 2026-06-09 1063596+reidbaker@users.noreply.github.com Add android-agent agent.json and update reidbaker-agent skills (flutter/flutter#187746) 2026-06-09 engine-flutter-autoroll@skia.org Roll Skia from aeed11c35004 to 9f02102df298 (9 revisions) (flutter/flutter#187744) 2026-06-09 bdero@google.com [Impeller] Remove the texture coordinate system Y-flip workaround (flutter/flutter#187686) 2026-06-09 41687333+rlueders@users.noreply.github.com [Impeller] Retry uncompressed when fixed-rate compression is exhausted (flutter/flutter#187586) 2026-06-09 burak.karahan@mail.ru Remove Material import from implicit animation tests (flutter/flutter#186673) 2026-06-09 engine-flutter-autoroll@skia.org Roll Packages from 13b49f4 to bd297cf (4 revisions) (flutter/flutter#187739) 2026-06-09 30870216+gaaclarke@users.noreply.github.com Updates dia_dll.py to support vs2026 (flutter/flutter#187714) 2026-06-09 bdero@google.com [Flutter GPU] Allow attaching specific texture mip levels and slices for rendering (flutter/flutter#187685) 2026-06-09 engine-flutter-autoroll@skia.org Roll Dart SDK from 39f1c44e294f to f3441f2067ae (1 revision) (flutter/flutter#187711) 2026-06-09 bdero@google.com [flutter_tools] Hot reload Flutter GPU shader bundles (flutter/flutter#187654) 2026-06-09 katelovett@google.com Update triage links (flutter/flutter#187709) 2026-06-09 engine-flutter-autoroll@skia.org Roll Skia from 43f135735152 to aeed11c35004 (11 revisions) (flutter/flutter#187721) 2026-06-09 jason-simmons@users.noreply.github.com Use workspace resolution for the meta package in dev/integration_tests/record_use_test_package (flutter/flutter#187733) If this roll has caused a breakage, revert this CL and stop the roller using the controls here: https://autoroll.skia.org/r/flutter-packages Please CC louisehsu@google.com,stuartmorgan@google.com on the revert to ensure that a human is aware of the problem. To file a bug in Packages: https://github.com/flutter/flutter/issues/new/choose To report a problem with the AutoRoller itself, please file a bug: https://issues.skia.org/issues/new?component=1389291&template=1850622 Documentation for the AutoRoller is here: https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md
flutter#187586) Fixes flutter#187564 ## Issue On the Pixel 10 (Tensor G5 / **Imagination PowerVR** GPU), Impeller's Vulkan backend crashes the raster thread under GPU pressure: ``` [ERROR:impeller/renderer/backend/vulkan/allocator_vk.cc] Unable to allocate Vulkan Image: ErrorCompressionExhaustedEXT Type: Texture2D ... Usage: { ShaderRead, RenderTarget } [ERROR:impeller/renderer/render_target.cc] Could not create color texture. [ERROR:impeller/renderer/render_target.cc] Render target does not have color attachment at index 0. F/libc: Fatal signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x0 in tid NNNN (1.raster) ``` (In release builds the same failure surfaces as `[FATAL:flutter/impeller/display_list/canvas.cc(1471)] Check failed: back_texture. Context is valid:0` SIGABRT, or a bare SIGSEGV @ 0x20 on the `*.raster` thread.) ### Root cause Impeller requests **fixed-rate image compression** (`VkImageCompressionControlEXT`) for lossy render targets (`CreateOffscreenMSAA`'s color-resolve texture). When the PowerVR driver's fixed-rate-compression resources are exhausted, `vmaCreateImage` returns `VK_ERROR_COMPRESSION_EXHAUSTED_EXT`. `AllocatedTextureSourceVK` did not handle this — it logged and returned an invalid texture, which became a render target with no color attachment, and the raster thread then dereferenced the null texture. This is a regression: it does **not** reproduce on Flutter 3.41.9, but does on 3.44.x. It is PowerVR-specific (the error is tied to the driver's compression resource pool) and GPU-state-dependent (it fires once cumulative GPU compression pressure is high enough). ## Fix `VK_ERROR_COMPRESSION_EXHAUSTED_EXT` is, per the Vulkan spec, only returned for fixed-rate compression requests — so retrying the same allocation **without** compression is always a valid recovery. On that error, `AllocatedTextureSourceVK` now unlinks `VkImageCompressionControlEXT` from the create-info chain and retries `vmaCreateImage` once uncompressed (logging a one-time warning). The texture is identical, just stored uncompressed; the only cost is on the failure path (a small amount of extra memory/bandwidth for the affected texture, instead of a crash). ## Tests - **Unit test** (`allocator_vk_unittests.cc` → `RetriesUncompressedOnCompressionExhausted`): extends the Vulkan mock to advertise fixed-rate compression and to fail the first compressed `vkCreateImage` with `VK_ERROR_COMPRESSION_EXHAUSTED_EXT`, then asserts the allocator returns a **valid** texture and called `vkCreateImage` **twice** (compressed attempt + uncompressed retry). Passes; the other allocator tests are unaffected. - **On-device A/B** (Pixel 10, locally-built `android_profile_arm64`, same repro, same GPU-pressured state): | Engine | Result | |---|---| | Unpatched | `ErrorCompressionExhausted` → **SIGSEGV** on `1.raster` (crash) | | Patched | exhaustion → retry → **survives**; logs `Fixed-rate image compression exhausted; falling back to uncompressed image allocation` | ## Repro A pure-Flutter app that stacks enough full-screen `BackdropFilter` / `saveLayer` offscreen render targets to exhaust the PowerVR compression pool (see `lib/main.dart` in the linked repro). Crashes on the unpatched engine; runs on the patched one. Stable on either with `--no-enable-impeller`. ## Environment - Flutter 3.44.x (regressed from 3.41.9) - Device: Pixel 10, Android 17 (API 37) - GPU: Imagination PowerVR (Tensor G5); renderer Impeller / Vulkan ## Pre-launch checklist - [x] Added a unit test (or explained why not possible). - [x] Listed any breaking changes (none). - [x] Signed the [CLA](https://cla.developers.google.com/). --------- Co-authored-by: John "codefu" McDole <codefu@google.com>
Fixes #187564
Issue
On the Pixel 10 (Tensor G5 / Imagination PowerVR GPU), Impeller's Vulkan backend
crashes the raster thread under GPU pressure:
(In release builds the same failure surfaces as
[FATAL:flutter/impeller/display_list/canvas.cc(1471)] Check failed: back_texture. Context is valid:0SIGABRT, or a bare SIGSEGV @ 0x20 on the
*.rasterthread.)Root cause
Impeller requests fixed-rate image compression (
VkImageCompressionControlEXT) forlossy render targets (
CreateOffscreenMSAA's color-resolve texture). When the PowerVRdriver's fixed-rate-compression resources are exhausted,
vmaCreateImagereturnsVK_ERROR_COMPRESSION_EXHAUSTED_EXT.AllocatedTextureSourceVKdid not handle this — itlogged and returned an invalid texture, which became a render target with no color
attachment, and the raster thread then dereferenced the null texture.
This is a regression: it does not reproduce on Flutter 3.41.9, but does on 3.44.x.
It is PowerVR-specific (the error is tied to the driver's compression resource pool) and
GPU-state-dependent (it fires once cumulative GPU compression pressure is high enough).
Fix
VK_ERROR_COMPRESSION_EXHAUSTED_EXTis, per the Vulkan spec, only returned for fixed-ratecompression requests — so retrying the same allocation without compression is always a
valid recovery. On that error,
AllocatedTextureSourceVKnow unlinksVkImageCompressionControlEXTfrom the create-info chain and retriesvmaCreateImageonceuncompressed (logging a one-time warning). The texture is identical, just stored
uncompressed; the only cost is on the failure path (a small amount of extra
memory/bandwidth for the affected texture, instead of a crash).
Tests
Unit test (
allocator_vk_unittests.cc→RetriesUncompressedOnCompressionExhausted):extends the Vulkan mock to advertise fixed-rate compression and to fail the first
compressed
vkCreateImagewithVK_ERROR_COMPRESSION_EXHAUSTED_EXT, then asserts theallocator returns a valid texture and called
vkCreateImagetwice (compressedattempt + uncompressed retry). Passes; the other allocator tests are unaffected.
On-device A/B (Pixel 10, locally-built
android_profile_arm64, same repro, sameGPU-pressured state):
ErrorCompressionExhausted→ SIGSEGV on1.raster(crash)Fixed-rate image compression exhausted; falling back to uncompressed image allocationRepro
A pure-Flutter app that stacks enough full-screen
BackdropFilter/saveLayeroffscreenrender targets to exhaust the PowerVR compression pool (see
lib/main.dartin the linkedrepro). Crashes on the unpatched engine; runs on the patched one. Stable on either with
--no-enable-impeller.Environment
Pre-launch checklist