1use wgt::TextureDataOrder;
2
3#[derive(Clone, Debug, PartialEq, Eq, Hash)]
5pub struct BufferInitDescriptor<'a> {
6 pub label: crate::Label<'a>,
8 pub contents: &'a [u8],
10 pub usage: crate::BufferUsages,
13}
14
15pub trait DeviceExt {
17 fn create_buffer_init(&self, desc: &BufferInitDescriptor<'_>) -> crate::Buffer;
19
20 fn create_texture_with_data(
29 &self,
30 queue: &crate::Queue,
31 desc: &crate::TextureDescriptor<'_>,
32 order: TextureDataOrder,
33 data: &[u8],
34 ) -> crate::Texture;
35}
36
37impl DeviceExt for crate::Device {
38 fn create_buffer_init(&self, descriptor: &BufferInitDescriptor<'_>) -> crate::Buffer {
39 if descriptor.contents.is_empty() {
41 let wgt_descriptor = crate::BufferDescriptor {
42 label: descriptor.label,
43 size: 0,
44 usage: descriptor.usage,
45 mapped_at_creation: false,
46 };
47
48 self.create_buffer(&wgt_descriptor)
49 } else {
50 let unpadded_size = descriptor.contents.len() as crate::BufferAddress;
51 let align_mask = crate::COPY_BUFFER_ALIGNMENT - 1;
56 let padded_size =
57 ((unpadded_size + align_mask) & !align_mask).max(crate::COPY_BUFFER_ALIGNMENT);
58
59 let wgt_descriptor = crate::BufferDescriptor {
60 label: descriptor.label,
61 size: padded_size,
62 usage: descriptor.usage,
63 mapped_at_creation: true,
64 };
65
66 let buffer = self.create_buffer(&wgt_descriptor);
67
68 buffer.slice(..).get_mapped_range_mut()[..unpadded_size as usize]
69 .copy_from_slice(descriptor.contents);
70 buffer.unmap();
71
72 buffer
73 }
74 }
75
76 fn create_texture_with_data(
77 &self,
78 queue: &crate::Queue,
79 desc: &crate::TextureDescriptor<'_>,
80 order: TextureDataOrder,
81 data: &[u8],
82 ) -> crate::Texture {
83 let mut desc = desc.to_owned();
85 desc.usage |= crate::TextureUsages::COPY_DST;
86 let texture = self.create_texture(&desc);
87
88 let block_size = desc.format.block_copy_size(None).unwrap_or(4);
92 let (block_width, block_height) = desc.format.block_dimensions();
93 let layer_iterations = desc.array_layer_count();
94
95 let outer_iteration;
96 let inner_iteration;
97 match order {
98 TextureDataOrder::LayerMajor => {
99 outer_iteration = layer_iterations;
100 inner_iteration = desc.mip_level_count;
101 }
102 TextureDataOrder::MipMajor => {
103 outer_iteration = desc.mip_level_count;
104 inner_iteration = layer_iterations;
105 }
106 }
107
108 let mut binary_offset = 0;
109 for outer in 0..outer_iteration {
110 for inner in 0..inner_iteration {
111 let (layer, mip) = match order {
112 TextureDataOrder::LayerMajor => (outer, inner),
113 TextureDataOrder::MipMajor => (inner, outer),
114 };
115
116 let mut mip_size = desc.mip_level_size(mip).unwrap();
117 if desc.dimension != wgt::TextureDimension::D3 {
119 mip_size.depth_or_array_layers = 1;
120 }
121
122 let mip_physical = mip_size.physical_size(desc.format);
126
127 let width_blocks = mip_physical.width / block_width;
130 let height_blocks = mip_physical.height / block_height;
131
132 let bytes_per_row = width_blocks * block_size;
133 let data_size = bytes_per_row * height_blocks * mip_size.depth_or_array_layers;
134
135 let end_offset = binary_offset + data_size as usize;
136
137 queue.write_texture(
138 crate::TexelCopyTextureInfo {
139 texture: &texture,
140 mip_level: mip,
141 origin: crate::Origin3d {
142 x: 0,
143 y: 0,
144 z: layer,
145 },
146 aspect: wgt::TextureAspect::All,
147 },
148 &data[binary_offset..end_offset],
149 crate::TexelCopyBufferLayout {
150 offset: 0,
151 bytes_per_row: Some(bytes_per_row),
152 rows_per_image: Some(height_blocks),
153 },
154 mip_physical,
155 );
156
157 binary_offset = end_offset;
158 }
159 }
160
161 texture
162 }
163}