bevy/crates/bevy_image/src/ktx2.rs

1529 lines
67 KiB
Rust
Raw Normal View History

#[cfg(any(feature = "flate2", feature = "ruzstd"))]
use std::io::Read;
#[cfg(feature = "basis-universal")]
use basis_universal::{
DecodeFlags, LowLevelUastcTranscoder, SliceParametersUastc, TranscoderBlockFormat,
};
Made `bevy_color` a dependency of `bevy_render` (#12105) # Objective - Fixes #12068 ## Solution - Split `bevy_render::color::colorspace` across the various space implementations in `bevy_color` as appropriate. - Moved `From` implementations involving `bevy_render::color::LegacyColor` into `bevy_render::color` ## Migration Guide ### `bevy_render::color::colorspace::SrgbColorSpace::<f32>::linear_to_nonlinear_srgb` Use `bevy_color::color::gamma_function_inverse` ### `bevy_render::color::colorspace::SrgbColorSpace::<f32>::nonlinear_to_linear_srgb` Use `bevy_color::color::gamma_function` ### `bevy_render::color::colorspace::SrgbColorSpace::<u8>::linear_to_nonlinear_srgb` Modify the `u8` value to instead be an `f32` (`|x| x as f32 / 255.`), use `bevy_color::color::gamma_function_inverse`, and back again. ### `bevy_render::color::colorspace::SrgbColorSpace::<u8>::nonlinear_to_linear_srgb` Modify the `u8` value to instead be an `f32` (`|x| x as f32 / 255.`), use `bevy_color::color::gamma_function`, and back again. ### `bevy_render::color::colorspace::HslRepresentation::hsl_to_nonlinear_srgb` Use `Hsla`'s implementation of `Into<Srgba>` ### `bevy_render::color::colorspace::HslRepresentation::nonlinear_srgb_to_hsl` Use `Srgba`'s implementation of `Into<Hsla>` ### `bevy_render::color::colorspace::LchRepresentation::lch_to_nonlinear_srgb` Use `Lcha`'s implementation of `Into<Srgba>` ### `bevy_render::color::colorspace::LchRepresentation::nonlinear_srgb_to_lch` Use `Srgba`'s implementation of `Into<Lcha>`
2024-02-25 22:35:00 +00:00
use bevy_color::Srgba;
Support array / cubemap / cubemap array textures in KTX2 (#5325) # Objective - Fix / support KTX2 array / cubemap / cubemap array textures - Fixes #4495 . Supersedes #4514 . ## Solution - Add `Option<TextureViewDescriptor>` to `Image` to enable configuration of the `TextureViewDimension` of a texture. - This allows users to set `D2Array`, `D3`, `Cube`, `CubeArray` or whatever they need - Automatically configure this when loading KTX2 - Transcode all layers and faces instead of just one - Use the UASTC block size of 128 bits, and the number of blocks in x/y for a given mip level in order to determine the offset of the layer and face within the KTX2 mip level data - `wgpu` wants data ordered as layer 0 mip 0..n, layer 1 mip 0..n, etc. See https://docs.rs/wgpu/latest/wgpu/util/trait.DeviceExt.html#tymethod.create_texture_with_data - Reorder the data KTX2 mip X layer Y face Z to `wgpu` layer Y face Z mip X order - Add a `skybox` example to demonstrate / test loading cubemaps from PNG and KTX2, including ASTC 4x4, BC7, and ETC2 compression for support everywhere. Note that you need to enable the `ktx2,zstd` features to be able to load the compressed textures. --- ## Changelog - Fixed: KTX2 array / cubemap / cubemap array textures - Fixes: Validation failure for compressed textures stored in KTX2 where the width/height are not a multiple of the block dimensions. - Added: `Image` now has an `Option<TextureViewDescriptor>` field to enable configuration of the texture view. This is useful for configuring the `TextureViewDimension` when it is not just a plain 2D texture and the loader could/did not identify what it should be. Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2022-07-30 07:02:58 +00:00
use bevy_utils::default;
#[cfg(any(feature = "flate2", feature = "ruzstd"))]
use ktx2::SupercompressionScheme;
use ktx2::{
BasicDataFormatDescriptor, ChannelTypeQualifiers, ColorModel, DataFormatDescriptorHeader,
Header, SampleInformation,
};
use wgpu::TextureViewDescriptor;
use wgpu_types::{
AstcBlock, AstcChannel, Extent3d, TextureDimension, TextureFormat, TextureViewDimension,
Support array / cubemap / cubemap array textures in KTX2 (#5325) # Objective - Fix / support KTX2 array / cubemap / cubemap array textures - Fixes #4495 . Supersedes #4514 . ## Solution - Add `Option<TextureViewDescriptor>` to `Image` to enable configuration of the `TextureViewDimension` of a texture. - This allows users to set `D2Array`, `D3`, `Cube`, `CubeArray` or whatever they need - Automatically configure this when loading KTX2 - Transcode all layers and faces instead of just one - Use the UASTC block size of 128 bits, and the number of blocks in x/y for a given mip level in order to determine the offset of the layer and face within the KTX2 mip level data - `wgpu` wants data ordered as layer 0 mip 0..n, layer 1 mip 0..n, etc. See https://docs.rs/wgpu/latest/wgpu/util/trait.DeviceExt.html#tymethod.create_texture_with_data - Reorder the data KTX2 mip X layer Y face Z to `wgpu` layer Y face Z mip X order - Add a `skybox` example to demonstrate / test loading cubemaps from PNG and KTX2, including ASTC 4x4, BC7, and ETC2 compression for support everywhere. Note that you need to enable the `ktx2,zstd` features to be able to load the compressed textures. --- ## Changelog - Fixed: KTX2 array / cubemap / cubemap array textures - Fixes: Validation failure for compressed textures stored in KTX2 where the width/height are not a multiple of the block dimensions. - Added: `Image` now has an `Option<TextureViewDescriptor>` field to enable configuration of the texture view. This is useful for configuring the `TextureViewDimension` when it is not just a plain 2D texture and the loader could/did not identify what it should be. Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2022-07-30 07:02:58 +00:00
};
use super::{CompressedImageFormats, DataFormat, Image, TextureError, TranscodeFormat};
#[cfg(feature = "ktx2")]
pub fn ktx2_buffer_to_image(
buffer: &[u8],
supported_compressed_formats: CompressedImageFormats,
is_srgb: bool,
) -> Result<Image, TextureError> {
let ktx2 = ktx2::Reader::new(buffer)
.map_err(|err| TextureError::InvalidData(format!("Failed to parse ktx2 file: {err:?}")))?;
let Header {
pixel_width: width,
pixel_height: height,
pixel_depth: depth,
layer_count,
Support array / cubemap / cubemap array textures in KTX2 (#5325) # Objective - Fix / support KTX2 array / cubemap / cubemap array textures - Fixes #4495 . Supersedes #4514 . ## Solution - Add `Option<TextureViewDescriptor>` to `Image` to enable configuration of the `TextureViewDimension` of a texture. - This allows users to set `D2Array`, `D3`, `Cube`, `CubeArray` or whatever they need - Automatically configure this when loading KTX2 - Transcode all layers and faces instead of just one - Use the UASTC block size of 128 bits, and the number of blocks in x/y for a given mip level in order to determine the offset of the layer and face within the KTX2 mip level data - `wgpu` wants data ordered as layer 0 mip 0..n, layer 1 mip 0..n, etc. See https://docs.rs/wgpu/latest/wgpu/util/trait.DeviceExt.html#tymethod.create_texture_with_data - Reorder the data KTX2 mip X layer Y face Z to `wgpu` layer Y face Z mip X order - Add a `skybox` example to demonstrate / test loading cubemaps from PNG and KTX2, including ASTC 4x4, BC7, and ETC2 compression for support everywhere. Note that you need to enable the `ktx2,zstd` features to be able to load the compressed textures. --- ## Changelog - Fixed: KTX2 array / cubemap / cubemap array textures - Fixes: Validation failure for compressed textures stored in KTX2 where the width/height are not a multiple of the block dimensions. - Added: `Image` now has an `Option<TextureViewDescriptor>` field to enable configuration of the texture view. This is useful for configuring the `TextureViewDimension` when it is not just a plain 2D texture and the loader could/did not identify what it should be. Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2022-07-30 07:02:58 +00:00
face_count,
level_count,
supercompression_scheme,
..
} = ktx2.header();
Support array / cubemap / cubemap array textures in KTX2 (#5325) # Objective - Fix / support KTX2 array / cubemap / cubemap array textures - Fixes #4495 . Supersedes #4514 . ## Solution - Add `Option<TextureViewDescriptor>` to `Image` to enable configuration of the `TextureViewDimension` of a texture. - This allows users to set `D2Array`, `D3`, `Cube`, `CubeArray` or whatever they need - Automatically configure this when loading KTX2 - Transcode all layers and faces instead of just one - Use the UASTC block size of 128 bits, and the number of blocks in x/y for a given mip level in order to determine the offset of the layer and face within the KTX2 mip level data - `wgpu` wants data ordered as layer 0 mip 0..n, layer 1 mip 0..n, etc. See https://docs.rs/wgpu/latest/wgpu/util/trait.DeviceExt.html#tymethod.create_texture_with_data - Reorder the data KTX2 mip X layer Y face Z to `wgpu` layer Y face Z mip X order - Add a `skybox` example to demonstrate / test loading cubemaps from PNG and KTX2, including ASTC 4x4, BC7, and ETC2 compression for support everywhere. Note that you need to enable the `ktx2,zstd` features to be able to load the compressed textures. --- ## Changelog - Fixed: KTX2 array / cubemap / cubemap array textures - Fixes: Validation failure for compressed textures stored in KTX2 where the width/height are not a multiple of the block dimensions. - Added: `Image` now has an `Option<TextureViewDescriptor>` field to enable configuration of the texture view. This is useful for configuring the `TextureViewDimension` when it is not just a plain 2D texture and the loader could/did not identify what it should be. Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2022-07-30 07:02:58 +00:00
let layer_count = layer_count.max(1);
let face_count = face_count.max(1);
let depth = depth.max(1);
// Handle supercompression
let mut levels = Vec::new();
if let Some(supercompression_scheme) = supercompression_scheme {
for (_level, _level_data) in ktx2.levels().enumerate() {
match supercompression_scheme {
#[cfg(feature = "flate2")]
SupercompressionScheme::ZLIB => {
let mut decoder = flate2::bufread::ZlibDecoder::new(_level_data);
let mut decompressed = Vec::new();
decoder.read_to_end(&mut decompressed).map_err(|err| {
TextureError::SuperDecompressionError(format!(
"Failed to decompress {supercompression_scheme:?} for mip {_level}: {err:?}",
))
})?;
levels.push(decompressed);
}
#[cfg(feature = "ruzstd")]
SupercompressionScheme::Zstandard => {
let mut cursor = std::io::Cursor::new(_level_data);
let mut decoder = ruzstd::StreamingDecoder::new(&mut cursor)
.map_err(|err| TextureError::SuperDecompressionError(err.to_string()))?;
let mut decompressed = Vec::new();
decoder.read_to_end(&mut decompressed).map_err(|err| {
TextureError::SuperDecompressionError(format!(
"Failed to decompress {supercompression_scheme:?} for mip {_level}: {err:?}",
))
})?;
levels.push(decompressed);
}
_ => {
return Err(TextureError::SuperDecompressionError(format!(
"Unsupported supercompression scheme: {supercompression_scheme:?}",
)));
}
}
}
} else {
levels = ktx2.levels().map(<[u8]>::to_vec).collect();
}
// Identify the format
let texture_format = ktx2_get_texture_format(&ktx2, is_srgb).or_else(|error| match error {
// Transcode if needed and supported
TextureError::FormatRequiresTranscodingError(transcode_format) => {
Support array / cubemap / cubemap array textures in KTX2 (#5325) # Objective - Fix / support KTX2 array / cubemap / cubemap array textures - Fixes #4495 . Supersedes #4514 . ## Solution - Add `Option<TextureViewDescriptor>` to `Image` to enable configuration of the `TextureViewDimension` of a texture. - This allows users to set `D2Array`, `D3`, `Cube`, `CubeArray` or whatever they need - Automatically configure this when loading KTX2 - Transcode all layers and faces instead of just one - Use the UASTC block size of 128 bits, and the number of blocks in x/y for a given mip level in order to determine the offset of the layer and face within the KTX2 mip level data - `wgpu` wants data ordered as layer 0 mip 0..n, layer 1 mip 0..n, etc. See https://docs.rs/wgpu/latest/wgpu/util/trait.DeviceExt.html#tymethod.create_texture_with_data - Reorder the data KTX2 mip X layer Y face Z to `wgpu` layer Y face Z mip X order - Add a `skybox` example to demonstrate / test loading cubemaps from PNG and KTX2, including ASTC 4x4, BC7, and ETC2 compression for support everywhere. Note that you need to enable the `ktx2,zstd` features to be able to load the compressed textures. --- ## Changelog - Fixed: KTX2 array / cubemap / cubemap array textures - Fixes: Validation failure for compressed textures stored in KTX2 where the width/height are not a multiple of the block dimensions. - Added: `Image` now has an `Option<TextureViewDescriptor>` field to enable configuration of the texture view. This is useful for configuring the `TextureViewDimension` when it is not just a plain 2D texture and the loader could/did not identify what it should be. Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2022-07-30 07:02:58 +00:00
let mut transcoded = vec![Vec::default(); levels.len()];
let texture_format = match transcode_format {
TranscodeFormat::R8UnormSrgb => {
let (mut original_width, mut original_height) = (width, height);
for (level, level_data) in levels.iter().enumerate() {
transcoded[level] = level_data
.iter()
.copied()
.map(|v| (Srgba::gamma_function(v as f32 / 255.) * 255.).floor() as u8)
.collect::<Vec<u8>>();
// Next mip dimensions are half the current, minimum 1x1
original_width = (original_width / 2).max(1);
original_height = (original_height / 2).max(1);
}
TextureFormat::R8Unorm
}
TranscodeFormat::Rg8UnormSrgb => {
let (mut original_width, mut original_height) = (width, height);
for (level, level_data) in levels.iter().enumerate() {
transcoded[level] = level_data
.iter()
.copied()
.map(|v| (Srgba::gamma_function(v as f32 / 255.) * 255.).floor() as u8)
.collect::<Vec<u8>>();
// Next mip dimensions are half the current, minimum 1x1
original_width = (original_width / 2).max(1);
original_height = (original_height / 2).max(1);
}
TextureFormat::Rg8Unorm
}
TranscodeFormat::Rgb8 => {
Support array / cubemap / cubemap array textures in KTX2 (#5325) # Objective - Fix / support KTX2 array / cubemap / cubemap array textures - Fixes #4495 . Supersedes #4514 . ## Solution - Add `Option<TextureViewDescriptor>` to `Image` to enable configuration of the `TextureViewDimension` of a texture. - This allows users to set `D2Array`, `D3`, `Cube`, `CubeArray` or whatever they need - Automatically configure this when loading KTX2 - Transcode all layers and faces instead of just one - Use the UASTC block size of 128 bits, and the number of blocks in x/y for a given mip level in order to determine the offset of the layer and face within the KTX2 mip level data - `wgpu` wants data ordered as layer 0 mip 0..n, layer 1 mip 0..n, etc. See https://docs.rs/wgpu/latest/wgpu/util/trait.DeviceExt.html#tymethod.create_texture_with_data - Reorder the data KTX2 mip X layer Y face Z to `wgpu` layer Y face Z mip X order - Add a `skybox` example to demonstrate / test loading cubemaps from PNG and KTX2, including ASTC 4x4, BC7, and ETC2 compression for support everywhere. Note that you need to enable the `ktx2,zstd` features to be able to load the compressed textures. --- ## Changelog - Fixed: KTX2 array / cubemap / cubemap array textures - Fixes: Validation failure for compressed textures stored in KTX2 where the width/height are not a multiple of the block dimensions. - Added: `Image` now has an `Option<TextureViewDescriptor>` field to enable configuration of the texture view. This is useful for configuring the `TextureViewDimension` when it is not just a plain 2D texture and the loader could/did not identify what it should be. Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2022-07-30 07:02:58 +00:00
let mut rgba = vec![255u8; width as usize * height as usize * 4];
for (level, level_data) in levels.iter().enumerate() {
let n_pixels = (width as usize >> level).max(1) * (height as usize >> level).max(1);
Support array / cubemap / cubemap array textures in KTX2 (#5325) # Objective - Fix / support KTX2 array / cubemap / cubemap array textures - Fixes #4495 . Supersedes #4514 . ## Solution - Add `Option<TextureViewDescriptor>` to `Image` to enable configuration of the `TextureViewDimension` of a texture. - This allows users to set `D2Array`, `D3`, `Cube`, `CubeArray` or whatever they need - Automatically configure this when loading KTX2 - Transcode all layers and faces instead of just one - Use the UASTC block size of 128 bits, and the number of blocks in x/y for a given mip level in order to determine the offset of the layer and face within the KTX2 mip level data - `wgpu` wants data ordered as layer 0 mip 0..n, layer 1 mip 0..n, etc. See https://docs.rs/wgpu/latest/wgpu/util/trait.DeviceExt.html#tymethod.create_texture_with_data - Reorder the data KTX2 mip X layer Y face Z to `wgpu` layer Y face Z mip X order - Add a `skybox` example to demonstrate / test loading cubemaps from PNG and KTX2, including ASTC 4x4, BC7, and ETC2 compression for support everywhere. Note that you need to enable the `ktx2,zstd` features to be able to load the compressed textures. --- ## Changelog - Fixed: KTX2 array / cubemap / cubemap array textures - Fixes: Validation failure for compressed textures stored in KTX2 where the width/height are not a multiple of the block dimensions. - Added: `Image` now has an `Option<TextureViewDescriptor>` field to enable configuration of the texture view. This is useful for configuring the `TextureViewDimension` when it is not just a plain 2D texture and the loader could/did not identify what it should be. Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2022-07-30 07:02:58 +00:00
let mut offset = 0;
for _layer in 0..layer_count {
for _face in 0..face_count {
for i in 0..n_pixels {
rgba[i * 4] = level_data[offset];
rgba[i * 4 + 1] = level_data[offset + 1];
rgba[i * 4 + 2] = level_data[offset + 2];
offset += 3;
}
transcoded[level].extend_from_slice(&rgba[0..n_pixels * 4]);
Support array / cubemap / cubemap array textures in KTX2 (#5325) # Objective - Fix / support KTX2 array / cubemap / cubemap array textures - Fixes #4495 . Supersedes #4514 . ## Solution - Add `Option<TextureViewDescriptor>` to `Image` to enable configuration of the `TextureViewDimension` of a texture. - This allows users to set `D2Array`, `D3`, `Cube`, `CubeArray` or whatever they need - Automatically configure this when loading KTX2 - Transcode all layers and faces instead of just one - Use the UASTC block size of 128 bits, and the number of blocks in x/y for a given mip level in order to determine the offset of the layer and face within the KTX2 mip level data - `wgpu` wants data ordered as layer 0 mip 0..n, layer 1 mip 0..n, etc. See https://docs.rs/wgpu/latest/wgpu/util/trait.DeviceExt.html#tymethod.create_texture_with_data - Reorder the data KTX2 mip X layer Y face Z to `wgpu` layer Y face Z mip X order - Add a `skybox` example to demonstrate / test loading cubemaps from PNG and KTX2, including ASTC 4x4, BC7, and ETC2 compression for support everywhere. Note that you need to enable the `ktx2,zstd` features to be able to load the compressed textures. --- ## Changelog - Fixed: KTX2 array / cubemap / cubemap array textures - Fixes: Validation failure for compressed textures stored in KTX2 where the width/height are not a multiple of the block dimensions. - Added: `Image` now has an `Option<TextureViewDescriptor>` field to enable configuration of the texture view. This is useful for configuring the `TextureViewDimension` when it is not just a plain 2D texture and the loader could/did not identify what it should be. Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2022-07-30 07:02:58 +00:00
}
}
}
if is_srgb {
TextureFormat::Rgba8UnormSrgb
} else {
TextureFormat::Rgba8Unorm
}
}
#[cfg(feature = "basis-universal")]
TranscodeFormat::Uastc(data_format) => {
let (transcode_block_format, texture_format) =
get_transcoded_formats(supported_compressed_formats, data_format, is_srgb);
let texture_format_info = texture_format;
Support array / cubemap / cubemap array textures in KTX2 (#5325) # Objective - Fix / support KTX2 array / cubemap / cubemap array textures - Fixes #4495 . Supersedes #4514 . ## Solution - Add `Option<TextureViewDescriptor>` to `Image` to enable configuration of the `TextureViewDimension` of a texture. - This allows users to set `D2Array`, `D3`, `Cube`, `CubeArray` or whatever they need - Automatically configure this when loading KTX2 - Transcode all layers and faces instead of just one - Use the UASTC block size of 128 bits, and the number of blocks in x/y for a given mip level in order to determine the offset of the layer and face within the KTX2 mip level data - `wgpu` wants data ordered as layer 0 mip 0..n, layer 1 mip 0..n, etc. See https://docs.rs/wgpu/latest/wgpu/util/trait.DeviceExt.html#tymethod.create_texture_with_data - Reorder the data KTX2 mip X layer Y face Z to `wgpu` layer Y face Z mip X order - Add a `skybox` example to demonstrate / test loading cubemaps from PNG and KTX2, including ASTC 4x4, BC7, and ETC2 compression for support everywhere. Note that you need to enable the `ktx2,zstd` features to be able to load the compressed textures. --- ## Changelog - Fixed: KTX2 array / cubemap / cubemap array textures - Fixes: Validation failure for compressed textures stored in KTX2 where the width/height are not a multiple of the block dimensions. - Added: `Image` now has an `Option<TextureViewDescriptor>` field to enable configuration of the texture view. This is useful for configuring the `TextureViewDimension` when it is not just a plain 2D texture and the loader could/did not identify what it should be. Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2022-07-30 07:02:58 +00:00
let (block_width_pixels, block_height_pixels) = (
texture_format_info.block_dimensions().0,
texture_format_info.block_dimensions().1,
Support array / cubemap / cubemap array textures in KTX2 (#5325) # Objective - Fix / support KTX2 array / cubemap / cubemap array textures - Fixes #4495 . Supersedes #4514 . ## Solution - Add `Option<TextureViewDescriptor>` to `Image` to enable configuration of the `TextureViewDimension` of a texture. - This allows users to set `D2Array`, `D3`, `Cube`, `CubeArray` or whatever they need - Automatically configure this when loading KTX2 - Transcode all layers and faces instead of just one - Use the UASTC block size of 128 bits, and the number of blocks in x/y for a given mip level in order to determine the offset of the layer and face within the KTX2 mip level data - `wgpu` wants data ordered as layer 0 mip 0..n, layer 1 mip 0..n, etc. See https://docs.rs/wgpu/latest/wgpu/util/trait.DeviceExt.html#tymethod.create_texture_with_data - Reorder the data KTX2 mip X layer Y face Z to `wgpu` layer Y face Z mip X order - Add a `skybox` example to demonstrate / test loading cubemaps from PNG and KTX2, including ASTC 4x4, BC7, and ETC2 compression for support everywhere. Note that you need to enable the `ktx2,zstd` features to be able to load the compressed textures. --- ## Changelog - Fixed: KTX2 array / cubemap / cubemap array textures - Fixes: Validation failure for compressed textures stored in KTX2 where the width/height are not a multiple of the block dimensions. - Added: `Image` now has an `Option<TextureViewDescriptor>` field to enable configuration of the texture view. This is useful for configuring the `TextureViewDimension` when it is not just a plain 2D texture and the loader could/did not identify what it should be. Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2022-07-30 07:02:58 +00:00
);
// Texture is not a depth or stencil format, it is possible to pass `None` and unwrap
Update to wgpu 0.19 and raw-window-handle 0.6 (#11280) # Objective Keep core dependencies up to date. ## Solution Update the dependencies. wgpu 0.19 only supports raw-window-handle (rwh) 0.6, so bumping that was included in this. The rwh 0.6 version bump is just the simplest way of doing it. There might be a way we can take advantage of wgpu's new safe surface creation api, but I'm not familiar enough with bevy's window management to untangle it and my attempt ended up being a mess of lifetimes and rustc complaining about missing trait impls (that were implemented). Thanks to @MiniaczQ for the (much simpler) rwh 0.6 version bump code. Unblocks https://github.com/bevyengine/bevy/pull/9172 and https://github.com/bevyengine/bevy/pull/10812 ~~This might be blocked on cpal and oboe updating their ndk versions to 0.8, as they both currently target ndk 0.7 which uses rwh 0.5.2~~ Tested on android, and everything seems to work correctly (audio properly stops when minimized, and plays when re-focusing the app). --- ## Changelog - `wgpu` has been updated to 0.19! The long awaited arcanization has been merged (for more info, see https://gfx-rs.github.io/2023/11/24/arcanization.html), and Vulkan should now be working again on Intel GPUs. - Targeting WebGPU now requires that you add the new `webgpu` feature (setting the `RUSTFLAGS` environment variable to `--cfg=web_sys_unstable_apis` is still required). This feature currently overrides the `webgl2` feature if you have both enabled (the `webgl2` feature is enabled by default), so it is not recommended to add it as a default feature to libraries without putting it behind a flag that allows library users to opt out of it! In the future we plan on supporting wasm binaries that can target both webgl2 and webgpu now that wgpu added support for doing so (see https://github.com/bevyengine/bevy/issues/11505). - `raw-window-handle` has been updated to version 0.6. ## Migration Guide - `bevy_render::instance_index::get_instance_index()` has been removed as the webgl2 workaround is no longer required as it was fixed upstream in wgpu. The `BASE_INSTANCE_WORKAROUND` shaderdef has also been removed. - WebGPU now requires the new `webgpu` feature to be enabled. The `webgpu` feature currently overrides the `webgl2` feature so you no longer need to disable all default features and re-add them all when targeting `webgpu`, but binaries built with both the `webgpu` and `webgl2` features will only target the webgpu backend, and will only work on browsers that support WebGPU. - Places where you conditionally compiled things for webgl2 need to be updated because of this change, eg: - `#[cfg(any(not(feature = "webgl"), not(target_arch = "wasm32")))]` becomes `#[cfg(any(not(feature = "webgl") ,not(target_arch = "wasm32"), feature = "webgpu"))]` - `#[cfg(all(feature = "webgl", target_arch = "wasm32"))]` becomes `#[cfg(all(feature = "webgl", target_arch = "wasm32", not(feature = "webgpu")))]` - `if cfg!(all(feature = "webgl", target_arch = "wasm32"))` becomes `if cfg!(all(feature = "webgl", target_arch = "wasm32", not(feature = "webgpu")))` - `create_texture_with_data` now also takes a `TextureDataOrder`. You can probably just set this to `TextureDataOrder::default()` - `TextureFormat`'s `block_size` has been renamed to `block_copy_size` - See the `wgpu` changelog for anything I might've missed: https://github.com/gfx-rs/wgpu/blob/trunk/CHANGELOG.md --------- Co-authored-by: François <mockersf@gmail.com>
2024-01-26 18:14:21 +00:00
let block_bytes = texture_format_info.block_copy_size(None).unwrap();
let transcoder = LowLevelUastcTranscoder::new();
for (level, level_data) in levels.iter().enumerate() {
Support array / cubemap / cubemap array textures in KTX2 (#5325) # Objective - Fix / support KTX2 array / cubemap / cubemap array textures - Fixes #4495 . Supersedes #4514 . ## Solution - Add `Option<TextureViewDescriptor>` to `Image` to enable configuration of the `TextureViewDimension` of a texture. - This allows users to set `D2Array`, `D3`, `Cube`, `CubeArray` or whatever they need - Automatically configure this when loading KTX2 - Transcode all layers and faces instead of just one - Use the UASTC block size of 128 bits, and the number of blocks in x/y for a given mip level in order to determine the offset of the layer and face within the KTX2 mip level data - `wgpu` wants data ordered as layer 0 mip 0..n, layer 1 mip 0..n, etc. See https://docs.rs/wgpu/latest/wgpu/util/trait.DeviceExt.html#tymethod.create_texture_with_data - Reorder the data KTX2 mip X layer Y face Z to `wgpu` layer Y face Z mip X order - Add a `skybox` example to demonstrate / test loading cubemaps from PNG and KTX2, including ASTC 4x4, BC7, and ETC2 compression for support everywhere. Note that you need to enable the `ktx2,zstd` features to be able to load the compressed textures. --- ## Changelog - Fixed: KTX2 array / cubemap / cubemap array textures - Fixes: Validation failure for compressed textures stored in KTX2 where the width/height are not a multiple of the block dimensions. - Added: `Image` now has an `Option<TextureViewDescriptor>` field to enable configuration of the texture view. This is useful for configuring the `TextureViewDimension` when it is not just a plain 2D texture and the loader could/did not identify what it should be. Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2022-07-30 07:02:58 +00:00
let (level_width, level_height) = (
(width >> level as u32).max(1),
(height >> level as u32).max(1),
);
let (num_blocks_x, num_blocks_y) = (
level_width.div_ceil(block_width_pixels) .max(1),
level_height.div_ceil(block_height_pixels) .max(1),
Support array / cubemap / cubemap array textures in KTX2 (#5325) # Objective - Fix / support KTX2 array / cubemap / cubemap array textures - Fixes #4495 . Supersedes #4514 . ## Solution - Add `Option<TextureViewDescriptor>` to `Image` to enable configuration of the `TextureViewDimension` of a texture. - This allows users to set `D2Array`, `D3`, `Cube`, `CubeArray` or whatever they need - Automatically configure this when loading KTX2 - Transcode all layers and faces instead of just one - Use the UASTC block size of 128 bits, and the number of blocks in x/y for a given mip level in order to determine the offset of the layer and face within the KTX2 mip level data - `wgpu` wants data ordered as layer 0 mip 0..n, layer 1 mip 0..n, etc. See https://docs.rs/wgpu/latest/wgpu/util/trait.DeviceExt.html#tymethod.create_texture_with_data - Reorder the data KTX2 mip X layer Y face Z to `wgpu` layer Y face Z mip X order - Add a `skybox` example to demonstrate / test loading cubemaps from PNG and KTX2, including ASTC 4x4, BC7, and ETC2 compression for support everywhere. Note that you need to enable the `ktx2,zstd` features to be able to load the compressed textures. --- ## Changelog - Fixed: KTX2 array / cubemap / cubemap array textures - Fixes: Validation failure for compressed textures stored in KTX2 where the width/height are not a multiple of the block dimensions. - Added: `Image` now has an `Option<TextureViewDescriptor>` field to enable configuration of the texture view. This is useful for configuring the `TextureViewDimension` when it is not just a plain 2D texture and the loader could/did not identify what it should be. Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2022-07-30 07:02:58 +00:00
);
let level_bytes = (num_blocks_x * num_blocks_y * block_bytes) as usize;
Support array / cubemap / cubemap array textures in KTX2 (#5325) # Objective - Fix / support KTX2 array / cubemap / cubemap array textures - Fixes #4495 . Supersedes #4514 . ## Solution - Add `Option<TextureViewDescriptor>` to `Image` to enable configuration of the `TextureViewDimension` of a texture. - This allows users to set `D2Array`, `D3`, `Cube`, `CubeArray` or whatever they need - Automatically configure this when loading KTX2 - Transcode all layers and faces instead of just one - Use the UASTC block size of 128 bits, and the number of blocks in x/y for a given mip level in order to determine the offset of the layer and face within the KTX2 mip level data - `wgpu` wants data ordered as layer 0 mip 0..n, layer 1 mip 0..n, etc. See https://docs.rs/wgpu/latest/wgpu/util/trait.DeviceExt.html#tymethod.create_texture_with_data - Reorder the data KTX2 mip X layer Y face Z to `wgpu` layer Y face Z mip X order - Add a `skybox` example to demonstrate / test loading cubemaps from PNG and KTX2, including ASTC 4x4, BC7, and ETC2 compression for support everywhere. Note that you need to enable the `ktx2,zstd` features to be able to load the compressed textures. --- ## Changelog - Fixed: KTX2 array / cubemap / cubemap array textures - Fixes: Validation failure for compressed textures stored in KTX2 where the width/height are not a multiple of the block dimensions. - Added: `Image` now has an `Option<TextureViewDescriptor>` field to enable configuration of the texture view. This is useful for configuring the `TextureViewDimension` when it is not just a plain 2D texture and the loader could/did not identify what it should be. Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2022-07-30 07:02:58 +00:00
let mut offset = 0;
for _layer in 0..layer_count {
for _face in 0..face_count {
// NOTE: SliceParametersUastc does not implement Clone nor Copy so
// it has to be created per use
let slice_parameters = SliceParametersUastc {
num_blocks_x,
num_blocks_y,
has_alpha: false,
original_width: level_width,
original_height: level_height,
};
transcoder
.transcode_slice(
&level_data[offset..(offset + level_bytes)],
slice_parameters,
DecodeFlags::HIGH_QUALITY,
transcode_block_format,
)
.map(|mut transcoded_level| transcoded[level].append(&mut transcoded_level))
.map_err(|error| {
TextureError::SuperDecompressionError(format!(
"Failed to transcode mip level {level} from UASTC to {transcode_block_format:?}: {error:?}",
Support array / cubemap / cubemap array textures in KTX2 (#5325) # Objective - Fix / support KTX2 array / cubemap / cubemap array textures - Fixes #4495 . Supersedes #4514 . ## Solution - Add `Option<TextureViewDescriptor>` to `Image` to enable configuration of the `TextureViewDimension` of a texture. - This allows users to set `D2Array`, `D3`, `Cube`, `CubeArray` or whatever they need - Automatically configure this when loading KTX2 - Transcode all layers and faces instead of just one - Use the UASTC block size of 128 bits, and the number of blocks in x/y for a given mip level in order to determine the offset of the layer and face within the KTX2 mip level data - `wgpu` wants data ordered as layer 0 mip 0..n, layer 1 mip 0..n, etc. See https://docs.rs/wgpu/latest/wgpu/util/trait.DeviceExt.html#tymethod.create_texture_with_data - Reorder the data KTX2 mip X layer Y face Z to `wgpu` layer Y face Z mip X order - Add a `skybox` example to demonstrate / test loading cubemaps from PNG and KTX2, including ASTC 4x4, BC7, and ETC2 compression for support everywhere. Note that you need to enable the `ktx2,zstd` features to be able to load the compressed textures. --- ## Changelog - Fixed: KTX2 array / cubemap / cubemap array textures - Fixes: Validation failure for compressed textures stored in KTX2 where the width/height are not a multiple of the block dimensions. - Added: `Image` now has an `Option<TextureViewDescriptor>` field to enable configuration of the texture view. This is useful for configuring the `TextureViewDimension` when it is not just a plain 2D texture and the loader could/did not identify what it should be. Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2022-07-30 07:02:58 +00:00
))
})?;
offset += level_bytes;
}
}
}
texture_format
}
// ETC1S is a subset of ETC1 which is a subset of ETC2
// TODO: Implement transcoding
TranscodeFormat::Etc1s => {
let texture_format = if is_srgb {
TextureFormat::Etc2Rgb8UnormSrgb
} else {
TextureFormat::Etc2Rgb8Unorm
};
if !supported_compressed_formats.supports(texture_format) {
return Err(error);
}
transcoded = levels.to_vec();
texture_format
}
#[cfg(not(feature = "basis-universal"))]
_ => return Err(error),
};
levels = transcoded;
Ok(texture_format)
}
_ => Err(error),
})?;
if !supported_compressed_formats.supports(texture_format) {
return Err(TextureError::UnsupportedTextureFormat(format!(
"Format not supported by this GPU: {texture_format:?}",
)));
}
Support array / cubemap / cubemap array textures in KTX2 (#5325) # Objective - Fix / support KTX2 array / cubemap / cubemap array textures - Fixes #4495 . Supersedes #4514 . ## Solution - Add `Option<TextureViewDescriptor>` to `Image` to enable configuration of the `TextureViewDimension` of a texture. - This allows users to set `D2Array`, `D3`, `Cube`, `CubeArray` or whatever they need - Automatically configure this when loading KTX2 - Transcode all layers and faces instead of just one - Use the UASTC block size of 128 bits, and the number of blocks in x/y for a given mip level in order to determine the offset of the layer and face within the KTX2 mip level data - `wgpu` wants data ordered as layer 0 mip 0..n, layer 1 mip 0..n, etc. See https://docs.rs/wgpu/latest/wgpu/util/trait.DeviceExt.html#tymethod.create_texture_with_data - Reorder the data KTX2 mip X layer Y face Z to `wgpu` layer Y face Z mip X order - Add a `skybox` example to demonstrate / test loading cubemaps from PNG and KTX2, including ASTC 4x4, BC7, and ETC2 compression for support everywhere. Note that you need to enable the `ktx2,zstd` features to be able to load the compressed textures. --- ## Changelog - Fixed: KTX2 array / cubemap / cubemap array textures - Fixes: Validation failure for compressed textures stored in KTX2 where the width/height are not a multiple of the block dimensions. - Added: `Image` now has an `Option<TextureViewDescriptor>` field to enable configuration of the texture view. This is useful for configuring the `TextureViewDimension` when it is not just a plain 2D texture and the loader could/did not identify what it should be. Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2022-07-30 07:02:58 +00:00
// Reorder data from KTX2 MipXLayerYFaceZ to wgpu LayerYFaceZMipX
let texture_format_info = texture_format;
Support array / cubemap / cubemap array textures in KTX2 (#5325) # Objective - Fix / support KTX2 array / cubemap / cubemap array textures - Fixes #4495 . Supersedes #4514 . ## Solution - Add `Option<TextureViewDescriptor>` to `Image` to enable configuration of the `TextureViewDimension` of a texture. - This allows users to set `D2Array`, `D3`, `Cube`, `CubeArray` or whatever they need - Automatically configure this when loading KTX2 - Transcode all layers and faces instead of just one - Use the UASTC block size of 128 bits, and the number of blocks in x/y for a given mip level in order to determine the offset of the layer and face within the KTX2 mip level data - `wgpu` wants data ordered as layer 0 mip 0..n, layer 1 mip 0..n, etc. See https://docs.rs/wgpu/latest/wgpu/util/trait.DeviceExt.html#tymethod.create_texture_with_data - Reorder the data KTX2 mip X layer Y face Z to `wgpu` layer Y face Z mip X order - Add a `skybox` example to demonstrate / test loading cubemaps from PNG and KTX2, including ASTC 4x4, BC7, and ETC2 compression for support everywhere. Note that you need to enable the `ktx2,zstd` features to be able to load the compressed textures. --- ## Changelog - Fixed: KTX2 array / cubemap / cubemap array textures - Fixes: Validation failure for compressed textures stored in KTX2 where the width/height are not a multiple of the block dimensions. - Added: `Image` now has an `Option<TextureViewDescriptor>` field to enable configuration of the texture view. This is useful for configuring the `TextureViewDimension` when it is not just a plain 2D texture and the loader could/did not identify what it should be. Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2022-07-30 07:02:58 +00:00
let (block_width_pixels, block_height_pixels) = (
texture_format_info.block_dimensions().0 as usize,
texture_format_info.block_dimensions().1 as usize,
Support array / cubemap / cubemap array textures in KTX2 (#5325) # Objective - Fix / support KTX2 array / cubemap / cubemap array textures - Fixes #4495 . Supersedes #4514 . ## Solution - Add `Option<TextureViewDescriptor>` to `Image` to enable configuration of the `TextureViewDimension` of a texture. - This allows users to set `D2Array`, `D3`, `Cube`, `CubeArray` or whatever they need - Automatically configure this when loading KTX2 - Transcode all layers and faces instead of just one - Use the UASTC block size of 128 bits, and the number of blocks in x/y for a given mip level in order to determine the offset of the layer and face within the KTX2 mip level data - `wgpu` wants data ordered as layer 0 mip 0..n, layer 1 mip 0..n, etc. See https://docs.rs/wgpu/latest/wgpu/util/trait.DeviceExt.html#tymethod.create_texture_with_data - Reorder the data KTX2 mip X layer Y face Z to `wgpu` layer Y face Z mip X order - Add a `skybox` example to demonstrate / test loading cubemaps from PNG and KTX2, including ASTC 4x4, BC7, and ETC2 compression for support everywhere. Note that you need to enable the `ktx2,zstd` features to be able to load the compressed textures. --- ## Changelog - Fixed: KTX2 array / cubemap / cubemap array textures - Fixes: Validation failure for compressed textures stored in KTX2 where the width/height are not a multiple of the block dimensions. - Added: `Image` now has an `Option<TextureViewDescriptor>` field to enable configuration of the texture view. This is useful for configuring the `TextureViewDimension` when it is not just a plain 2D texture and the loader could/did not identify what it should be. Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2022-07-30 07:02:58 +00:00
);
// Texture is not a depth or stencil format, it is possible to pass `None` and unwrap
Update to wgpu 0.19 and raw-window-handle 0.6 (#11280) # Objective Keep core dependencies up to date. ## Solution Update the dependencies. wgpu 0.19 only supports raw-window-handle (rwh) 0.6, so bumping that was included in this. The rwh 0.6 version bump is just the simplest way of doing it. There might be a way we can take advantage of wgpu's new safe surface creation api, but I'm not familiar enough with bevy's window management to untangle it and my attempt ended up being a mess of lifetimes and rustc complaining about missing trait impls (that were implemented). Thanks to @MiniaczQ for the (much simpler) rwh 0.6 version bump code. Unblocks https://github.com/bevyengine/bevy/pull/9172 and https://github.com/bevyengine/bevy/pull/10812 ~~This might be blocked on cpal and oboe updating their ndk versions to 0.8, as they both currently target ndk 0.7 which uses rwh 0.5.2~~ Tested on android, and everything seems to work correctly (audio properly stops when minimized, and plays when re-focusing the app). --- ## Changelog - `wgpu` has been updated to 0.19! The long awaited arcanization has been merged (for more info, see https://gfx-rs.github.io/2023/11/24/arcanization.html), and Vulkan should now be working again on Intel GPUs. - Targeting WebGPU now requires that you add the new `webgpu` feature (setting the `RUSTFLAGS` environment variable to `--cfg=web_sys_unstable_apis` is still required). This feature currently overrides the `webgl2` feature if you have both enabled (the `webgl2` feature is enabled by default), so it is not recommended to add it as a default feature to libraries without putting it behind a flag that allows library users to opt out of it! In the future we plan on supporting wasm binaries that can target both webgl2 and webgpu now that wgpu added support for doing so (see https://github.com/bevyengine/bevy/issues/11505). - `raw-window-handle` has been updated to version 0.6. ## Migration Guide - `bevy_render::instance_index::get_instance_index()` has been removed as the webgl2 workaround is no longer required as it was fixed upstream in wgpu. The `BASE_INSTANCE_WORKAROUND` shaderdef has also been removed. - WebGPU now requires the new `webgpu` feature to be enabled. The `webgpu` feature currently overrides the `webgl2` feature so you no longer need to disable all default features and re-add them all when targeting `webgpu`, but binaries built with both the `webgpu` and `webgl2` features will only target the webgpu backend, and will only work on browsers that support WebGPU. - Places where you conditionally compiled things for webgl2 need to be updated because of this change, eg: - `#[cfg(any(not(feature = "webgl"), not(target_arch = "wasm32")))]` becomes `#[cfg(any(not(feature = "webgl") ,not(target_arch = "wasm32"), feature = "webgpu"))]` - `#[cfg(all(feature = "webgl", target_arch = "wasm32"))]` becomes `#[cfg(all(feature = "webgl", target_arch = "wasm32", not(feature = "webgpu")))]` - `if cfg!(all(feature = "webgl", target_arch = "wasm32"))` becomes `if cfg!(all(feature = "webgl", target_arch = "wasm32", not(feature = "webgpu")))` - `create_texture_with_data` now also takes a `TextureDataOrder`. You can probably just set this to `TextureDataOrder::default()` - `TextureFormat`'s `block_size` has been renamed to `block_copy_size` - See the `wgpu` changelog for anything I might've missed: https://github.com/gfx-rs/wgpu/blob/trunk/CHANGELOG.md --------- Co-authored-by: François <mockersf@gmail.com>
2024-01-26 18:14:21 +00:00
let block_bytes = texture_format_info.block_copy_size(None).unwrap() as usize;
Support array / cubemap / cubemap array textures in KTX2 (#5325) # Objective - Fix / support KTX2 array / cubemap / cubemap array textures - Fixes #4495 . Supersedes #4514 . ## Solution - Add `Option<TextureViewDescriptor>` to `Image` to enable configuration of the `TextureViewDimension` of a texture. - This allows users to set `D2Array`, `D3`, `Cube`, `CubeArray` or whatever they need - Automatically configure this when loading KTX2 - Transcode all layers and faces instead of just one - Use the UASTC block size of 128 bits, and the number of blocks in x/y for a given mip level in order to determine the offset of the layer and face within the KTX2 mip level data - `wgpu` wants data ordered as layer 0 mip 0..n, layer 1 mip 0..n, etc. See https://docs.rs/wgpu/latest/wgpu/util/trait.DeviceExt.html#tymethod.create_texture_with_data - Reorder the data KTX2 mip X layer Y face Z to `wgpu` layer Y face Z mip X order - Add a `skybox` example to demonstrate / test loading cubemaps from PNG and KTX2, including ASTC 4x4, BC7, and ETC2 compression for support everywhere. Note that you need to enable the `ktx2,zstd` features to be able to load the compressed textures. --- ## Changelog - Fixed: KTX2 array / cubemap / cubemap array textures - Fixes: Validation failure for compressed textures stored in KTX2 where the width/height are not a multiple of the block dimensions. - Added: `Image` now has an `Option<TextureViewDescriptor>` field to enable configuration of the texture view. This is useful for configuring the `TextureViewDimension` when it is not just a plain 2D texture and the loader could/did not identify what it should be. Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2022-07-30 07:02:58 +00:00
let mut wgpu_data = vec![Vec::default(); (layer_count * face_count) as usize];
for (level, level_data) in levels.iter().enumerate() {
let (level_width, level_height, level_depth) = (
Support array / cubemap / cubemap array textures in KTX2 (#5325) # Objective - Fix / support KTX2 array / cubemap / cubemap array textures - Fixes #4495 . Supersedes #4514 . ## Solution - Add `Option<TextureViewDescriptor>` to `Image` to enable configuration of the `TextureViewDimension` of a texture. - This allows users to set `D2Array`, `D3`, `Cube`, `CubeArray` or whatever they need - Automatically configure this when loading KTX2 - Transcode all layers and faces instead of just one - Use the UASTC block size of 128 bits, and the number of blocks in x/y for a given mip level in order to determine the offset of the layer and face within the KTX2 mip level data - `wgpu` wants data ordered as layer 0 mip 0..n, layer 1 mip 0..n, etc. See https://docs.rs/wgpu/latest/wgpu/util/trait.DeviceExt.html#tymethod.create_texture_with_data - Reorder the data KTX2 mip X layer Y face Z to `wgpu` layer Y face Z mip X order - Add a `skybox` example to demonstrate / test loading cubemaps from PNG and KTX2, including ASTC 4x4, BC7, and ETC2 compression for support everywhere. Note that you need to enable the `ktx2,zstd` features to be able to load the compressed textures. --- ## Changelog - Fixed: KTX2 array / cubemap / cubemap array textures - Fixes: Validation failure for compressed textures stored in KTX2 where the width/height are not a multiple of the block dimensions. - Added: `Image` now has an `Option<TextureViewDescriptor>` field to enable configuration of the texture view. This is useful for configuring the `TextureViewDimension` when it is not just a plain 2D texture and the loader could/did not identify what it should be. Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2022-07-30 07:02:58 +00:00
(width as usize >> level).max(1),
(height as usize >> level).max(1),
(depth as usize >> level).max(1),
Support array / cubemap / cubemap array textures in KTX2 (#5325) # Objective - Fix / support KTX2 array / cubemap / cubemap array textures - Fixes #4495 . Supersedes #4514 . ## Solution - Add `Option<TextureViewDescriptor>` to `Image` to enable configuration of the `TextureViewDimension` of a texture. - This allows users to set `D2Array`, `D3`, `Cube`, `CubeArray` or whatever they need - Automatically configure this when loading KTX2 - Transcode all layers and faces instead of just one - Use the UASTC block size of 128 bits, and the number of blocks in x/y for a given mip level in order to determine the offset of the layer and face within the KTX2 mip level data - `wgpu` wants data ordered as layer 0 mip 0..n, layer 1 mip 0..n, etc. See https://docs.rs/wgpu/latest/wgpu/util/trait.DeviceExt.html#tymethod.create_texture_with_data - Reorder the data KTX2 mip X layer Y face Z to `wgpu` layer Y face Z mip X order - Add a `skybox` example to demonstrate / test loading cubemaps from PNG and KTX2, including ASTC 4x4, BC7, and ETC2 compression for support everywhere. Note that you need to enable the `ktx2,zstd` features to be able to load the compressed textures. --- ## Changelog - Fixed: KTX2 array / cubemap / cubemap array textures - Fixes: Validation failure for compressed textures stored in KTX2 where the width/height are not a multiple of the block dimensions. - Added: `Image` now has an `Option<TextureViewDescriptor>` field to enable configuration of the texture view. This is useful for configuring the `TextureViewDimension` when it is not just a plain 2D texture and the loader could/did not identify what it should be. Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2022-07-30 07:02:58 +00:00
);
let (num_blocks_x, num_blocks_y) = (
level_width.div_ceil(block_width_pixels).max(1),
level_height.div_ceil(block_height_pixels).max(1),
Support array / cubemap / cubemap array textures in KTX2 (#5325) # Objective - Fix / support KTX2 array / cubemap / cubemap array textures - Fixes #4495 . Supersedes #4514 . ## Solution - Add `Option<TextureViewDescriptor>` to `Image` to enable configuration of the `TextureViewDimension` of a texture. - This allows users to set `D2Array`, `D3`, `Cube`, `CubeArray` or whatever they need - Automatically configure this when loading KTX2 - Transcode all layers and faces instead of just one - Use the UASTC block size of 128 bits, and the number of blocks in x/y for a given mip level in order to determine the offset of the layer and face within the KTX2 mip level data - `wgpu` wants data ordered as layer 0 mip 0..n, layer 1 mip 0..n, etc. See https://docs.rs/wgpu/latest/wgpu/util/trait.DeviceExt.html#tymethod.create_texture_with_data - Reorder the data KTX2 mip X layer Y face Z to `wgpu` layer Y face Z mip X order - Add a `skybox` example to demonstrate / test loading cubemaps from PNG and KTX2, including ASTC 4x4, BC7, and ETC2 compression for support everywhere. Note that you need to enable the `ktx2,zstd` features to be able to load the compressed textures. --- ## Changelog - Fixed: KTX2 array / cubemap / cubemap array textures - Fixes: Validation failure for compressed textures stored in KTX2 where the width/height are not a multiple of the block dimensions. - Added: `Image` now has an `Option<TextureViewDescriptor>` field to enable configuration of the texture view. This is useful for configuring the `TextureViewDimension` when it is not just a plain 2D texture and the loader could/did not identify what it should be. Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2022-07-30 07:02:58 +00:00
);
let level_bytes = num_blocks_x * num_blocks_y * level_depth * block_bytes;
Support array / cubemap / cubemap array textures in KTX2 (#5325) # Objective - Fix / support KTX2 array / cubemap / cubemap array textures - Fixes #4495 . Supersedes #4514 . ## Solution - Add `Option<TextureViewDescriptor>` to `Image` to enable configuration of the `TextureViewDimension` of a texture. - This allows users to set `D2Array`, `D3`, `Cube`, `CubeArray` or whatever they need - Automatically configure this when loading KTX2 - Transcode all layers and faces instead of just one - Use the UASTC block size of 128 bits, and the number of blocks in x/y for a given mip level in order to determine the offset of the layer and face within the KTX2 mip level data - `wgpu` wants data ordered as layer 0 mip 0..n, layer 1 mip 0..n, etc. See https://docs.rs/wgpu/latest/wgpu/util/trait.DeviceExt.html#tymethod.create_texture_with_data - Reorder the data KTX2 mip X layer Y face Z to `wgpu` layer Y face Z mip X order - Add a `skybox` example to demonstrate / test loading cubemaps from PNG and KTX2, including ASTC 4x4, BC7, and ETC2 compression for support everywhere. Note that you need to enable the `ktx2,zstd` features to be able to load the compressed textures. --- ## Changelog - Fixed: KTX2 array / cubemap / cubemap array textures - Fixes: Validation failure for compressed textures stored in KTX2 where the width/height are not a multiple of the block dimensions. - Added: `Image` now has an `Option<TextureViewDescriptor>` field to enable configuration of the texture view. This is useful for configuring the `TextureViewDimension` when it is not just a plain 2D texture and the loader could/did not identify what it should be. Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2022-07-30 07:02:58 +00:00
let mut index = 0;
for _layer in 0..layer_count {
for _face in 0..face_count {
let offset = index * level_bytes;
wgpu_data[index].extend_from_slice(&level_data[offset..(offset + level_bytes)]);
index += 1;
}
}
}
// Assign the data and fill in the rest of the metadata now the possible
// error cases have been handled
let mut image = Image::default();
image.texture_descriptor.format = texture_format;
Support array / cubemap / cubemap array textures in KTX2 (#5325) # Objective - Fix / support KTX2 array / cubemap / cubemap array textures - Fixes #4495 . Supersedes #4514 . ## Solution - Add `Option<TextureViewDescriptor>` to `Image` to enable configuration of the `TextureViewDimension` of a texture. - This allows users to set `D2Array`, `D3`, `Cube`, `CubeArray` or whatever they need - Automatically configure this when loading KTX2 - Transcode all layers and faces instead of just one - Use the UASTC block size of 128 bits, and the number of blocks in x/y for a given mip level in order to determine the offset of the layer and face within the KTX2 mip level data - `wgpu` wants data ordered as layer 0 mip 0..n, layer 1 mip 0..n, etc. See https://docs.rs/wgpu/latest/wgpu/util/trait.DeviceExt.html#tymethod.create_texture_with_data - Reorder the data KTX2 mip X layer Y face Z to `wgpu` layer Y face Z mip X order - Add a `skybox` example to demonstrate / test loading cubemaps from PNG and KTX2, including ASTC 4x4, BC7, and ETC2 compression for support everywhere. Note that you need to enable the `ktx2,zstd` features to be able to load the compressed textures. --- ## Changelog - Fixed: KTX2 array / cubemap / cubemap array textures - Fixes: Validation failure for compressed textures stored in KTX2 where the width/height are not a multiple of the block dimensions. - Added: `Image` now has an `Option<TextureViewDescriptor>` field to enable configuration of the texture view. This is useful for configuring the `TextureViewDimension` when it is not just a plain 2D texture and the loader could/did not identify what it should be. Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2022-07-30 07:02:58 +00:00
image.data = wgpu_data.into_iter().flatten().collect::<Vec<_>>();
image.texture_descriptor.size = Extent3d {
width,
height,
Support array / cubemap / cubemap array textures in KTX2 (#5325) # Objective - Fix / support KTX2 array / cubemap / cubemap array textures - Fixes #4495 . Supersedes #4514 . ## Solution - Add `Option<TextureViewDescriptor>` to `Image` to enable configuration of the `TextureViewDimension` of a texture. - This allows users to set `D2Array`, `D3`, `Cube`, `CubeArray` or whatever they need - Automatically configure this when loading KTX2 - Transcode all layers and faces instead of just one - Use the UASTC block size of 128 bits, and the number of blocks in x/y for a given mip level in order to determine the offset of the layer and face within the KTX2 mip level data - `wgpu` wants data ordered as layer 0 mip 0..n, layer 1 mip 0..n, etc. See https://docs.rs/wgpu/latest/wgpu/util/trait.DeviceExt.html#tymethod.create_texture_with_data - Reorder the data KTX2 mip X layer Y face Z to `wgpu` layer Y face Z mip X order - Add a `skybox` example to demonstrate / test loading cubemaps from PNG and KTX2, including ASTC 4x4, BC7, and ETC2 compression for support everywhere. Note that you need to enable the `ktx2,zstd` features to be able to load the compressed textures. --- ## Changelog - Fixed: KTX2 array / cubemap / cubemap array textures - Fixes: Validation failure for compressed textures stored in KTX2 where the width/height are not a multiple of the block dimensions. - Added: `Image` now has an `Option<TextureViewDescriptor>` field to enable configuration of the texture view. This is useful for configuring the `TextureViewDimension` when it is not just a plain 2D texture and the loader could/did not identify what it should be. Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2022-07-30 07:02:58 +00:00
depth_or_array_layers: if layer_count > 1 || face_count > 1 {
layer_count * face_count
} else {
depth
}
.max(1),
}
.physical_size(texture_format);
image.texture_descriptor.mip_level_count = level_count;
image.texture_descriptor.dimension = if depth > 1 {
TextureDimension::D3
} else if image.is_compressed() || height > 1 {
TextureDimension::D2
} else {
TextureDimension::D1
};
Support array / cubemap / cubemap array textures in KTX2 (#5325) # Objective - Fix / support KTX2 array / cubemap / cubemap array textures - Fixes #4495 . Supersedes #4514 . ## Solution - Add `Option<TextureViewDescriptor>` to `Image` to enable configuration of the `TextureViewDimension` of a texture. - This allows users to set `D2Array`, `D3`, `Cube`, `CubeArray` or whatever they need - Automatically configure this when loading KTX2 - Transcode all layers and faces instead of just one - Use the UASTC block size of 128 bits, and the number of blocks in x/y for a given mip level in order to determine the offset of the layer and face within the KTX2 mip level data - `wgpu` wants data ordered as layer 0 mip 0..n, layer 1 mip 0..n, etc. See https://docs.rs/wgpu/latest/wgpu/util/trait.DeviceExt.html#tymethod.create_texture_with_data - Reorder the data KTX2 mip X layer Y face Z to `wgpu` layer Y face Z mip X order - Add a `skybox` example to demonstrate / test loading cubemaps from PNG and KTX2, including ASTC 4x4, BC7, and ETC2 compression for support everywhere. Note that you need to enable the `ktx2,zstd` features to be able to load the compressed textures. --- ## Changelog - Fixed: KTX2 array / cubemap / cubemap array textures - Fixes: Validation failure for compressed textures stored in KTX2 where the width/height are not a multiple of the block dimensions. - Added: `Image` now has an `Option<TextureViewDescriptor>` field to enable configuration of the texture view. This is useful for configuring the `TextureViewDimension` when it is not just a plain 2D texture and the loader could/did not identify what it should be. Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2022-07-30 07:02:58 +00:00
let mut dimension = None;
if face_count == 6 {
dimension = Some(if layer_count > 1 {
TextureViewDimension::CubeArray
} else {
TextureViewDimension::Cube
});
} else if layer_count > 1 {
dimension = Some(TextureViewDimension::D2Array);
} else if depth > 1 {
dimension = Some(TextureViewDimension::D3);
}
if dimension.is_some() {
image.texture_view_descriptor = Some(TextureViewDescriptor {
dimension,
..default()
});
}
Ok(image)
}
#[cfg(feature = "basis-universal")]
pub fn get_transcoded_formats(
supported_compressed_formats: CompressedImageFormats,
data_format: DataFormat,
is_srgb: bool,
) -> (TranscoderBlockFormat, TextureFormat) {
match data_format {
DataFormat::Rrr => {
if supported_compressed_formats.contains(CompressedImageFormats::BC) {
(TranscoderBlockFormat::BC4, TextureFormat::Bc4RUnorm)
} else if supported_compressed_formats.contains(CompressedImageFormats::ETC2) {
(
TranscoderBlockFormat::ETC2_EAC_R11,
TextureFormat::EacR11Unorm,
)
} else {
(TranscoderBlockFormat::RGBA32, TextureFormat::R8Unorm)
}
}
DataFormat::Rrrg | DataFormat::Rg => {
if supported_compressed_formats.contains(CompressedImageFormats::BC) {
(TranscoderBlockFormat::BC5, TextureFormat::Bc5RgUnorm)
} else if supported_compressed_formats.contains(CompressedImageFormats::ETC2) {
(
TranscoderBlockFormat::ETC2_EAC_RG11,
TextureFormat::EacRg11Unorm,
)
} else {
(TranscoderBlockFormat::RGBA32, TextureFormat::Rg8Unorm)
}
}
// NOTE: Rgba16Float should be transcoded to BC6H/ASTC_HDR. Neither are supported by
// basis-universal, nor is ASTC_HDR supported by wgpu
DataFormat::Rgb | DataFormat::Rgba => {
// NOTE: UASTC can be losslessly transcoded to ASTC4x4 and ASTC uses the same
// space as BC7 (128-bits per 4x4 texel block) so prefer ASTC over BC for
// transcoding speed and quality.
if supported_compressed_formats.contains(CompressedImageFormats::ASTC_LDR) {
(
TranscoderBlockFormat::ASTC_4x4,
TextureFormat::Astc {
block: AstcBlock::B4x4,
channel: if is_srgb {
AstcChannel::UnormSrgb
} else {
AstcChannel::Unorm
},
},
)
} else if supported_compressed_formats.contains(CompressedImageFormats::BC) {
(
TranscoderBlockFormat::BC7,
if is_srgb {
TextureFormat::Bc7RgbaUnormSrgb
} else {
TextureFormat::Bc7RgbaUnorm
},
)
} else if supported_compressed_formats.contains(CompressedImageFormats::ETC2) {
(
TranscoderBlockFormat::ETC2_RGBA,
if is_srgb {
TextureFormat::Etc2Rgba8UnormSrgb
} else {
TextureFormat::Etc2Rgba8Unorm
},
)
} else {
(
TranscoderBlockFormat::RGBA32,
if is_srgb {
TextureFormat::Rgba8UnormSrgb
} else {
TextureFormat::Rgba8Unorm
},
)
}
}
}
}
#[cfg(feature = "ktx2")]
pub fn ktx2_get_texture_format<Data: AsRef<[u8]>>(
ktx2: &ktx2::Reader<Data>,
is_srgb: bool,
) -> Result<TextureFormat, TextureError> {
if let Some(format) = ktx2.header().format {
return ktx2_format_to_texture_format(format, is_srgb);
}
for data_format_descriptor in ktx2.data_format_descriptors() {
if data_format_descriptor.header == DataFormatDescriptorHeader::BASIC {
let basic_data_format_descriptor =
BasicDataFormatDescriptor::parse(data_format_descriptor.data)
.map_err(|err| TextureError::InvalidData(format!("KTX2: {err:?}")))?;
let sample_information = basic_data_format_descriptor
.sample_information()
.collect::<Vec<_>>();
return ktx2_dfd_to_texture_format(
&basic_data_format_descriptor,
&sample_information,
is_srgb,
);
}
}
Err(TextureError::UnsupportedTextureFormat(
"Unknown".to_string(),
))
}
enum DataType {
Unorm,
UnormSrgb,
Snorm,
Float,
Uint,
Sint,
}
Add `core` and `alloc` over `std` Lints (#15281) # Objective - Fixes #6370 - Closes #6581 ## Solution - Added the following lints to the workspace: - `std_instead_of_core` - `std_instead_of_alloc` - `alloc_instead_of_core` - Used `cargo +nightly fmt` with [item level use formatting](https://rust-lang.github.io/rustfmt/?version=v1.6.0&search=#Item%5C%3A) to split all `use` statements into single items. - Used `cargo clippy --workspace --all-targets --all-features --fix --allow-dirty` to _attempt_ to resolve the new linting issues, and intervened where the lint was unable to resolve the issue automatically (usually due to needing an `extern crate alloc;` statement in a crate root). - Manually removed certain uses of `std` where negative feature gating prevented `--all-features` from finding the offending uses. - Used `cargo +nightly fmt` with [crate level use formatting](https://rust-lang.github.io/rustfmt/?version=v1.6.0&search=#Crate%5C%3A) to re-merge all `use` statements matching Bevy's previous styling. - Manually fixed cases where the `fmt` tool could not re-merge `use` statements due to conditional compilation attributes. ## Testing - Ran CI locally ## Migration Guide The MSRV is now 1.81. Please update to this version or higher. ## Notes - This is a _massive_ change to try and push through, which is why I've outlined the semi-automatic steps I used to create this PR, in case this fails and someone else tries again in the future. - Making this change has no impact on user code, but does mean Bevy contributors will be warned to use `core` and `alloc` instead of `std` where possible. - This lint is a critical first step towards investigating `no_std` options for Bevy. --------- Co-authored-by: François Mockers <francois.mockers@vleue.com>
2024-09-27 00:59:59 +00:00
// This can be obtained from core::mem::transmute::<f32, u32>(1.0f32). It is used for identifying
// normalized sample types as in Unorm or Snorm.
const F32_1_AS_U32: u32 = 1065353216;
fn sample_information_to_data_type(
sample: &SampleInformation,
is_srgb: bool,
) -> Result<DataType, TextureError> {
// Exponent flag not supported
if sample
.channel_type_qualifiers
.contains(ChannelTypeQualifiers::EXPONENT)
{
return Err(TextureError::UnsupportedTextureFormat(
"Unsupported KTX2 channel type qualifier: exponent".to_string(),
));
}
Ok(
if sample
.channel_type_qualifiers
.contains(ChannelTypeQualifiers::FLOAT)
{
// If lower bound of range is 0 then unorm, else if upper bound is 1.0f32 as u32
if sample
.channel_type_qualifiers
.contains(ChannelTypeQualifiers::SIGNED)
{
if sample.upper == F32_1_AS_U32 {
DataType::Snorm
} else {
DataType::Float
}
} else if is_srgb {
DataType::UnormSrgb
} else {
DataType::Unorm
}
} else if sample
.channel_type_qualifiers
.contains(ChannelTypeQualifiers::SIGNED)
{
DataType::Sint
} else {
DataType::Uint
},
)
}
#[cfg(feature = "ktx2")]
pub fn ktx2_dfd_to_texture_format(
data_format_descriptor: &BasicDataFormatDescriptor,
sample_information: &[SampleInformation],
is_srgb: bool,
) -> Result<TextureFormat, TextureError> {
Ok(match data_format_descriptor.color_model {
Some(ColorModel::RGBSDA) => {
match sample_information.len() {
1 => {
// Only red channel allowed
if sample_information[0].channel_type != 0 {
return Err(TextureError::UnsupportedTextureFormat(
"Only red-component single-component KTX2 RGBSDA formats supported"
.to_string(),
));
}
let sample = &sample_information[0];
let data_type = sample_information_to_data_type(sample, false)?;
match sample.bit_length {
8 => match data_type {
DataType::Unorm => TextureFormat::R8Unorm,
DataType::UnormSrgb => {
return Err(TextureError::UnsupportedTextureFormat(
"UnormSrgb not supported for R8".to_string(),
));
}
DataType::Snorm => TextureFormat::R8Snorm,
DataType::Float => {
return Err(TextureError::UnsupportedTextureFormat(
"Float not supported for R8".to_string(),
));
}
DataType::Uint => TextureFormat::R8Uint,
DataType::Sint => TextureFormat::R8Sint,
},
16 => match data_type {
DataType::Unorm => TextureFormat::R16Unorm,
DataType::UnormSrgb => {
return Err(TextureError::UnsupportedTextureFormat(
"UnormSrgb not supported for R16".to_string(),
));
}
DataType::Snorm => TextureFormat::R16Snorm,
DataType::Float => TextureFormat::R16Float,
DataType::Uint => TextureFormat::R16Uint,
DataType::Sint => TextureFormat::R16Sint,
},
32 => match data_type {
DataType::Unorm => {
return Err(TextureError::UnsupportedTextureFormat(
"Unorm not supported for R32".to_string(),
));
}
DataType::UnormSrgb => {
return Err(TextureError::UnsupportedTextureFormat(
"UnormSrgb not supported for R32".to_string(),
));
}
DataType::Snorm => {
return Err(TextureError::UnsupportedTextureFormat(
"Snorm not supported for R32".to_string(),
));
}
DataType::Float => TextureFormat::R32Float,
DataType::Uint => TextureFormat::R32Uint,
DataType::Sint => TextureFormat::R32Sint,
},
v => {
return Err(TextureError::UnsupportedTextureFormat(format!(
"Unsupported sample bit length for RGBSDA 1-channel format: {v}",
)));
}
}
}
2 => {
// Only red and green channels allowed
if sample_information[0].channel_type != 0
|| sample_information[1].channel_type != 1
{
return Err(TextureError::UnsupportedTextureFormat(
"Only red-green-component two-component KTX2 RGBSDA formats supported"
.to_string(),
));
}
// Only same bit length for all channels
assert_eq!(
sample_information[0].bit_length,
sample_information[1].bit_length
);
// Only same channel type qualifiers for all channels
assert_eq!(
sample_information[0].channel_type_qualifiers,
sample_information[1].channel_type_qualifiers
);
// Only same sample range for all channels
assert_eq!(sample_information[0].lower, sample_information[1].lower);
assert_eq!(sample_information[0].upper, sample_information[1].upper);
let sample = &sample_information[0];
let data_type = sample_information_to_data_type(sample, false)?;
match sample.bit_length {
8 => match data_type {
DataType::Unorm => TextureFormat::Rg8Unorm,
DataType::UnormSrgb => {
return Err(TextureError::UnsupportedTextureFormat(
"UnormSrgb not supported for Rg8".to_string(),
));
}
DataType::Snorm => TextureFormat::Rg8Snorm,
DataType::Float => {
return Err(TextureError::UnsupportedTextureFormat(
"Float not supported for Rg8".to_string(),
));
}
DataType::Uint => TextureFormat::Rg8Uint,
DataType::Sint => TextureFormat::Rg8Sint,
},
16 => match data_type {
DataType::Unorm => TextureFormat::Rg16Unorm,
DataType::UnormSrgb => {
return Err(TextureError::UnsupportedTextureFormat(
"UnormSrgb not supported for Rg16".to_string(),
));
}
DataType::Snorm => TextureFormat::Rg16Snorm,
DataType::Float => TextureFormat::Rg16Float,
DataType::Uint => TextureFormat::Rg16Uint,
DataType::Sint => TextureFormat::Rg16Sint,
},
32 => match data_type {
DataType::Unorm => {
return Err(TextureError::UnsupportedTextureFormat(
"Unorm not supported for Rg32".to_string(),
));
}
DataType::UnormSrgb => {
return Err(TextureError::UnsupportedTextureFormat(
"UnormSrgb not supported for Rg32".to_string(),
));
}
DataType::Snorm => {
return Err(TextureError::UnsupportedTextureFormat(
"Snorm not supported for Rg32".to_string(),
));
}
DataType::Float => TextureFormat::Rg32Float,
DataType::Uint => TextureFormat::Rg32Uint,
DataType::Sint => TextureFormat::Rg32Sint,
},
v => {
return Err(TextureError::UnsupportedTextureFormat(format!(
"Unsupported sample bit length for RGBSDA 2-channel format: {v}",
)));
}
}
}
3 => {
if sample_information[0].channel_type == 0
&& sample_information[0].bit_length == 11
&& sample_information[1].channel_type == 1
&& sample_information[1].bit_length == 11
&& sample_information[2].channel_type == 2
&& sample_information[2].bit_length == 10
{
TextureFormat::Rg11b10Ufloat
} else if sample_information[0].channel_type == 0
&& sample_information[0].bit_length == 9
&& sample_information[1].channel_type == 1
&& sample_information[1].bit_length == 9
&& sample_information[2].channel_type == 2
&& sample_information[2].bit_length == 9
{
TextureFormat::Rgb9e5Ufloat
} else if sample_information[0].channel_type == 0
&& sample_information[0].bit_length == 8
&& sample_information[1].channel_type == 1
&& sample_information[1].bit_length == 8
&& sample_information[2].channel_type == 2
&& sample_information[2].bit_length == 8
{
return Err(TextureError::FormatRequiresTranscodingError(
TranscodeFormat::Rgb8,
));
} else {
return Err(TextureError::UnsupportedTextureFormat(
"3-component formats not supported".to_string(),
));
}
}
4 => {
// Only RGBA or BGRA channels allowed
let is_rgba = sample_information[0].channel_type == 0;
assert!(
sample_information[0].channel_type == 0
|| sample_information[0].channel_type == 2
);
assert_eq!(sample_information[1].channel_type, 1);
assert_eq!(
sample_information[2].channel_type,
if is_rgba { 2 } else { 0 }
);
assert_eq!(sample_information[3].channel_type, 15);
// Handle one special packed format
if sample_information[0].bit_length == 10
&& sample_information[1].bit_length == 10
&& sample_information[2].bit_length == 10
&& sample_information[3].bit_length == 2
{
return Ok(TextureFormat::Rgb10a2Unorm);
}
// Only same bit length for all channels
assert!(
sample_information[0].bit_length == sample_information[1].bit_length
&& sample_information[0].bit_length == sample_information[2].bit_length
&& sample_information[0].bit_length == sample_information[3].bit_length
);
assert!(
sample_information[0].lower == sample_information[1].lower
&& sample_information[0].lower == sample_information[2].lower
&& sample_information[0].lower == sample_information[3].lower
);
assert!(
sample_information[0].upper == sample_information[1].upper
&& sample_information[0].upper == sample_information[2].upper
&& sample_information[0].upper == sample_information[3].upper
);
let sample = &sample_information[0];
let data_type = sample_information_to_data_type(sample, is_srgb)?;
match sample.bit_length {
8 => match data_type {
DataType::Unorm => {
if is_rgba {
TextureFormat::Rgba8Unorm
} else {
TextureFormat::Bgra8Unorm
}
}
DataType::UnormSrgb => {
if is_rgba {
TextureFormat::Rgba8UnormSrgb
} else {
TextureFormat::Bgra8UnormSrgb
}
}
DataType::Snorm => {
if is_rgba {
TextureFormat::Rgba8Snorm
} else {
return Err(TextureError::UnsupportedTextureFormat(
"Bgra8 not supported for Snorm".to_string(),
));
}
}
DataType::Float => {
return Err(TextureError::UnsupportedTextureFormat(
"Float not supported for Rgba8/Bgra8".to_string(),
));
}
DataType::Uint => {
if is_rgba {
// NOTE: This is more about how you want to use the data so
// TextureFormat::Rgba8Uint is incorrect here
if is_srgb {
TextureFormat::Rgba8UnormSrgb
} else {
TextureFormat::Rgba8Unorm
}
} else {
return Err(TextureError::UnsupportedTextureFormat(
"Bgra8 not supported for Uint".to_string(),
));
}
}
DataType::Sint => {
if is_rgba {
// NOTE: This is more about how you want to use the data so
// TextureFormat::Rgba8Sint is incorrect here
TextureFormat::Rgba8Snorm
} else {
return Err(TextureError::UnsupportedTextureFormat(
"Bgra8 not supported for Sint".to_string(),
));
}
}
},
16 => match data_type {
DataType::Unorm => {
if is_rgba {
TextureFormat::Rgba16Unorm
} else {
return Err(TextureError::UnsupportedTextureFormat(
"Bgra16 not supported for Unorm".to_string(),
));
}
}
DataType::UnormSrgb => {
return Err(TextureError::UnsupportedTextureFormat(
"UnormSrgb not supported for Rgba16/Bgra16".to_string(),
));
}
DataType::Snorm => {
if is_rgba {
TextureFormat::Rgba16Snorm
} else {
return Err(TextureError::UnsupportedTextureFormat(
"Bgra16 not supported for Snorm".to_string(),
));
}
}
DataType::Float => {
if is_rgba {
TextureFormat::Rgba16Float
} else {
return Err(TextureError::UnsupportedTextureFormat(
"Bgra16 not supported for Float".to_string(),
));
}
}
DataType::Uint => {
if is_rgba {
TextureFormat::Rgba16Uint
} else {
return Err(TextureError::UnsupportedTextureFormat(
"Bgra16 not supported for Uint".to_string(),
));
}
}
DataType::Sint => {
if is_rgba {
TextureFormat::Rgba16Sint
} else {
return Err(TextureError::UnsupportedTextureFormat(
"Bgra16 not supported for Sint".to_string(),
));
}
}
},
32 => match data_type {
DataType::Unorm => {
return Err(TextureError::UnsupportedTextureFormat(
"Unorm not supported for Rgba32/Bgra32".to_string(),
));
}
DataType::UnormSrgb => {
return Err(TextureError::UnsupportedTextureFormat(
"UnormSrgb not supported for Rgba32/Bgra32".to_string(),
));
}
DataType::Snorm => {
return Err(TextureError::UnsupportedTextureFormat(
"Snorm not supported for Rgba32/Bgra32".to_string(),
));
}
DataType::Float => {
if is_rgba {
TextureFormat::Rgba32Float
} else {
return Err(TextureError::UnsupportedTextureFormat(
"Bgra32 not supported for Float".to_string(),
));
}
}
DataType::Uint => {
if is_rgba {
TextureFormat::Rgba32Uint
} else {
return Err(TextureError::UnsupportedTextureFormat(
"Bgra32 not supported for Uint".to_string(),
));
}
}
DataType::Sint => {
if is_rgba {
TextureFormat::Rgba32Sint
} else {
return Err(TextureError::UnsupportedTextureFormat(
"Bgra32 not supported for Sint".to_string(),
));
}
}
},
v => {
return Err(TextureError::UnsupportedTextureFormat(format!(
"Unsupported sample bit length for RGBSDA 4-channel format: {v}",
)));
}
}
}
v => {
return Err(TextureError::UnsupportedTextureFormat(format!(
"Unsupported channel count for RGBSDA format: {v}",
)));
}
}
}
Some(ColorModel::YUVSDA)
| Some(ColorModel::YIQSDA)
| Some(ColorModel::LabSDA)
| Some(ColorModel::CMYKA)
| Some(ColorModel::HSVAAng)
| Some(ColorModel::HSLAAng)
| Some(ColorModel::HSVAHex)
| Some(ColorModel::HSLAHex)
| Some(ColorModel::YCgCoA)
| Some(ColorModel::YcCbcCrc)
| Some(ColorModel::ICtCp)
| Some(ColorModel::CIEXYZ)
| Some(ColorModel::CIEXYY) => {
return Err(TextureError::UnsupportedTextureFormat(format!(
"{:?}",
data_format_descriptor.color_model
)));
}
Some(ColorModel::XYZW) => {
// Same number of channels in both texel block dimensions and sample info descriptions
assert_eq!(
data_format_descriptor.texel_block_dimensions[0] as usize,
sample_information.len()
);
match sample_information.len() {
4 => {
// Only RGBA or BGRA channels allowed
assert_eq!(sample_information[0].channel_type, 0);
assert_eq!(sample_information[1].channel_type, 1);
assert_eq!(sample_information[2].channel_type, 2);
assert_eq!(sample_information[3].channel_type, 3);
// Only same bit length for all channels
assert!(
sample_information[0].bit_length == sample_information[1].bit_length
&& sample_information[0].bit_length == sample_information[2].bit_length
&& sample_information[0].bit_length == sample_information[3].bit_length
);
// Only same channel type qualifiers for all channels
assert!(
sample_information[0].channel_type_qualifiers
== sample_information[1].channel_type_qualifiers
&& sample_information[0].channel_type_qualifiers
== sample_information[2].channel_type_qualifiers
&& sample_information[0].channel_type_qualifiers
== sample_information[3].channel_type_qualifiers
);
// Only same sample range for all channels
assert!(
sample_information[0].lower == sample_information[1].lower
&& sample_information[0].lower == sample_information[2].lower
&& sample_information[0].lower == sample_information[3].lower
);
assert!(
sample_information[0].upper == sample_information[1].upper
&& sample_information[0].upper == sample_information[2].upper
&& sample_information[0].upper == sample_information[3].upper
);
let sample = &sample_information[0];
let data_type = sample_information_to_data_type(sample, false)?;
match sample.bit_length {
8 => match data_type {
DataType::Unorm => TextureFormat::Rgba8Unorm,
DataType::UnormSrgb => {
return Err(TextureError::UnsupportedTextureFormat(
"UnormSrgb not supported for XYZW".to_string(),
));
}
DataType::Snorm => TextureFormat::Rgba8Snorm,
DataType::Float => {
return Err(TextureError::UnsupportedTextureFormat(
"Float not supported for Rgba8/Bgra8".to_string(),
));
}
DataType::Uint => TextureFormat::Rgba8Uint,
DataType::Sint => TextureFormat::Rgba8Sint,
},
16 => match data_type {
DataType::Unorm => TextureFormat::Rgba16Unorm,
DataType::UnormSrgb => {
return Err(TextureError::UnsupportedTextureFormat(
"UnormSrgb not supported for Rgba16/Bgra16".to_string(),
));
}
DataType::Snorm => TextureFormat::Rgba16Snorm,
DataType::Float => TextureFormat::Rgba16Float,
DataType::Uint => TextureFormat::Rgba16Uint,
DataType::Sint => TextureFormat::Rgba16Sint,
},
32 => match data_type {
DataType::Unorm => {
return Err(TextureError::UnsupportedTextureFormat(
"Unorm not supported for Rgba32/Bgra32".to_string(),
));
}
DataType::UnormSrgb => {
return Err(TextureError::UnsupportedTextureFormat(
"UnormSrgb not supported for Rgba32/Bgra32".to_string(),
));
}
DataType::Snorm => {
return Err(TextureError::UnsupportedTextureFormat(
"Snorm not supported for Rgba32/Bgra32".to_string(),
));
}
DataType::Float => TextureFormat::Rgba32Float,
DataType::Uint => TextureFormat::Rgba32Uint,
DataType::Sint => TextureFormat::Rgba32Sint,
},
v => {
return Err(TextureError::UnsupportedTextureFormat(format!(
"Unsupported sample bit length for XYZW 4-channel format: {v}",
)));
}
}
}
v => {
return Err(TextureError::UnsupportedTextureFormat(format!(
"Unsupported channel count for XYZW format: {v}",
)));
}
}
}
Some(ColorModel::BC1A) => {
if is_srgb {
TextureFormat::Bc1RgbaUnormSrgb
} else {
TextureFormat::Bc1RgbaUnorm
}
}
Some(ColorModel::BC2) => {
if is_srgb {
TextureFormat::Bc2RgbaUnormSrgb
} else {
TextureFormat::Bc2RgbaUnorm
}
}
Some(ColorModel::BC3) => {
if is_srgb {
TextureFormat::Bc3RgbaUnormSrgb
} else {
TextureFormat::Bc3RgbaUnorm
}
}
Some(ColorModel::BC4) => {
if sample_information[0].lower == 0 {
TextureFormat::Bc4RUnorm
} else {
TextureFormat::Bc4RSnorm
}
}
// FIXME: Red and green channels can be swapped for ATI2n/3Dc
Some(ColorModel::BC5) => {
if sample_information[0].lower == 0 {
TextureFormat::Bc5RgUnorm
} else {
TextureFormat::Bc5RgSnorm
}
}
Some(ColorModel::BC6H) => {
if sample_information[0].lower == 0 {
TextureFormat::Bc6hRgbUfloat
} else {
TextureFormat::Bc6hRgbFloat
}
}
Some(ColorModel::BC7) => {
if is_srgb {
TextureFormat::Bc7RgbaUnormSrgb
} else {
TextureFormat::Bc7RgbaUnorm
}
}
// ETC1 a subset of ETC2 only supporting Rgb8
Some(ColorModel::ETC1) => {
if is_srgb {
TextureFormat::Etc2Rgb8UnormSrgb
} else {
TextureFormat::Etc2Rgb8Unorm
}
}
Some(ColorModel::ETC2) => match sample_information.len() {
1 => {
let sample = &sample_information[0];
match sample.channel_type {
0 => {
if sample_information[0]
.channel_type_qualifiers
.contains(ChannelTypeQualifiers::SIGNED)
{
TextureFormat::EacR11Snorm
} else {
TextureFormat::EacR11Unorm
}
}
2 => {
if is_srgb {
TextureFormat::Etc2Rgb8UnormSrgb
} else {
TextureFormat::Etc2Rgb8Unorm
}
}
_ => {
return Err(TextureError::UnsupportedTextureFormat(format!(
"Invalid ETC2 sample channel type: {}",
sample.channel_type
)))
}
}
}
2 => {
let sample0 = &sample_information[0];
let sample1 = &sample_information[1];
if sample0.channel_type == 0 && sample1.channel_type == 1 {
if sample0
.channel_type_qualifiers
.contains(ChannelTypeQualifiers::SIGNED)
{
TextureFormat::EacRg11Snorm
} else {
TextureFormat::EacRg11Unorm
}
} else if sample0.channel_type == 2 && sample1.channel_type == 15 {
if is_srgb {
TextureFormat::Etc2Rgb8A1UnormSrgb
} else {
TextureFormat::Etc2Rgb8A1Unorm
}
} else if sample0.channel_type == 15 && sample1.channel_type == 2 {
if is_srgb {
TextureFormat::Etc2Rgba8UnormSrgb
} else {
TextureFormat::Etc2Rgba8Unorm
}
} else {
return Err(TextureError::UnsupportedTextureFormat(format!(
"Invalid ETC2 2-sample channel types: {} {}",
sample0.channel_type, sample1.channel_type
)));
}
}
v => {
return Err(TextureError::UnsupportedTextureFormat(format!(
"Unsupported channel count for ETC2 format: {v}",
)));
}
},
Some(ColorModel::ASTC) => TextureFormat::Astc {
block: match (
data_format_descriptor.texel_block_dimensions[0],
data_format_descriptor.texel_block_dimensions[1],
) {
(4, 4) => AstcBlock::B4x4,
(5, 4) => AstcBlock::B5x4,
(5, 5) => AstcBlock::B5x5,
(6, 5) => AstcBlock::B6x5,
(8, 5) => AstcBlock::B8x5,
(8, 8) => AstcBlock::B8x8,
(10, 5) => AstcBlock::B10x5,
(10, 6) => AstcBlock::B10x6,
(10, 8) => AstcBlock::B10x8,
(10, 10) => AstcBlock::B10x10,
(12, 10) => AstcBlock::B12x10,
(12, 12) => AstcBlock::B12x12,
d => {
return Err(TextureError::UnsupportedTextureFormat(format!(
"Invalid ASTC dimension: {} x {}",
d.0, d.1
)))
}
},
channel: if is_srgb {
AstcChannel::UnormSrgb
} else {
AstcChannel::Unorm
},
},
Some(ColorModel::ETC1S) => {
return Err(TextureError::FormatRequiresTranscodingError(
TranscodeFormat::Etc1s,
));
}
Some(ColorModel::PVRTC) => {
return Err(TextureError::UnsupportedTextureFormat(
"PVRTC is not supported".to_string(),
));
}
Some(ColorModel::PVRTC2) => {
return Err(TextureError::UnsupportedTextureFormat(
"PVRTC2 is not supported".to_string(),
));
}
Some(ColorModel::UASTC) => {
return Err(TextureError::FormatRequiresTranscodingError(
TranscodeFormat::Uastc(match sample_information[0].channel_type {
0 => DataFormat::Rgb,
3 => DataFormat::Rgba,
4 => DataFormat::Rrr,
5 => DataFormat::Rrrg,
6 => DataFormat::Rg,
channel_type => {
return Err(TextureError::UnsupportedTextureFormat(format!(
"Invalid KTX2 UASTC channel type: {channel_type}",
)))
}
}),
));
}
None => {
return Err(TextureError::UnsupportedTextureFormat(
"Unspecified KTX2 color model".to_string(),
));
}
_ => {
return Err(TextureError::UnsupportedTextureFormat(format!(
"Unknown KTX2 color model: {:?}",
data_format_descriptor.color_model
)));
}
})
}
#[cfg(feature = "ktx2")]
pub fn ktx2_format_to_texture_format(
ktx2_format: ktx2::Format,
is_srgb: bool,
) -> Result<TextureFormat, TextureError> {
Ok(match ktx2_format {
ktx2::Format::R8_UNORM | ktx2::Format::R8_SRGB => {
if is_srgb {
return Err(TextureError::FormatRequiresTranscodingError(
TranscodeFormat::R8UnormSrgb,
));
}
TextureFormat::R8Unorm
}
ktx2::Format::R8_SNORM => TextureFormat::R8Snorm,
ktx2::Format::R8_UINT => TextureFormat::R8Uint,
ktx2::Format::R8_SINT => TextureFormat::R8Sint,
ktx2::Format::R8G8_UNORM | ktx2::Format::R8G8_SRGB => {
if is_srgb {
return Err(TextureError::FormatRequiresTranscodingError(
TranscodeFormat::Rg8UnormSrgb,
));
}
TextureFormat::Rg8Unorm
}
ktx2::Format::R8G8_SNORM => TextureFormat::Rg8Snorm,
ktx2::Format::R8G8_UINT => TextureFormat::Rg8Uint,
ktx2::Format::R8G8_SINT => TextureFormat::Rg8Sint,
ktx2::Format::R8G8B8_UNORM | ktx2::Format::R8G8B8_SRGB => {
return Err(TextureError::FormatRequiresTranscodingError(
TranscodeFormat::Rgb8,
));
}
ktx2::Format::R8G8B8A8_UNORM | ktx2::Format::R8G8B8A8_SRGB => {
if is_srgb {
TextureFormat::Rgba8UnormSrgb
} else {
TextureFormat::Rgba8Unorm
}
}
ktx2::Format::R8G8B8A8_SNORM => TextureFormat::Rgba8Snorm,
ktx2::Format::R8G8B8A8_UINT => TextureFormat::Rgba8Uint,
ktx2::Format::R8G8B8A8_SINT => TextureFormat::Rgba8Sint,
ktx2::Format::B8G8R8A8_UNORM | ktx2::Format::B8G8R8A8_SRGB => {
if is_srgb {
TextureFormat::Bgra8UnormSrgb
} else {
TextureFormat::Bgra8Unorm
}
}
ktx2::Format::A2R10G10B10_UNORM_PACK32 => TextureFormat::Rgb10a2Unorm,
ktx2::Format::R16_UNORM => TextureFormat::R16Unorm,
ktx2::Format::R16_SNORM => TextureFormat::R16Snorm,
ktx2::Format::R16_UINT => TextureFormat::R16Uint,
ktx2::Format::R16_SINT => TextureFormat::R16Sint,
ktx2::Format::R16_SFLOAT => TextureFormat::R16Float,
ktx2::Format::R16G16_UNORM => TextureFormat::Rg16Unorm,
ktx2::Format::R16G16_SNORM => TextureFormat::Rg16Snorm,
ktx2::Format::R16G16_UINT => TextureFormat::Rg16Uint,
ktx2::Format::R16G16_SINT => TextureFormat::Rg16Sint,
ktx2::Format::R16G16_SFLOAT => TextureFormat::Rg16Float,
ktx2::Format::R16G16B16A16_UNORM => TextureFormat::Rgba16Unorm,
ktx2::Format::R16G16B16A16_SNORM => TextureFormat::Rgba16Snorm,
ktx2::Format::R16G16B16A16_UINT => TextureFormat::Rgba16Uint,
ktx2::Format::R16G16B16A16_SINT => TextureFormat::Rgba16Sint,
ktx2::Format::R16G16B16A16_SFLOAT => TextureFormat::Rgba16Float,
ktx2::Format::R32_UINT => TextureFormat::R32Uint,
ktx2::Format::R32_SINT => TextureFormat::R32Sint,
ktx2::Format::R32_SFLOAT => TextureFormat::R32Float,
ktx2::Format::R32G32_UINT => TextureFormat::Rg32Uint,
ktx2::Format::R32G32_SINT => TextureFormat::Rg32Sint,
ktx2::Format::R32G32_SFLOAT => TextureFormat::Rg32Float,
ktx2::Format::R32G32B32A32_UINT => TextureFormat::Rgba32Uint,
ktx2::Format::R32G32B32A32_SINT => TextureFormat::Rgba32Sint,
ktx2::Format::R32G32B32A32_SFLOAT => TextureFormat::Rgba32Float,
ktx2::Format::B10G11R11_UFLOAT_PACK32 => TextureFormat::Rg11b10Ufloat,
ktx2::Format::E5B9G9R9_UFLOAT_PACK32 => TextureFormat::Rgb9e5Ufloat,
ktx2::Format::X8_D24_UNORM_PACK32 => TextureFormat::Depth24Plus,
ktx2::Format::D32_SFLOAT => TextureFormat::Depth32Float,
ktx2::Format::D24_UNORM_S8_UINT => TextureFormat::Depth24PlusStencil8,
ktx2::Format::BC1_RGB_UNORM_BLOCK
| ktx2::Format::BC1_RGB_SRGB_BLOCK
| ktx2::Format::BC1_RGBA_UNORM_BLOCK
| ktx2::Format::BC1_RGBA_SRGB_BLOCK => {
if is_srgb {
TextureFormat::Bc1RgbaUnormSrgb
} else {
TextureFormat::Bc1RgbaUnorm
}
}
ktx2::Format::BC2_UNORM_BLOCK | ktx2::Format::BC2_SRGB_BLOCK => {
if is_srgb {
TextureFormat::Bc2RgbaUnormSrgb
} else {
TextureFormat::Bc2RgbaUnorm
}
}
ktx2::Format::BC3_UNORM_BLOCK | ktx2::Format::BC3_SRGB_BLOCK => {
if is_srgb {
TextureFormat::Bc3RgbaUnormSrgb
} else {
TextureFormat::Bc3RgbaUnorm
}
}
ktx2::Format::BC4_UNORM_BLOCK => TextureFormat::Bc4RUnorm,
ktx2::Format::BC4_SNORM_BLOCK => TextureFormat::Bc4RSnorm,
ktx2::Format::BC5_UNORM_BLOCK => TextureFormat::Bc5RgUnorm,
ktx2::Format::BC5_SNORM_BLOCK => TextureFormat::Bc5RgSnorm,
ktx2::Format::BC6H_UFLOAT_BLOCK => TextureFormat::Bc6hRgbUfloat,
ktx2::Format::BC6H_SFLOAT_BLOCK => TextureFormat::Bc6hRgbFloat,
ktx2::Format::BC7_UNORM_BLOCK | ktx2::Format::BC7_SRGB_BLOCK => {
if is_srgb {
TextureFormat::Bc7RgbaUnormSrgb
} else {
TextureFormat::Bc7RgbaUnorm
}
}
ktx2::Format::ETC2_R8G8B8_UNORM_BLOCK | ktx2::Format::ETC2_R8G8B8_SRGB_BLOCK => {
if is_srgb {
TextureFormat::Etc2Rgb8UnormSrgb
} else {
TextureFormat::Etc2Rgb8Unorm
}
}
ktx2::Format::ETC2_R8G8B8A1_UNORM_BLOCK | ktx2::Format::ETC2_R8G8B8A1_SRGB_BLOCK => {
if is_srgb {
TextureFormat::Etc2Rgb8A1UnormSrgb
} else {
TextureFormat::Etc2Rgb8A1Unorm
}
}
ktx2::Format::ETC2_R8G8B8A8_UNORM_BLOCK | ktx2::Format::ETC2_R8G8B8A8_SRGB_BLOCK => {
if is_srgb {
TextureFormat::Etc2Rgba8UnormSrgb
} else {
TextureFormat::Etc2Rgba8Unorm
}
}
ktx2::Format::EAC_R11_UNORM_BLOCK => TextureFormat::EacR11Unorm,
ktx2::Format::EAC_R11_SNORM_BLOCK => TextureFormat::EacR11Snorm,
ktx2::Format::EAC_R11G11_UNORM_BLOCK => TextureFormat::EacRg11Unorm,
ktx2::Format::EAC_R11G11_SNORM_BLOCK => TextureFormat::EacRg11Snorm,
ktx2::Format::ASTC_4x4_UNORM_BLOCK | ktx2::Format::ASTC_4x4_SRGB_BLOCK => {
TextureFormat::Astc {
block: AstcBlock::B4x4,
channel: if is_srgb {
AstcChannel::UnormSrgb
} else {
AstcChannel::Unorm
},
}
}
ktx2::Format::ASTC_5x4_UNORM_BLOCK | ktx2::Format::ASTC_5x4_SRGB_BLOCK => {
TextureFormat::Astc {
block: AstcBlock::B5x4,
channel: if is_srgb {
AstcChannel::UnormSrgb
} else {
AstcChannel::Unorm
},
}
}
ktx2::Format::ASTC_5x5_UNORM_BLOCK | ktx2::Format::ASTC_5x5_SRGB_BLOCK => {
TextureFormat::Astc {
block: AstcBlock::B5x5,
channel: if is_srgb {
AstcChannel::UnormSrgb
} else {
AstcChannel::Unorm
},
}
}
ktx2::Format::ASTC_6x5_UNORM_BLOCK | ktx2::Format::ASTC_6x5_SRGB_BLOCK => {
TextureFormat::Astc {
block: AstcBlock::B6x5,
channel: if is_srgb {
AstcChannel::UnormSrgb
} else {
AstcChannel::Unorm
},
}
}
ktx2::Format::ASTC_6x6_UNORM_BLOCK | ktx2::Format::ASTC_6x6_SRGB_BLOCK => {
TextureFormat::Astc {
block: AstcBlock::B6x6,
channel: if is_srgb {
AstcChannel::UnormSrgb
} else {
AstcChannel::Unorm
},
}
}
ktx2::Format::ASTC_8x5_UNORM_BLOCK | ktx2::Format::ASTC_8x5_SRGB_BLOCK => {
TextureFormat::Astc {
block: AstcBlock::B8x5,
channel: if is_srgb {
AstcChannel::UnormSrgb
} else {
AstcChannel::Unorm
},
}
}
ktx2::Format::ASTC_8x6_UNORM_BLOCK | ktx2::Format::ASTC_8x6_SRGB_BLOCK => {
TextureFormat::Astc {
block: AstcBlock::B8x6,
channel: if is_srgb {
AstcChannel::UnormSrgb
} else {
AstcChannel::Unorm
},
}
}
ktx2::Format::ASTC_8x8_UNORM_BLOCK | ktx2::Format::ASTC_8x8_SRGB_BLOCK => {
TextureFormat::Astc {
block: AstcBlock::B8x8,
channel: if is_srgb {
AstcChannel::UnormSrgb
} else {
AstcChannel::Unorm
},
}
}
ktx2::Format::ASTC_10x5_UNORM_BLOCK | ktx2::Format::ASTC_10x5_SRGB_BLOCK => {
TextureFormat::Astc {
block: AstcBlock::B10x5,
channel: if is_srgb {
AstcChannel::UnormSrgb
} else {
AstcChannel::Unorm
},
}
}
ktx2::Format::ASTC_10x6_UNORM_BLOCK | ktx2::Format::ASTC_10x6_SRGB_BLOCK => {
TextureFormat::Astc {
block: AstcBlock::B10x6,
channel: if is_srgb {
AstcChannel::UnormSrgb
} else {
AstcChannel::Unorm
},
}
}
ktx2::Format::ASTC_10x8_UNORM_BLOCK | ktx2::Format::ASTC_10x8_SRGB_BLOCK => {
TextureFormat::Astc {
block: AstcBlock::B10x8,
channel: if is_srgb {
AstcChannel::UnormSrgb
} else {
AstcChannel::Unorm
},
}
}
ktx2::Format::ASTC_10x10_UNORM_BLOCK | ktx2::Format::ASTC_10x10_SRGB_BLOCK => {
TextureFormat::Astc {
block: AstcBlock::B10x10,
channel: if is_srgb {
AstcChannel::UnormSrgb
} else {
AstcChannel::Unorm
},
}
}
ktx2::Format::ASTC_12x10_UNORM_BLOCK | ktx2::Format::ASTC_12x10_SRGB_BLOCK => {
TextureFormat::Astc {
block: AstcBlock::B12x10,
channel: if is_srgb {
AstcChannel::UnormSrgb
} else {
AstcChannel::Unorm
},
}
}
ktx2::Format::ASTC_12x12_UNORM_BLOCK | ktx2::Format::ASTC_12x12_SRGB_BLOCK => {
TextureFormat::Astc {
block: AstcBlock::B12x12,
channel: if is_srgb {
AstcChannel::UnormSrgb
} else {
AstcChannel::Unorm
},
}
}
_ => {
return Err(TextureError::UnsupportedTextureFormat(format!(
"{ktx2_format:?}"
)))
}
})
}
#[cfg(test)]
mod tests {
use crate::CompressedImageFormats;
use super::ktx2_buffer_to_image;
#[test]
fn test_ktx_levels() {
:pencil2: Fix typos across bevy (#16702) # Objective Fixes typos in bevy project, following suggestion in https://github.com/bevyengine/bevy-website/pull/1912#pullrequestreview-2483499337 ## Solution I used https://github.com/crate-ci/typos to find them. I included only the ones that feel undebatable too me, but I am not in game engine so maybe some terms are expected. I left out the following typos: - `reparametrize` => `reparameterize`: There are a lot of occurences, I believe this was expected - `semicircles` => `hemicircles`: 2 occurences, may mean something specific in geometry - `invertation` => `inversion`: may mean something specific - `unparented` => `parentless`: may mean something specific - `metalness` => `metallicity`: may mean something specific ## Testing - Did you test these changes? If so, how? I did not test the changes, most changes are related to raw text. I expect the others to be tested by the CI. - Are there any parts that need more testing? I do not think - How can other people (reviewers) test your changes? Is there anything specific they need to know? To me there is nothing to test - If relevant, what platforms did you test these changes on, and are there any important ones you can't test? --- ## Migration Guide > This section is optional. If there are no breaking changes, you can delete this section. (kept in case I include the `reparameterize` change here) - If this PR is a breaking change (relative to the last release of Bevy), describe how a user might need to migrate their code to support these changes - Simply adding new functionality is not a breaking change. - Fixing behavior that was definitely a bug, rather than a questionable design choice is not a breaking change. ## Questions - [x] Should I include the above typos? No (https://github.com/bevyengine/bevy/pull/16702#issuecomment-2525271152) - [ ] Should I add `typos` to the CI? (I will check how to configure it properly) This project looks awesome, I really enjoy reading the progress made, thanks to everyone involved.
2024-12-08 01:18:39 +00:00
// R8UnormSrgb texture with 4x4 pixels data and 3 levels of mipmaps
let buffer = vec![
0xab, 0x4b, 0x54, 0x58, 0x20, 0x32, 0x30, 0xbb, 0x0d, 10, 0x1a, 10, 0x0f, 0, 0, 0, 1,
0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0,
0, 0, 0x98, 0, 0, 0, 0x2c, 0, 0, 0, 0xc4, 0, 0, 0, 0x5c, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0x28, 1, 0, 0, 0, 0, 0, 0, 0x10, 0, 0, 0, 0, 0, 0, 0, 0x10,
0, 0, 0, 0, 0, 0, 0, 0x24, 1, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0,
0, 0, 0, 0x20, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
0x2c, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0x28, 0, 1, 1, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0, 0, 0, 0x12, 0, 0, 0, 0x4b, 0x54, 0x58,
0x6f, 0x72, 0x69, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0, 0x72, 0x64, 0, 0,
0, 0x10, 0, 0, 0, 0x4b, 0x54, 0x58, 0x73, 0x77, 0x69, 0x7a, 0x7a, 0x6c, 0x65, 0, 0x72,
0x72, 0x72, 0x31, 0, 0x2c, 0, 0, 0, 0x4b, 0x54, 0x58, 0x77, 0x72, 0x69, 0x74, 0x65,
0x72, 0, 0x74, 0x6f, 0x6b, 0x74, 0x78, 0x20, 0x76, 0x34, 0x2e, 0x33, 0x2e, 0x30, 0x7e,
0x32, 0x38, 0x20, 0x2f, 0x20, 0x6c, 0x69, 0x62, 0x6b, 0x74, 0x78, 0x20, 0x76, 0x34,
0x2e, 0x33, 0x2e, 0x30, 0x7e, 0x31, 0, 0x4a, 0, 0, 0, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a,
0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a,
0x4a,
];
let supported_compressed_formats = CompressedImageFormats::empty();
let result = ktx2_buffer_to_image(&buffer, supported_compressed_formats, true);
assert!(result.is_ok());
}
}