diff options
Diffstat (limited to 'wgpu/src/image/raster.rs')
-rw-r--r-- | wgpu/src/image/raster.rs | 154 |
1 files changed, 56 insertions, 98 deletions
diff --git a/wgpu/src/image/raster.rs b/wgpu/src/image/raster.rs index fa107879..4f69df8c 100644 --- a/wgpu/src/image/raster.rs +++ b/wgpu/src/image/raster.rs @@ -1,17 +1,11 @@ +use crate::image::atlas::{self, Atlas}; use iced_native::image; -use std::{ - collections::{HashMap, HashSet}, - rc::Rc, -}; +use std::collections::{HashMap, HashSet}; #[derive(Debug)] pub enum Memory { Host(::image::ImageBuffer<::image::Bgra<u8>, Vec<u8>>), - Device { - bind_group: Rc<wgpu::BindGroup>, - width: u32, - height: u32, - }, + Device(atlas::Entry), NotFound, Invalid, } @@ -20,97 +14,11 @@ impl Memory { pub fn dimensions(&self) -> (u32, u32) { match self { Memory::Host(image) => image.dimensions(), - Memory::Device { width, height, .. } => (*width, *height), + Memory::Device(entry) => entry.size(), Memory::NotFound => (1, 1), Memory::Invalid => (1, 1), } } - - pub fn upload( - &mut self, - device: &wgpu::Device, - encoder: &mut wgpu::CommandEncoder, - texture_layout: &wgpu::BindGroupLayout, - ) -> Option<Rc<wgpu::BindGroup>> { - match self { - Memory::Host(image) => { - let (width, height) = image.dimensions(); - - let extent = wgpu::Extent3d { - width, - height, - depth: 1, - }; - - let texture = device.create_texture(&wgpu::TextureDescriptor { - size: extent, - array_layer_count: 1, - mip_level_count: 1, - sample_count: 1, - dimension: wgpu::TextureDimension::D2, - format: wgpu::TextureFormat::Bgra8UnormSrgb, - usage: wgpu::TextureUsage::COPY_DST - | wgpu::TextureUsage::SAMPLED, - }); - - let temp_buf = { - let flat_samples = image.as_flat_samples(); - let slice = flat_samples.as_slice(); - - device - .create_buffer_mapped( - slice.len(), - wgpu::BufferUsage::COPY_SRC, - ) - .fill_from_slice(slice) - }; - - encoder.copy_buffer_to_texture( - wgpu::BufferCopyView { - buffer: &temp_buf, - offset: 0, - row_pitch: 4 * width as u32, - image_height: height as u32, - }, - wgpu::TextureCopyView { - texture: &texture, - array_layer: 0, - mip_level: 0, - origin: wgpu::Origin3d { - x: 0.0, - y: 0.0, - z: 0.0, - }, - }, - extent, - ); - - let bind_group = - device.create_bind_group(&wgpu::BindGroupDescriptor { - layout: texture_layout, - bindings: &[wgpu::Binding { - binding: 0, - resource: wgpu::BindingResource::TextureView( - &texture.create_default_view(), - ), - }], - }); - - let bind_group = Rc::new(bind_group); - - *self = Memory::Device { - bind_group: bind_group.clone(), - width, - height, - }; - - Some(bind_group) - } - Memory::Device { bind_group, .. } => Some(bind_group.clone()), - Memory::NotFound => None, - Memory::Invalid => None, - } - } } #[derive(Debug)] @@ -147,16 +55,66 @@ impl Cache { Memory::Invalid } } + image::Data::Pixels { + width, + height, + pixels, + } => { + if let Some(image) = ::image::ImageBuffer::from_vec( + *width, + *height, + pixels.to_vec(), + ) { + Memory::Host(image) + } else { + Memory::Invalid + } + } }; self.insert(handle, memory); self.get(handle).unwrap() } - pub fn trim(&mut self) { + pub fn upload( + &mut self, + handle: &image::Handle, + device: &wgpu::Device, + encoder: &mut wgpu::CommandEncoder, + atlas: &mut Atlas, + ) -> Option<&atlas::Entry> { + let memory = self.load(handle); + + if let Memory::Host(image) = memory { + let (width, height) = image.dimensions(); + + let entry = atlas.upload(width, height, &image, device, encoder)?; + + *memory = Memory::Device(entry); + } + + if let Memory::Device(allocation) = memory { + Some(allocation) + } else { + None + } + } + + pub fn trim(&mut self, atlas: &mut Atlas) { let hits = &self.hits; - self.map.retain(|k, _| hits.contains(k)); + self.map.retain(|k, memory| { + let retain = hits.contains(k); + + if !retain { + if let Memory::Device(entry) = memory { + atlas.remove(entry); + } + } + + retain + }); + self.hits.clear(); } |