diff --git a/Cargo.lock b/Cargo.lock index f9bd213ec0..8e0c22335b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1440,12 +1440,6 @@ dependencies = [ "typenum", ] -[[package]] -name = "vec_map" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" - [[package]] name = "void" version = "1.0.2" @@ -1606,7 +1600,6 @@ dependencies = [ "thread-id", "tracing", "tracing-subscriber", - "vec_map", "wgpu-types", ] diff --git a/wgpu-core/Cargo.toml b/wgpu-core/Cargo.toml index 6e6d08b221..b1d672bf65 100644 --- a/wgpu-core/Cargo.toml +++ b/wgpu-core/Cargo.toml @@ -39,7 +39,6 @@ spirv_headers = { version = "1.4.2" } thread-id = { version = "3", optional = true } tracing = { version = "0.1", default-features = false, features = ["std"] } tracing-subscriber = { version = "0.2", optional = true } -vec_map = "0.8.1" [dependencies.naga] git = "https://github.com/gfx-rs/naga" diff --git a/wgpu-core/src/hub.rs b/wgpu-core/src/hub.rs index 6bd6439361..47ca13d6de 100644 --- a/wgpu-core/src/hub.rs +++ b/wgpu-core/src/hub.rs @@ -21,7 +21,6 @@ use crate::{ }; use parking_lot::{Mutex, RwLock, RwLockReadGuard, RwLockWriteGuard}; -use vec_map::VecMap; use wgt::Backend; #[cfg(debug_assertions)] @@ -77,10 +76,18 @@ impl IdentityManager { } } +#[allow(dead_code)] +#[derive(Debug)] +enum Element { + Vacant, + Occupied(T, Epoch), + Error, +} + #[derive(Debug)] pub struct Storage { //TODO: consider concurrent hashmap? - map: VecMap<(T, Epoch)>, + map: Vec>, kind: &'static str, _phantom: PhantomData, } @@ -89,12 +96,13 @@ impl ops::Index for Storage { type Output = T; fn index(&self, id: I) -> &T { let (index, epoch, _) = id.unzip(); - let (ref value, storage_epoch) = match self.map.get(index as usize) { - Some(v) => v, - None => panic!("{}[{}] does not exist", self.kind, index), + let (ref value, storage_epoch) = match self.map[index as usize] { + Element::Occupied(ref v, epoch) => (v, epoch), + Element::Vacant => panic!("{}[{}] does not exist", self.kind, index), + Element::Error => panic!("{}[{}] is in error state", self.kind, index), }; assert_eq!( - epoch, *storage_epoch, + epoch, storage_epoch, "{}[{}] is no longer alive", self.kind, index ); @@ -105,12 +113,13 @@ impl ops::Index for Storage { impl ops::IndexMut for Storage { fn index_mut(&mut self, id: I) -> &mut T { let (index, epoch, _) = id.unzip(); - let (ref mut value, storage_epoch) = match self.map.get_mut(index as usize) { - Some(v) => v, - None => panic!("{}[{}] does not exist", self.kind, index), + let (value, storage_epoch) = match self.map[index as usize] { + Element::Occupied(ref mut v, epoch) => (v, epoch), + Element::Vacant => panic!("{}[{}] does not exist", self.kind, index), + Element::Error => panic!("{}[{}] is in error state", self.kind, index), }; assert_eq!( - epoch, *storage_epoch, + epoch, storage_epoch, "{}[{}] is no longer alive", self.kind, index ); @@ -121,32 +130,49 @@ impl ops::IndexMut for Storage { impl Storage { pub fn contains(&self, id: I) -> bool { let (index, epoch, _) = id.unzip(); - match self.map.get(index as usize) { - Some(&(_, storage_epoch)) => epoch == storage_epoch, - None => false, + match self.map[index as usize] { + Element::Occupied(_, storage_epoch) => epoch == storage_epoch, + _ => false, } } - pub fn insert(&mut self, id: I, value: T) -> Option { + pub fn insert(&mut self, id: I, value: T) { let (index, epoch, _) = id.unzip(); - let old = self.map.insert(index as usize, (value, epoch)); - old.map(|(v, _storage_epoch)| v) + if let Some(diff) = (index as usize).checked_sub(self.map.len()) { + self.map.resize_with(diff + 1, || Element::Vacant); + } + match std::mem::replace( + &mut self.map[index as usize], + Element::Occupied(value, epoch), + ) { + Element::Vacant => {} + _ => panic!("Id slot already occupied"), + } } pub fn remove(&mut self, id: I) -> Option { let (index, epoch, _) = id.unzip(); - self.map - .remove(index as usize) - .map(|(value, storage_epoch)| { - assert_eq!(epoch, storage_epoch); - value - }) + if let Element::Occupied(value, storage_epoch) = + std::mem::replace(&mut self.map[index as usize], Element::Vacant) + { + assert_eq!(epoch, storage_epoch); + Some(value) + } else { + None + } } pub fn iter(&self, backend: Backend) -> impl Iterator { - self.map.iter().map(move |(index, (value, storage_epoch))| { - (I::zip(index as Index, *storage_epoch, backend), value) - }) + self.map + .iter() + .enumerate() + .filter_map(move |(index, x)| match *x { + Element::Occupied(ref value, storage_epoch) => { + Some((I::zip(index as Index, storage_epoch, backend), value)) + } + _ => None, + }) + .into_iter() } } @@ -328,7 +354,7 @@ impl> Registry { Registry { identity: factory.spawn(0), data: RwLock::new(Storage { - map: VecMap::new(), + map: Vec::new(), kind, _phantom: PhantomData, }), @@ -340,7 +366,7 @@ impl> Registry { Registry { identity: factory.spawn(1), data: RwLock::new(Storage { - map: VecMap::new(), + map: Vec::new(), kind, _phantom: PhantomData, }), @@ -352,8 +378,7 @@ impl> Registry { impl> Registry { pub fn register>(&self, id: I, value: T, _token: &mut Token) { debug_assert_eq!(id.unzip().2, self.backend); - let old = self.data.write().insert(id, value); - assert!(old.is_none()); + self.data.write().insert(id, value); } pub fn read<'a, A: Access>( @@ -446,92 +471,120 @@ impl Hub { use hal::{device::Device as _, window::PresentationSurface as _}; let mut devices = self.devices.data.write(); - for (device, _) in devices.map.values_mut() { - device.prepare_to_die(); + for element in devices.map.iter_mut() { + if let Element::Occupied(device, _) = element { + device.prepare_to_die(); + } } - for (_, (sampler, _)) in self.samplers.data.write().map.drain() { - unsafe { - devices[sampler.device_id.value] - .raw - .destroy_sampler(sampler.raw); + for element in self.samplers.data.write().map.drain(..) { + if let Element::Occupied(sampler, _) = element { + unsafe { + devices[sampler.device_id.value] + .raw + .destroy_sampler(sampler.raw); + } } } { let textures = self.textures.data.read(); - for (_, (texture_view, _)) in self.texture_views.data.write().map.drain() { - match texture_view.inner { - TextureViewInner::Native { raw, source_id } => { - let device = &devices[textures[source_id.value].device_id.value]; - unsafe { - device.raw.destroy_image_view(raw); + for element in self.texture_views.data.write().map.drain(..) { + if let Element::Occupied(texture_view, _) = element { + match texture_view.inner { + TextureViewInner::Native { raw, source_id } => { + let device = &devices[textures[source_id.value].device_id.value]; + unsafe { + device.raw.destroy_image_view(raw); + } } + TextureViewInner::SwapChain { .. } => {} //TODO } - TextureViewInner::SwapChain { .. } => {} //TODO } } } - for (_, (texture, _)) in self.textures.data.write().map.drain() { - devices[texture.device_id.value].destroy_texture(texture); - } - for (_, (buffer, _)) in self.buffers.data.write().map.drain() { - //TODO: unmap if needed - devices[buffer.device_id.value].destroy_buffer(buffer); - } - for (_, (command_buffer, _)) in self.command_buffers.data.write().map.drain() { - devices[command_buffer.device_id.value] - .com_allocator - .after_submit(command_buffer, 0); - } - for (_, (bind_group, _)) in self.bind_groups.data.write().map.drain() { - let device = &devices[bind_group.device_id.value]; - device.destroy_bind_group(bind_group); - } - - for (_, (module, _)) in self.shader_modules.data.write().map.drain() { - let device = &devices[module.device_id.value]; - unsafe { - device.raw.destroy_shader_module(module.raw); + for element in self.textures.data.write().map.drain(..) { + if let Element::Occupied(texture, _) = element { + devices[texture.device_id.value].destroy_texture(texture); } } - for (_, (bgl, _)) in self.bind_group_layouts.data.write().map.drain() { - let device = &devices[bgl.device_id.value]; - unsafe { - device.raw.destroy_descriptor_set_layout(bgl.raw); + for element in self.buffers.data.write().map.drain(..) { + if let Element::Occupied(buffer, _) = element { + //TODO: unmap if needed + devices[buffer.device_id.value].destroy_buffer(buffer); } } - for (_, (pipeline_layout, _)) in self.pipeline_layouts.data.write().map.drain() { - let device = &devices[pipeline_layout.device_id.value]; - unsafe { - device.raw.destroy_pipeline_layout(pipeline_layout.raw); + for element in self.command_buffers.data.write().map.drain(..) { + if let Element::Occupied(command_buffer, _) = element { + devices[command_buffer.device_id.value] + .com_allocator + .after_submit(command_buffer, 0); } } - for (_, (pipeline, _)) in self.compute_pipelines.data.write().map.drain() { - let device = &devices[pipeline.device_id.value]; - unsafe { - device.raw.destroy_compute_pipeline(pipeline.raw); - } - } - for (_, (pipeline, _)) in self.render_pipelines.data.write().map.drain() { - let device = &devices[pipeline.device_id.value]; - unsafe { - device.raw.destroy_graphics_pipeline(pipeline.raw); + for element in self.bind_groups.data.write().map.drain(..) { + if let Element::Occupied(bind_group, _) = element { + let device = &devices[bind_group.device_id.value]; + device.destroy_bind_group(bind_group); } } - for (index, (swap_chain, epoch)) in self.swap_chains.data.write().map.drain() { - let device = &devices[swap_chain.device_id.value]; - let surface = &mut surface_guard[TypedId::zip(index as Index, epoch, B::VARIANT)]; - let suf = B::get_surface_mut(surface); - unsafe { - device.raw.destroy_semaphore(swap_chain.semaphore); - suf.unconfigure_swapchain(&device.raw); + for element in self.shader_modules.data.write().map.drain(..) { + if let Element::Occupied(module, _) = element { + let device = &devices[module.device_id.value]; + unsafe { + device.raw.destroy_shader_module(module.raw); + } + } + } + for element in self.bind_group_layouts.data.write().map.drain(..) { + if let Element::Occupied(bgl, _) = element { + let device = &devices[bgl.device_id.value]; + unsafe { + device.raw.destroy_descriptor_set_layout(bgl.raw); + } + } + } + for element in self.pipeline_layouts.data.write().map.drain(..) { + if let Element::Occupied(pipeline_layout, _) = element { + let device = &devices[pipeline_layout.device_id.value]; + unsafe { + device.raw.destroy_pipeline_layout(pipeline_layout.raw); + } + } + } + for element in self.compute_pipelines.data.write().map.drain(..) { + if let Element::Occupied(pipeline, _) = element { + let device = &devices[pipeline.device_id.value]; + unsafe { + device.raw.destroy_compute_pipeline(pipeline.raw); + } + } + } + for element in self.render_pipelines.data.write().map.drain(..) { + if let Element::Occupied(pipeline, _) = element { + let device = &devices[pipeline.device_id.value]; + unsafe { + device.raw.destroy_graphics_pipeline(pipeline.raw); + } } } - for (_, (device, _)) in devices.map.drain() { - device.dispose(); + for (index, element) in self.swap_chains.data.write().map.drain(..).enumerate() { + if let Element::Occupied(swap_chain, epoch) = element { + let device = &devices[swap_chain.device_id.value]; + let surface = &mut surface_guard[TypedId::zip(index as Index, epoch, B::VARIANT)]; + let suf = B::get_surface_mut(surface); + unsafe { + device.raw.destroy_semaphore(swap_chain.semaphore); + suf.unconfigure_swapchain(&device.raw); + } + } + } + + for element in devices.map.drain(..) { + if let Element::Occupied(device, _) = element { + device.dispose(); + } } } } @@ -609,8 +662,10 @@ impl Drop for Global { } // destroy surfaces - for (_, (surface, _)) in surface_guard.map.drain() { - self.instance.destroy_surface(surface); + for element in surface_guard.map.drain(..) { + if let Element::Occupied(surface, _) = element { + self.instance.destroy_surface(surface); + } } } }