wgpu-core: Move storage code to new storage module.

This commit is contained in:
Jim Blandy 2023-05-22 18:50:46 -07:00
parent 17d5361879
commit 4d1fbeb753
20 changed files with 308 additions and 284 deletions

View File

@ -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,
};

View File

@ -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,

View File

@ -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<G: GlobalIdentityHandlerFactory> Global<G> {
}
pub(crate) fn clear_texture<A: HalApi>(
storage: &hub::Storage<Texture<A>, TextureId>,
storage: &storage::Storage<Texture<A>, TextureId>,
dst_texture_id: Valid<TextureId>,
range: TextureInitRange,
encoder: &mut A::CommandEncoder,

View File

@ -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,

View File

@ -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,
};

View File

@ -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,
};

View File

@ -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};

View File

@ -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,

View File

@ -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,
};

View File

@ -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,

View File

@ -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)]

View File

@ -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<T> {
/// 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<T, I: id::TypedId> {
pub(crate) map: Vec<Element<T>>,
pub(crate) kind: &'static str,
pub(crate) _phantom: PhantomData<I>,
}
impl<T, I: id::TypedId> ops::Index<id::Valid<I>> for Storage<T, I> {
type Output = T;
fn index(&self, id: id::Valid<I>) -> &T {
self.get(id.0).unwrap()
}
}
impl<T, I: id::TypedId> ops::IndexMut<id::Valid<I>> for Storage<T, I> {
fn index_mut(&mut self, id: id::Valid<I>) -> &mut T {
self.get_mut(id.0).unwrap()
}
}
impl<T, I: id::TypedId> Storage<T, I> {
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<Option<&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(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<T>) {
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<T> {
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<T> {
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<Item = (I, &T)> {
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::<T>(),
..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.
///

View File

@ -45,7 +45,7 @@ type Dummy = hal::api::Empty;
/// [`Global`]: crate::global::Global
/// [`Hub`]: crate::hub::Hub
/// [`Hub<A>`]: crate::hub::Hub
/// [`Storage`]: crate::hub::Storage
/// [`Storage`]: crate::storage::Storage
/// [`Texture<A>`]: crate::resource::Texture
/// [`Index`]: std::ops::Index
/// [`IndexMut`]: std::ops::IndexMut

View File

@ -53,6 +53,7 @@ pub mod pipeline;
pub mod present;
pub mod registry;
pub mod resource;
pub mod storage;
mod track;
mod validation;

View File

@ -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)]

234
wgpu-core/src/storage.rs Normal file
View File

@ -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<T> {
/// 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<T, I: id::TypedId> {
pub(crate) map: Vec<Element<T>>,
pub(crate) kind: &'static str,
pub(crate) _phantom: PhantomData<I>,
}
impl<T, I: id::TypedId> ops::Index<id::Valid<I>> for Storage<T, I> {
type Output = T;
fn index(&self, id: id::Valid<I>) -> &T {
self.get(id.0).unwrap()
}
}
impl<T, I: id::TypedId> ops::IndexMut<id::Valid<I>> for Storage<T, I> {
fn index_mut(&mut self, id: id::Valid<I>) -> &mut T {
self.get_mut(id.0).unwrap()
}
}
impl<T, I: id::TypedId> Storage<T, I> {
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<Option<&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(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<T>) {
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<T> {
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<T> {
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<Item = (I, &T)> {
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::<T>(),
..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
}
}

View File

@ -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<A: HalApi> BufferBindGroupState<A> {
/// Adds the given resource with the given state.
pub fn add_single<'a>(
&mut self,
storage: &'a hub::Storage<Buffer<A>, BufferId>,
storage: &'a storage::Storage<Buffer<A>, BufferId>,
id: BufferId,
state: BufferUses,
) -> Option<&'a Buffer<A>> {
@ -216,7 +216,7 @@ impl<A: HalApi> BufferUsageScope<A> {
/// the vectors will be extended. A call to set_size is not needed.
pub fn merge_single<'a>(
&mut self,
storage: &'a hub::Storage<Buffer<A>, BufferId>,
storage: &'a storage::Storage<Buffer<A>, BufferId>,
id: BufferId,
new_state: BufferUses,
) -> Result<&'a Buffer<A>, UsageConflict> {
@ -349,7 +349,7 @@ impl<A: HalApi> BufferTracker<A> {
/// the vectors will be extended. A call to set_size is not needed.
pub fn set_single<'a>(
&mut self,
storage: &'a hub::Storage<Buffer<A>, BufferId>,
storage: &'a storage::Storage<Buffer<A>, BufferId>,
id: BufferId,
state: BufferUses,
) -> Option<(&'a Buffer<A>, Option<PendingTransition<BufferUses>>)> {

View File

@ -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<A: HalApi> {
impl<A: HalApi> RenderBundleScope<A> {
/// Create the render bundle scope and pull the maximum IDs from the hubs.
pub fn new(
buffers: &hub::Storage<resource::Buffer<A>, id::BufferId>,
textures: &hub::Storage<resource::Texture<A>, id::TextureId>,
bind_groups: &hub::Storage<binding_model::BindGroup<A>, id::BindGroupId>,
render_pipelines: &hub::Storage<pipeline::RenderPipeline<A>, id::RenderPipelineId>,
query_sets: &hub::Storage<resource::QuerySet<A>, id::QuerySetId>,
buffers: &storage::Storage<resource::Buffer<A>, id::BufferId>,
textures: &storage::Storage<resource::Texture<A>, id::TextureId>,
bind_groups: &storage::Storage<binding_model::BindGroup<A>, id::BindGroupId>,
render_pipelines: &storage::Storage<pipeline::RenderPipeline<A>, id::RenderPipelineId>,
query_sets: &storage::Storage<resource::QuerySet<A>, id::QuerySetId>,
) -> Self {
let mut value = Self {
buffers: BufferUsageScope::new(),
@ -392,7 +391,7 @@ impl<A: HalApi> RenderBundleScope<A> {
/// length of the storage given at the call to `new`.
pub unsafe fn merge_bind_group(
&mut self,
textures: &hub::Storage<resource::Texture<A>, id::TextureId>,
textures: &storage::Storage<resource::Texture<A>, id::TextureId>,
bind_group: &BindGroupStates<A>,
) -> Result<(), UsageConflict> {
unsafe { self.buffers.merge_bind_group(&bind_group.buffers)? };
@ -416,8 +415,8 @@ pub(crate) struct UsageScope<A: HalApi> {
impl<A: HalApi> UsageScope<A> {
/// Create the render bundle scope and pull the maximum IDs from the hubs.
pub fn new(
buffers: &hub::Storage<resource::Buffer<A>, id::BufferId>,
textures: &hub::Storage<resource::Texture<A>, id::TextureId>,
buffers: &storage::Storage<resource::Buffer<A>, id::BufferId>,
textures: &storage::Storage<resource::Texture<A>, id::TextureId>,
) -> Self {
let mut value = Self {
buffers: BufferUsageScope::new(),
@ -441,7 +440,7 @@ impl<A: HalApi> UsageScope<A> {
/// length of the storage given at the call to `new`.
pub unsafe fn merge_bind_group(
&mut self,
textures: &hub::Storage<resource::Texture<A>, id::TextureId>,
textures: &storage::Storage<resource::Texture<A>, id::TextureId>,
bind_group: &BindGroupStates<A>,
) -> Result<(), UsageConflict> {
unsafe {
@ -464,7 +463,7 @@ impl<A: HalApi> UsageScope<A> {
/// length of the storage given at the call to `new`.
pub unsafe fn merge_render_bundle(
&mut self,
textures: &hub::Storage<resource::Texture<A>, id::TextureId>,
textures: &storage::Storage<resource::Texture<A>, id::TextureId>,
render_bundle: &RenderBundleScope<A>,
) -> Result<(), UsageConflict> {
self.buffers.merge_usage_scope(&render_bundle.buffers)?;
@ -506,17 +505,19 @@ impl<A: HalApi> Tracker<A> {
/// Pull the maximum IDs from the hubs.
pub fn set_size(
&mut self,
buffers: Option<&hub::Storage<resource::Buffer<A>, id::BufferId>>,
textures: Option<&hub::Storage<resource::Texture<A>, id::TextureId>>,
views: Option<&hub::Storage<resource::TextureView<A>, id::TextureViewId>>,
samplers: Option<&hub::Storage<resource::Sampler<A>, id::SamplerId>>,
bind_groups: Option<&hub::Storage<binding_model::BindGroup<A>, id::BindGroupId>>,
buffers: Option<&storage::Storage<resource::Buffer<A>, id::BufferId>>,
textures: Option<&storage::Storage<resource::Texture<A>, id::TextureId>>,
views: Option<&storage::Storage<resource::TextureView<A>, id::TextureViewId>>,
samplers: Option<&storage::Storage<resource::Sampler<A>, id::SamplerId>>,
bind_groups: Option<&storage::Storage<binding_model::BindGroup<A>, id::BindGroupId>>,
compute_pipelines: Option<
&hub::Storage<pipeline::ComputePipeline<A>, id::ComputePipelineId>,
&storage::Storage<pipeline::ComputePipeline<A>, id::ComputePipelineId>,
>,
render_pipelines: Option<&hub::Storage<pipeline::RenderPipeline<A>, id::RenderPipelineId>>,
bundles: Option<&hub::Storage<command::RenderBundle<A>, id::RenderBundleId>>,
query_sets: Option<&hub::Storage<resource::QuerySet<A>, id::QuerySetId>>,
render_pipelines: Option<
&storage::Storage<pipeline::RenderPipeline<A>, id::RenderPipelineId>,
>,
bundles: Option<&storage::Storage<command::RenderBundle<A>, id::RenderBundleId>>,
query_sets: Option<&storage::Storage<resource::QuerySet<A>, id::QuerySetId>>,
) {
if let Some(buffers) = buffers {
self.buffers.set_size(buffers.len());
@ -571,7 +572,7 @@ impl<A: HalApi> Tracker<A> {
/// value given to `set_size`
pub unsafe fn set_and_remove_from_usage_scope_sparse(
&mut self,
textures: &hub::Storage<resource::Texture<A>, id::TextureId>,
textures: &storage::Storage<resource::Texture<A>, id::TextureId>,
scope: &mut UsageScope<A>,
bind_group: &BindGroupStates<A>,
) {

View File

@ -10,6 +10,7 @@ use crate::{
hal_api::HalApi,
hub,
id::{TypedId, Valid},
storage,
track::ResourceMetadata,
RefCount,
};
@ -45,7 +46,11 @@ impl<T: hub::Resource, Id: TypedId> StatelessBindGroupSate<T, Id> {
}
/// Adds the given resource.
pub fn add_single<'a>(&mut self, storage: &'a hub::Storage<T, Id>, id: Id) -> Option<&'a T> {
pub fn add_single<'a>(
&mut self,
storage: &'a storage::Storage<T, Id>,
id: Id,
) -> Option<&'a T> {
let resource = storage.get(id).ok()?;
self.resources
@ -118,7 +123,11 @@ impl<A: HalApi, T: hub::Resource, Id: TypedId> StatelessTracker<A, T, Id> {
///
/// 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<T, Id>, id: Id) -> Option<&'a T> {
pub fn add_single<'a>(
&mut self,
storage: &'a storage::Storage<T, Id>,
id: Id,
) -> Option<&'a T> {
let item = storage.get(id).ok()?;
let (index32, epoch, _) = id.unzip();

View File

@ -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<A: HalApi> TextureBindGroupState<A> {
/// Adds the given resource with the given state.
pub fn add_single<'a>(
&mut self,
storage: &'a hub::Storage<Texture<A>, TextureId>,
storage: &'a storage::Storage<Texture<A>, TextureId>,
id: TextureId,
ref_count: RefCount,
selector: Option<TextureSelector>,
@ -279,7 +279,7 @@ impl<A: HalApi> TextureUsageScope<A> {
/// the vectors will be extended. A call to set_size is not needed.
pub fn merge_usage_scope(
&mut self,
storage: &hub::Storage<Texture<A>, TextureId>,
storage: &storage::Storage<Texture<A>, TextureId>,
scope: &Self,
) -> Result<(), UsageConflict> {
let incoming_size = scope.set.simple.len();
@ -326,7 +326,7 @@ impl<A: HalApi> TextureUsageScope<A> {
/// method is called.
pub unsafe fn merge_bind_group(
&mut self,
storage: &hub::Storage<Texture<A>, TextureId>,
storage: &storage::Storage<Texture<A>, TextureId>,
bind_group: &TextureBindGroupState<A>,
) -> Result<(), UsageConflict> {
for &(id, ref selector, ref ref_count, state) in &bind_group.textures {
@ -351,7 +351,7 @@ impl<A: HalApi> TextureUsageScope<A> {
/// method is called.
pub unsafe fn merge_single(
&mut self,
storage: &hub::Storage<Texture<A>, TextureId>,
storage: &storage::Storage<Texture<A>, TextureId>,
id: Valid<TextureId>,
selector: Option<TextureSelector>,
ref_count: &RefCount,
@ -564,7 +564,7 @@ impl<A: HalApi> TextureTracker<A> {
/// the vectors will be extended. A call to set_size is not needed.
pub fn set_from_tracker(
&mut self,
storage: &hub::Storage<Texture<A>, TextureId>,
storage: &storage::Storage<Texture<A>, TextureId>,
tracker: &Self,
) {
let incoming_size = tracker.start_set.simple.len();
@ -610,7 +610,7 @@ impl<A: HalApi> TextureTracker<A> {
/// the vectors will be extended. A call to set_size is not needed.
pub fn set_from_usage_scope(
&mut self,
storage: &hub::Storage<Texture<A>, TextureId>,
storage: &storage::Storage<Texture<A>, TextureId>,
scope: &TextureUsageScope<A>,
) {
let incoming_size = scope.set.simple.len();
@ -662,7 +662,7 @@ impl<A: HalApi> TextureTracker<A> {
/// method is called.
pub unsafe fn set_and_remove_from_usage_scope_sparse(
&mut self,
storage: &hub::Storage<Texture<A>, TextureId>,
storage: &storage::Storage<Texture<A>, TextureId>,
scope: &mut TextureUsageScope<A>,
bind_group_state: &TextureBindGroupState<A>,
) {
@ -877,7 +877,7 @@ impl<'a> TextureStateProvider<'a> {
/// out of the texture storage.
#[inline(always)]
unsafe fn texture_data_from_texture<A: HalApi>(
storage: &hub::Storage<Texture<A>, TextureId>,
storage: &storage::Storage<Texture<A>, TextureId>,
index32: u32,
) -> (&LifeGuard, &TextureSelector) {
let texture = unsafe { storage.get_unchecked(index32) };