use wgpu TextureDataOrder (#19829)
# Objective - Fixes #19140 ## Solution - Use TextureDataOrder ## Testing - ran some examples that use ktx2 textures, they look fine
This commit is contained in:
parent
479c93d72b
commit
5fabb5343d
@ -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,
|
||||
|
@ -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<Vec<u8>>,
|
||||
/// 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<Option<&'static str>, &'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,
|
||||
|
@ -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::<Vec<_>>());
|
||||
image.data = Some(levels.into_iter().flatten().collect::<Vec<_>>());
|
||||
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.
|
||||
|
@ -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 {
|
||||
|
@ -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<u16>]) -> 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,
|
||||
|
Loading…
Reference in New Issue
Block a user