Skip to content

KTX2 Updates: ETC1s/BasisLZ, ASTC HDR, and faster Zstd#18411

Closed
brianreavis wants to merge 48 commits intobevyengine:mainfrom
brianreavis:pr-ktx2-updates
Closed

KTX2 Updates: ETC1s/BasisLZ, ASTC HDR, and faster Zstd#18411
brianreavis wants to merge 48 commits intobevyengine:mainfrom
brianreavis:pr-ktx2-updates

Conversation

@brianreavis
Copy link
Copy Markdown
Contributor

@brianreavis brianreavis commented Mar 19, 2025

Objective

This PR expands Bevy’s supported KTX2 texture formats and transcoding capabilities (and .basis capabilities, as well). It also features some bugfixes and optimizations to improve speed and memory use. For more details on the changes, jump to the Changelog section below.

Updated Dependencies

  • Updated ktx2 to 0.4.0 for ASTC HDR constants (thanks @cwfitzgerald & @expenses)
  • Updated basis-universal to a forked version with updates:
    • Synced to basis_universal/2da6664
    • New: KTX2 decoding, transcoding, and encoding support
    • New: HDR texture support
    • New: Distinct feature flags for "encoding" and "transcoding" (for lighter builds)

Faster Zstd Decompression

Users can now choose the backend for Zstd supercompressed files:

  • zstd (faster native bindings, new default) via the "zstd_native" feature.
  • ruzstd (safer, previous Bevy default) via the "zstd_rust" feature.

In benchmarks, reading a 284kb supercompressed KTX2 was 44% faster with zstd than ruzstd.

Showcase

cargo run --example texture_support --features="ktx2 basis-universal bmp gif exr ico jpeg pnm qoi tga tiff webp dds"
image

To test behavior when a user has a GPU that does not support compressed textures, run with the --no-compressed-textures argument:

cargo run --example texture_support --features="ktx2 basis-universal bmp gif exr ico jpeg pnm qoi tga tiff webp dds" -- --no-compressed-textures

For Maintainers / Reviewers

Test by running the example above. When reviewing the changes, make sure you look for the "Load diff" links on ktx2.rs and texture_support.rs (they're easy to miss).

Important

Before merging, unless/until the basis-universal updates are submitted and merged upstream, I suggest forking my fork of basis-universal-rs and pointing to it. Also, fork the basis_universal submodule within it.

Related Issues

Migration Guide

  • If you have optional dependencies disabled and use functionality that requires zstd decompression ("tonemapping_luts" or "ktx2"), specify the zstd implementation you want to use using one of the following feature flags: "zstd_native" (faster) or "zstd_rust" (safer)
  • If you were writing compressed images using Bevy's asset processing, you’ll need to enable the "compressed_image_saver" feature (this is no longer enabled by default for all builds)
  • C++17 (or newer) is required by basis_universal

Changelog

  • Added "texture_support" example that demonstrates support for numerous formats.
  • .basis Texture Support Updates:
  • KTX2 Texture Support Updates:
    • Fixed UASTC decompression on systems w/o compressed texture support (range panic)
    • Added support for ETC1s/BasisLZ (via basis_universal)
    • Added support for ASTC HDR (all block sizes)
    • Added support for uncompressed Rgb32Float, Rgb32Sint, Rgb32Uint
    • Added support for native Zstd decompression via zstd ("zstd_native" feature).
      This mode is notably faster – performing 44% faster for a 284kb file.
    • sRGB detection is now automatic (this used to be a user-specified foot gun)
    • Optimizations for improved speed / memory use
    • Updated ktx2 to 0.4.0
  • CompressedImageSaver Updates:
    • The asset processor now outputs KTX2 files instead of Basis Universal (.basis) files.
    • Added support for compression of HDR data: R32Float, Rg32Float, Rgba32Float
  • Fixed DDS field order interpretation for R8G8B8 (fixes red and blue channels being backward)

@brianreavis brianreavis marked this pull request as draft March 19, 2025 02:47
@github-actions
Copy link
Copy Markdown
Contributor

You added a new feature but didn't add a description for it. Please update the root Cargo.toml file.

@brianreavis brianreavis changed the title [DRAFT] KTX2 Texture Support Updates [DRAFT] KTX2 Texture Support Updates: ETC1s/BasisLZ, ASTC HDR, and Faster Zstd Mar 19, 2025
@brianreavis brianreavis changed the title [DRAFT] KTX2 Texture Support Updates: ETC1s/BasisLZ, ASTC HDR, and Faster Zstd KTX2 Updates: ETC1s/BasisLZ, ASTC HDR, and faster Zstd Mar 19, 2025
@cwfitzgerald
Copy link
Copy Markdown

Will try to get a KTX2 release out.

@kristoff3r kristoff3r added A-Rendering Drawing game state to the screen D-Modest A "normal" level of difficulty; suitable for simple features or challenging fixes S-Needs-Review Needs reviewer attention (from anyone!) to move forward labels Mar 20, 2025
@github-actions
Copy link
Copy Markdown
Contributor

The generated examples/README.md is out of sync with the example metadata in Cargo.toml or the example readme template. Please run cargo run -p build-templated-pages -- update examples to update it, and commit the file change.

@brianreavis brianreavis marked this pull request as ready for review March 25, 2025 01:21
@brianreavis brianreavis requested a review from superdump March 25, 2025 01:57
@brianreavis brianreavis added C-Performance A change motivated by improving speed, memory usage or compile times C-Dependencies A change to the crates that Bevy depends on C-Feature A new feature, making something new possible D-Unsafe Touches with unsafe code in some way C-Bug An unexpected or incorrect behavior labels Mar 25, 2025
github-merge-queue bot pushed a commit that referenced this pull request Mar 25, 2025
…" builds) (#18538)

# Objective

- Fixes #17891
- Cherry-picked from #18411

## Solution

The `name` argument could either be made permanent (by removing the
`#[cfg(...)]` condition) or eliminated entirely. I opted to remove it,
as debugging a specific DDS texture edge case in GLTF files doesn't seem
necessary, and there isn't any other foreseeable need to have it.

## Migration Guide

- `Image::from_buffer()` no longer has a `name` argument that's only
present in debug builds when the `"dds"` feature is enabled. If you
happen to pass a name, remove it.
@IceSentry
Copy link
Copy Markdown
Contributor

There's some good stuff in there, but I think this PR should be broken up a bit. Like the KTX2 update could be one PR, the zstd_native/rust split could be another. I'm sure there are others too.

Also, adding a bunch of binary assets isn't ideal if we want to keep the size of the repo in check.

@brianreavis
Copy link
Copy Markdown
Contributor Author

brianreavis commented Mar 28, 2025

There's some good stuff in there, but I think this PR should be broken up a bit. Like the KTX2 update could be one PR, the zstd_native/rust split could be another. I'm sure there are others too.

I can see the case for breaking out the zstd changes to its own PR. I'm not so sure about others being plausible and worthwhile – but am open to feedback. I'm going to hold off on the breakouts until this gets added to a milestone.

Also, adding a bunch of binary assets isn't ideal if we want to keep the size of the repo in check.

Any suggestions on this front?

@janhohenheim janhohenheim modified the milestone: 0.17 May 13, 2025
@atlv24 atlv24 mentioned this pull request Jun 24, 2025
github-merge-queue bot pushed a commit that referenced this pull request Jun 26, 2025
# Objective

- add support for alternate zstd backend through `zstd` for faster
decompression

## Solution

- make existing `zstd` feature only specify that support is required,
disambiguate which backend to use via two other features `zstd_native`
and `zstd_rust`.
- Similar to the approach taken by #18411, but we keep current behavior
by defaulting to the rust implementation because its safer, and isolate
this change.

NOTE: the default feature-set may seem to not currently require `zstd`,
but it does, it is enabled transitively by the `tonemapping_luts`
feature, which is a default feature. Thus this does not add default
features.

## Testing

- Cargo clippy on both feature combinations
github-merge-queue bot pushed a commit that referenced this pull request Jun 29, 2025
# Objective

- Fix bug in dds channel order transcode
- taken from #18411

## Solution

- fix it
- improve docs a bit

## Testing

- example in linked pr
github-merge-queue bot pushed a commit that referenced this pull request Jun 29, 2025
# Objective

- avoid several internal vec copies while collecting all the level data
in ktx2 load
- merge another little piece of #18411 (benchmarks there found this to
be a significant win)

## Solution

- reserve and extend

## Testing

- ran a few examples that load ktx2 images, like ssr. looks fine

## Future work

- fast path logic to skip the reading into different vecs and just read
it all in one go into the final buffer instead
- as above, but directly into gpu staging buffer perhaps
@beicause
Copy link
Copy Markdown
Contributor

beicause commented Nov 3, 2025

I think this is a very useful update, unfortunately the upstream basis-universal-rs does not seem to be under active maintenance, I would greatly appreciate it if bevy could maintain a fork.

Also, adding a bunch of binary assets isn't ideal if we want to keep the size of the repo in check.

I would suggest reducing the test combinations, e.g. remove other ASTC textures except 4x4 linear, 4x4 srgb, 6x6 hdr, only adding one ktx2 zstd variant, and remove uastc rdo textures.

@alice-i-cecile
Copy link
Copy Markdown
Member

This PR should be remade at this point: a lot of related work has been merged, and resolving the diff and comments will be quite confusing.

@alice-i-cecile alice-i-cecile added S-Adopt-Me The original PR author has no intent to complete this work. Pick me up! and removed S-Needs-Review Needs reviewer attention (from anyone!) to move forward labels Nov 7, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-Rendering Drawing game state to the screen C-Bug An unexpected or incorrect behavior C-Dependencies A change to the crates that Bevy depends on C-Feature A new feature, making something new possible C-Performance A change motivated by improving speed, memory usage or compile times D-Modest A "normal" level of difficulty; suitable for simple features or challenging fixes D-Unsafe Touches with unsafe code in some way S-Adopt-Me The original PR author has no intent to complete this work. Pick me up!

Projects

No open projects
Status: Done

Development

Successfully merging this pull request may close these issues.

Format requires transcoding: Uastc(Rgb), this is an error in bevy_render

7 participants