diff --git a/wgpu-core/src/command/bind.rs b/wgpu-core/src/command/bind.rs index 1452ddb84..9b87028e3 100644 --- a/wgpu-core/src/command/bind.rs +++ b/wgpu-core/src/command/bind.rs @@ -2,9 +2,9 @@ use crate::{ binding_model::{BindGroup, LateMinBufferBindingSizeMismatch, PipelineLayout}, device::SHADER_STAGE_COUNT, hal_api::HalApi, - hub::Storage, id::{BindGroupId, BindGroupLayoutId, PipelineLayoutId, Valid}, pipeline::LateSizedBufferGroup, + storage::Storage, Stored, }; diff --git a/wgpu-core/src/command/bundle.rs b/wgpu-core/src/command/bundle.rs index 8372c41c8..a594b0abe 100644 --- a/wgpu-core/src/command/bundle.rs +++ b/wgpu-core/src/command/bundle.rs @@ -91,12 +91,13 @@ use crate::{ }, error::{ErrorFormatter, PrettyError}, hal_api::HalApi, - hub::{Hub, Resource, Storage, Token}, + hub::{Hub, Resource, Token}, id, identity::GlobalIdentityHandlerFactory, init_tracker::{BufferInitTrackerAction, MemoryInitKind, TextureInitTrackerAction}, pipeline::{self, PipelineFlags}, resource, + storage::Storage, track::RenderBundleScope, validation::check_buffer_usage, Label, LabelHelpers, LifeGuard, Stored, diff --git a/wgpu-core/src/command/clear.rs b/wgpu-core/src/command/clear.rs index a180c3343..9f677298b 100644 --- a/wgpu-core/src/command/clear.rs +++ b/wgpu-core/src/command/clear.rs @@ -7,11 +7,12 @@ use crate::{ get_lowest_common_denom, global::Global, hal_api::HalApi, - hub::{self, Token}, + hub::Token, id::{BufferId, CommandEncoderId, DeviceId, TextureId, Valid}, identity::GlobalIdentityHandlerFactory, init_tracker::{MemoryInitKind, TextureInitRange}, resource::{Texture, TextureClearMode}, + storage, track::{TextureSelector, TextureTracker}, }; @@ -235,7 +236,7 @@ impl Global { } pub(crate) fn clear_texture( - storage: &hub::Storage, TextureId>, + storage: &storage::Storage, TextureId>, dst_texture_id: Valid, range: TextureInitRange, encoder: &mut A::CommandEncoder, diff --git a/wgpu-core/src/command/compute.rs b/wgpu-core/src/command/compute.rs index bd5c26095..bc7c463f4 100644 --- a/wgpu-core/src/command/compute.rs +++ b/wgpu-core/src/command/compute.rs @@ -13,12 +13,13 @@ use crate::{ error::{ErrorFormatter, PrettyError}, global::Global, hal_api::HalApi, - hub::{Storage, Token}, + hub::Token, id, identity::GlobalIdentityHandlerFactory, init_tracker::MemoryInitKind, pipeline, resource::{self, Buffer, Texture}, + storage::Storage, track::{Tracker, UsageConflict, UsageScope}, validation::{check_buffer_usage, MissingBufferUsageError}, Label, diff --git a/wgpu-core/src/command/memory_init.rs b/wgpu-core/src/command/memory_init.rs index 4aee08973..e8d5f7313 100644 --- a/wgpu-core/src/command/memory_init.rs +++ b/wgpu-core/src/command/memory_init.rs @@ -5,10 +5,10 @@ use hal::CommandEncoder; use crate::{ device::Device, hal_api::HalApi, - hub::Storage, id::{self, TextureId}, init_tracker::*, resource::{Buffer, Texture}, + storage::Storage, track::{TextureTracker, Tracker}, FastHashMap, }; diff --git a/wgpu-core/src/command/mod.rs b/wgpu-core/src/command/mod.rs index 627bc80d7..fef73303f 100644 --- a/wgpu-core/src/command/mod.rs +++ b/wgpu-core/src/command/mod.rs @@ -23,10 +23,11 @@ use crate::track::{Tracker, UsageScope}; use crate::{ global::Global, hal_api::HalApi, - hub::{Storage, Token}, + hub::Token, id, identity::GlobalIdentityHandlerFactory, resource::{Buffer, Texture}, + storage::Storage, Label, Stored, }; diff --git a/wgpu-core/src/command/query.rs b/wgpu-core/src/command/query.rs index b319f7ff3..c34aa48c9 100644 --- a/wgpu-core/src/command/query.rs +++ b/wgpu-core/src/command/query.rs @@ -6,11 +6,12 @@ use crate::{ command::{CommandBuffer, CommandEncoderError}, global::Global, hal_api::HalApi, - hub::{Storage, Token}, + hub::Token, id::{self, Id, TypedId}, identity::GlobalIdentityHandlerFactory, init_tracker::MemoryInitKind, resource::QuerySet, + storage::Storage, Epoch, FastHashMap, Index, }; use std::{iter, marker::PhantomData}; diff --git a/wgpu-core/src/command/render.rs b/wgpu-core/src/command/render.rs index 6aaa49858..6da48fc00 100644 --- a/wgpu-core/src/command/render.rs +++ b/wgpu-core/src/command/render.rs @@ -16,12 +16,13 @@ use crate::{ error::{ErrorFormatter, PrettyError}, global::Global, hal_api::HalApi, - hub::{Storage, Token}, + hub::Token, id, identity::GlobalIdentityHandlerFactory, init_tracker::{MemoryInitKind, TextureInitRange, TextureInitTrackerAction}, pipeline::{self, PipelineFlags}, resource::{self, Buffer, Texture, TextureView, TextureViewNotRenderableReason}, + storage::Storage, track::{TextureSelector, UsageConflict, UsageScope}, validation::{ check_buffer_usage, check_texture_usage, MissingBufferUsageError, MissingTextureUsageError, diff --git a/wgpu-core/src/command/transfer.rs b/wgpu-core/src/command/transfer.rs index 3a1763f09..58f88a70e 100644 --- a/wgpu-core/src/command/transfer.rs +++ b/wgpu-core/src/command/transfer.rs @@ -7,7 +7,7 @@ use crate::{ error::{ErrorFormatter, PrettyError}, global::Global, hal_api::HalApi, - hub::{Storage, Token}, + hub::Token, id::{BufferId, CommandEncoderId, TextureId, Valid}, identity::GlobalIdentityHandlerFactory, init_tracker::{ @@ -15,6 +15,7 @@ use crate::{ TextureInitTrackerAction, }, resource::{Texture, TextureErrorDimension}, + storage::Storage, track::TextureSelector, }; diff --git a/wgpu-core/src/device/mod.rs b/wgpu-core/src/device/mod.rs index c688b6402..1b49c39af 100644 --- a/wgpu-core/src/device/mod.rs +++ b/wgpu-core/src/device/mod.rs @@ -3,7 +3,7 @@ use crate::{ device::life::WaitIdleError, global::Global, hal_api::HalApi, - hub::{Hub, InvalidId, Storage, Token}, + hub::{Hub, Token}, id, identity::{GlobalIdentityHandlerFactory, Input}, init_tracker::{ @@ -14,6 +14,7 @@ use crate::{ pipeline, present, resource::{self, BufferAccessResult, BufferMapState, TextureViewNotRenderableReason}, resource::{BufferAccessError, BufferMapOperation}, + storage::{InvalidId, Storage}, track::{BindGroupStates, TextureSelector, Tracker}, validation::{self, check_buffer_usage, check_texture_usage}, FastHashMap, Label, LabelHelpers as _, LifeGuard, MultiRefCount, RefCount, Stored, diff --git a/wgpu-core/src/global.rs b/wgpu-core/src/global.rs index c3fd78442..533126596 100644 --- a/wgpu-core/src/global.rs +++ b/wgpu-core/src/global.rs @@ -1,11 +1,11 @@ use crate::{ hal_api::HalApi, - hub::{Element, StorageReport}, hub::{HubReport, Hubs}, id, identity::GlobalIdentityHandlerFactory, instance::{Instance, Surface}, registry::Registry, + storage::{Element, StorageReport}, }; #[derive(Debug)] diff --git a/wgpu-core/src/hub.rs b/wgpu-core/src/hub.rs index 77d0d6614..78beb7d46 100644 --- a/wgpu-core/src/hub.rs +++ b/wgpu-core/src/hub.rs @@ -140,6 +140,7 @@ creation fails, the id supplied for that resource is marked to indicate as much, allowing subsequent operations using that id to be properly flagged as errors as well. +[`Backend`]: wgt::Backend [`Global`]: crate::global::Global [`Global::new`]: crate::global::Global::new [`gfx_select`]: crate::gfx_select @@ -165,243 +166,12 @@ use crate::{ pipeline::{ComputePipeline, RenderPipeline, ShaderModule}, registry::Registry, resource::{Buffer, QuerySet, Sampler, StagingBuffer, Texture, TextureClearMode, TextureView}, - Epoch, Index, + storage::{Element, Storage, StorageReport}, }; -use wgt::Backend; - #[cfg(debug_assertions)] use std::cell::Cell; -use std::{fmt::Debug, marker::PhantomData, mem, ops}; - -/// An entry in a `Storage::map` table. -#[derive(Debug)] -pub(crate) enum Element { - /// There are no live ids with this index. - Vacant, - - /// There is one live id with this index, allocated at the given - /// epoch. - Occupied(T, Epoch), - - /// Like `Occupied`, but an error occurred when creating the - /// resource. - /// - /// The given `String` is the resource's descriptor label. - Error(Epoch, String), -} - -#[derive(Clone, Debug, Default)] -pub struct StorageReport { - pub num_occupied: usize, - pub num_vacant: usize, - pub num_error: usize, - pub element_size: usize, -} - -impl StorageReport { - pub fn is_empty(&self) -> bool { - self.num_occupied + self.num_vacant + self.num_error == 0 - } -} - -#[derive(Clone, Debug)] -pub(crate) struct InvalidId; - -/// A table of `T` values indexed by the id type `I`. -/// -/// The table is represented as a vector indexed by the ids' index -/// values, so you should use an id allocator like `IdentityManager` -/// that keeps the index values dense and close to zero. -#[derive(Debug)] -pub struct Storage { - pub(crate) map: Vec>, - pub(crate) kind: &'static str, - pub(crate) _phantom: PhantomData, -} - -impl ops::Index> for Storage { - type Output = T; - fn index(&self, id: id::Valid) -> &T { - self.get(id.0).unwrap() - } -} - -impl ops::IndexMut> for Storage { - fn index_mut(&mut self, id: id::Valid) -> &mut T { - self.get_mut(id.0).unwrap() - } -} - -impl Storage { - pub(crate) fn contains(&self, id: I) -> bool { - let (index, epoch, _) = id.unzip(); - match self.map.get(index as usize) { - Some(&Element::Vacant) => false, - Some(&Element::Occupied(_, storage_epoch) | &Element::Error(storage_epoch, _)) => { - storage_epoch == epoch - } - None => false, - } - } - - /// Attempts to get a reference to an item behind a potentially invalid ID. - /// - /// Returns [`None`] if there is an epoch mismatch, or the entry is empty. - /// - /// This function is primarily intended for the `as_hal` family of functions - /// where you may need to fallibly get a object backed by an id that could - /// be in a different hub. - pub(crate) fn try_get(&self, id: I) -> Result, InvalidId> { - let (index, epoch, _) = id.unzip(); - let (result, storage_epoch) = match self.map.get(index as usize) { - Some(&Element::Occupied(ref v, epoch)) => (Ok(Some(v)), epoch), - Some(&Element::Vacant) => return Ok(None), - Some(&Element::Error(epoch, ..)) => (Err(InvalidId), epoch), - None => return Err(InvalidId), - }; - assert_eq!( - epoch, storage_epoch, - "{}[{}] is no longer alive", - self.kind, index - ); - result - } - - /// Get a reference to an item behind a potentially invalid ID. - /// Panics if there is an epoch mismatch, or the entry is empty. - pub(crate) fn get(&self, id: I) -> Result<&T, InvalidId> { - let (index, epoch, _) = id.unzip(); - let (result, storage_epoch) = match self.map.get(index as usize) { - Some(&Element::Occupied(ref v, epoch)) => (Ok(v), epoch), - Some(&Element::Vacant) => panic!("{}[{}] does not exist", self.kind, index), - Some(&Element::Error(epoch, ..)) => (Err(InvalidId), epoch), - None => return Err(InvalidId), - }; - assert_eq!( - epoch, storage_epoch, - "{}[{}] is no longer alive", - self.kind, index - ); - result - } - - /// Get a mutable reference to an item behind a potentially invalid ID. - /// Panics if there is an epoch mismatch, or the entry is empty. - pub(crate) fn get_mut(&mut self, id: I) -> Result<&mut T, InvalidId> { - let (index, epoch, _) = id.unzip(); - let (result, storage_epoch) = match self.map.get_mut(index as usize) { - Some(&mut Element::Occupied(ref mut v, epoch)) => (Ok(v), epoch), - Some(&mut Element::Vacant) | None => panic!("{}[{}] does not exist", self.kind, index), - Some(&mut Element::Error(epoch, ..)) => (Err(InvalidId), epoch), - }; - assert_eq!( - epoch, storage_epoch, - "{}[{}] is no longer alive", - self.kind, index - ); - result - } - - pub(crate) unsafe fn get_unchecked(&self, id: u32) -> &T { - match self.map[id as usize] { - Element::Occupied(ref v, _) => v, - Element::Vacant => panic!("{}[{}] does not exist", self.kind, id), - Element::Error(_, _) => panic!(""), - } - } - - pub(crate) fn label_for_invalid_id(&self, id: I) -> &str { - let (index, _, _) = id.unzip(); - match self.map.get(index as usize) { - Some(&Element::Error(_, ref label)) => label, - _ => "", - } - } - - 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], element) { - Element::Vacant => {} - _ => panic!("Index {index:?} is already occupied"), - } - } - - 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, label: &str) { - let (index, epoch, _) = id.unzip(); - self.insert_impl(index as usize, Element::Error(epoch, label.to_string())) - } - - pub(crate) fn force_replace(&mut self, id: I, value: T) { - let (index, epoch, _) = id.unzip(); - self.map[index as usize] = Element::Occupied(value, epoch); - } - - pub(crate) fn remove(&mut self, id: I) -> Option { - let (index, epoch, _) = id.unzip(); - match std::mem::replace(&mut self.map[index as usize], Element::Vacant) { - Element::Occupied(value, storage_epoch) => { - assert_eq!(epoch, storage_epoch); - Some(value) - } - Element::Error(..) => None, - Element::Vacant => panic!("Cannot remove a vacant resource"), - } - } - - // Prevents panic on out of range access, allows Vacant elements. - pub(crate) fn _try_remove(&mut self, id: I) -> Option { - let (index, epoch, _) = id.unzip(); - if index as usize >= self.map.len() { - 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); - Some(value) - } else { - None - } - } - - pub(crate) fn iter(&self, backend: Backend) -> impl Iterator { - 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, - }) - } - - pub(crate) fn len(&self) -> usize { - self.map.len() - } - - pub(crate) fn generate_report(&self) -> StorageReport { - let mut report = StorageReport { - element_size: mem::size_of::(), - ..Default::default() - }; - for element in self.map.iter() { - match *element { - Element::Occupied(..) => report.num_occupied += 1, - Element::Vacant => report.num_vacant += 1, - Element::Error(..) => report.num_error += 1, - } - } - report - } -} +use std::{fmt::Debug, marker::PhantomData}; /// Type system for enforcing the lock order on [`Hub`] fields. /// diff --git a/wgpu-core/src/id.rs b/wgpu-core/src/id.rs index 412344000..6aa2aa287 100644 --- a/wgpu-core/src/id.rs +++ b/wgpu-core/src/id.rs @@ -45,7 +45,7 @@ type Dummy = hal::api::Empty; /// [`Global`]: crate::global::Global /// [`Hub`]: crate::hub::Hub /// [`Hub`]: crate::hub::Hub -/// [`Storage`]: crate::hub::Storage +/// [`Storage`]: crate::storage::Storage /// [`Texture`]: crate::resource::Texture /// [`Index`]: std::ops::Index /// [`IndexMut`]: std::ops::IndexMut diff --git a/wgpu-core/src/lib.rs b/wgpu-core/src/lib.rs index 4fe8d6188..542b29941 100644 --- a/wgpu-core/src/lib.rs +++ b/wgpu-core/src/lib.rs @@ -53,6 +53,7 @@ pub mod pipeline; pub mod present; pub mod registry; pub mod resource; +pub mod storage; mod track; mod validation; diff --git a/wgpu-core/src/registry.rs b/wgpu-core/src/registry.rs index fa633705a..9f1ed4250 100644 --- a/wgpu-core/src/registry.rs +++ b/wgpu-core/src/registry.rs @@ -4,9 +4,10 @@ use parking_lot::{RwLock, RwLockReadGuard, RwLockWriteGuard}; use wgt::Backend; use crate::{ - hub::{Access, Resource, Storage, Token}, + hub::{Access, Resource, Token}, id, identity::{IdentityHandler, IdentityHandlerFactory}, + storage::Storage, }; #[derive(Debug)] diff --git a/wgpu-core/src/storage.rs b/wgpu-core/src/storage.rs new file mode 100644 index 000000000..07387b019 --- /dev/null +++ b/wgpu-core/src/storage.rs @@ -0,0 +1,234 @@ +use std::{marker::PhantomData, mem, ops}; + +use wgt::Backend; + +use crate::{id, Epoch, Index}; + +/// An entry in a `Storage::map` table. +#[derive(Debug)] +pub(crate) enum Element { + /// There are no live ids with this index. + Vacant, + + /// There is one live id with this index, allocated at the given + /// epoch. + Occupied(T, Epoch), + + /// Like `Occupied`, but an error occurred when creating the + /// resource. + /// + /// The given `String` is the resource's descriptor label. + Error(Epoch, String), +} + +#[derive(Clone, Debug, Default)] +pub struct StorageReport { + pub num_occupied: usize, + pub num_vacant: usize, + pub num_error: usize, + pub element_size: usize, +} + +impl StorageReport { + pub fn is_empty(&self) -> bool { + self.num_occupied + self.num_vacant + self.num_error == 0 + } +} + +#[derive(Clone, Debug)] +pub(crate) struct InvalidId; + +/// A table of `T` values indexed by the id type `I`. +/// +/// The table is represented as a vector indexed by the ids' index +/// values, so you should use an id allocator like `IdentityManager` +/// that keeps the index values dense and close to zero. +#[derive(Debug)] +pub struct Storage { + pub(crate) map: Vec>, + pub(crate) kind: &'static str, + pub(crate) _phantom: PhantomData, +} + +impl ops::Index> for Storage { + type Output = T; + fn index(&self, id: id::Valid) -> &T { + self.get(id.0).unwrap() + } +} + +impl ops::IndexMut> for Storage { + fn index_mut(&mut self, id: id::Valid) -> &mut T { + self.get_mut(id.0).unwrap() + } +} + +impl Storage { + pub(crate) fn contains(&self, id: I) -> bool { + let (index, epoch, _) = id.unzip(); + match self.map.get(index as usize) { + Some(&Element::Vacant) => false, + Some(&Element::Occupied(_, storage_epoch) | &Element::Error(storage_epoch, _)) => { + storage_epoch == epoch + } + None => false, + } + } + + /// Attempts to get a reference to an item behind a potentially invalid ID. + /// + /// Returns [`None`] if there is an epoch mismatch, or the entry is empty. + /// + /// This function is primarily intended for the `as_hal` family of functions + /// where you may need to fallibly get a object backed by an id that could + /// be in a different hub. + pub(crate) fn try_get(&self, id: I) -> Result, InvalidId> { + let (index, epoch, _) = id.unzip(); + let (result, storage_epoch) = match self.map.get(index as usize) { + Some(&Element::Occupied(ref v, epoch)) => (Ok(Some(v)), epoch), + Some(&Element::Vacant) => return Ok(None), + Some(&Element::Error(epoch, ..)) => (Err(InvalidId), epoch), + None => return Err(InvalidId), + }; + assert_eq!( + epoch, storage_epoch, + "{}[{}] is no longer alive", + self.kind, index + ); + result + } + + /// Get a reference to an item behind a potentially invalid ID. + /// Panics if there is an epoch mismatch, or the entry is empty. + pub(crate) fn get(&self, id: I) -> Result<&T, InvalidId> { + let (index, epoch, _) = id.unzip(); + let (result, storage_epoch) = match self.map.get(index as usize) { + Some(&Element::Occupied(ref v, epoch)) => (Ok(v), epoch), + Some(&Element::Vacant) => panic!("{}[{}] does not exist", self.kind, index), + Some(&Element::Error(epoch, ..)) => (Err(InvalidId), epoch), + None => return Err(InvalidId), + }; + assert_eq!( + epoch, storage_epoch, + "{}[{}] is no longer alive", + self.kind, index + ); + result + } + + /// Get a mutable reference to an item behind a potentially invalid ID. + /// Panics if there is an epoch mismatch, or the entry is empty. + pub(crate) fn get_mut(&mut self, id: I) -> Result<&mut T, InvalidId> { + let (index, epoch, _) = id.unzip(); + let (result, storage_epoch) = match self.map.get_mut(index as usize) { + Some(&mut Element::Occupied(ref mut v, epoch)) => (Ok(v), epoch), + Some(&mut Element::Vacant) | None => panic!("{}[{}] does not exist", self.kind, index), + Some(&mut Element::Error(epoch, ..)) => (Err(InvalidId), epoch), + }; + assert_eq!( + epoch, storage_epoch, + "{}[{}] is no longer alive", + self.kind, index + ); + result + } + + pub(crate) unsafe fn get_unchecked(&self, id: u32) -> &T { + match self.map[id as usize] { + Element::Occupied(ref v, _) => v, + Element::Vacant => panic!("{}[{}] does not exist", self.kind, id), + Element::Error(_, _) => panic!(""), + } + } + + pub(crate) fn label_for_invalid_id(&self, id: I) -> &str { + let (index, _, _) = id.unzip(); + match self.map.get(index as usize) { + Some(&Element::Error(_, ref label)) => label, + _ => "", + } + } + + 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], element) { + Element::Vacant => {} + _ => panic!("Index {index:?} is already occupied"), + } + } + + 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, label: &str) { + let (index, epoch, _) = id.unzip(); + self.insert_impl(index as usize, Element::Error(epoch, label.to_string())) + } + + pub(crate) fn force_replace(&mut self, id: I, value: T) { + let (index, epoch, _) = id.unzip(); + self.map[index as usize] = Element::Occupied(value, epoch); + } + + pub(crate) fn remove(&mut self, id: I) -> Option { + let (index, epoch, _) = id.unzip(); + match std::mem::replace(&mut self.map[index as usize], Element::Vacant) { + Element::Occupied(value, storage_epoch) => { + assert_eq!(epoch, storage_epoch); + Some(value) + } + Element::Error(..) => None, + Element::Vacant => panic!("Cannot remove a vacant resource"), + } + } + + // Prevents panic on out of range access, allows Vacant elements. + pub(crate) fn _try_remove(&mut self, id: I) -> Option { + let (index, epoch, _) = id.unzip(); + if index as usize >= self.map.len() { + 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); + Some(value) + } else { + None + } + } + + pub(crate) fn iter(&self, backend: Backend) -> impl Iterator { + 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, + }) + } + + pub(crate) fn len(&self) -> usize { + self.map.len() + } + + pub(crate) fn generate_report(&self) -> StorageReport { + let mut report = StorageReport { + element_size: mem::size_of::(), + ..Default::default() + }; + for element in self.map.iter() { + match *element { + Element::Occupied(..) => report.num_occupied += 1, + Element::Vacant => report.num_vacant += 1, + Element::Error(..) => report.num_error += 1, + } + } + report + } +} diff --git a/wgpu-core/src/track/buffer.rs b/wgpu-core/src/track/buffer.rs index e8cd63ece..b5e61c5a2 100644 --- a/wgpu-core/src/track/buffer.rs +++ b/wgpu-core/src/track/buffer.rs @@ -10,9 +10,9 @@ use std::{borrow::Cow, marker::PhantomData, vec::Drain}; use super::PendingTransition; use crate::{ hal_api::HalApi, - hub, id::{BufferId, TypedId, Valid}, resource::Buffer, + storage, track::{ invalid_resource_state, skip_barrier, ResourceMetadata, ResourceMetadataProvider, ResourceUses, UsageConflict, @@ -73,7 +73,7 @@ impl BufferBindGroupState { /// Adds the given resource with the given state. pub fn add_single<'a>( &mut self, - storage: &'a hub::Storage, BufferId>, + storage: &'a storage::Storage, BufferId>, id: BufferId, state: BufferUses, ) -> Option<&'a Buffer> { @@ -216,7 +216,7 @@ impl BufferUsageScope { /// the vectors will be extended. A call to set_size is not needed. pub fn merge_single<'a>( &mut self, - storage: &'a hub::Storage, BufferId>, + storage: &'a storage::Storage, BufferId>, id: BufferId, new_state: BufferUses, ) -> Result<&'a Buffer, UsageConflict> { @@ -349,7 +349,7 @@ impl BufferTracker { /// the vectors will be extended. A call to set_size is not needed. pub fn set_single<'a>( &mut self, - storage: &'a hub::Storage, BufferId>, + storage: &'a storage::Storage, BufferId>, id: BufferId, state: BufferUses, ) -> Option<(&'a Buffer, Option>)> { diff --git a/wgpu-core/src/track/mod.rs b/wgpu-core/src/track/mod.rs index 31f0eb250..111b4e961 100644 --- a/wgpu-core/src/track/mod.rs +++ b/wgpu-core/src/track/mod.rs @@ -102,9 +102,8 @@ mod texture; use crate::{ binding_model, command, conv, hal_api::HalApi, - hub, id::{self, TypedId}, - pipeline, resource, + pipeline, resource, storage, }; use std::{fmt, ops}; @@ -358,11 +357,11 @@ pub(crate) struct RenderBundleScope { impl RenderBundleScope { /// Create the render bundle scope and pull the maximum IDs from the hubs. pub fn new( - buffers: &hub::Storage, id::BufferId>, - textures: &hub::Storage, id::TextureId>, - bind_groups: &hub::Storage, id::BindGroupId>, - render_pipelines: &hub::Storage, id::RenderPipelineId>, - query_sets: &hub::Storage, id::QuerySetId>, + buffers: &storage::Storage, id::BufferId>, + textures: &storage::Storage, id::TextureId>, + bind_groups: &storage::Storage, id::BindGroupId>, + render_pipelines: &storage::Storage, id::RenderPipelineId>, + query_sets: &storage::Storage, id::QuerySetId>, ) -> Self { let mut value = Self { buffers: BufferUsageScope::new(), @@ -392,7 +391,7 @@ impl RenderBundleScope { /// length of the storage given at the call to `new`. pub unsafe fn merge_bind_group( &mut self, - textures: &hub::Storage, id::TextureId>, + textures: &storage::Storage, id::TextureId>, bind_group: &BindGroupStates, ) -> Result<(), UsageConflict> { unsafe { self.buffers.merge_bind_group(&bind_group.buffers)? }; @@ -416,8 +415,8 @@ pub(crate) struct UsageScope { impl UsageScope { /// Create the render bundle scope and pull the maximum IDs from the hubs. pub fn new( - buffers: &hub::Storage, id::BufferId>, - textures: &hub::Storage, id::TextureId>, + buffers: &storage::Storage, id::BufferId>, + textures: &storage::Storage, id::TextureId>, ) -> Self { let mut value = Self { buffers: BufferUsageScope::new(), @@ -441,7 +440,7 @@ impl UsageScope { /// length of the storage given at the call to `new`. pub unsafe fn merge_bind_group( &mut self, - textures: &hub::Storage, id::TextureId>, + textures: &storage::Storage, id::TextureId>, bind_group: &BindGroupStates, ) -> Result<(), UsageConflict> { unsafe { @@ -464,7 +463,7 @@ impl UsageScope { /// length of the storage given at the call to `new`. pub unsafe fn merge_render_bundle( &mut self, - textures: &hub::Storage, id::TextureId>, + textures: &storage::Storage, id::TextureId>, render_bundle: &RenderBundleScope, ) -> Result<(), UsageConflict> { self.buffers.merge_usage_scope(&render_bundle.buffers)?; @@ -506,17 +505,19 @@ impl Tracker { /// Pull the maximum IDs from the hubs. pub fn set_size( &mut self, - buffers: Option<&hub::Storage, id::BufferId>>, - textures: Option<&hub::Storage, id::TextureId>>, - views: Option<&hub::Storage, id::TextureViewId>>, - samplers: Option<&hub::Storage, id::SamplerId>>, - bind_groups: Option<&hub::Storage, id::BindGroupId>>, + buffers: Option<&storage::Storage, id::BufferId>>, + textures: Option<&storage::Storage, id::TextureId>>, + views: Option<&storage::Storage, id::TextureViewId>>, + samplers: Option<&storage::Storage, id::SamplerId>>, + bind_groups: Option<&storage::Storage, id::BindGroupId>>, compute_pipelines: Option< - &hub::Storage, id::ComputePipelineId>, + &storage::Storage, id::ComputePipelineId>, >, - render_pipelines: Option<&hub::Storage, id::RenderPipelineId>>, - bundles: Option<&hub::Storage, id::RenderBundleId>>, - query_sets: Option<&hub::Storage, id::QuerySetId>>, + render_pipelines: Option< + &storage::Storage, id::RenderPipelineId>, + >, + bundles: Option<&storage::Storage, id::RenderBundleId>>, + query_sets: Option<&storage::Storage, id::QuerySetId>>, ) { if let Some(buffers) = buffers { self.buffers.set_size(buffers.len()); @@ -571,7 +572,7 @@ impl Tracker { /// value given to `set_size` pub unsafe fn set_and_remove_from_usage_scope_sparse( &mut self, - textures: &hub::Storage, id::TextureId>, + textures: &storage::Storage, id::TextureId>, scope: &mut UsageScope, bind_group: &BindGroupStates, ) { diff --git a/wgpu-core/src/track/stateless.rs b/wgpu-core/src/track/stateless.rs index 269269044..5ea5904d7 100644 --- a/wgpu-core/src/track/stateless.rs +++ b/wgpu-core/src/track/stateless.rs @@ -10,6 +10,7 @@ use crate::{ hal_api::HalApi, hub, id::{TypedId, Valid}, + storage, track::ResourceMetadata, RefCount, }; @@ -45,7 +46,11 @@ impl StatelessBindGroupSate { } /// Adds the given resource. - pub fn add_single<'a>(&mut self, storage: &'a hub::Storage, id: Id) -> Option<&'a T> { + pub fn add_single<'a>( + &mut self, + storage: &'a storage::Storage, + id: Id, + ) -> Option<&'a T> { let resource = storage.get(id).ok()?; self.resources @@ -118,7 +123,11 @@ impl StatelessTracker { /// /// If the ID is higher than the length of internal vectors, /// the vectors will be extended. A call to set_size is not needed. - pub fn add_single<'a>(&mut self, storage: &'a hub::Storage, id: Id) -> Option<&'a T> { + pub fn add_single<'a>( + &mut self, + storage: &'a storage::Storage, + id: Id, + ) -> Option<&'a T> { let item = storage.get(id).ok()?; let (index32, epoch, _) = id.unzip(); diff --git a/wgpu-core/src/track/texture.rs b/wgpu-core/src/track/texture.rs index cf76ca999..8b0926adf 100644 --- a/wgpu-core/src/track/texture.rs +++ b/wgpu-core/src/track/texture.rs @@ -22,9 +22,9 @@ use super::{range::RangedStates, PendingTransition}; use crate::{ hal_api::HalApi, - hub, id::{TextureId, TypedId, Valid}, resource::Texture, + storage, track::{ invalid_resource_state, skip_barrier, ResourceMetadata, ResourceMetadataProvider, ResourceUses, UsageConflict, @@ -185,7 +185,7 @@ impl TextureBindGroupState { /// Adds the given resource with the given state. pub fn add_single<'a>( &mut self, - storage: &'a hub::Storage, TextureId>, + storage: &'a storage::Storage, TextureId>, id: TextureId, ref_count: RefCount, selector: Option, @@ -279,7 +279,7 @@ impl TextureUsageScope { /// the vectors will be extended. A call to set_size is not needed. pub fn merge_usage_scope( &mut self, - storage: &hub::Storage, TextureId>, + storage: &storage::Storage, TextureId>, scope: &Self, ) -> Result<(), UsageConflict> { let incoming_size = scope.set.simple.len(); @@ -326,7 +326,7 @@ impl TextureUsageScope { /// method is called. pub unsafe fn merge_bind_group( &mut self, - storage: &hub::Storage, TextureId>, + storage: &storage::Storage, TextureId>, bind_group: &TextureBindGroupState, ) -> Result<(), UsageConflict> { for &(id, ref selector, ref ref_count, state) in &bind_group.textures { @@ -351,7 +351,7 @@ impl TextureUsageScope { /// method is called. pub unsafe fn merge_single( &mut self, - storage: &hub::Storage, TextureId>, + storage: &storage::Storage, TextureId>, id: Valid, selector: Option, ref_count: &RefCount, @@ -564,7 +564,7 @@ impl TextureTracker { /// the vectors will be extended. A call to set_size is not needed. pub fn set_from_tracker( &mut self, - storage: &hub::Storage, TextureId>, + storage: &storage::Storage, TextureId>, tracker: &Self, ) { let incoming_size = tracker.start_set.simple.len(); @@ -610,7 +610,7 @@ impl TextureTracker { /// the vectors will be extended. A call to set_size is not needed. pub fn set_from_usage_scope( &mut self, - storage: &hub::Storage, TextureId>, + storage: &storage::Storage, TextureId>, scope: &TextureUsageScope, ) { let incoming_size = scope.set.simple.len(); @@ -662,7 +662,7 @@ impl TextureTracker { /// method is called. pub unsafe fn set_and_remove_from_usage_scope_sparse( &mut self, - storage: &hub::Storage, TextureId>, + storage: &storage::Storage, TextureId>, scope: &mut TextureUsageScope, bind_group_state: &TextureBindGroupState, ) { @@ -877,7 +877,7 @@ impl<'a> TextureStateProvider<'a> { /// out of the texture storage. #[inline(always)] unsafe fn texture_data_from_texture( - storage: &hub::Storage, TextureId>, + storage: &storage::Storage, TextureId>, index32: u32, ) -> (&LifeGuard, &TextureSelector) { let texture = unsafe { storage.get_unchecked(index32) };