Skip to content

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

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 48 commits into
base: main
Choose a base branch
from

Conversation

brianreavis
Copy link
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
Copy link
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

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
Copy link
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.

@cwfitzgerald
Copy link

Ktx2 0.4.0 is out https://github.com/BVE-Reborn/ktx2/releases/tag/v0.4.0

@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
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
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
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-Needs-Review Needs reviewer attention (from anyone!) to move forward
Projects
Status: No status
Development

Successfully merging this pull request may close these issues.

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