mirror of
https://github.com/gfx-rs/wgpu.git
synced 2026-04-22 03:02:01 -04:00
[rs] Add create_texture_with_data helper
This commit is contained in:
@@ -168,7 +168,7 @@ async fn setup<E: Example>(title: &str) -> Setup {
|
||||
label: None,
|
||||
features: (optional_features & adapter_features) | required_features,
|
||||
limits: needed_limits,
|
||||
shader_validation: true,
|
||||
shader_validation: false,
|
||||
},
|
||||
trace_dir.ok().as_ref().map(std::path::Path::new),
|
||||
)
|
||||
|
||||
@@ -165,16 +165,6 @@ impl framework::Example for Skybox {
|
||||
let layer_size = wgpu::Extent3d { depth: 1, ..size };
|
||||
let max_mips = layer_size.max_mips();
|
||||
|
||||
let texture = device.create_texture(&wgpu::TextureDescriptor {
|
||||
size,
|
||||
mip_level_count: max_mips as u32,
|
||||
sample_count: 1,
|
||||
dimension: wgpu::TextureDimension::D2,
|
||||
format: skybox_format,
|
||||
usage: wgpu::TextureUsage::SAMPLED | wgpu::TextureUsage::COPY_DST,
|
||||
label: None,
|
||||
});
|
||||
|
||||
log::debug!(
|
||||
"Copying {:?} skybox images of size {}, {}, 6 with {} mips to gpu",
|
||||
skybox_format,
|
||||
@@ -193,60 +183,19 @@ impl framework::Example for Skybox {
|
||||
|
||||
let image = ddsfile::Dds::read(&mut std::io::Cursor::new(&bytes)).unwrap();
|
||||
|
||||
let format_info = skybox_format.describe();
|
||||
|
||||
let mut binary_offset = 0;
|
||||
for layer in 0..6 {
|
||||
for mip in 0..max_mips {
|
||||
let mip_size = layer_size.at_mip_level(mip).unwrap();
|
||||
|
||||
// When uploading mips of compressed textures and the mip is supposed to be
|
||||
// a size that isn't a multiple of the block size, the mip needs to be uploaded
|
||||
// as it's "physical size" which is the size rounded up to the nearest block size.
|
||||
let mip_physical = mip_size.physical_size(skybox_format);
|
||||
|
||||
log::debug!(
|
||||
"Copying layer {} mip {} of virtual size ({}, {}) and physical size ({}, {})",
|
||||
layer,
|
||||
mip,
|
||||
mip_size.width,
|
||||
mip_size.height,
|
||||
mip_physical.width,
|
||||
mip_physical.height,
|
||||
);
|
||||
|
||||
// All these calculations are performed on the physical size as that's the
|
||||
// data that exists in the buffer.
|
||||
let width_blocks = mip_physical.width / format_info.block_dimensions.0 as u32;
|
||||
let height_blocks = mip_physical.height / format_info.block_dimensions.1 as u32;
|
||||
|
||||
let bytes_per_row = width_blocks * format_info.block_size as u32;
|
||||
let data_size = bytes_per_row * height_blocks;
|
||||
|
||||
let end_offset = binary_offset + data_size as usize;
|
||||
|
||||
queue.write_texture(
|
||||
wgpu::TextureCopyView {
|
||||
texture: &texture,
|
||||
mip_level: mip as u32,
|
||||
origin: wgpu::Origin3d {
|
||||
x: 0,
|
||||
y: 0,
|
||||
z: layer,
|
||||
},
|
||||
},
|
||||
&image.data[binary_offset..end_offset],
|
||||
wgpu::TextureDataLayout {
|
||||
offset: 0,
|
||||
bytes_per_row,
|
||||
rows_per_image: 0,
|
||||
},
|
||||
mip_physical,
|
||||
);
|
||||
|
||||
binary_offset = end_offset;
|
||||
}
|
||||
}
|
||||
let texture = device.create_texture_with_data(
|
||||
&queue,
|
||||
&wgpu::TextureDescriptor {
|
||||
size,
|
||||
mip_level_count: max_mips as u32,
|
||||
sample_count: 1,
|
||||
dimension: wgpu::TextureDimension::D2,
|
||||
format: skybox_format,
|
||||
usage: wgpu::TextureUsage::SAMPLED | wgpu::TextureUsage::COPY_DST,
|
||||
label: None,
|
||||
},
|
||||
&image.data,
|
||||
);
|
||||
|
||||
let texture_view = texture.create_view(&wgpu::TextureViewDescriptor {
|
||||
label: None,
|
||||
|
||||
@@ -4,6 +4,7 @@ mod belt;
|
||||
|
||||
use std::{
|
||||
borrow::Cow,
|
||||
convert::TryFrom,
|
||||
mem::{align_of, size_of},
|
||||
ptr::copy_nonoverlapping,
|
||||
};
|
||||
@@ -55,6 +56,22 @@ pub fn make_spirv<'a>(data: &'a [u8]) -> super::ShaderSource<'a> {
|
||||
pub trait DeviceExt {
|
||||
/// Creates a [`Buffer`] with data to initialize it.
|
||||
fn create_buffer_init(&self, desc: &BufferInitDescriptor) -> crate::Buffer;
|
||||
|
||||
/// Upload an entire texture and its mipmaps from a source buffer.
|
||||
///
|
||||
/// Expects all mipmaps to be tightly packed in the data buffer.
|
||||
///
|
||||
/// If the texture is a 2DArray texture, uploads each layer in order, expecting
|
||||
/// each layer and its mips to be tightly packed.
|
||||
///
|
||||
/// Example:
|
||||
/// Layer0Mip0 Layer0Mip1 Layer0Mip2 ... Layer1Mip0 Layer1Mip1 Layer1Mip2 ...
|
||||
fn create_texture_with_data(
|
||||
&self,
|
||||
queue: &crate::Queue,
|
||||
desc: &crate::TextureDescriptor,
|
||||
data: &[u8],
|
||||
) -> crate::Texture;
|
||||
}
|
||||
|
||||
impl DeviceExt for crate::Device {
|
||||
@@ -86,6 +103,77 @@ impl DeviceExt for crate::Device {
|
||||
buffer.unmap();
|
||||
buffer
|
||||
}
|
||||
|
||||
fn create_texture_with_data(
|
||||
&self,
|
||||
queue: &crate::Queue,
|
||||
desc: &crate::TextureDescriptor,
|
||||
data: &[u8],
|
||||
) -> crate::Texture {
|
||||
let texture = self.create_texture(desc);
|
||||
|
||||
let format_info = desc.format.describe();
|
||||
|
||||
let (layer_iterations, mip_extent) = if desc.dimension == crate::TextureDimension::D3 {
|
||||
(1, desc.size)
|
||||
} else {
|
||||
(
|
||||
desc.size.depth,
|
||||
crate::Extent3d {
|
||||
depth: 1,
|
||||
..desc.size
|
||||
},
|
||||
)
|
||||
};
|
||||
|
||||
let mip_level_count =
|
||||
u8::try_from(desc.mip_level_count).expect("mip level count overflows a u8");
|
||||
|
||||
let mut binary_offset = 0;
|
||||
for layer in 0..layer_iterations {
|
||||
for mip in 0..mip_level_count {
|
||||
let mip_size = mip_extent.at_mip_level(mip).unwrap();
|
||||
|
||||
// When uploading mips of compressed textures and the mip is supposed to be
|
||||
// a size that isn't a multiple of the block size, the mip needs to be uploaded
|
||||
// as it's "physical size" which is the size rounded up to the nearest block size.
|
||||
let mip_physical = mip_size.physical_size(desc.format);
|
||||
|
||||
// All these calculations are performed on the physical size as that's the
|
||||
// data that exists in the buffer.
|
||||
let width_blocks = mip_physical.width / format_info.block_dimensions.0 as u32;
|
||||
let height_blocks = mip_physical.height / format_info.block_dimensions.1 as u32;
|
||||
|
||||
let bytes_per_row = width_blocks * format_info.block_size as u32;
|
||||
let data_size = bytes_per_row * height_blocks;
|
||||
|
||||
let end_offset = binary_offset + data_size as usize;
|
||||
|
||||
queue.write_texture(
|
||||
crate::TextureCopyView {
|
||||
texture: &texture,
|
||||
mip_level: mip as u32,
|
||||
origin: crate::Origin3d {
|
||||
x: 0,
|
||||
y: 0,
|
||||
z: layer,
|
||||
},
|
||||
},
|
||||
&data[binary_offset..end_offset],
|
||||
crate::TextureDataLayout {
|
||||
offset: 0,
|
||||
bytes_per_row,
|
||||
rows_per_image: 0,
|
||||
},
|
||||
mip_physical,
|
||||
);
|
||||
|
||||
binary_offset = end_offset;
|
||||
}
|
||||
}
|
||||
|
||||
texture
|
||||
}
|
||||
}
|
||||
|
||||
/// Describes a [`Buffer`] when allocating.
|
||||
|
||||
Reference in New Issue
Block a user