You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[Impeller] Support rendering compressed texture formats / add capability to detect support. #148443
I'm not sure what the actual level of device support is on Vulkan and would need to do some research. For iOS, there is a handy feature set table here: https://developer.apple.com/metal/Metal-Feature-Set-Tables.pdf . We could look at the intersection of minimum supported formats as a starting point.
These formats specify how pixel data is compressed, but don't include header information on the format/size like commonly used network image formats like PNG/JPEG. This metadata would need to be provided by the application. I'm not sure if there are other standards here like ASTC in PNG or if the expectation is that the application level logic will handle transport compression/bundling.
For example, a low-level dart:ui API for decompressing.
import'dart:ui'as uil
[
void main() {
Uint8List data = getBytes(...);
if (!ui.Codec.checkFormatSupport(PixelFormatASTC_4x4_sRGB)) { //Probably a different namereturn;
}
var ui.image =await ui.decodeCompressedTexture(data, width:100, height:100, format:VK_FORMAT_BC1_RGB_UNORM_BLOCK);
We can't support these in the Skia backend as the formats are unsupported as far as I know, unless we wrote separate import code and treated them as external textures (which I'd rather not do).
We currently resize images using Skia's software codecs which don't support these formats, so resizing would fail until we switch to GPU based resizing.
Exposing support for compressed texture formats as described is necessary, but I don't believe is sufficient in making a usable system. Especially given the myriad of formats that GPUs can natively support and the offline tooling necessary.
For reference, this is the guidance on Android. Also, Unity also does the transcoding like I described in an earlier comment. I am not sure if they use the open standard though. But from the perspective of an easy to use system, some sort of transcoding would be necessary.
We don't need to build an end to end usable system though, that can be done as a package/community project. The only thing the community can't do is add engine support
It would be very interesting to be able to load compressed textures directly from KTX file, and to know which texture format would be preferred from a list of possibles - for example S3TC/DXT1...
As referenced above, we have proposed a design for compressed texture support in Flutter and have a limited but functional POC. The design document update is pending, in the meantime it can be viewed here (Google Docs)
Folding in design detail from #187072, which I filed as a duplicate of this issue and am now closing. The Flutter GPU surface work that depends on this is tracked in #187073.
Suggested scope, grouped into three hardware families:
BC (S3TC, RGTC, BPTC): BC1 to BC7. Desktop GPUs.
ETC2 and EAC. Mobile, and any OpenGL ES 3.0 or WebGL2 context.
ASTC LDR. Modern mobile and some desktop.
Skip these initially: PVRTC (deprecated, Apple only, being removed from WebGL), ETC1 (legacy, superseded by ETC2), ASTC HDR, and BC6H HDR. They can be added later behind the same query.
Work items:
Add the compressed PixelFormat values for the three families.
Make descriptor math block-aware. Add bytes-per-block and block dimensions to formats.h, and update GetByteSizeOfBaseMipLevel and GetBytesPerRow to round to block extents.
Add a compressed upload path: glCompressedTexSubImage2D (GLES), vkCmdCopyBufferToImage with block extents (Vulkan), and replaceRegion with compressed formats (Metal).
Enforce usage restrictions: sample plus copy-destination only. No render target, no storage, no transient storage mode, and no runtime mip generation.
Map the formats in each backend, gated by capability detection: Vulkan feature flags (textureCompressionBC, textureCompressionETC2, textureCompressionASTC_LDR), GLES extension strings, and Metal GPU family checks.
Capability query API on impeller::Capabilities:
enumclassTextureCompressionType {
kBC, // Desktop. BC1 to BC7.kETC2, // Mobile, GLES3, WebGL2.kASTC, // Modern mobile, some desktop.
};
// True if the device supports a whole compressed family.virtualboolSupportsTextureCompression(TextureCompressionType type) const = 0;
// Per-format, per-usage query. Covers compressed and uncompressed formats.virtualboolSupportsTextureFormat(PixelFormat format,
TextureUsage usage) const = 0;
SupportsTextureFormat is the general primitive. SupportsTextureCompression is a convenience for the common "can I use this family at all" check.
No single compressed format works everywhere, which is why the query is required. Coverage is near-universal per tier: ETC2 and EAC are guaranteed on OpenGL ES 3.0 and WebGL2 and present on all mobile GPUs and Apple Silicon, BC is effectively guaranteed on desktop, and ASTC covers modern mobile. Together the three families cover essentially every target, and a single asset reaches all of them through KTX2 or Basis Universal transcoding at the asset layer, with uncompressed RGBA as the final fallback.
Activity
chinmaygarde commentedon May 16, 2024
Exposing support for compressed texture formats as described is necessary, but I don't believe is sufficient in making a usable system. Especially given the myriad of formats that GPUs can natively support and the offline tooling necessary.
I am in favor of one of the supercompressed formats in a standardized container like ktx2. In Dart code, the user can specify a file in a KTX2 container and we can do some minor conversion to a known supported format at runtime.
chinmaygarde commentedon May 16, 2024
For reference, this is the guidance on Android. Also, Unity also does the transcoding like I described in an earlier comment. I am not sure if they use the open standard though. But from the perspective of an easy to use system, some sort of transcoding would be necessary.
chinmaygarde commentedon May 16, 2024
More guidance on how other engines reason about a usable way to work with compressed textures. This also uses KTX2 for the container.
jonahwilliams commentedon May 16, 2024
We don't need to build an end to end usable system though, that can be done as a package/community project. The only thing the community can't do is add engine support
time4tea commentedon Apr 28, 2025
It would be very interesting to be able to load compressed textures directly from KTX file, and to know which texture format would be preferred from a list of possibles - for example S3TC/DXT1...
planetmarshall commentedon Nov 17, 2025
As referenced above, we have proposed a design for compressed texture support in Flutter and have a limited but functional POC. The design document update is pending, in the meantime it can be viewed here (Google Docs)
bdero commentedon May 26, 2026
Folding in design detail from #187072, which I filed as a duplicate of this issue and am now closing. The Flutter GPU surface work that depends on this is tracked in #187073.
Suggested scope, grouped into three hardware families:
Skip these initially: PVRTC (deprecated, Apple only, being removed from WebGL), ETC1 (legacy, superseded by ETC2), ASTC HDR, and BC6H HDR. They can be added later behind the same query.
Work items:
PixelFormatvalues for the three families.formats.h, and updateGetByteSizeOfBaseMipLevelandGetBytesPerRowto round to block extents.glCompressedTexSubImage2D(GLES),vkCmdCopyBufferToImagewith block extents (Vulkan), andreplaceRegionwith compressed formats (Metal).textureCompressionBC,textureCompressionETC2,textureCompressionASTC_LDR), GLES extension strings, and Metal GPU family checks.Capability query API on
impeller::Capabilities:SupportsTextureFormatis the general primitive.SupportsTextureCompressionis a convenience for the common "can I use this family at all" check.No single compressed format works everywhere, which is why the query is required. Coverage is near-universal per tier: ETC2 and EAC are guaranteed on OpenGL ES 3.0 and WebGL2 and present on all mobile GPUs and Apple Silicon, BC is effectively guaranteed on desktop, and ASTC covers modern mobile. Together the three families cover essentially every target, and a single asset reaches all of them through KTX2 or Basis Universal transcoding at the asset layer, with uncompressed RGBA as the final fallback.
[Impeller] Add block-compressed texture format support (BC, ETC2, AST…
[Impeller] Add block-compressed texture format support (BC, ETC2, AST…