summaryrefslogtreecommitdiffstats
path: root/wgpu/src/image
diff options
context:
space:
mode:
Diffstat (limited to 'wgpu/src/image')
-rw-r--r--wgpu/src/image/atlas.rs92
-rw-r--r--wgpu/src/image/raster.rs4
-rw-r--r--wgpu/src/image/vector.rs18
3 files changed, 77 insertions, 37 deletions
diff --git a/wgpu/src/image/atlas.rs b/wgpu/src/image/atlas.rs
index 86a5ff49..660ebe44 100644
--- a/wgpu/src/image/atlas.rs
+++ b/wgpu/src/image/atlas.rs
@@ -28,8 +28,8 @@ impl Atlas {
};
let texture = device.create_texture(&wgpu::TextureDescriptor {
+ label: Some("iced_wgpu::image texture atlas"),
size: extent,
- array_layer_count: 2,
mip_level_count: 1,
sample_count: 1,
dimension: wgpu::TextureDimension::D2,
@@ -39,12 +39,15 @@ impl Atlas {
| wgpu::TextureUsage::SAMPLED,
});
- let texture_view = texture.create_default_view();
+ let texture_view = texture.create_view(&wgpu::TextureViewDescriptor {
+ dimension: Some(wgpu::TextureViewDimension::D2Array),
+ ..Default::default()
+ });
Atlas {
texture,
texture_view,
- layers: vec![Layer::Empty, Layer::Empty],
+ layers: vec![Layer::Empty],
}
}
@@ -56,17 +59,16 @@ impl Atlas {
self.layers.len()
}
- pub fn upload<C>(
+ pub fn upload(
&mut self,
width: u32,
height: u32,
- data: &[C],
+ data: &[u8],
device: &wgpu::Device,
encoder: &mut wgpu::CommandEncoder,
- ) -> Option<Entry>
- where
- C: Copy + 'static,
- {
+ ) -> Option<Entry> {
+ use wgpu::util::DeviceExt;
+
let entry = {
let current_size = self.layers.len();
let entry = self.allocate(width, height)?;
@@ -80,9 +82,31 @@ impl Atlas {
log::info!("Allocated atlas entry: {:?}", entry);
- let buffer = device
- .create_buffer_mapped(data.len(), wgpu::BufferUsage::COPY_SRC)
- .fill_from_slice(data);
+ // It is a webgpu requirement that:
+ // BufferCopyView.layout.bytes_per_row % wgpu::COPY_BYTES_PER_ROW_ALIGNMENT == 0
+ // So we calculate padded_width by rounding width up to the next
+ // multiple of wgpu::COPY_BYTES_PER_ROW_ALIGNMENT.
+ let align = wgpu::COPY_BYTES_PER_ROW_ALIGNMENT;
+ let padding = (align - (4 * width) % align) % align;
+ let padded_width = (4 * width + padding) as usize;
+ let padded_data_size = padded_width * height as usize;
+
+ let mut padded_data = vec![0; padded_data_size];
+
+ for row in 0..height as usize {
+ let offset = row * padded_width;
+
+ padded_data[offset..offset + 4 * width as usize].copy_from_slice(
+ &data[row * 4 * width as usize..(row + 1) * 4 * width as usize],
+ )
+ }
+
+ let buffer =
+ device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
+ label: Some("iced_wgpu::image staging buffer"),
+ contents: &padded_data,
+ usage: wgpu::BufferUsage::COPY_SRC,
+ });
match &entry {
Entry::Contiguous(allocation) => {
@@ -90,6 +114,7 @@ impl Atlas {
&buffer,
width,
height,
+ padding,
0,
&allocation,
encoder,
@@ -98,12 +123,13 @@ impl Atlas {
Entry::Fragmented { fragments, .. } => {
for fragment in fragments {
let (x, y) = fragment.position;
- let offset = (y * width + x) as usize * 4;
+ let offset = (y * padded_width as u32 + 4 * x) as usize;
self.upload_allocation(
&buffer,
width,
height,
+ padding,
offset,
&fragment.allocation,
encoder,
@@ -256,6 +282,7 @@ impl Atlas {
buffer: &wgpu::Buffer,
image_width: u32,
image_height: u32,
+ padding: u32,
offset: usize,
allocation: &Allocation,
encoder: &mut wgpu::CommandEncoder,
@@ -273,18 +300,19 @@ impl Atlas {
encoder.copy_buffer_to_texture(
wgpu::BufferCopyView {
buffer,
- offset: offset as u64,
- row_pitch: 4 * image_width,
- image_height,
+ layout: wgpu::TextureDataLayout {
+ offset: offset as u64,
+ bytes_per_row: 4 * image_width + padding,
+ rows_per_image: image_height,
+ },
},
wgpu::TextureCopyView {
texture: &self.texture,
- array_layer: layer as u32,
mip_level: 0,
origin: wgpu::Origin3d {
- x: x as f32,
- y: y as f32,
- z: 0.0,
+ x,
+ y,
+ z: layer as u32,
},
},
extent,
@@ -302,12 +330,12 @@ impl Atlas {
}
let new_texture = device.create_texture(&wgpu::TextureDescriptor {
+ label: Some("iced_wgpu::image texture atlas"),
size: wgpu::Extent3d {
width: SIZE,
height: SIZE,
- depth: 1,
+ depth: self.layers.len() as u32,
},
- array_layer_count: self.layers.len() as u32,
mip_level_count: 1,
sample_count: 1,
dimension: wgpu::TextureDimension::D2,
@@ -329,22 +357,20 @@ impl Atlas {
encoder.copy_texture_to_texture(
wgpu::TextureCopyView {
texture: &self.texture,
- array_layer: i as u32,
mip_level: 0,
origin: wgpu::Origin3d {
- x: 0.0,
- y: 0.0,
- z: 0.0,
+ x: 0,
+ y: 0,
+ z: i as u32,
},
},
wgpu::TextureCopyView {
texture: &new_texture,
- array_layer: i as u32,
mip_level: 0,
origin: wgpu::Origin3d {
- x: 0.0,
- y: 0.0,
- z: 0.0,
+ x: 0,
+ y: 0,
+ z: i as u32,
},
},
wgpu::Extent3d {
@@ -356,6 +382,10 @@ impl Atlas {
}
self.texture = new_texture;
- self.texture_view = self.texture.create_default_view();
+ self.texture_view =
+ self.texture.create_view(&wgpu::TextureViewDescriptor {
+ dimension: Some(wgpu::TextureViewDimension::D2Array),
+ ..Default::default()
+ });
}
}
diff --git a/wgpu/src/image/raster.rs b/wgpu/src/image/raster.rs
index 4f69df8c..25607dab 100644
--- a/wgpu/src/image/raster.rs
+++ b/wgpu/src/image/raster.rs
@@ -43,14 +43,14 @@ impl Cache {
let memory = match handle.data() {
image::Data::Path(path) => {
if let Ok(image) = ::image::open(path) {
- Memory::Host(image.to_bgra())
+ Memory::Host(image.to_bgra8())
} else {
Memory::NotFound
}
}
image::Data::Bytes(bytes) => {
if let Ok(image) = ::image::load_from_memory(&bytes) {
- Memory::Host(image.to_bgra())
+ Memory::Host(image.to_bgra8())
} else {
Memory::Invalid
}
diff --git a/wgpu/src/image/vector.rs b/wgpu/src/image/vector.rs
index bae0f82f..95df2e99 100644
--- a/wgpu/src/image/vector.rs
+++ b/wgpu/src/image/vector.rs
@@ -45,9 +45,19 @@ impl Cache {
let opt = resvg::Options::default();
- let svg = match resvg::usvg::Tree::from_file(handle.path(), &opt.usvg) {
- Ok(tree) => Svg::Loaded(tree),
- Err(_) => Svg::NotFound,
+ let svg = match handle.data() {
+ svg::Data::Path(path) => {
+ match resvg::usvg::Tree::from_file(path, &opt.usvg) {
+ Ok(tree) => Svg::Loaded(tree),
+ Err(_) => Svg::NotFound,
+ }
+ }
+ svg::Data::Bytes(bytes) => {
+ match resvg::usvg::Tree::from_data(&bytes, &opt.usvg) {
+ Ok(tree) => Svg::Loaded(tree),
+ Err(_) => Svg::NotFound,
+ }
+ }
};
let _ = self.svgs.insert(handle.id(), svg);
@@ -107,7 +117,7 @@ impl Cache {
let allocation = texture_atlas.upload(
width,
height,
- canvas.get_data(),
+ bytemuck::cast_slice(canvas.get_data()),
device,
encoder,
)?;