Skip to content

[Impeller] Retry uncompressed when fixed-rate compression is exhausted#187586

Merged
auto-submit[bot] merged 4 commits into
flutter:masterfrom
rlueders:impeller-vulkan-compression-exhausted-retry
Jun 9, 2026
Merged

[Impeller] Retry uncompressed when fixed-rate compression is exhausted#187586
auto-submit[bot] merged 4 commits into
flutter:masterfrom
rlueders:impeller-vulkan-compression-exhausted-retry

Conversation

@rlueders

@rlueders rlueders commented Jun 4, 2026

Copy link
Copy Markdown
Contributor

Fixes #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.ccRetriesUncompressedOnCompressionExhausted):
    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 ErrorCompressionExhaustedSIGSEGV 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

  • Added a unit test (or explained why not possible).
  • Listed any breaking changes (none).
  • Signed the CLA.

@github-actions github-actions Bot added engine flutter/engine related. See also e: labels. e: impeller Impeller rendering backend issues and features requests labels Jun 4, 2026
@google-cla

google-cla Bot commented Jun 4, 2026

Copy link
Copy Markdown

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.
@rlueders rlueders force-pushed the impeller-vulkan-compression-exhausted-retry branch from 65d411f to b37f7f7 Compare June 4, 2026 20:52

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

@flutter-dashboard

Copy link
Copy Markdown

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:

  • Configuration Changes: The .ci.yaml file might have been modified between the creation of this pull request and the start of this test run. This can lead to ci yaml validation errors.
  • Infrastructure Issues: Problems with the CI environment itself (e.g., quota) could have caused the failure.

A blank commit, or merging to head, will be required to resume running CI for this PR.

Error Details:

GitHub Error: You have exceeded a secondary rate limit. Please wait a few minutes before you try again. For more on scraping GitHub and how it may affect your rights, please review our Terms of Service (https://docs.github.com/en/site-policy/github-terms/github-terms-of-service) If you reach out to GitHub Support for help, please include the request ID 997A:193DD0:48BA4FE:11698282:6A270CB6.

Stack trace:

#0      GitHub.handleStatusCode (package:github/src/common/github.dart:486:5)
#1      GitHub.request (package:github/src/common/github.dart:422:7)
<asynchronous suspension>
#2      GitHub.requestJson (package:github/src/common/github.dart:323:22)
<asynchronous suspension>
#3      RetryOptions.retry (package:retry/retry.dart:131:16)
<asynchronous suspension>
#4      LuciBuildService._scheduleTryBuilds (package:cocoon_service/src/service/luci_build_service.dart:307:26)
<asynchronous suspension>
#5      Scheduler._runCiTestingStage (package:cocoon_service/src/service/scheduler.dart:1468:9)
<asynchronous suspension>
#6      Scheduler.proceedToCiTestingStage (package:cocoon_service/src/service/scheduler.dart:1519:7)
<asynchronous suspension>
#7      Scheduler._closeSuccessfulEngineBuildStage (package:cocoon_service/src/service/scheduler.dart:1333:5)
<asynchronous suspension>
#8      Scheduler.processCheckRunCompleted (package:cocoon_service/src/service/scheduler.dart:1265:11)
<asynchronous suspension>
#9      PresubmitLuciSubscription.post (package:cocoon_service/src/request_handlers/presubmit_luci_subscription.dart:176:9)
<asynchronous suspension>
#10     RequestHandler.service (package:cocoon_service/src/request_handling/request_handler.dart:42:20)
<asynchronous suspension>
#11     SubscriptionHandler.service (package:cocoon_service/src/request_handling/subscription_handler.dart:139:5)
<asynchronous suspension>
#12     createServer.<anonymous closure> (package:cocoon_service/server.dart:448:7)
<asynchronous suspension>
#13     main.<anonymous closure>.<anonymous closure> (file:///app/app_dart/bin/gae_server.dart:187:9)
<asynchronous suspension>

@gaaclarke gaaclarke left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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!

Comment thread engine/src/flutter/impeller/renderer/backend/vulkan/test/mock_vulkan.cc Outdated
Comment thread engine/src/flutter/impeller/renderer/backend/vulkan/allocator_vk.cc Outdated
- mock_vulkan: move compression_requested into the while condition
- allocator_vk: use explicit types (vk::ImageCreateInfo::NativeType,
  vk::Result) instead of auto type deduction
@github-actions github-actions Bot removed the CICD Run CI/CD label Jun 8, 2026
@gaaclarke gaaclarke added the CICD Run CI/CD label Jun 8, 2026
gaaclarke
gaaclarke previously approved these changes Jun 8, 2026

@gaaclarke gaaclarke left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm! thanks

@gaaclarke gaaclarke requested a review from jason-simmons June 8, 2026 21:53
@rlueders

rlueders commented Jun 8, 2026

Copy link
Copy Markdown
Contributor Author

Thanks @gaaclarke. Both of those have been addressed.

@gaaclarke

Copy link
Copy Markdown
Member

@jason-simmons want to be a second reviewer on this?

@gaaclarke gaaclarke added the autosubmit Merge PR when tree becomes green via auto submit App label Jun 8, 2026
@auto-submit

auto-submit Bot commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

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 status or check suite Google testing has failed. Please fix the issues identified (or deflake) before re-applying this label.

@auto-submit auto-submit Bot removed the autosubmit Merge PR when tree becomes green via auto submit App label Jun 8, 2026
@gaaclarke

Copy link
Copy Markdown
Member

The CI failures are apropos:

[0;32m[ RUN      ] �[mGPUSurfaceVulkanImpeller.RecreatesTransientsWhenFrameSizeChanges
[INFO:flutter/testing/test_vulkan_context.cc(41)] Using Vulkan ICD: libvk_swiftshader.so
[WARNING:flutter/common/graphics/persistent_cache.cc(286)] Could not acquire the persistent cache directory. Caching of GPU resources on disk is disabled.
[FATAL:flutter/third_party/vulkan-deps/vulkan-headers/src/include/vulkan/vulkan.hpp(841)] Check failed: false.
[ERROR:flutter/fml/backtrace.cc(108)] Caught signal SIGABRT during program execution.
Frame 0: 0x743d740969fc pthread_kill
Frame 1: 0x743d74042476 gsignal
Frame 2: 0x743d740287f3 abort
Frame 3: 0x60ab8e7bf32e Unknown
Frame 4: 0x60ab8e7bf273 fml::LogMessage::~LogMessage()
Frame 5: 0x60ab9269aba8 impeller::vk::StructureChain<>::unlink()
Frame 6: 0x60ab92697ff5 impeller::vk::StructureChain<>::unlink<>()
Frame 7: 0x60ab9269814e impeller::AllocatedTextureSourceVK::AllocatedTextureSourceVK()::{lambda()#1}::operator()()
Frame 8: 0x60ab9268e382 impeller::AllocatedTextureSourceVK::AllocatedTextureSourceVK()
Frame 9: 0x60ab9268b9b9 std::__fl::construct_at[abi:nn210000]<>()
Frame 10: 0x60ab9268b8dd std::__fl::__construct_at[abi:nn210000]<>()
Frame 11: 0x60ab9268b651 std::__fl::allocator_traits<>::construct[abi:nn210000]<>()
Frame 12: 0x60ab9268b25d std::__fl::__shared_ptr_emplace<>::__shared_ptr_emplace[abi:nn210000]<>()
Frame 13: 0x60ab9268ae04 std::__fl::allocate_shared[abi:nn210000]<>()
Frame 14: 0x60ab926844d9 std::__fl::make_shared[abi:nn210000]<>()
Frame 15: 0x60ab9267f85f impeller::AllocatorVK::OnCreateTexture()
Frame 16: 0x60ab8e752af1 impeller::Allocator::CreateTexture()
Frame 17: 0x60ab9225a5c0 impeller::ContentContext::ContentContext()
Frame 18: 0x60ab92176eca std::__fl::make_unique[abi:nn210000]<>()
Frame 19: 0x60ab92176b13 impeller::AiksContext::AiksContext()
Frame 20: 0x60ab914bb868 std::__fl::construct_at[abi:nn210000]<>()
Frame 21: 0x60ab914bb725 std::__fl::__construct_at[abi:nn210000]<>()
Frame 22: 0x60ab914bb4b9 std::__fl::allocator_traits<>::construct[abi:nn210000]<>()
Frame 23: 0x60ab914bb0e9 std::__fl::__shared_ptr_emplace<>::__shared_ptr_emplace[abi:nn210000]<>()
Frame 24: 0x60ab914baca9 std::__fl::allocate_shared[abi:nn210000]<>()
Frame 25: 0x60ab914b723a std::__fl::make_shared[abi:nn210000]<>()
Frame 26: 0x60ab914a7951 flutter::GPUSurfaceVulkanImpeller::GPUSurfaceVulkanImpeller()

Comment thread engine/src/flutter/impeller/renderer/backend/vulkan/allocator_vk.cc Outdated
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.
@github-actions github-actions Bot removed the CICD Run CI/CD label Jun 9, 2026
@jason-simmons jason-simmons added the CICD Run CI/CD label Jun 9, 2026

@gaaclarke gaaclarke left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

@gaaclarke gaaclarke added the autosubmit Merge PR when tree becomes green via auto submit App label Jun 9, 2026
@jtmcdole jtmcdole added CICD Run CI/CD and removed CICD Run CI/CD labels Jun 9, 2026
@fluttergithubbot

Copy link
Copy Markdown
Contributor

An existing Git SHA, 6521ad9b991fe1473fec87d9627cfa12b691051d, was detected, and no actions were taken.

To re-trigger presubmits after closing or re-opeing a PR, or pushing a HEAD commit (i.e. with --force) that already was pushed before, push a blank commit (git commit --allow-empty -m "Trigger Build") or rebase to continue.

@github-actions github-actions Bot removed the CICD Run CI/CD label Jun 9, 2026
@jtmcdole jtmcdole added the CICD Run CI/CD label Jun 9, 2026
@jtmcdole

jtmcdole commented Jun 9, 2026

Copy link
Copy Markdown
Member

Re-adding the CICD label broke the system. I merged master and re-added the label

@auto-submit auto-submit Bot added this pull request to the merge queue Jun 9, 2026
Merged via the queue into flutter:master with commit 5177105 Jun 9, 2026
201 checks passed
@flutter-dashboard flutter-dashboard Bot removed the autosubmit Merge PR when tree becomes green via auto submit App label Jun 9, 2026
auto-submit Bot pushed a commit to flutter/packages that referenced this pull request Jun 11, 2026
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
via-guy pushed a commit to via-guy/flutter that referenced this pull request Jun 26, 2026
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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CICD Run CI/CD e: impeller Impeller rendering backend issues and features requests engine flutter/engine related. See also e: labels.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Impeller][Vulkan] Unhandled VK_ERROR_COMPRESSION_EXHAUSTED_EXT render-target allocation failure crashes the raster thread on PowerVR (Pixel 10)

5 participants