Skip to content

Commit

Permalink
bevy_render: Fix array textures in KTX2
Browse files Browse the repository at this point in the history
The GPU seems to want data in the order layer 0 mip 0..n, layer 1 mip 0..n,
etc. The ordering of the data in KTX2 confused me as it is the opposite - mip n
layer 0..n, mip n-1 layer 0..n, etc.
  • Loading branch information
superdump committed May 1, 2022
1 parent 7557f4d commit 2756009
Showing 1 changed file with 35 additions and 26 deletions.
61 changes: 35 additions & 26 deletions crates/bevy_render/src/texture/ktx2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ use ktx2::{
};
use wgpu::{Extent3d, TextureDimension, TextureFormat};

const UASTC_BLOCK_SIZE_BYTES: usize = 128 / 8;

use super::{CompressedImageFormats, DataFormat, Image, TextureError, TranscodeFormat};

pub fn ktx2_buffer_to_image(
Expand Down Expand Up @@ -115,33 +117,40 @@ pub fn ktx2_buffer_to_image(
let (block_width_pixels, block_height_pixels) = (4, 4);

let transcoder = LowLevelUastcTranscoder::new();
for (level, level_data) in levels.iter().enumerate() {
let slice_parameters = SliceParametersUastc {
num_blocks_x: ((original_width + block_width_pixels - 1)
/ block_width_pixels)
.max(1),
num_blocks_y: ((original_height + block_height_pixels - 1)
/ block_height_pixels)
.max(1),
has_alpha: false,
original_width,
original_height,
};
for layer in 0..layer_count as usize {
for (level, level_data) in levels.iter().enumerate() {
let (num_blocks_x, num_blocks_y) = (
((original_width + block_width_pixels - 1) / block_width_pixels).max(1),
((original_height + block_height_pixels - 1) / block_height_pixels)
.max(1),
);
let bytes_per_layer =
num_blocks_x as usize * num_blocks_y as usize * UASTC_BLOCK_SIZE_BYTES;

let slice_parameters = SliceParametersUastc {
num_blocks_x,
num_blocks_y,
has_alpha: false,
original_width,
original_height,
};

transcoder
.transcode_slice(
level_data,
slice_parameters,
DecodeFlags::HIGH_QUALITY,
transcode_block_format,
)
.map(|transcoded_level| transcoded.push(transcoded_level))
.map_err(|error| {
TextureError::SuperDecompressionError(format!(
"Failed to transcode mip level {} from UASTC to {:?}: {:?}",
level, transcode_block_format, error
))
})?;
transcoder
.transcode_slice(
&level_data[(layer * bytes_per_layer)
..((layer + 1) * bytes_per_layer)],
slice_parameters,
DecodeFlags::HIGH_QUALITY,
transcode_block_format,
)
.map(|transcoded_level| transcoded.push(transcoded_level))
.map_err(|error| {
TextureError::SuperDecompressionError(format!(
"Failed to transcode mip level {} layer {} from UASTC to {:?}: {:?}",
level, layer, transcode_block_format, error
))
})?;
}

// Next mip dimensions are half the current, minimum 1x1
original_width = (original_width / 2).max(1);
Expand Down

0 comments on commit 2756009

Please sign in to comment.