mirror of
https://github.com/gfx-rs/wgpu.git
synced 2025-02-18 09:52:35 +00:00
wgpu-core: Move storage code to new storage
module.
This commit is contained in:
parent
17d5361879
commit
4d1fbeb753
@ -2,9 +2,9 @@ use crate::{
|
|||||||
binding_model::{BindGroup, LateMinBufferBindingSizeMismatch, PipelineLayout},
|
binding_model::{BindGroup, LateMinBufferBindingSizeMismatch, PipelineLayout},
|
||||||
device::SHADER_STAGE_COUNT,
|
device::SHADER_STAGE_COUNT,
|
||||||
hal_api::HalApi,
|
hal_api::HalApi,
|
||||||
hub::Storage,
|
|
||||||
id::{BindGroupId, BindGroupLayoutId, PipelineLayoutId, Valid},
|
id::{BindGroupId, BindGroupLayoutId, PipelineLayoutId, Valid},
|
||||||
pipeline::LateSizedBufferGroup,
|
pipeline::LateSizedBufferGroup,
|
||||||
|
storage::Storage,
|
||||||
Stored,
|
Stored,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -91,12 +91,13 @@ use crate::{
|
|||||||
},
|
},
|
||||||
error::{ErrorFormatter, PrettyError},
|
error::{ErrorFormatter, PrettyError},
|
||||||
hal_api::HalApi,
|
hal_api::HalApi,
|
||||||
hub::{Hub, Resource, Storage, Token},
|
hub::{Hub, Resource, Token},
|
||||||
id,
|
id,
|
||||||
identity::GlobalIdentityHandlerFactory,
|
identity::GlobalIdentityHandlerFactory,
|
||||||
init_tracker::{BufferInitTrackerAction, MemoryInitKind, TextureInitTrackerAction},
|
init_tracker::{BufferInitTrackerAction, MemoryInitKind, TextureInitTrackerAction},
|
||||||
pipeline::{self, PipelineFlags},
|
pipeline::{self, PipelineFlags},
|
||||||
resource,
|
resource,
|
||||||
|
storage::Storage,
|
||||||
track::RenderBundleScope,
|
track::RenderBundleScope,
|
||||||
validation::check_buffer_usage,
|
validation::check_buffer_usage,
|
||||||
Label, LabelHelpers, LifeGuard, Stored,
|
Label, LabelHelpers, LifeGuard, Stored,
|
||||||
|
@ -7,11 +7,12 @@ use crate::{
|
|||||||
get_lowest_common_denom,
|
get_lowest_common_denom,
|
||||||
global::Global,
|
global::Global,
|
||||||
hal_api::HalApi,
|
hal_api::HalApi,
|
||||||
hub::{self, Token},
|
hub::Token,
|
||||||
id::{BufferId, CommandEncoderId, DeviceId, TextureId, Valid},
|
id::{BufferId, CommandEncoderId, DeviceId, TextureId, Valid},
|
||||||
identity::GlobalIdentityHandlerFactory,
|
identity::GlobalIdentityHandlerFactory,
|
||||||
init_tracker::{MemoryInitKind, TextureInitRange},
|
init_tracker::{MemoryInitKind, TextureInitRange},
|
||||||
resource::{Texture, TextureClearMode},
|
resource::{Texture, TextureClearMode},
|
||||||
|
storage,
|
||||||
track::{TextureSelector, TextureTracker},
|
track::{TextureSelector, TextureTracker},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -235,7 +236,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn clear_texture<A: HalApi>(
|
pub(crate) fn clear_texture<A: HalApi>(
|
||||||
storage: &hub::Storage<Texture<A>, TextureId>,
|
storage: &storage::Storage<Texture<A>, TextureId>,
|
||||||
dst_texture_id: Valid<TextureId>,
|
dst_texture_id: Valid<TextureId>,
|
||||||
range: TextureInitRange,
|
range: TextureInitRange,
|
||||||
encoder: &mut A::CommandEncoder,
|
encoder: &mut A::CommandEncoder,
|
||||||
|
@ -13,12 +13,13 @@ use crate::{
|
|||||||
error::{ErrorFormatter, PrettyError},
|
error::{ErrorFormatter, PrettyError},
|
||||||
global::Global,
|
global::Global,
|
||||||
hal_api::HalApi,
|
hal_api::HalApi,
|
||||||
hub::{Storage, Token},
|
hub::Token,
|
||||||
id,
|
id,
|
||||||
identity::GlobalIdentityHandlerFactory,
|
identity::GlobalIdentityHandlerFactory,
|
||||||
init_tracker::MemoryInitKind,
|
init_tracker::MemoryInitKind,
|
||||||
pipeline,
|
pipeline,
|
||||||
resource::{self, Buffer, Texture},
|
resource::{self, Buffer, Texture},
|
||||||
|
storage::Storage,
|
||||||
track::{Tracker, UsageConflict, UsageScope},
|
track::{Tracker, UsageConflict, UsageScope},
|
||||||
validation::{check_buffer_usage, MissingBufferUsageError},
|
validation::{check_buffer_usage, MissingBufferUsageError},
|
||||||
Label,
|
Label,
|
||||||
|
@ -5,10 +5,10 @@ use hal::CommandEncoder;
|
|||||||
use crate::{
|
use crate::{
|
||||||
device::Device,
|
device::Device,
|
||||||
hal_api::HalApi,
|
hal_api::HalApi,
|
||||||
hub::Storage,
|
|
||||||
id::{self, TextureId},
|
id::{self, TextureId},
|
||||||
init_tracker::*,
|
init_tracker::*,
|
||||||
resource::{Buffer, Texture},
|
resource::{Buffer, Texture},
|
||||||
|
storage::Storage,
|
||||||
track::{TextureTracker, Tracker},
|
track::{TextureTracker, Tracker},
|
||||||
FastHashMap,
|
FastHashMap,
|
||||||
};
|
};
|
||||||
|
@ -23,10 +23,11 @@ use crate::track::{Tracker, UsageScope};
|
|||||||
use crate::{
|
use crate::{
|
||||||
global::Global,
|
global::Global,
|
||||||
hal_api::HalApi,
|
hal_api::HalApi,
|
||||||
hub::{Storage, Token},
|
hub::Token,
|
||||||
id,
|
id,
|
||||||
identity::GlobalIdentityHandlerFactory,
|
identity::GlobalIdentityHandlerFactory,
|
||||||
resource::{Buffer, Texture},
|
resource::{Buffer, Texture},
|
||||||
|
storage::Storage,
|
||||||
Label, Stored,
|
Label, Stored,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -6,11 +6,12 @@ use crate::{
|
|||||||
command::{CommandBuffer, CommandEncoderError},
|
command::{CommandBuffer, CommandEncoderError},
|
||||||
global::Global,
|
global::Global,
|
||||||
hal_api::HalApi,
|
hal_api::HalApi,
|
||||||
hub::{Storage, Token},
|
hub::Token,
|
||||||
id::{self, Id, TypedId},
|
id::{self, Id, TypedId},
|
||||||
identity::GlobalIdentityHandlerFactory,
|
identity::GlobalIdentityHandlerFactory,
|
||||||
init_tracker::MemoryInitKind,
|
init_tracker::MemoryInitKind,
|
||||||
resource::QuerySet,
|
resource::QuerySet,
|
||||||
|
storage::Storage,
|
||||||
Epoch, FastHashMap, Index,
|
Epoch, FastHashMap, Index,
|
||||||
};
|
};
|
||||||
use std::{iter, marker::PhantomData};
|
use std::{iter, marker::PhantomData};
|
||||||
|
@ -16,12 +16,13 @@ use crate::{
|
|||||||
error::{ErrorFormatter, PrettyError},
|
error::{ErrorFormatter, PrettyError},
|
||||||
global::Global,
|
global::Global,
|
||||||
hal_api::HalApi,
|
hal_api::HalApi,
|
||||||
hub::{Storage, Token},
|
hub::Token,
|
||||||
id,
|
id,
|
||||||
identity::GlobalIdentityHandlerFactory,
|
identity::GlobalIdentityHandlerFactory,
|
||||||
init_tracker::{MemoryInitKind, TextureInitRange, TextureInitTrackerAction},
|
init_tracker::{MemoryInitKind, TextureInitRange, TextureInitTrackerAction},
|
||||||
pipeline::{self, PipelineFlags},
|
pipeline::{self, PipelineFlags},
|
||||||
resource::{self, Buffer, Texture, TextureView, TextureViewNotRenderableReason},
|
resource::{self, Buffer, Texture, TextureView, TextureViewNotRenderableReason},
|
||||||
|
storage::Storage,
|
||||||
track::{TextureSelector, UsageConflict, UsageScope},
|
track::{TextureSelector, UsageConflict, UsageScope},
|
||||||
validation::{
|
validation::{
|
||||||
check_buffer_usage, check_texture_usage, MissingBufferUsageError, MissingTextureUsageError,
|
check_buffer_usage, check_texture_usage, MissingBufferUsageError, MissingTextureUsageError,
|
||||||
|
@ -7,7 +7,7 @@ use crate::{
|
|||||||
error::{ErrorFormatter, PrettyError},
|
error::{ErrorFormatter, PrettyError},
|
||||||
global::Global,
|
global::Global,
|
||||||
hal_api::HalApi,
|
hal_api::HalApi,
|
||||||
hub::{Storage, Token},
|
hub::Token,
|
||||||
id::{BufferId, CommandEncoderId, TextureId, Valid},
|
id::{BufferId, CommandEncoderId, TextureId, Valid},
|
||||||
identity::GlobalIdentityHandlerFactory,
|
identity::GlobalIdentityHandlerFactory,
|
||||||
init_tracker::{
|
init_tracker::{
|
||||||
@ -15,6 +15,7 @@ use crate::{
|
|||||||
TextureInitTrackerAction,
|
TextureInitTrackerAction,
|
||||||
},
|
},
|
||||||
resource::{Texture, TextureErrorDimension},
|
resource::{Texture, TextureErrorDimension},
|
||||||
|
storage::Storage,
|
||||||
track::TextureSelector,
|
track::TextureSelector,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@ use crate::{
|
|||||||
device::life::WaitIdleError,
|
device::life::WaitIdleError,
|
||||||
global::Global,
|
global::Global,
|
||||||
hal_api::HalApi,
|
hal_api::HalApi,
|
||||||
hub::{Hub, InvalidId, Storage, Token},
|
hub::{Hub, Token},
|
||||||
id,
|
id,
|
||||||
identity::{GlobalIdentityHandlerFactory, Input},
|
identity::{GlobalIdentityHandlerFactory, Input},
|
||||||
init_tracker::{
|
init_tracker::{
|
||||||
@ -14,6 +14,7 @@ use crate::{
|
|||||||
pipeline, present,
|
pipeline, present,
|
||||||
resource::{self, BufferAccessResult, BufferMapState, TextureViewNotRenderableReason},
|
resource::{self, BufferAccessResult, BufferMapState, TextureViewNotRenderableReason},
|
||||||
resource::{BufferAccessError, BufferMapOperation},
|
resource::{BufferAccessError, BufferMapOperation},
|
||||||
|
storage::{InvalidId, Storage},
|
||||||
track::{BindGroupStates, TextureSelector, Tracker},
|
track::{BindGroupStates, TextureSelector, Tracker},
|
||||||
validation::{self, check_buffer_usage, check_texture_usage},
|
validation::{self, check_buffer_usage, check_texture_usage},
|
||||||
FastHashMap, Label, LabelHelpers as _, LifeGuard, MultiRefCount, RefCount, Stored,
|
FastHashMap, Label, LabelHelpers as _, LifeGuard, MultiRefCount, RefCount, Stored,
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
hal_api::HalApi,
|
hal_api::HalApi,
|
||||||
hub::{Element, StorageReport},
|
|
||||||
hub::{HubReport, Hubs},
|
hub::{HubReport, Hubs},
|
||||||
id,
|
id,
|
||||||
identity::GlobalIdentityHandlerFactory,
|
identity::GlobalIdentityHandlerFactory,
|
||||||
instance::{Instance, Surface},
|
instance::{Instance, Surface},
|
||||||
registry::Registry,
|
registry::Registry,
|
||||||
|
storage::{Element, StorageReport},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -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
|
as much, allowing subsequent operations using that id to be properly
|
||||||
flagged as errors as well.
|
flagged as errors as well.
|
||||||
|
|
||||||
|
[`Backend`]: wgt::Backend
|
||||||
[`Global`]: crate::global::Global
|
[`Global`]: crate::global::Global
|
||||||
[`Global::new`]: crate::global::Global::new
|
[`Global::new`]: crate::global::Global::new
|
||||||
[`gfx_select`]: crate::gfx_select
|
[`gfx_select`]: crate::gfx_select
|
||||||
@ -165,243 +166,12 @@ use crate::{
|
|||||||
pipeline::{ComputePipeline, RenderPipeline, ShaderModule},
|
pipeline::{ComputePipeline, RenderPipeline, ShaderModule},
|
||||||
registry::Registry,
|
registry::Registry,
|
||||||
resource::{Buffer, QuerySet, Sampler, StagingBuffer, Texture, TextureClearMode, TextureView},
|
resource::{Buffer, QuerySet, Sampler, StagingBuffer, Texture, TextureClearMode, TextureView},
|
||||||
Epoch, Index,
|
storage::{Element, Storage, StorageReport},
|
||||||
};
|
};
|
||||||
|
|
||||||
use wgt::Backend;
|
|
||||||
|
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
use std::{fmt::Debug, marker::PhantomData, mem, ops};
|
use std::{fmt::Debug, marker::PhantomData};
|
||||||
|
|
||||||
/// 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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Type system for enforcing the lock order on [`Hub`] fields.
|
/// Type system for enforcing the lock order on [`Hub`] fields.
|
||||||
///
|
///
|
||||||
|
@ -45,7 +45,7 @@ type Dummy = hal::api::Empty;
|
|||||||
/// [`Global`]: crate::global::Global
|
/// [`Global`]: crate::global::Global
|
||||||
/// [`Hub`]: crate::hub::Hub
|
/// [`Hub`]: crate::hub::Hub
|
||||||
/// [`Hub<A>`]: crate::hub::Hub
|
/// [`Hub<A>`]: crate::hub::Hub
|
||||||
/// [`Storage`]: crate::hub::Storage
|
/// [`Storage`]: crate::storage::Storage
|
||||||
/// [`Texture<A>`]: crate::resource::Texture
|
/// [`Texture<A>`]: crate::resource::Texture
|
||||||
/// [`Index`]: std::ops::Index
|
/// [`Index`]: std::ops::Index
|
||||||
/// [`IndexMut`]: std::ops::IndexMut
|
/// [`IndexMut`]: std::ops::IndexMut
|
||||||
|
@ -53,6 +53,7 @@ pub mod pipeline;
|
|||||||
pub mod present;
|
pub mod present;
|
||||||
pub mod registry;
|
pub mod registry;
|
||||||
pub mod resource;
|
pub mod resource;
|
||||||
|
pub mod storage;
|
||||||
mod track;
|
mod track;
|
||||||
mod validation;
|
mod validation;
|
||||||
|
|
||||||
|
@ -4,9 +4,10 @@ use parking_lot::{RwLock, RwLockReadGuard, RwLockWriteGuard};
|
|||||||
use wgt::Backend;
|
use wgt::Backend;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
hub::{Access, Resource, Storage, Token},
|
hub::{Access, Resource, Token},
|
||||||
id,
|
id,
|
||||||
identity::{IdentityHandler, IdentityHandlerFactory},
|
identity::{IdentityHandler, IdentityHandlerFactory},
|
||||||
|
storage::Storage,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
234
wgpu-core/src/storage.rs
Normal file
234
wgpu-core/src/storage.rs
Normal 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
|
||||||
|
}
|
||||||
|
}
|
@ -10,9 +10,9 @@ use std::{borrow::Cow, marker::PhantomData, vec::Drain};
|
|||||||
use super::PendingTransition;
|
use super::PendingTransition;
|
||||||
use crate::{
|
use crate::{
|
||||||
hal_api::HalApi,
|
hal_api::HalApi,
|
||||||
hub,
|
|
||||||
id::{BufferId, TypedId, Valid},
|
id::{BufferId, TypedId, Valid},
|
||||||
resource::Buffer,
|
resource::Buffer,
|
||||||
|
storage,
|
||||||
track::{
|
track::{
|
||||||
invalid_resource_state, skip_barrier, ResourceMetadata, ResourceMetadataProvider,
|
invalid_resource_state, skip_barrier, ResourceMetadata, ResourceMetadataProvider,
|
||||||
ResourceUses, UsageConflict,
|
ResourceUses, UsageConflict,
|
||||||
@ -73,7 +73,7 @@ impl<A: HalApi> BufferBindGroupState<A> {
|
|||||||
/// Adds the given resource with the given state.
|
/// Adds the given resource with the given state.
|
||||||
pub fn add_single<'a>(
|
pub fn add_single<'a>(
|
||||||
&mut self,
|
&mut self,
|
||||||
storage: &'a hub::Storage<Buffer<A>, BufferId>,
|
storage: &'a storage::Storage<Buffer<A>, BufferId>,
|
||||||
id: BufferId,
|
id: BufferId,
|
||||||
state: BufferUses,
|
state: BufferUses,
|
||||||
) -> Option<&'a Buffer<A>> {
|
) -> 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.
|
/// the vectors will be extended. A call to set_size is not needed.
|
||||||
pub fn merge_single<'a>(
|
pub fn merge_single<'a>(
|
||||||
&mut self,
|
&mut self,
|
||||||
storage: &'a hub::Storage<Buffer<A>, BufferId>,
|
storage: &'a storage::Storage<Buffer<A>, BufferId>,
|
||||||
id: BufferId,
|
id: BufferId,
|
||||||
new_state: BufferUses,
|
new_state: BufferUses,
|
||||||
) -> Result<&'a Buffer<A>, UsageConflict> {
|
) -> 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.
|
/// the vectors will be extended. A call to set_size is not needed.
|
||||||
pub fn set_single<'a>(
|
pub fn set_single<'a>(
|
||||||
&mut self,
|
&mut self,
|
||||||
storage: &'a hub::Storage<Buffer<A>, BufferId>,
|
storage: &'a storage::Storage<Buffer<A>, BufferId>,
|
||||||
id: BufferId,
|
id: BufferId,
|
||||||
state: BufferUses,
|
state: BufferUses,
|
||||||
) -> Option<(&'a Buffer<A>, Option<PendingTransition<BufferUses>>)> {
|
) -> Option<(&'a Buffer<A>, Option<PendingTransition<BufferUses>>)> {
|
||||||
|
@ -102,9 +102,8 @@ mod texture;
|
|||||||
use crate::{
|
use crate::{
|
||||||
binding_model, command, conv,
|
binding_model, command, conv,
|
||||||
hal_api::HalApi,
|
hal_api::HalApi,
|
||||||
hub,
|
|
||||||
id::{self, TypedId},
|
id::{self, TypedId},
|
||||||
pipeline, resource,
|
pipeline, resource, storage,
|
||||||
};
|
};
|
||||||
|
|
||||||
use std::{fmt, ops};
|
use std::{fmt, ops};
|
||||||
@ -358,11 +357,11 @@ pub(crate) struct RenderBundleScope<A: HalApi> {
|
|||||||
impl<A: HalApi> RenderBundleScope<A> {
|
impl<A: HalApi> RenderBundleScope<A> {
|
||||||
/// Create the render bundle scope and pull the maximum IDs from the hubs.
|
/// Create the render bundle scope and pull the maximum IDs from the hubs.
|
||||||
pub fn new(
|
pub fn new(
|
||||||
buffers: &hub::Storage<resource::Buffer<A>, id::BufferId>,
|
buffers: &storage::Storage<resource::Buffer<A>, id::BufferId>,
|
||||||
textures: &hub::Storage<resource::Texture<A>, id::TextureId>,
|
textures: &storage::Storage<resource::Texture<A>, id::TextureId>,
|
||||||
bind_groups: &hub::Storage<binding_model::BindGroup<A>, id::BindGroupId>,
|
bind_groups: &storage::Storage<binding_model::BindGroup<A>, id::BindGroupId>,
|
||||||
render_pipelines: &hub::Storage<pipeline::RenderPipeline<A>, id::RenderPipelineId>,
|
render_pipelines: &storage::Storage<pipeline::RenderPipeline<A>, id::RenderPipelineId>,
|
||||||
query_sets: &hub::Storage<resource::QuerySet<A>, id::QuerySetId>,
|
query_sets: &storage::Storage<resource::QuerySet<A>, id::QuerySetId>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let mut value = Self {
|
let mut value = Self {
|
||||||
buffers: BufferUsageScope::new(),
|
buffers: BufferUsageScope::new(),
|
||||||
@ -392,7 +391,7 @@ impl<A: HalApi> RenderBundleScope<A> {
|
|||||||
/// length of the storage given at the call to `new`.
|
/// length of the storage given at the call to `new`.
|
||||||
pub unsafe fn merge_bind_group(
|
pub unsafe fn merge_bind_group(
|
||||||
&mut self,
|
&mut self,
|
||||||
textures: &hub::Storage<resource::Texture<A>, id::TextureId>,
|
textures: &storage::Storage<resource::Texture<A>, id::TextureId>,
|
||||||
bind_group: &BindGroupStates<A>,
|
bind_group: &BindGroupStates<A>,
|
||||||
) -> Result<(), UsageConflict> {
|
) -> Result<(), UsageConflict> {
|
||||||
unsafe { self.buffers.merge_bind_group(&bind_group.buffers)? };
|
unsafe { self.buffers.merge_bind_group(&bind_group.buffers)? };
|
||||||
@ -416,8 +415,8 @@ pub(crate) struct UsageScope<A: HalApi> {
|
|||||||
impl<A: HalApi> UsageScope<A> {
|
impl<A: HalApi> UsageScope<A> {
|
||||||
/// Create the render bundle scope and pull the maximum IDs from the hubs.
|
/// Create the render bundle scope and pull the maximum IDs from the hubs.
|
||||||
pub fn new(
|
pub fn new(
|
||||||
buffers: &hub::Storage<resource::Buffer<A>, id::BufferId>,
|
buffers: &storage::Storage<resource::Buffer<A>, id::BufferId>,
|
||||||
textures: &hub::Storage<resource::Texture<A>, id::TextureId>,
|
textures: &storage::Storage<resource::Texture<A>, id::TextureId>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let mut value = Self {
|
let mut value = Self {
|
||||||
buffers: BufferUsageScope::new(),
|
buffers: BufferUsageScope::new(),
|
||||||
@ -441,7 +440,7 @@ impl<A: HalApi> UsageScope<A> {
|
|||||||
/// length of the storage given at the call to `new`.
|
/// length of the storage given at the call to `new`.
|
||||||
pub unsafe fn merge_bind_group(
|
pub unsafe fn merge_bind_group(
|
||||||
&mut self,
|
&mut self,
|
||||||
textures: &hub::Storage<resource::Texture<A>, id::TextureId>,
|
textures: &storage::Storage<resource::Texture<A>, id::TextureId>,
|
||||||
bind_group: &BindGroupStates<A>,
|
bind_group: &BindGroupStates<A>,
|
||||||
) -> Result<(), UsageConflict> {
|
) -> Result<(), UsageConflict> {
|
||||||
unsafe {
|
unsafe {
|
||||||
@ -464,7 +463,7 @@ impl<A: HalApi> UsageScope<A> {
|
|||||||
/// length of the storage given at the call to `new`.
|
/// length of the storage given at the call to `new`.
|
||||||
pub unsafe fn merge_render_bundle(
|
pub unsafe fn merge_render_bundle(
|
||||||
&mut self,
|
&mut self,
|
||||||
textures: &hub::Storage<resource::Texture<A>, id::TextureId>,
|
textures: &storage::Storage<resource::Texture<A>, id::TextureId>,
|
||||||
render_bundle: &RenderBundleScope<A>,
|
render_bundle: &RenderBundleScope<A>,
|
||||||
) -> Result<(), UsageConflict> {
|
) -> Result<(), UsageConflict> {
|
||||||
self.buffers.merge_usage_scope(&render_bundle.buffers)?;
|
self.buffers.merge_usage_scope(&render_bundle.buffers)?;
|
||||||
@ -506,17 +505,19 @@ impl<A: HalApi> Tracker<A> {
|
|||||||
/// Pull the maximum IDs from the hubs.
|
/// Pull the maximum IDs from the hubs.
|
||||||
pub fn set_size(
|
pub fn set_size(
|
||||||
&mut self,
|
&mut self,
|
||||||
buffers: Option<&hub::Storage<resource::Buffer<A>, id::BufferId>>,
|
buffers: Option<&storage::Storage<resource::Buffer<A>, id::BufferId>>,
|
||||||
textures: Option<&hub::Storage<resource::Texture<A>, id::TextureId>>,
|
textures: Option<&storage::Storage<resource::Texture<A>, id::TextureId>>,
|
||||||
views: Option<&hub::Storage<resource::TextureView<A>, id::TextureViewId>>,
|
views: Option<&storage::Storage<resource::TextureView<A>, id::TextureViewId>>,
|
||||||
samplers: Option<&hub::Storage<resource::Sampler<A>, id::SamplerId>>,
|
samplers: Option<&storage::Storage<resource::Sampler<A>, id::SamplerId>>,
|
||||||
bind_groups: Option<&hub::Storage<binding_model::BindGroup<A>, id::BindGroupId>>,
|
bind_groups: Option<&storage::Storage<binding_model::BindGroup<A>, id::BindGroupId>>,
|
||||||
compute_pipelines: Option<
|
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>>,
|
render_pipelines: Option<
|
||||||
bundles: Option<&hub::Storage<command::RenderBundle<A>, id::RenderBundleId>>,
|
&storage::Storage<pipeline::RenderPipeline<A>, id::RenderPipelineId>,
|
||||||
query_sets: Option<&hub::Storage<resource::QuerySet<A>, id::QuerySetId>>,
|
>,
|
||||||
|
bundles: Option<&storage::Storage<command::RenderBundle<A>, id::RenderBundleId>>,
|
||||||
|
query_sets: Option<&storage::Storage<resource::QuerySet<A>, id::QuerySetId>>,
|
||||||
) {
|
) {
|
||||||
if let Some(buffers) = buffers {
|
if let Some(buffers) = buffers {
|
||||||
self.buffers.set_size(buffers.len());
|
self.buffers.set_size(buffers.len());
|
||||||
@ -571,7 +572,7 @@ impl<A: HalApi> Tracker<A> {
|
|||||||
/// value given to `set_size`
|
/// value given to `set_size`
|
||||||
pub unsafe fn set_and_remove_from_usage_scope_sparse(
|
pub unsafe fn set_and_remove_from_usage_scope_sparse(
|
||||||
&mut self,
|
&mut self,
|
||||||
textures: &hub::Storage<resource::Texture<A>, id::TextureId>,
|
textures: &storage::Storage<resource::Texture<A>, id::TextureId>,
|
||||||
scope: &mut UsageScope<A>,
|
scope: &mut UsageScope<A>,
|
||||||
bind_group: &BindGroupStates<A>,
|
bind_group: &BindGroupStates<A>,
|
||||||
) {
|
) {
|
||||||
|
@ -10,6 +10,7 @@ use crate::{
|
|||||||
hal_api::HalApi,
|
hal_api::HalApi,
|
||||||
hub,
|
hub,
|
||||||
id::{TypedId, Valid},
|
id::{TypedId, Valid},
|
||||||
|
storage,
|
||||||
track::ResourceMetadata,
|
track::ResourceMetadata,
|
||||||
RefCount,
|
RefCount,
|
||||||
};
|
};
|
||||||
@ -45,7 +46,11 @@ impl<T: hub::Resource, Id: TypedId> StatelessBindGroupSate<T, Id> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Adds the given resource.
|
/// 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()?;
|
let resource = storage.get(id).ok()?;
|
||||||
|
|
||||||
self.resources
|
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,
|
/// If the ID is higher than the length of internal vectors,
|
||||||
/// the vectors will be extended. A call to set_size is not needed.
|
/// 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 item = storage.get(id).ok()?;
|
||||||
|
|
||||||
let (index32, epoch, _) = id.unzip();
|
let (index32, epoch, _) = id.unzip();
|
||||||
|
@ -22,9 +22,9 @@
|
|||||||
use super::{range::RangedStates, PendingTransition};
|
use super::{range::RangedStates, PendingTransition};
|
||||||
use crate::{
|
use crate::{
|
||||||
hal_api::HalApi,
|
hal_api::HalApi,
|
||||||
hub,
|
|
||||||
id::{TextureId, TypedId, Valid},
|
id::{TextureId, TypedId, Valid},
|
||||||
resource::Texture,
|
resource::Texture,
|
||||||
|
storage,
|
||||||
track::{
|
track::{
|
||||||
invalid_resource_state, skip_barrier, ResourceMetadata, ResourceMetadataProvider,
|
invalid_resource_state, skip_barrier, ResourceMetadata, ResourceMetadataProvider,
|
||||||
ResourceUses, UsageConflict,
|
ResourceUses, UsageConflict,
|
||||||
@ -185,7 +185,7 @@ impl<A: HalApi> TextureBindGroupState<A> {
|
|||||||
/// Adds the given resource with the given state.
|
/// Adds the given resource with the given state.
|
||||||
pub fn add_single<'a>(
|
pub fn add_single<'a>(
|
||||||
&mut self,
|
&mut self,
|
||||||
storage: &'a hub::Storage<Texture<A>, TextureId>,
|
storage: &'a storage::Storage<Texture<A>, TextureId>,
|
||||||
id: TextureId,
|
id: TextureId,
|
||||||
ref_count: RefCount,
|
ref_count: RefCount,
|
||||||
selector: Option<TextureSelector>,
|
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.
|
/// the vectors will be extended. A call to set_size is not needed.
|
||||||
pub fn merge_usage_scope(
|
pub fn merge_usage_scope(
|
||||||
&mut self,
|
&mut self,
|
||||||
storage: &hub::Storage<Texture<A>, TextureId>,
|
storage: &storage::Storage<Texture<A>, TextureId>,
|
||||||
scope: &Self,
|
scope: &Self,
|
||||||
) -> Result<(), UsageConflict> {
|
) -> Result<(), UsageConflict> {
|
||||||
let incoming_size = scope.set.simple.len();
|
let incoming_size = scope.set.simple.len();
|
||||||
@ -326,7 +326,7 @@ impl<A: HalApi> TextureUsageScope<A> {
|
|||||||
/// method is called.
|
/// method is called.
|
||||||
pub unsafe fn merge_bind_group(
|
pub unsafe fn merge_bind_group(
|
||||||
&mut self,
|
&mut self,
|
||||||
storage: &hub::Storage<Texture<A>, TextureId>,
|
storage: &storage::Storage<Texture<A>, TextureId>,
|
||||||
bind_group: &TextureBindGroupState<A>,
|
bind_group: &TextureBindGroupState<A>,
|
||||||
) -> Result<(), UsageConflict> {
|
) -> Result<(), UsageConflict> {
|
||||||
for &(id, ref selector, ref ref_count, state) in &bind_group.textures {
|
for &(id, ref selector, ref ref_count, state) in &bind_group.textures {
|
||||||
@ -351,7 +351,7 @@ impl<A: HalApi> TextureUsageScope<A> {
|
|||||||
/// method is called.
|
/// method is called.
|
||||||
pub unsafe fn merge_single(
|
pub unsafe fn merge_single(
|
||||||
&mut self,
|
&mut self,
|
||||||
storage: &hub::Storage<Texture<A>, TextureId>,
|
storage: &storage::Storage<Texture<A>, TextureId>,
|
||||||
id: Valid<TextureId>,
|
id: Valid<TextureId>,
|
||||||
selector: Option<TextureSelector>,
|
selector: Option<TextureSelector>,
|
||||||
ref_count: &RefCount,
|
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.
|
/// the vectors will be extended. A call to set_size is not needed.
|
||||||
pub fn set_from_tracker(
|
pub fn set_from_tracker(
|
||||||
&mut self,
|
&mut self,
|
||||||
storage: &hub::Storage<Texture<A>, TextureId>,
|
storage: &storage::Storage<Texture<A>, TextureId>,
|
||||||
tracker: &Self,
|
tracker: &Self,
|
||||||
) {
|
) {
|
||||||
let incoming_size = tracker.start_set.simple.len();
|
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.
|
/// the vectors will be extended. A call to set_size is not needed.
|
||||||
pub fn set_from_usage_scope(
|
pub fn set_from_usage_scope(
|
||||||
&mut self,
|
&mut self,
|
||||||
storage: &hub::Storage<Texture<A>, TextureId>,
|
storage: &storage::Storage<Texture<A>, TextureId>,
|
||||||
scope: &TextureUsageScope<A>,
|
scope: &TextureUsageScope<A>,
|
||||||
) {
|
) {
|
||||||
let incoming_size = scope.set.simple.len();
|
let incoming_size = scope.set.simple.len();
|
||||||
@ -662,7 +662,7 @@ impl<A: HalApi> TextureTracker<A> {
|
|||||||
/// method is called.
|
/// method is called.
|
||||||
pub unsafe fn set_and_remove_from_usage_scope_sparse(
|
pub unsafe fn set_and_remove_from_usage_scope_sparse(
|
||||||
&mut self,
|
&mut self,
|
||||||
storage: &hub::Storage<Texture<A>, TextureId>,
|
storage: &storage::Storage<Texture<A>, TextureId>,
|
||||||
scope: &mut TextureUsageScope<A>,
|
scope: &mut TextureUsageScope<A>,
|
||||||
bind_group_state: &TextureBindGroupState<A>,
|
bind_group_state: &TextureBindGroupState<A>,
|
||||||
) {
|
) {
|
||||||
@ -877,7 +877,7 @@ impl<'a> TextureStateProvider<'a> {
|
|||||||
/// out of the texture storage.
|
/// out of the texture storage.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
unsafe fn texture_data_from_texture<A: HalApi>(
|
unsafe fn texture_data_from_texture<A: HalApi>(
|
||||||
storage: &hub::Storage<Texture<A>, TextureId>,
|
storage: &storage::Storage<Texture<A>, TextureId>,
|
||||||
index32: u32,
|
index32: u32,
|
||||||
) -> (&LifeGuard, &TextureSelector) {
|
) -> (&LifeGuard, &TextureSelector) {
|
||||||
let texture = unsafe { storage.get_unchecked(index32) };
|
let texture = unsafe { storage.get_unchecked(index32) };
|
||||||
|
Loading…
Reference in New Issue
Block a user