diff --git a/crates/bevy_core_pipeline/src/tonemapping/mod.rs b/crates/bevy_core_pipeline/src/tonemapping/mod.rs index f4d88357db..c57d49d32b 100644 --- a/crates/bevy_core_pipeline/src/tonemapping/mod.rs +++ b/crates/bevy_core_pipeline/src/tonemapping/mod.rs @@ -447,6 +447,7 @@ pub fn lut_placeholder() -> Image { let data = vec![255, 0, 255, 255]; Image { data: Some(data), + data_order: TextureDataOrder::default(), texture_descriptor: TextureDescriptor { size: Extent3d::default(), format, diff --git a/crates/bevy_image/src/image.rs b/crates/bevy_image/src/image.rs index a5ced88ec6..b6da5c5333 100644 --- a/crates/bevy_image/src/image.rs +++ b/crates/bevy_image/src/image.rs @@ -18,8 +18,8 @@ use serde::{Deserialize, Serialize}; use thiserror::Error; use wgpu_types::{ AddressMode, CompareFunction, Extent3d, Features, FilterMode, SamplerBorderColor, - SamplerDescriptor, TextureDescriptor, TextureDimension, TextureFormat, TextureUsages, - TextureViewDescriptor, + SamplerDescriptor, TextureDataOrder, TextureDescriptor, TextureDimension, TextureFormat, + TextureUsages, TextureViewDescriptor, }; /// Trait used to provide default values for Bevy-external types that @@ -372,6 +372,10 @@ pub struct Image { /// CPU, then this should be `None`. /// Otherwise, it should always be `Some`. pub data: Option>, + /// For texture data with layers and mips, this field controls how wgpu interprets the buffer layout. + /// + /// Use [`TextureDataOrder::default()`] for all other cases. + pub data_order: TextureDataOrder, // TODO: this nesting makes accessing Image metadata verbose. Either flatten out descriptor or add accessors. pub texture_descriptor: TextureDescriptor, &'static [TextureFormat]>, /// The [`ImageSampler`] to use during rendering. @@ -764,6 +768,7 @@ impl Image { ) -> Self { Image { data: None, + data_order: TextureDataOrder::default(), texture_descriptor: TextureDescriptor { size, format, diff --git a/crates/bevy_image/src/ktx2.rs b/crates/bevy_image/src/ktx2.rs index c8245f3893..b4d838b4a9 100644 --- a/crates/bevy_image/src/ktx2.rs +++ b/crates/bevy_image/src/ktx2.rs @@ -238,43 +238,12 @@ pub fn ktx2_buffer_to_image( ))); } - // Reorder data from KTX2 MipXLayerYFaceZ to wgpu LayerYFaceZMipX - let texture_format_info = texture_format; - let (block_width_pixels, block_height_pixels) = ( - texture_format_info.block_dimensions().0 as usize, - texture_format_info.block_dimensions().1 as usize, - ); - // Texture is not a depth or stencil format, it is possible to pass `None` and unwrap - let block_bytes = texture_format_info.block_copy_size(None).unwrap() as usize; - - 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) = ( - (width as usize >> level).max(1), - (height as usize >> level).max(1), - (depth as usize >> level).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), - ); - let level_bytes = num_blocks_x * num_blocks_y * level_depth * block_bytes; - - 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; - image.data = Some(wgpu_data.into_iter().flatten().collect::>()); + image.data = Some(levels.into_iter().flatten().collect::>()); + image.data_order = wgpu_types::TextureDataOrder::MipMajor; // Note: we must give wgpu the logical texture dimensions, so it can correctly compute mip sizes. // However this currently causes wgpu to panic if the dimensions arent a multiple of blocksize. // See https://github.com/gfx-rs/wgpu/issues/7677 for more context. diff --git a/crates/bevy_render/src/texture/gpu_image.rs b/crates/bevy_render/src/texture/gpu_image.rs index 1337df5e00..6fbc9dfea7 100644 --- a/crates/bevy_render/src/texture/gpu_image.rs +++ b/crates/bevy_render/src/texture/gpu_image.rs @@ -51,8 +51,7 @@ impl RenderAsset for GpuImage { render_device.create_texture_with_data( render_queue, &image.texture_descriptor, - // TODO: Is this correct? Do we need to use `MipMajor` if it's a ktx2 file? - wgpu::util::TextureDataOrder::default(), + image.data_order, data, ) } else { diff --git a/crates/bevy_sprite/src/tilemap_chunk/mod.rs b/crates/bevy_sprite/src/tilemap_chunk/mod.rs index 1ac8568643..174816154b 100644 --- a/crates/bevy_sprite/src/tilemap_chunk/mod.rs +++ b/crates/bevy_sprite/src/tilemap_chunk/mod.rs @@ -16,7 +16,9 @@ use bevy_math::{FloatOrd, UVec2, Vec2, Vec3}; use bevy_platform::collections::HashMap; use bevy_render::{ mesh::{Indices, Mesh, Mesh2d, PrimitiveTopology}, - render_resource::{TextureDescriptor, TextureDimension, TextureFormat, TextureUsages}, + render_resource::{ + TextureDataOrder, TextureDescriptor, TextureDimension, TextureFormat, TextureUsages, + }, }; use tracing::warn; @@ -198,6 +200,7 @@ fn make_chunk_image(size: &UVec2, indices: &[Option]) -> Image { .flat_map(|i| u16::to_ne_bytes(i.unwrap_or(u16::MAX))) .collect(), ), + data_order: TextureDataOrder::default(), texture_descriptor: TextureDescriptor { size: size.to_extents(), dimension: TextureDimension::D2,