diff --git a/wgpu-core/src/device/mod.rs b/wgpu-core/src/device/mod.rs index dba2fa9ec..cf5cf96a5 100644 --- a/wgpu-core/src/device/mod.rs +++ b/wgpu-core/src/device/mod.rs @@ -1844,6 +1844,15 @@ impl Global { Ok(id) } + pub fn bind_group_error( + &self, + id_in: Input, + ) -> id::BindGroupId { + let hub = B::hub(self); + let mut token = Token::root(); + hub.bind_groups.register_error(id_in, &mut token) + } + pub fn bind_group_destroy(&self, bind_group_id: id::BindGroupId) { span!(_guard, INFO, "BindGroup::drop"); diff --git a/wgpu-core/src/hub.rs b/wgpu-core/src/hub.rs index ebccf1afa..bae29f4a4 100644 --- a/wgpu-core/src/hub.rs +++ b/wgpu-core/src/hub.rs @@ -76,17 +76,15 @@ impl IdentityManager { } } -#[allow(dead_code)] #[derive(Debug)] enum Element { Vacant, Occupied(T, Epoch), - Error, + Error(Epoch), } #[derive(Debug)] pub struct Storage { - //TODO: consider concurrent hashmap? map: Vec>, kind: &'static str, _phantom: PhantomData, @@ -99,7 +97,7 @@ impl ops::Index for Storage { 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), + Element::Error(_) => panic!("{}[{}] is in error state", self.kind, index), }; assert_eq!( epoch, storage_epoch, @@ -116,7 +114,7 @@ impl ops::IndexMut for Storage { 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), + Element::Error(_) => panic!("{}[{}] is in error state", self.kind, index), }; assert_eq!( epoch, storage_epoch, @@ -128,34 +126,41 @@ impl ops::IndexMut for Storage { } impl Storage { - pub fn contains(&self, id: I) -> bool { + pub(crate) fn contains(&self, id: I) -> bool { let (index, epoch, _) = id.unzip(); match self.map[index as usize] { - Element::Occupied(_, storage_epoch) => epoch == storage_epoch, - _ => false, + Element::Vacant => false, + Element::Occupied(_, storage_epoch) | Element::Error(storage_epoch) => { + epoch == storage_epoch + } } } - pub fn insert(&mut self, id: I, value: T) { - let (index, epoch, _) = id.unzip(); - if index as usize >= self.map.len() { - self.map.resize_with(index as usize + 1, || Element::Vacant); + fn insert_impl(&mut self, index: usize, element: Element) { + if index >= self.map.len() { + self.map.resize_with(index + 1, || Element::Vacant); } - match std::mem::replace( - &mut self.map[index as usize], - Element::Occupied(value, epoch), - ) { + match std::mem::replace(&mut self.map[index], element) { Element::Vacant => {} - _ => panic!("Id slot already occupied"), + _ => panic!("Index {:?} is already occupied", index), } } - pub fn remove(&mut self, id: I) -> Option { + pub(crate) fn insert(&mut self, id: I, value: T) { + let (index, epoch, _) = id.unzip(); + self.insert_impl(index as usize, Element::Occupied(value, epoch)) + } + + pub(crate) fn insert_error(&mut self, id: I) { + let (index, epoch, _) = id.unzip(); + self.insert_impl(index as usize, Element::Error(epoch)) + } + + pub(crate) fn remove(&mut self, id: I) -> Option { let (index, epoch, _) = id.unzip(); if index as usize >= self.map.len() { - return None; - } - if let Element::Occupied(value, storage_epoch) = + None + } else if let Element::Occupied(value, storage_epoch) = std::mem::replace(&mut self.map[index as usize], Element::Vacant) { assert_eq!(epoch, storage_epoch); @@ -165,7 +170,7 @@ impl Storage { } } - pub fn iter(&self, backend: Backend) -> impl Iterator { + pub(crate) fn iter(&self, backend: Backend) -> impl Iterator { self.map .iter() .enumerate() @@ -379,19 +384,19 @@ impl> Registry { } impl> Registry { - pub fn register>(&self, id: I, value: T, _token: &mut Token) { + pub(crate) fn register>(&self, id: I, value: T, _token: &mut Token) { debug_assert_eq!(id.unzip().2, self.backend); self.data.write().insert(id, value); } - pub fn read<'a, A: Access>( + pub(crate) fn read<'a, A: Access>( &'a self, _token: &'a mut Token, ) -> (RwLockReadGuard<'a, Storage>, Token<'a, T>) { (self.data.read(), Token::new()) } - pub fn write<'a, A: Access>( + pub(crate) fn write<'a, A: Access>( &'a self, _token: &'a mut Token, ) -> (RwLockWriteGuard<'a, Storage>, Token<'a, T>) { @@ -400,7 +405,7 @@ impl> Registry { } impl> Registry { - pub fn register_identity>( + pub(crate) fn register_identity>( &self, id_in: >::Input, value: T, @@ -411,7 +416,18 @@ impl> Registry { id } - pub fn unregister<'a, A: Access>( + pub(crate) fn register_error>( + &self, + id_in: >::Input, + _token: &mut Token, + ) -> I { + let id = self.identity.process(id_in, self.backend); + debug_assert_eq!(id.unzip().2, self.backend); + self.data.write().insert_error(id); + id + } + + pub(crate) fn unregister<'a, A: Access>( &self, id: I, _token: &'a mut Token, @@ -422,7 +438,7 @@ impl> Registry { (value, Token::new()) } - pub fn free_id(&self, id: I) { + pub(crate) fn free_id(&self, id: I) { self.identity.free(id) } }