Update ktx2 to 0.4.0 (#19073)

# Objective

Adopted #19065
Closes #19065

Updates the requirements on [ktx2](https://github.com/BVE-Reborn/ktx2)
to permit the latest version.
- [Release notes](https://github.com/BVE-Reborn/ktx2/releases)
-
[Changelog](https://github.com/BVE-Reborn/ktx2/blob/trunk/CHANGELOG.md)
- [Commits](https://github.com/BVE-Reborn/ktx2/compare/v0.3.0...v0.4.0)

# Overview

- Some renames
- A `u8` became `NonZero<u8>`
- Some methods return a new `Level` struct with a `data` member instead
of raw level data.

# Testing

- Passed CI locally
- Ran several examples which utilize `ktx2` files: `scrolling_fog`,
`mixed_lighting`, `skybox`, `lightmaps`.

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
This commit is contained in:
Rob Parrett 2025-05-05 09:42:36 -07:00 committed by GitHub
parent ea7e868f5c
commit 831fe305e4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 38 additions and 39 deletions

View File

@ -66,7 +66,7 @@ futures-lite = "2.0.1"
guillotiere = "0.6.0" guillotiere = "0.6.0"
rectangle-pack = "0.4" rectangle-pack = "0.4"
ddsfile = { version = "0.5.2", optional = true } ddsfile = { version = "0.5.2", optional = true }
ktx2 = { version = "0.3.0", optional = true } ktx2 = { version = "0.4.0", optional = true }
# For ktx2 supercompression # For ktx2 supercompression
flate2 = { version = "1.0.22", optional = true } flate2 = { version = "1.0.22", optional = true }
ruzstd = { version = "0.8.0", optional = true } ruzstd = { version = "0.8.0", optional = true }

View File

@ -10,8 +10,8 @@ use bevy_utils::default;
#[cfg(any(feature = "flate2", feature = "ruzstd"))] #[cfg(any(feature = "flate2", feature = "ruzstd"))]
use ktx2::SupercompressionScheme; use ktx2::SupercompressionScheme;
use ktx2::{ use ktx2::{
BasicDataFormatDescriptor, ChannelTypeQualifiers, ColorModel, DataFormatDescriptorHeader, ChannelTypeQualifiers, ColorModel, DfdBlockBasic, DfdBlockHeaderBasic, DfdHeader, Header,
Header, SampleInformation, SampleInformation,
}; };
use wgpu_types::{ use wgpu_types::{
AstcBlock, AstcChannel, Extent3d, TextureDimension, TextureFormat, TextureViewDescriptor, AstcBlock, AstcChannel, Extent3d, TextureDimension, TextureFormat, TextureViewDescriptor,
@ -45,28 +45,28 @@ pub fn ktx2_buffer_to_image(
// Handle supercompression // Handle supercompression
let mut levels = Vec::new(); let mut levels = Vec::new();
if let Some(supercompression_scheme) = supercompression_scheme { if let Some(supercompression_scheme) = supercompression_scheme {
for (_level, _level_data) in ktx2.levels().enumerate() { for (level_index, level) in ktx2.levels().enumerate() {
match supercompression_scheme { match supercompression_scheme {
#[cfg(feature = "flate2")] #[cfg(feature = "flate2")]
SupercompressionScheme::ZLIB => { SupercompressionScheme::ZLIB => {
let mut decoder = flate2::bufread::ZlibDecoder::new(_level_data); let mut decoder = flate2::bufread::ZlibDecoder::new(level.data);
let mut decompressed = Vec::new(); let mut decompressed = Vec::new();
decoder.read_to_end(&mut decompressed).map_err(|err| { decoder.read_to_end(&mut decompressed).map_err(|err| {
TextureError::SuperDecompressionError(format!( TextureError::SuperDecompressionError(format!(
"Failed to decompress {supercompression_scheme:?} for mip {_level}: {err:?}", "Failed to decompress {supercompression_scheme:?} for mip {level_index}: {err:?}",
)) ))
})?; })?;
levels.push(decompressed); levels.push(decompressed);
} }
#[cfg(feature = "ruzstd")] #[cfg(feature = "ruzstd")]
SupercompressionScheme::Zstandard => { SupercompressionScheme::Zstandard => {
let mut cursor = std::io::Cursor::new(_level_data); let mut cursor = std::io::Cursor::new(level.data);
let mut decoder = ruzstd::decoding::StreamingDecoder::new(&mut cursor) let mut decoder = ruzstd::decoding::StreamingDecoder::new(&mut cursor)
.map_err(|err| TextureError::SuperDecompressionError(err.to_string()))?; .map_err(|err| TextureError::SuperDecompressionError(err.to_string()))?;
let mut decompressed = Vec::new(); let mut decompressed = Vec::new();
decoder.read_to_end(&mut decompressed).map_err(|err| { decoder.read_to_end(&mut decompressed).map_err(|err| {
TextureError::SuperDecompressionError(format!( TextureError::SuperDecompressionError(format!(
"Failed to decompress {supercompression_scheme:?} for mip {_level}: {err:?}", "Failed to decompress {supercompression_scheme:?} for mip {level_index}: {err:?}",
)) ))
})?; })?;
levels.push(decompressed); levels.push(decompressed);
@ -79,7 +79,7 @@ pub fn ktx2_buffer_to_image(
} }
} }
} else { } else {
levels = ktx2.levels().map(<[u8]>::to_vec).collect(); levels = ktx2.levels().map(|level| level.data.to_vec()).collect();
} }
// Identify the format // Identify the format
@ -397,16 +397,15 @@ pub fn ktx2_get_texture_format<Data: AsRef<[u8]>>(
return ktx2_format_to_texture_format(format, is_srgb); return ktx2_format_to_texture_format(format, is_srgb);
} }
for data_format_descriptor in ktx2.data_format_descriptors() { for data_format_descriptor in ktx2.dfd_blocks() {
if data_format_descriptor.header == DataFormatDescriptorHeader::BASIC { if data_format_descriptor.header == DfdHeader::BASIC {
let basic_data_format_descriptor = let basic_data_format_descriptor = DfdBlockBasic::parse(data_format_descriptor.data)
BasicDataFormatDescriptor::parse(data_format_descriptor.data) .map_err(|err| TextureError::InvalidData(format!("KTX2: {err:?}")))?;
.map_err(|err| TextureError::InvalidData(format!("KTX2: {err:?}")))?;
let sample_information = basic_data_format_descriptor let sample_information = basic_data_format_descriptor
.sample_information() .sample_information()
.collect::<Vec<_>>(); .collect::<Vec<_>>();
return ktx2_dfd_to_texture_format( return ktx2_dfd_header_to_texture_format(
&basic_data_format_descriptor, &basic_data_format_descriptor.header,
&sample_information, &sample_information,
is_srgb, is_srgb,
); );
@ -476,8 +475,8 @@ fn sample_information_to_data_type(
} }
#[cfg(feature = "ktx2")] #[cfg(feature = "ktx2")]
pub fn ktx2_dfd_to_texture_format( pub fn ktx2_dfd_header_to_texture_format(
data_format_descriptor: &BasicDataFormatDescriptor, data_format_descriptor: &DfdBlockHeaderBasic,
sample_information: &[SampleInformation], sample_information: &[SampleInformation],
is_srgb: bool, is_srgb: bool,
) -> Result<TextureFormat, TextureError> { ) -> Result<TextureFormat, TextureError> {
@ -495,7 +494,7 @@ pub fn ktx2_dfd_to_texture_format(
let sample = &sample_information[0]; let sample = &sample_information[0];
let data_type = sample_information_to_data_type(sample, false)?; let data_type = sample_information_to_data_type(sample, false)?;
match sample.bit_length { match sample.bit_length.get() {
8 => match data_type { 8 => match data_type {
DataType::Unorm => TextureFormat::R8Unorm, DataType::Unorm => TextureFormat::R8Unorm,
DataType::UnormSrgb => { DataType::UnormSrgb => {
@ -577,7 +576,7 @@ pub fn ktx2_dfd_to_texture_format(
let sample = &sample_information[0]; let sample = &sample_information[0];
let data_type = sample_information_to_data_type(sample, false)?; let data_type = sample_information_to_data_type(sample, false)?;
match sample.bit_length { match sample.bit_length.get() {
8 => match data_type { 8 => match data_type {
DataType::Unorm => TextureFormat::Rg8Unorm, DataType::Unorm => TextureFormat::Rg8Unorm,
DataType::UnormSrgb => { DataType::UnormSrgb => {
@ -635,27 +634,27 @@ pub fn ktx2_dfd_to_texture_format(
} }
3 => { 3 => {
if sample_information[0].channel_type == 0 if sample_information[0].channel_type == 0
&& sample_information[0].bit_length == 11 && sample_information[0].bit_length.get() == 11
&& sample_information[1].channel_type == 1 && sample_information[1].channel_type == 1
&& sample_information[1].bit_length == 11 && sample_information[1].bit_length.get() == 11
&& sample_information[2].channel_type == 2 && sample_information[2].channel_type == 2
&& sample_information[2].bit_length == 10 && sample_information[2].bit_length.get() == 10
{ {
TextureFormat::Rg11b10Ufloat TextureFormat::Rg11b10Ufloat
} else if sample_information[0].channel_type == 0 } else if sample_information[0].channel_type == 0
&& sample_information[0].bit_length == 9 && sample_information[0].bit_length.get() == 9
&& sample_information[1].channel_type == 1 && sample_information[1].channel_type == 1
&& sample_information[1].bit_length == 9 && sample_information[1].bit_length.get() == 9
&& sample_information[2].channel_type == 2 && sample_information[2].channel_type == 2
&& sample_information[2].bit_length == 9 && sample_information[2].bit_length.get() == 9
{ {
TextureFormat::Rgb9e5Ufloat TextureFormat::Rgb9e5Ufloat
} else if sample_information[0].channel_type == 0 } else if sample_information[0].channel_type == 0
&& sample_information[0].bit_length == 8 && sample_information[0].bit_length.get() == 8
&& sample_information[1].channel_type == 1 && sample_information[1].channel_type == 1
&& sample_information[1].bit_length == 8 && sample_information[1].bit_length.get() == 8
&& sample_information[2].channel_type == 2 && sample_information[2].channel_type == 2
&& sample_information[2].bit_length == 8 && sample_information[2].bit_length.get() == 8
{ {
return Err(TextureError::FormatRequiresTranscodingError( return Err(TextureError::FormatRequiresTranscodingError(
TranscodeFormat::Rgb8, TranscodeFormat::Rgb8,
@ -681,10 +680,10 @@ pub fn ktx2_dfd_to_texture_format(
assert_eq!(sample_information[3].channel_type, 15); assert_eq!(sample_information[3].channel_type, 15);
// Handle one special packed format // Handle one special packed format
if sample_information[0].bit_length == 10 if sample_information[0].bit_length.get() == 10
&& sample_information[1].bit_length == 10 && sample_information[1].bit_length.get() == 10
&& sample_information[2].bit_length == 10 && sample_information[2].bit_length.get() == 10
&& sample_information[3].bit_length == 2 && sample_information[3].bit_length.get() == 2
{ {
return Ok(TextureFormat::Rgb10a2Unorm); return Ok(TextureFormat::Rgb10a2Unorm);
} }
@ -708,7 +707,7 @@ pub fn ktx2_dfd_to_texture_format(
let sample = &sample_information[0]; let sample = &sample_information[0];
let data_type = sample_information_to_data_type(sample, is_srgb)?; let data_type = sample_information_to_data_type(sample, is_srgb)?;
match sample.bit_length { match sample.bit_length.get() {
8 => match data_type { 8 => match data_type {
DataType::Unorm => { DataType::Unorm => {
if is_rgba { if is_rgba {
@ -896,7 +895,7 @@ pub fn ktx2_dfd_to_texture_format(
Some(ColorModel::XYZW) => { Some(ColorModel::XYZW) => {
// Same number of channels in both texel block dimensions and sample info descriptions // Same number of channels in both texel block dimensions and sample info descriptions
assert_eq!( assert_eq!(
data_format_descriptor.texel_block_dimensions[0] as usize, data_format_descriptor.texel_block_dimensions[0].get() as usize,
sample_information.len() sample_information.len()
); );
match sample_information.len() { match sample_information.len() {
@ -935,7 +934,7 @@ pub fn ktx2_dfd_to_texture_format(
let sample = &sample_information[0]; let sample = &sample_information[0];
let data_type = sample_information_to_data_type(sample, false)?; let data_type = sample_information_to_data_type(sample, false)?;
match sample.bit_length { match sample.bit_length.get() {
8 => match data_type { 8 => match data_type {
DataType::Unorm => TextureFormat::Rgba8Unorm, DataType::Unorm => TextureFormat::Rgba8Unorm,
DataType::UnormSrgb => { DataType::UnormSrgb => {
@ -1124,8 +1123,8 @@ pub fn ktx2_dfd_to_texture_format(
}, },
Some(ColorModel::ASTC) => TextureFormat::Astc { Some(ColorModel::ASTC) => TextureFormat::Astc {
block: match ( block: match (
data_format_descriptor.texel_block_dimensions[0], data_format_descriptor.texel_block_dimensions[0].get(),
data_format_descriptor.texel_block_dimensions[1], data_format_descriptor.texel_block_dimensions[1].get(),
) { ) {
(4, 4) => AstcBlock::B4x4, (4, 4) => AstcBlock::B4x4,
(5, 4) => AstcBlock::B5x4, (5, 4) => AstcBlock::B5x4,

View File

@ -97,7 +97,7 @@ downcast-rs = { version = "2", default-features = false, features = ["std"] }
thiserror = { version = "2", default-features = false } thiserror = { version = "2", default-features = false }
derive_more = { version = "1", default-features = false, features = ["from"] } derive_more = { version = "1", default-features = false, features = ["from"] }
futures-lite = "2.0.1" futures-lite = "2.0.1"
ktx2 = { version = "0.3.0", optional = true } ktx2 = { version = "0.4.0", optional = true }
encase = { version = "0.10", features = ["glam"] } encase = { version = "0.10", features = ["glam"] }
# For wgpu profiling using tracing. Use `RUST_LOG=info` to also capture the wgpu spans. # For wgpu profiling using tracing. Use `RUST_LOG=info` to also capture the wgpu spans.
profiling = { version = "1", features = [ profiling = { version = "1", features = [