Repository navigation
Description
Steps to reproduce
- Run any app using
flutter_gpuon an Android device where Impeller selects the Vulkan backend (e.g. Samsung Galaxy A54 / Mali-G68 / Vulkan 1.3 — logcat showsUsing the Impeller rendering backend (Vulkan).). - Query compressed texture support:
import 'package:flutter_gpu/gpu.dart' as gpu;
final bc = gpu.gpuContext.supportsTextureCompression(gpu.TextureCompressionFamily.bc);
final etc2 = gpu.gpuContext.supportsTextureCompression(gpu.TextureCompressionFamily.etc2);
final astc = gpu.gpuContext.supportsTextureCompression(gpu.TextureCompressionFamily.astc);
// bc=false etc2=false astc=false — on hardware that fully supports ETC2 + ASTCThe same is observable through package:flutter_scene 0.18.x, whose KTX2 upload path logs:
flutter_scene texture compression support: bc=false etc2=false astc=false (transcode runs off the main isolate; rgba8 fallback otherwise)
Expected results
On a Vulkan 1.3 Android device with a Mali/Adreno GPU, etc2 should be true (mandatory in practice on mobile Vulkan implementations) and astc should be true where VkPhysicalDeviceFeatures::textureCompressionASTC_LDR is supported — matching what the GLES and Metal backends already report on equivalent hardware.
Actual results
All LDR compression families report false on every Android Vulkan device, regardless of hardware support. Compressed texture uploads are impossible on the flagship Android backend, forcing consumers (e.g. flutter_scene) to fall back to uncompressed RGBA8 (≈8× VRAM).
Regression range
This is a follow-up defect to the PR that added compressed-texture support, not a pre-existing limitation:
- Introduced by [Impeller] Add block-compressed texture format support (BC, ETC2, ASTC) #187077 ([Impeller] Add block-compressed texture format support (BC, ETC2, ASTC), merged 2026-05-28), which is part of the umbrella issue [Impeller] Support rendering compressed texture formats / add capability to detect support. #148443.
- That PR wired the capability read-back on all three backends (Vulkan/GLES/Metal) but, on Vulkan only, never added the matching enable at device creation. So the query reads back features that were never requested and returns
falseunconditionally. - The Flutter GPU public surface +
supportsTextureCompressionquery ([Flutter GPU] Expose compressed texture formats and a format capability query #187073 / [Flutter GPU] Add block-compressed texture format support (BC, ETC2, ASTC LDR) #187281, merged 2026-06-02) then exposes this always-falseresult to Dart.
Net effect: the feature shipped functional on GLES and Metal, but dead-on-arrival on Android/Vulkan — the default backend on modern Android.
Root cause (from source)
CapabilitiesVK answers the query from the enabled device features:
engine/src/flutter/impeller/renderer/backend/vulkan/capabilities_vk.cc (@ 47215701bc6e, also present on current master):
// ~line 670
{
const auto& features = enabled_features.get().features;
supports_texture_compression_bc_ = features.textureCompressionBC;
supports_texture_compression_etc2_ = features.textureCompressionETC2;
supports_texture_compression_astc_ = features.textureCompressionASTC_LDR;
}…but GetEnabledDeviceFeatures() never requests those core features when building the required_chain passed to vkCreateDevice. The "Base features" block only enables two features:
// ~line 446 ("Base features")
{
auto& required = required_chain.get().features;
const auto& supported = supported_chain.get().features;
required.fillModeNonSolid = supported.fillModeNonSolid;
required.samplerAnisotropy = supported.samplerAnisotropy;
}textureCompressionETC2 / textureCompressionASTC_LDR / textureCompressionBC are absent, so they are never enabled, so the capability reads back false unconditionally. (Notably, ASTC HDR is wired — via VK_EXT_texture_compression_astc_hdr at ~line 502 — while the far more common LDR core features are not, which suggests an oversight rather than a policy.)
For comparison, the other two backends wire this correctly:
- GLES —
engine/src/flutter/impeller/renderer/backend/gles/capabilities_gles.cc(~line 186-202): ETC2 fromIsES() && major >= 3, ASTC fromGL_KHR/OES_texture_compression_astc*extensions. - Metal —
engine/src/flutter/impeller/renderer/backend/metal/context_mtl.mm(~line 55-105): ETC2/ASTC onMTLGPUFamilyApple2+, ASTC HDR onApple6+.
Vulkan on Android is therefore the only backend where block-compressed textures can never be used — and it is the default backend on modern Android devices.
Evidence from #187077's own diff
The introducing PR (#187077) makes the asymmetry unambiguous. In capabilities_vk.cc it added the read-back for all four families in SetPhysicalDevice:
+ {
+ const auto& features = enabled_features.get().features;
+ supports_texture_compression_bc_ = features.textureCompressionBC;
+ supports_texture_compression_etc2_ = features.textureCompressionETC2;
+ supports_texture_compression_astc_ = features.textureCompressionASTC_LDR;
+ }
+ supports_texture_compression_astc_hdr_ = /* ...from the HDR extension... */;…but in GetEnabledDeviceFeatures the same PR wired the enable for only ASTC HDR:
+ // VK_EXT_texture_compression_astc_hdr
+ ...
+ required.textureCompressionASTC_HDR = supported.textureCompressionASTC_HDR;No required.textureCompressionETC2 / ASTC_LDR / BC = supported.* line was added anywhere. So three of the four families are read back from features that are never requested — they can only ever be false. It is a three-line omission within the PR that added the feature, not a design decision.
Proposed fix
Mirror the existing samplerAnisotropy pattern in the "Base features" block of CapabilitiesVK::GetEnabledDeviceFeatures (the same block that already wires fillModeNonSolid and samplerAnisotropy):
required.textureCompressionETC2 = supported.textureCompressionETC2;
required.textureCompressionASTC_LDR = supported.textureCompressionASTC_LDR;
required.textureCompressionBC = supported.textureCompressionBC;The read-back at ~line 670 then reports real hardware support with no further changes — this is the one piece #187077 wired on GLES/Metal but missed on Vulkan. (Note: ASTC HDR is already enabled this way at ~line 502 via VK_EXT_texture_compression_astc_hdr, so the three core LDR/BC/ETC2 features are the only gap.) It is a three-line change with no new extensions and no API surface impact.
Evidence device
- Samsung Galaxy A54 5G (SM-A546E), Exynos 1380, Mali-G68 MP5
- Android 16 (SDK 36),
android.hardware.vulkan.version=4206592(Vulkan 1.3) - Impeller backend: Vulkan (confirmed via logcat)
- Hardware supports ETC2 (mandatory on Mali) and ASTC LDR
Impact
flutter_gpuconsumers cannot use compressed textures on Android/Vulkan at all.flutter_scene0.18.x ships a KTX2/Basis pipeline that silently falls back to RGBA8 (≈8× texture memory, higher bandwidth) on the entire Android Vulkan population, while iOS (Metal) and Android GLES devices get compression.
Flutter doctor
flutter doctor -v (master channel)
[!] Flutter (Channel master, 3.46.0-1.0.pre-322, on Ubuntu 24.04.3 LTS 6.18.33.2-microsoft-standard-WSL2, locale C.UTF-8)
• Flutter version 3.46.0-1.0.pre-322 on channel master at /home/guszxtavo/flutter-master
• Upstream repository https://github.com/flutter/flutter.git
• Framework revision 47215701bc (10 days ago), 2026-06-27 02:19:27 -0400
• Engine revision 47215701bc
• Dart version 3.13.0 (build 3.13.0-254.0.dev)
• DevTools version 2.59.0
• Feature flags: enable-web, enable-linux-desktop, enable-macos-desktop, enable-windows-desktop, enable-android, enable-ios, cli-animations, enable-native-assets, enable-dart-data-assets, enable-swift-package-manager, omit-legacy-version-file, enable-lldb-debugging, enable-uiscene-migration, enable-riscv64
[✓] Android toolchain - develop for Android devices (Android SDK version 36.0.0)
• Android SDK at /home/guszxtavo/Android/Sdk
• Platform android-36, build-tools 36.0.0
• Java version OpenJDK Runtime Environment (build 17.0.19+10-1-24.04.2-Ubuntu)
• All Android licenses accepted.
[✓] Chrome - develop for the web
• Chrome at google-chrome
[✓] Network resources
• All expected network resources are available.
Test device (connected over adb Wi-Fi during repro): SM-A546E (Galaxy A54 5G), android-arm64, Android 16 (API 36), Exynos 1380 / Mali-G68 MP5, android.hardware.vulkan.version=4206592 (Vulkan 1.3).
Activity
[Impeller] Add regression test for Vulkan block-compressed texture su…
[Impeller] Enable ETC2/ASTC LDR/BC texture compression features at Vu…
[Impeller] Add regression test for Vulkan block-compressed texture su…
[Impeller] Add regression test for Vulkan block-compressed texture su…
[Impeller] Enable ETC2/ASTC LDR/BC texture compression features at Vu…
github-actions commentedon Aug 18, 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.