mirror of
https://github.com/gfx-rs/wgpu.git
synced 2025-12-08 21:26:17 +00:00
wgpu-core: Move identity code to new identity module.
This commit is contained in:
parent
13bd3eea55
commit
29914b308f
@ -95,7 +95,7 @@ fn check_unstable(state: &OpState, api_name: &str) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub type Instance =
|
pub type Instance =
|
||||||
std::sync::Arc<wgpu_core::global::Global<wgpu_core::hub::IdentityManagerFactory>>;
|
std::sync::Arc<wgpu_core::global::Global<wgpu_core::identity::IdentityManagerFactory>>;
|
||||||
|
|
||||||
struct WebGpuAdapter(Instance, wgpu_core::id::AdapterId);
|
struct WebGpuAdapter(Instance, wgpu_core::id::AdapterId);
|
||||||
impl Resource for WebGpuAdapter {
|
impl Resource for WebGpuAdapter {
|
||||||
@ -324,7 +324,7 @@ pub async fn op_webgpu_request_adapter(
|
|||||||
} else {
|
} else {
|
||||||
state.put(std::sync::Arc::new(wgpu_core::global::Global::new(
|
state.put(std::sync::Arc::new(wgpu_core::global::Global::new(
|
||||||
"webgpu",
|
"webgpu",
|
||||||
wgpu_core::hub::IdentityManagerFactory,
|
wgpu_core::identity::IdentityManagerFactory,
|
||||||
wgpu_types::InstanceDescriptor {
|
wgpu_types::InstanceDescriptor {
|
||||||
backends,
|
backends,
|
||||||
dx12_shader_compiler: wgpu_types::Dx12Compiler::Fxc,
|
dx12_shader_compiler: wgpu_types::Dx12Compiler::Fxc,
|
||||||
|
|||||||
@ -48,7 +48,7 @@ fn main() {
|
|||||||
IdentityPassThroughFactory,
|
IdentityPassThroughFactory,
|
||||||
wgt::InstanceDescriptor::default(),
|
wgt::InstanceDescriptor::default(),
|
||||||
);
|
);
|
||||||
let mut command_buffer_id_manager = wgc::hub::IdentityManager::default();
|
let mut command_buffer_id_manager = wgc::identity::IdentityManager::default();
|
||||||
|
|
||||||
#[cfg(feature = "winit")]
|
#[cfg(feature = "winit")]
|
||||||
let surface = global.instance_create_surface(
|
let surface = global.instance_create_surface(
|
||||||
|
|||||||
@ -15,7 +15,9 @@ use std::{borrow::Cow, fmt::Debug, fs, marker::PhantomData, path::Path};
|
|||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct IdentityPassThrough<I>(PhantomData<I>);
|
pub struct IdentityPassThrough<I>(PhantomData<I>);
|
||||||
|
|
||||||
impl<I: Clone + Debug + wgc::id::TypedId> wgc::hub::IdentityHandler<I> for IdentityPassThrough<I> {
|
impl<I: Clone + Debug + wgc::id::TypedId> wgc::identity::IdentityHandler<I>
|
||||||
|
for IdentityPassThrough<I>
|
||||||
|
{
|
||||||
type Input = I;
|
type Input = I;
|
||||||
fn process(&self, id: I, backend: wgt::Backend) -> I {
|
fn process(&self, id: I, backend: wgt::Backend) -> I {
|
||||||
let (index, epoch, _backend) = id.unzip();
|
let (index, epoch, _backend) = id.unzip();
|
||||||
@ -26,7 +28,7 @@ impl<I: Clone + Debug + wgc::id::TypedId> wgc::hub::IdentityHandler<I> for Ident
|
|||||||
|
|
||||||
pub struct IdentityPassThroughFactory;
|
pub struct IdentityPassThroughFactory;
|
||||||
|
|
||||||
impl<I: Clone + Debug + wgc::id::TypedId> wgc::hub::IdentityHandlerFactory<I>
|
impl<I: Clone + Debug + wgc::id::TypedId> wgc::identity::IdentityHandlerFactory<I>
|
||||||
for IdentityPassThroughFactory
|
for IdentityPassThroughFactory
|
||||||
{
|
{
|
||||||
type Filter = IdentityPassThrough<I>;
|
type Filter = IdentityPassThrough<I>;
|
||||||
@ -34,7 +36,7 @@ impl<I: Clone + Debug + wgc::id::TypedId> wgc::hub::IdentityHandlerFactory<I>
|
|||||||
IdentityPassThrough(PhantomData)
|
IdentityPassThrough(PhantomData)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl wgc::hub::GlobalIdentityHandlerFactory for IdentityPassThroughFactory {}
|
impl wgc::identity::GlobalIdentityHandlerFactory for IdentityPassThroughFactory {}
|
||||||
|
|
||||||
pub trait GlobalPlay {
|
pub trait GlobalPlay {
|
||||||
fn encode_commands<A: wgc::hal_api::HalApi>(
|
fn encode_commands<A: wgc::hal_api::HalApi>(
|
||||||
@ -47,7 +49,7 @@ pub trait GlobalPlay {
|
|||||||
device: wgc::id::DeviceId,
|
device: wgc::id::DeviceId,
|
||||||
action: trace::Action,
|
action: trace::Action,
|
||||||
dir: &Path,
|
dir: &Path,
|
||||||
comb_manager: &mut wgc::hub::IdentityManager,
|
comb_manager: &mut wgc::identity::IdentityManager,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -151,7 +153,7 @@ impl GlobalPlay for wgc::global::Global<IdentityPassThroughFactory> {
|
|||||||
device: wgc::id::DeviceId,
|
device: wgc::id::DeviceId,
|
||||||
action: trace::Action,
|
action: trace::Action,
|
||||||
dir: &Path,
|
dir: &Path,
|
||||||
comb_manager: &mut wgc::hub::IdentityManager,
|
comb_manager: &mut wgc::identity::IdentityManager,
|
||||||
) {
|
) {
|
||||||
use wgc::device::trace::Action;
|
use wgc::device::trace::Action;
|
||||||
log::info!("action {:?}", action);
|
log::info!("action {:?}", action);
|
||||||
|
|||||||
@ -98,7 +98,7 @@ impl Test<'_> {
|
|||||||
panic!("{:?}", e);
|
panic!("{:?}", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut command_buffer_id_manager = wgc::hub::IdentityManager::default();
|
let mut command_buffer_id_manager = wgc::identity::IdentityManager::default();
|
||||||
println!("\t\t\tRunning...");
|
println!("\t\t\tRunning...");
|
||||||
for action in self.actions {
|
for action in self.actions {
|
||||||
wgc::gfx_select!(device => global.process(device, action, dir, &mut command_buffer_id_manager));
|
wgc::gfx_select!(device => global.process(device, action, dir, &mut command_buffer_id_manager));
|
||||||
|
|||||||
@ -91,8 +91,9 @@ use crate::{
|
|||||||
},
|
},
|
||||||
error::{ErrorFormatter, PrettyError},
|
error::{ErrorFormatter, PrettyError},
|
||||||
hal_api::HalApi,
|
hal_api::HalApi,
|
||||||
hub::{GlobalIdentityHandlerFactory, Hub, Resource, Storage, Token},
|
hub::{Hub, Resource, Storage, Token},
|
||||||
id,
|
id,
|
||||||
|
identity::GlobalIdentityHandlerFactory,
|
||||||
init_tracker::{BufferInitTrackerAction, MemoryInitKind, TextureInitTrackerAction},
|
init_tracker::{BufferInitTrackerAction, MemoryInitKind, TextureInitTrackerAction},
|
||||||
pipeline::{self, PipelineFlags},
|
pipeline::{self, PipelineFlags},
|
||||||
resource,
|
resource,
|
||||||
|
|||||||
@ -7,8 +7,9 @@ use crate::{
|
|||||||
get_lowest_common_denom,
|
get_lowest_common_denom,
|
||||||
global::Global,
|
global::Global,
|
||||||
hal_api::HalApi,
|
hal_api::HalApi,
|
||||||
hub::{self, GlobalIdentityHandlerFactory, Token},
|
hub::{self, Token},
|
||||||
id::{BufferId, CommandEncoderId, DeviceId, TextureId, Valid},
|
id::{BufferId, CommandEncoderId, DeviceId, TextureId, Valid},
|
||||||
|
identity::GlobalIdentityHandlerFactory,
|
||||||
init_tracker::{MemoryInitKind, TextureInitRange},
|
init_tracker::{MemoryInitKind, TextureInitRange},
|
||||||
resource::{Texture, TextureClearMode},
|
resource::{Texture, TextureClearMode},
|
||||||
track::{TextureSelector, TextureTracker},
|
track::{TextureSelector, TextureTracker},
|
||||||
|
|||||||
@ -13,8 +13,9 @@ use crate::{
|
|||||||
error::{ErrorFormatter, PrettyError},
|
error::{ErrorFormatter, PrettyError},
|
||||||
global::Global,
|
global::Global,
|
||||||
hal_api::HalApi,
|
hal_api::HalApi,
|
||||||
hub::{GlobalIdentityHandlerFactory, Storage, Token},
|
hub::{Storage, Token},
|
||||||
id,
|
id,
|
||||||
|
identity::GlobalIdentityHandlerFactory,
|
||||||
init_tracker::MemoryInitKind,
|
init_tracker::MemoryInitKind,
|
||||||
pipeline,
|
pipeline,
|
||||||
resource::{self, Buffer, Texture},
|
resource::{self, Buffer, Texture},
|
||||||
|
|||||||
@ -23,8 +23,9 @@ use crate::track::{Tracker, UsageScope};
|
|||||||
use crate::{
|
use crate::{
|
||||||
global::Global,
|
global::Global,
|
||||||
hal_api::HalApi,
|
hal_api::HalApi,
|
||||||
hub::{GlobalIdentityHandlerFactory, Storage, Token},
|
hub::{Storage, Token},
|
||||||
id,
|
id,
|
||||||
|
identity::GlobalIdentityHandlerFactory,
|
||||||
resource::{Buffer, Texture},
|
resource::{Buffer, Texture},
|
||||||
Label, Stored,
|
Label, Stored,
|
||||||
};
|
};
|
||||||
|
|||||||
@ -6,8 +6,9 @@ use crate::{
|
|||||||
command::{CommandBuffer, CommandEncoderError},
|
command::{CommandBuffer, CommandEncoderError},
|
||||||
global::Global,
|
global::Global,
|
||||||
hal_api::HalApi,
|
hal_api::HalApi,
|
||||||
hub::{GlobalIdentityHandlerFactory, Storage, Token},
|
hub::{Storage, Token},
|
||||||
id::{self, Id, TypedId},
|
id::{self, Id, TypedId},
|
||||||
|
identity::GlobalIdentityHandlerFactory,
|
||||||
init_tracker::MemoryInitKind,
|
init_tracker::MemoryInitKind,
|
||||||
resource::QuerySet,
|
resource::QuerySet,
|
||||||
Epoch, FastHashMap, Index,
|
Epoch, FastHashMap, Index,
|
||||||
|
|||||||
@ -16,8 +16,9 @@ use crate::{
|
|||||||
error::{ErrorFormatter, PrettyError},
|
error::{ErrorFormatter, PrettyError},
|
||||||
global::Global,
|
global::Global,
|
||||||
hal_api::HalApi,
|
hal_api::HalApi,
|
||||||
hub::{GlobalIdentityHandlerFactory, Storage, Token},
|
hub::{Storage, Token},
|
||||||
id,
|
id,
|
||||||
|
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},
|
||||||
|
|||||||
@ -7,8 +7,9 @@ use crate::{
|
|||||||
error::{ErrorFormatter, PrettyError},
|
error::{ErrorFormatter, PrettyError},
|
||||||
global::Global,
|
global::Global,
|
||||||
hal_api::HalApi,
|
hal_api::HalApi,
|
||||||
hub::{GlobalIdentityHandlerFactory, Storage, Token},
|
hub::{Storage, Token},
|
||||||
id::{BufferId, CommandEncoderId, TextureId, Valid},
|
id::{BufferId, CommandEncoderId, TextureId, Valid},
|
||||||
|
identity::GlobalIdentityHandlerFactory,
|
||||||
init_tracker::{
|
init_tracker::{
|
||||||
has_copy_partial_init_tracker_coverage, MemoryInitKind, TextureInitRange,
|
has_copy_partial_init_tracker_coverage, MemoryInitKind, TextureInitRange,
|
||||||
TextureInitTrackerAction,
|
TextureInitTrackerAction,
|
||||||
|
|||||||
@ -6,8 +6,10 @@ use crate::{
|
|||||||
DeviceError,
|
DeviceError,
|
||||||
},
|
},
|
||||||
hal_api::HalApi,
|
hal_api::HalApi,
|
||||||
hub::{GlobalIdentityHandlerFactory, Hub, Token},
|
hub::{Hub, Token},
|
||||||
id, resource,
|
id,
|
||||||
|
identity::GlobalIdentityHandlerFactory,
|
||||||
|
resource,
|
||||||
track::{BindGroupStates, RenderBundleScope, Tracker},
|
track::{BindGroupStates, RenderBundleScope, Tracker},
|
||||||
RefCount, Stored, SubmissionIndex,
|
RefCount, Stored, SubmissionIndex,
|
||||||
};
|
};
|
||||||
|
|||||||
@ -3,8 +3,9 @@ use crate::{
|
|||||||
device::life::WaitIdleError,
|
device::life::WaitIdleError,
|
||||||
global::Global,
|
global::Global,
|
||||||
hal_api::HalApi,
|
hal_api::HalApi,
|
||||||
hub::{GlobalIdentityHandlerFactory, Hub, Input, InvalidId, Storage, Token},
|
hub::{Hub, InvalidId, Storage, Token},
|
||||||
id,
|
id,
|
||||||
|
identity::{GlobalIdentityHandlerFactory, Input},
|
||||||
init_tracker::{
|
init_tracker::{
|
||||||
BufferInitTracker, BufferInitTrackerAction, MemoryInitKind, TextureInitRange,
|
BufferInitTracker, BufferInitTrackerAction, MemoryInitKind, TextureInitRange,
|
||||||
TextureInitTracker, TextureInitTrackerAction,
|
TextureInitTracker, TextureInitTrackerAction,
|
||||||
|
|||||||
@ -10,8 +10,9 @@ use crate::{
|
|||||||
get_lowest_common_denom,
|
get_lowest_common_denom,
|
||||||
global::Global,
|
global::Global,
|
||||||
hal_api::HalApi,
|
hal_api::HalApi,
|
||||||
hub::{GlobalIdentityHandlerFactory, Input, Token},
|
hub::Token,
|
||||||
id,
|
id,
|
||||||
|
identity::{GlobalIdentityHandlerFactory, Input},
|
||||||
init_tracker::{has_copy_partial_init_tracker_coverage, TextureInitRange},
|
init_tracker::{has_copy_partial_init_tracker_coverage, TextureInitRange},
|
||||||
resource::{BufferAccessError, BufferMapState, StagingBuffer, TextureInner},
|
resource::{BufferAccessError, BufferMapState, StagingBuffer, TextureInner},
|
||||||
track, FastHashSet, SubmissionIndex,
|
track, FastHashSet, SubmissionIndex,
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
use core::fmt;
|
use core::fmt;
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
|
|
||||||
use crate::{gfx_select, global::Global, hub::IdentityManagerFactory};
|
use crate::{gfx_select, global::Global, identity::IdentityManagerFactory};
|
||||||
|
|
||||||
pub struct ErrorFormatter<'a> {
|
pub struct ErrorFormatter<'a> {
|
||||||
writer: &'a mut dyn fmt::Write,
|
writer: &'a mut dyn fmt::Write,
|
||||||
|
|||||||
@ -1,10 +1,10 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
hal_api::HalApi,
|
hal_api::HalApi,
|
||||||
hub::GlobalIdentityHandlerFactory,
|
|
||||||
hub::Registry,
|
hub::Registry,
|
||||||
hub::{Element, StorageReport},
|
hub::{Element, StorageReport},
|
||||||
hub::{HubReport, Hubs},
|
hub::{HubReport, Hubs},
|
||||||
id,
|
id,
|
||||||
|
identity::GlobalIdentityHandlerFactory,
|
||||||
instance::{Instance, Surface},
|
instance::{Instance, Surface},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -156,7 +156,7 @@ impl<G: GlobalIdentityHandlerFactory> Drop for Global<G> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
fn _test_send_sync(global: &Global<crate::hub::IdentityManagerFactory>) {
|
fn _test_send_sync(global: &Global<crate::identity::IdentityManagerFactory>) {
|
||||||
fn test_internal<T: Send + Sync>(_: T) {}
|
fn test_internal<T: Send + Sync>(_: T) {}
|
||||||
test_internal(global)
|
test_internal(global)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,7 +2,8 @@ use wgt::Backend;
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
global::Global,
|
global::Global,
|
||||||
hub::{GlobalIdentityHandlerFactory, Hub},
|
hub::Hub,
|
||||||
|
identity::GlobalIdentityHandlerFactory,
|
||||||
instance::{HalSurface, Instance, Surface},
|
instance::{HalSurface, Instance, Surface},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -148,6 +148,8 @@ flagged as errors as well.
|
|||||||
[`Id<R>`]: crate::id::Id
|
[`Id<R>`]: crate::id::Id
|
||||||
[wrapped in a mutex]: trait.IdentityHandler.html#impl-IdentityHandler%3CI%3E-for-Mutex%3CIdentityManager%3E
|
[wrapped in a mutex]: trait.IdentityHandler.html#impl-IdentityHandler%3CI%3E-for-Mutex%3CIdentityManager%3E
|
||||||
[WebGPU]: https://www.w3.org/TR/webgpu/
|
[WebGPU]: https://www.w3.org/TR/webgpu/
|
||||||
|
[`IdentityManager`]: crate::identity::IdentityManager
|
||||||
|
[`Input<G, I>`]: crate::identity::Input
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -157,93 +159,20 @@ use crate::{
|
|||||||
device::Device,
|
device::Device,
|
||||||
hal_api::HalApi,
|
hal_api::HalApi,
|
||||||
id,
|
id,
|
||||||
|
identity::{GlobalIdentityHandlerFactory, IdentityHandler, IdentityHandlerFactory},
|
||||||
instance::{Adapter, HalSurface, Instance, Surface},
|
instance::{Adapter, HalSurface, Instance, Surface},
|
||||||
pipeline::{ComputePipeline, RenderPipeline, ShaderModule},
|
pipeline::{ComputePipeline, RenderPipeline, ShaderModule},
|
||||||
resource::{Buffer, QuerySet, Sampler, StagingBuffer, Texture, TextureClearMode, TextureView},
|
resource::{Buffer, QuerySet, Sampler, StagingBuffer, Texture, TextureClearMode, TextureView},
|
||||||
Epoch, Index,
|
Epoch, Index,
|
||||||
};
|
};
|
||||||
|
|
||||||
use parking_lot::{Mutex, RwLock, RwLockReadGuard, RwLockWriteGuard};
|
use parking_lot::{RwLock, RwLockReadGuard, RwLockWriteGuard};
|
||||||
use wgt::Backend;
|
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, mem, ops};
|
||||||
|
|
||||||
/// A simple structure to allocate [`Id`] identifiers.
|
|
||||||
///
|
|
||||||
/// Calling [`alloc`] returns a fresh, never-before-seen id. Calling [`free`]
|
|
||||||
/// marks an id as dead; it will never be returned again by `alloc`.
|
|
||||||
///
|
|
||||||
/// Use `IdentityManager::default` to construct new instances.
|
|
||||||
///
|
|
||||||
/// `IdentityManager` returns `Id`s whose index values are suitable for use as
|
|
||||||
/// indices into a `Storage<T>` that holds those ids' referents:
|
|
||||||
///
|
|
||||||
/// - Every live id has a distinct index value. Each live id's index selects a
|
|
||||||
/// distinct element in the vector.
|
|
||||||
///
|
|
||||||
/// - `IdentityManager` prefers low index numbers. If you size your vector to
|
|
||||||
/// accommodate the indices produced here, the vector's length will reflect
|
|
||||||
/// the highwater mark of actual occupancy.
|
|
||||||
///
|
|
||||||
/// - `IdentityManager` reuses the index values of freed ids before returning
|
|
||||||
/// ids with new index values. Freed vector entries get reused.
|
|
||||||
///
|
|
||||||
/// See the module-level documentation for an overview of how this
|
|
||||||
/// fits together.
|
|
||||||
///
|
|
||||||
/// [`Id`]: crate::id::Id
|
|
||||||
/// [`Backend`]: wgt::Backend;
|
|
||||||
/// [`alloc`]: IdentityManager::alloc
|
|
||||||
/// [`free`]: IdentityManager::free
|
|
||||||
#[derive(Debug, Default)]
|
|
||||||
pub struct IdentityManager {
|
|
||||||
/// Available index values. If empty, then `epochs.len()` is the next index
|
|
||||||
/// to allocate.
|
|
||||||
free: Vec<Index>,
|
|
||||||
|
|
||||||
/// The next or currently-live epoch value associated with each `Id` index.
|
|
||||||
///
|
|
||||||
/// If there is a live id with index `i`, then `epochs[i]` is its epoch; any
|
|
||||||
/// id with the same index but an older epoch is dead.
|
|
||||||
///
|
|
||||||
/// If index `i` is currently unused, `epochs[i]` is the epoch to use in its
|
|
||||||
/// next `Id`.
|
|
||||||
epochs: Vec<Epoch>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl IdentityManager {
|
|
||||||
/// Allocate a fresh, never-before-seen id with the given `backend`.
|
|
||||||
///
|
|
||||||
/// The backend is incorporated into the id, so that ids allocated with
|
|
||||||
/// different `backend` values are always distinct.
|
|
||||||
pub fn alloc<I: id::TypedId>(&mut self, backend: Backend) -> I {
|
|
||||||
match self.free.pop() {
|
|
||||||
Some(index) => I::zip(index, self.epochs[index as usize], backend),
|
|
||||||
None => {
|
|
||||||
let epoch = 1;
|
|
||||||
let id = I::zip(self.epochs.len() as Index, epoch, backend);
|
|
||||||
self.epochs.push(epoch);
|
|
||||||
id
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Free `id`. It will never be returned from `alloc` again.
|
|
||||||
pub fn free<I: id::TypedId + Debug>(&mut self, id: I) {
|
|
||||||
let (index, epoch, _backend) = id.unzip();
|
|
||||||
let pe = &mut self.epochs[index as usize];
|
|
||||||
assert_eq!(*pe, epoch);
|
|
||||||
// If the epoch reaches EOL, the index doesn't go
|
|
||||||
// into the free list, will never be reused again.
|
|
||||||
if epoch < id::EPOCH_MASK {
|
|
||||||
*pe = epoch + 1;
|
|
||||||
self.free.push(index);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// An entry in a `Storage::map` table.
|
/// An entry in a `Storage::map` table.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub(crate) enum Element<T> {
|
pub(crate) enum Element<T> {
|
||||||
@ -654,96 +583,6 @@ impl<'a, T> Drop for Token<'a, T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A type that can build true ids from proto-ids, and free true ids.
|
|
||||||
///
|
|
||||||
/// For some implementations, the true id is based on the proto-id.
|
|
||||||
/// The caller is responsible for providing well-allocated proto-ids.
|
|
||||||
///
|
|
||||||
/// For other implementations, the proto-id carries no information
|
|
||||||
/// (it's `()`, say), and this `IdentityHandler` type takes care of
|
|
||||||
/// allocating a fresh true id.
|
|
||||||
///
|
|
||||||
/// See the module-level documentation for details.
|
|
||||||
pub trait IdentityHandler<I>: Debug {
|
|
||||||
/// The type of proto-id consumed by this filter, to produce a true id.
|
|
||||||
type Input: Clone + Debug;
|
|
||||||
|
|
||||||
/// Given a proto-id value `id`, return a true id for `backend`.
|
|
||||||
fn process(&self, id: Self::Input, backend: Backend) -> I;
|
|
||||||
|
|
||||||
/// Free the true id `id`.
|
|
||||||
fn free(&self, id: I);
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<I: id::TypedId + Debug> IdentityHandler<I> for Mutex<IdentityManager> {
|
|
||||||
type Input = ();
|
|
||||||
fn process(&self, _id: Self::Input, backend: Backend) -> I {
|
|
||||||
self.lock().alloc(backend)
|
|
||||||
}
|
|
||||||
fn free(&self, id: I) {
|
|
||||||
self.lock().free(id)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A type that can produce [`IdentityHandler`] filters for ids of type `I`.
|
|
||||||
///
|
|
||||||
/// See the module-level documentation for details.
|
|
||||||
pub trait IdentityHandlerFactory<I> {
|
|
||||||
/// The type of filter this factory constructs.
|
|
||||||
///
|
|
||||||
/// "Filter" and "handler" seem to both mean the same thing here:
|
|
||||||
/// something that can produce true ids from proto-ids.
|
|
||||||
type Filter: IdentityHandler<I>;
|
|
||||||
|
|
||||||
/// Create an [`IdentityHandler<I>`] implementation that can
|
|
||||||
/// transform proto-ids into ids of type `I`.
|
|
||||||
///
|
|
||||||
/// [`IdentityHandler<I>`]: IdentityHandler
|
|
||||||
fn spawn(&self) -> Self::Filter;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A global identity handler factory based on [`IdentityManager`].
|
|
||||||
///
|
|
||||||
/// Each of this type's `IdentityHandlerFactory<I>::spawn` methods
|
|
||||||
/// returns a `Mutex<IdentityManager<I>>`, which allocates fresh `I`
|
|
||||||
/// ids itself, and takes `()` as its proto-id type.
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct IdentityManagerFactory;
|
|
||||||
|
|
||||||
impl<I: id::TypedId + Debug> IdentityHandlerFactory<I> for IdentityManagerFactory {
|
|
||||||
type Filter = Mutex<IdentityManager>;
|
|
||||||
fn spawn(&self) -> Self::Filter {
|
|
||||||
Mutex::new(IdentityManager::default())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A factory that can build [`IdentityHandler`]s for all resource
|
|
||||||
/// types.
|
|
||||||
pub trait GlobalIdentityHandlerFactory:
|
|
||||||
IdentityHandlerFactory<id::AdapterId>
|
|
||||||
+ IdentityHandlerFactory<id::DeviceId>
|
|
||||||
+ IdentityHandlerFactory<id::PipelineLayoutId>
|
|
||||||
+ IdentityHandlerFactory<id::ShaderModuleId>
|
|
||||||
+ IdentityHandlerFactory<id::BindGroupLayoutId>
|
|
||||||
+ IdentityHandlerFactory<id::BindGroupId>
|
|
||||||
+ IdentityHandlerFactory<id::CommandBufferId>
|
|
||||||
+ IdentityHandlerFactory<id::RenderBundleId>
|
|
||||||
+ IdentityHandlerFactory<id::RenderPipelineId>
|
|
||||||
+ IdentityHandlerFactory<id::ComputePipelineId>
|
|
||||||
+ IdentityHandlerFactory<id::QuerySetId>
|
|
||||||
+ IdentityHandlerFactory<id::BufferId>
|
|
||||||
+ IdentityHandlerFactory<id::StagingBufferId>
|
|
||||||
+ IdentityHandlerFactory<id::TextureId>
|
|
||||||
+ IdentityHandlerFactory<id::TextureViewId>
|
|
||||||
+ IdentityHandlerFactory<id::SamplerId>
|
|
||||||
+ IdentityHandlerFactory<id::SurfaceId>
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
impl GlobalIdentityHandlerFactory for IdentityManagerFactory {}
|
|
||||||
|
|
||||||
pub type Input<G, I> = <<G as IdentityHandlerFactory<I>>::Filter as IdentityHandler<I>>::Input;
|
|
||||||
|
|
||||||
pub trait Resource {
|
pub trait Resource {
|
||||||
const TYPE: &'static str;
|
const TYPE: &'static str;
|
||||||
fn life_guard(&self) -> &crate::LifeGuard;
|
fn life_guard(&self) -> &crate::LifeGuard;
|
||||||
@ -1293,17 +1132,3 @@ impl<F: GlobalIdentityHandlerFactory> Hubs<F> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_epoch_end_of_life() {
|
|
||||||
use id::TypedId as _;
|
|
||||||
let mut man = IdentityManager::default();
|
|
||||||
man.epochs.push(id::EPOCH_MASK);
|
|
||||||
man.free.push(0);
|
|
||||||
let id1 = man.alloc::<id::BufferId>(Backend::Empty);
|
|
||||||
assert_eq!(id1.unzip().0, 0);
|
|
||||||
man.free(id1);
|
|
||||||
let id2 = man.alloc::<id::BufferId>(Backend::Empty);
|
|
||||||
// confirm that the index 0 is no longer re-used
|
|
||||||
assert_eq!(id2.unzip().0, 1);
|
|
||||||
}
|
|
||||||
|
|||||||
183
wgpu-core/src/identity.rs
Normal file
183
wgpu-core/src/identity.rs
Normal file
@ -0,0 +1,183 @@
|
|||||||
|
use parking_lot::Mutex;
|
||||||
|
use wgt::Backend;
|
||||||
|
|
||||||
|
use crate::{id, Epoch, Index};
|
||||||
|
use std::fmt::Debug;
|
||||||
|
|
||||||
|
/// A simple structure to allocate [`Id`] identifiers.
|
||||||
|
///
|
||||||
|
/// Calling [`alloc`] returns a fresh, never-before-seen id. Calling [`free`]
|
||||||
|
/// marks an id as dead; it will never be returned again by `alloc`.
|
||||||
|
///
|
||||||
|
/// Use `IdentityManager::default` to construct new instances.
|
||||||
|
///
|
||||||
|
/// `IdentityManager` returns `Id`s whose index values are suitable for use as
|
||||||
|
/// indices into a `Storage<T>` that holds those ids' referents:
|
||||||
|
///
|
||||||
|
/// - Every live id has a distinct index value. Each live id's index selects a
|
||||||
|
/// distinct element in the vector.
|
||||||
|
///
|
||||||
|
/// - `IdentityManager` prefers low index numbers. If you size your vector to
|
||||||
|
/// accommodate the indices produced here, the vector's length will reflect
|
||||||
|
/// the highwater mark of actual occupancy.
|
||||||
|
///
|
||||||
|
/// - `IdentityManager` reuses the index values of freed ids before returning
|
||||||
|
/// ids with new index values. Freed vector entries get reused.
|
||||||
|
///
|
||||||
|
/// See the module-level documentation for an overview of how this
|
||||||
|
/// fits together.
|
||||||
|
///
|
||||||
|
/// [`Id`]: crate::id::Id
|
||||||
|
/// [`Backend`]: wgt::Backend;
|
||||||
|
/// [`alloc`]: IdentityManager::alloc
|
||||||
|
/// [`free`]: IdentityManager::free
|
||||||
|
#[derive(Debug, Default)]
|
||||||
|
pub struct IdentityManager {
|
||||||
|
/// Available index values. If empty, then `epochs.len()` is the next index
|
||||||
|
/// to allocate.
|
||||||
|
free: Vec<Index>,
|
||||||
|
|
||||||
|
/// The next or currently-live epoch value associated with each `Id` index.
|
||||||
|
///
|
||||||
|
/// If there is a live id with index `i`, then `epochs[i]` is its epoch; any
|
||||||
|
/// id with the same index but an older epoch is dead.
|
||||||
|
///
|
||||||
|
/// If index `i` is currently unused, `epochs[i]` is the epoch to use in its
|
||||||
|
/// next `Id`.
|
||||||
|
epochs: Vec<Epoch>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IdentityManager {
|
||||||
|
/// Allocate a fresh, never-before-seen id with the given `backend`.
|
||||||
|
///
|
||||||
|
/// The backend is incorporated into the id, so that ids allocated with
|
||||||
|
/// different `backend` values are always distinct.
|
||||||
|
pub fn alloc<I: id::TypedId>(&mut self, backend: Backend) -> I {
|
||||||
|
match self.free.pop() {
|
||||||
|
Some(index) => I::zip(index, self.epochs[index as usize], backend),
|
||||||
|
None => {
|
||||||
|
let epoch = 1;
|
||||||
|
let id = I::zip(self.epochs.len() as Index, epoch, backend);
|
||||||
|
self.epochs.push(epoch);
|
||||||
|
id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Free `id`. It will never be returned from `alloc` again.
|
||||||
|
pub fn free<I: id::TypedId + Debug>(&mut self, id: I) {
|
||||||
|
let (index, epoch, _backend) = id.unzip();
|
||||||
|
let pe = &mut self.epochs[index as usize];
|
||||||
|
assert_eq!(*pe, epoch);
|
||||||
|
// If the epoch reaches EOL, the index doesn't go
|
||||||
|
// into the free list, will never be reused again.
|
||||||
|
if epoch < id::EPOCH_MASK {
|
||||||
|
*pe = epoch + 1;
|
||||||
|
self.free.push(index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A type that can build true ids from proto-ids, and free true ids.
|
||||||
|
///
|
||||||
|
/// For some implementations, the true id is based on the proto-id.
|
||||||
|
/// The caller is responsible for providing well-allocated proto-ids.
|
||||||
|
///
|
||||||
|
/// For other implementations, the proto-id carries no information
|
||||||
|
/// (it's `()`, say), and this `IdentityHandler` type takes care of
|
||||||
|
/// allocating a fresh true id.
|
||||||
|
///
|
||||||
|
/// See the module-level documentation for details.
|
||||||
|
pub trait IdentityHandler<I>: Debug {
|
||||||
|
/// The type of proto-id consumed by this filter, to produce a true id.
|
||||||
|
type Input: Clone + Debug;
|
||||||
|
|
||||||
|
/// Given a proto-id value `id`, return a true id for `backend`.
|
||||||
|
fn process(&self, id: Self::Input, backend: Backend) -> I;
|
||||||
|
|
||||||
|
/// Free the true id `id`.
|
||||||
|
fn free(&self, id: I);
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<I: id::TypedId + Debug> IdentityHandler<I> for Mutex<IdentityManager> {
|
||||||
|
type Input = ();
|
||||||
|
fn process(&self, _id: Self::Input, backend: Backend) -> I {
|
||||||
|
self.lock().alloc(backend)
|
||||||
|
}
|
||||||
|
fn free(&self, id: I) {
|
||||||
|
self.lock().free(id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A type that can produce [`IdentityHandler`] filters for ids of type `I`.
|
||||||
|
///
|
||||||
|
/// See the module-level documentation for details.
|
||||||
|
pub trait IdentityHandlerFactory<I> {
|
||||||
|
/// The type of filter this factory constructs.
|
||||||
|
///
|
||||||
|
/// "Filter" and "handler" seem to both mean the same thing here:
|
||||||
|
/// something that can produce true ids from proto-ids.
|
||||||
|
type Filter: IdentityHandler<I>;
|
||||||
|
|
||||||
|
/// Create an [`IdentityHandler<I>`] implementation that can
|
||||||
|
/// transform proto-ids into ids of type `I`.
|
||||||
|
///
|
||||||
|
/// [`IdentityHandler<I>`]: IdentityHandler
|
||||||
|
fn spawn(&self) -> Self::Filter;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A global identity handler factory based on [`IdentityManager`].
|
||||||
|
///
|
||||||
|
/// Each of this type's `IdentityHandlerFactory<I>::spawn` methods
|
||||||
|
/// returns a `Mutex<IdentityManager<I>>`, which allocates fresh `I`
|
||||||
|
/// ids itself, and takes `()` as its proto-id type.
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct IdentityManagerFactory;
|
||||||
|
|
||||||
|
impl<I: id::TypedId + Debug> IdentityHandlerFactory<I> for IdentityManagerFactory {
|
||||||
|
type Filter = Mutex<IdentityManager>;
|
||||||
|
fn spawn(&self) -> Self::Filter {
|
||||||
|
Mutex::new(IdentityManager::default())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A factory that can build [`IdentityHandler`]s for all resource
|
||||||
|
/// types.
|
||||||
|
pub trait GlobalIdentityHandlerFactory:
|
||||||
|
IdentityHandlerFactory<id::AdapterId>
|
||||||
|
+ IdentityHandlerFactory<id::DeviceId>
|
||||||
|
+ IdentityHandlerFactory<id::PipelineLayoutId>
|
||||||
|
+ IdentityHandlerFactory<id::ShaderModuleId>
|
||||||
|
+ IdentityHandlerFactory<id::BindGroupLayoutId>
|
||||||
|
+ IdentityHandlerFactory<id::BindGroupId>
|
||||||
|
+ IdentityHandlerFactory<id::CommandBufferId>
|
||||||
|
+ IdentityHandlerFactory<id::RenderBundleId>
|
||||||
|
+ IdentityHandlerFactory<id::RenderPipelineId>
|
||||||
|
+ IdentityHandlerFactory<id::ComputePipelineId>
|
||||||
|
+ IdentityHandlerFactory<id::QuerySetId>
|
||||||
|
+ IdentityHandlerFactory<id::BufferId>
|
||||||
|
+ IdentityHandlerFactory<id::StagingBufferId>
|
||||||
|
+ IdentityHandlerFactory<id::TextureId>
|
||||||
|
+ IdentityHandlerFactory<id::TextureViewId>
|
||||||
|
+ IdentityHandlerFactory<id::SamplerId>
|
||||||
|
+ IdentityHandlerFactory<id::SurfaceId>
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GlobalIdentityHandlerFactory for IdentityManagerFactory {}
|
||||||
|
|
||||||
|
pub type Input<G, I> = <<G as IdentityHandlerFactory<I>>::Filter as IdentityHandler<I>>::Input;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_epoch_end_of_life() {
|
||||||
|
use id::TypedId as _;
|
||||||
|
let mut man = IdentityManager::default();
|
||||||
|
man.epochs.push(id::EPOCH_MASK);
|
||||||
|
man.free.push(0);
|
||||||
|
let id1 = man.alloc::<id::BufferId>(Backend::Empty);
|
||||||
|
assert_eq!(id1.unzip().0, 0);
|
||||||
|
man.free(id1);
|
||||||
|
let id2 = man.alloc::<id::BufferId>(Backend::Empty);
|
||||||
|
// confirm that the index 0 is no longer re-used
|
||||||
|
assert_eq!(id2.unzip().0, 1);
|
||||||
|
}
|
||||||
@ -2,8 +2,9 @@ use crate::{
|
|||||||
device::{Device, DeviceDescriptor},
|
device::{Device, DeviceDescriptor},
|
||||||
global::Global,
|
global::Global,
|
||||||
hal_api::HalApi,
|
hal_api::HalApi,
|
||||||
hub::{GlobalIdentityHandlerFactory, Input, Token},
|
hub::Token,
|
||||||
id::{AdapterId, DeviceId, SurfaceId, Valid},
|
id::{AdapterId, DeviceId, SurfaceId, Valid},
|
||||||
|
identity::{GlobalIdentityHandlerFactory, Input},
|
||||||
present::Presentation,
|
present::Presentation,
|
||||||
LabelHelpers, LifeGuard, Stored, DOWNLEVEL_WARNING_MESSAGE,
|
LabelHelpers, LifeGuard, Stored, DOWNLEVEL_WARNING_MESSAGE,
|
||||||
};
|
};
|
||||||
|
|||||||
@ -46,6 +46,7 @@ pub mod global;
|
|||||||
pub mod hal_api;
|
pub mod hal_api;
|
||||||
pub mod hub;
|
pub mod hub;
|
||||||
pub mod id;
|
pub mod id;
|
||||||
|
pub mod identity;
|
||||||
mod init_tracker;
|
mod init_tracker;
|
||||||
pub mod instance;
|
pub mod instance;
|
||||||
pub mod pipeline;
|
pub mod pipeline;
|
||||||
|
|||||||
@ -18,8 +18,9 @@ use crate::{
|
|||||||
device::{DeviceError, MissingDownlevelFlags},
|
device::{DeviceError, MissingDownlevelFlags},
|
||||||
global::Global,
|
global::Global,
|
||||||
hal_api::HalApi,
|
hal_api::HalApi,
|
||||||
hub::{GlobalIdentityHandlerFactory, Input, Token},
|
hub::Token,
|
||||||
id::{DeviceId, SurfaceId, TextureId, Valid},
|
id::{DeviceId, SurfaceId, TextureId, Valid},
|
||||||
|
identity::{GlobalIdentityHandlerFactory, Input},
|
||||||
init_tracker::TextureInitTracker,
|
init_tracker::TextureInitTracker,
|
||||||
resource, track, LifeGuard, Stored,
|
resource, track, LifeGuard, Stored,
|
||||||
};
|
};
|
||||||
|
|||||||
@ -2,8 +2,9 @@ use crate::{
|
|||||||
device::{DeviceError, HostMap, MissingDownlevelFlags, MissingFeatures},
|
device::{DeviceError, HostMap, MissingDownlevelFlags, MissingFeatures},
|
||||||
global::Global,
|
global::Global,
|
||||||
hal_api::HalApi,
|
hal_api::HalApi,
|
||||||
hub::{GlobalIdentityHandlerFactory, Resource, Token},
|
hub::{Resource, Token},
|
||||||
id::{AdapterId, DeviceId, SurfaceId, TextureId, Valid},
|
id::{AdapterId, DeviceId, SurfaceId, TextureId, Valid},
|
||||||
|
identity::GlobalIdentityHandlerFactory,
|
||||||
init_tracker::{BufferInitTracker, TextureInitTracker},
|
init_tracker::{BufferInitTracker, TextureInitTracker},
|
||||||
track::TextureSelector,
|
track::TextureSelector,
|
||||||
validation::MissingBufferUsageError,
|
validation::MissingBufferUsageError,
|
||||||
|
|||||||
@ -26,7 +26,7 @@ use wgc::id::TypedId;
|
|||||||
|
|
||||||
const LABEL: &str = "label";
|
const LABEL: &str = "label";
|
||||||
|
|
||||||
pub struct Context(wgc::global::Global<wgc::hub::IdentityManagerFactory>);
|
pub struct Context(wgc::global::Global<wgc::identity::IdentityManagerFactory>);
|
||||||
|
|
||||||
impl Drop for Context {
|
impl Drop for Context {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
@ -45,7 +45,7 @@ impl Context {
|
|||||||
Self(unsafe {
|
Self(unsafe {
|
||||||
wgc::global::Global::from_hal_instance::<A>(
|
wgc::global::Global::from_hal_instance::<A>(
|
||||||
"wgpu",
|
"wgpu",
|
||||||
wgc::hub::IdentityManagerFactory,
|
wgc::identity::IdentityManagerFactory,
|
||||||
hal_instance,
|
hal_instance,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
@ -60,11 +60,11 @@ impl Context {
|
|||||||
|
|
||||||
pub unsafe fn from_core_instance(core_instance: wgc::instance::Instance) -> Self {
|
pub unsafe fn from_core_instance(core_instance: wgc::instance::Instance) -> Self {
|
||||||
Self(unsafe {
|
Self(unsafe {
|
||||||
wgc::global::Global::from_instance(wgc::hub::IdentityManagerFactory, core_instance)
|
wgc::global::Global::from_instance(wgc::identity::IdentityManagerFactory, core_instance)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn global(&self) -> &wgc::global::Global<wgc::hub::IdentityManagerFactory> {
|
pub(crate) fn global(&self) -> &wgc::global::Global<wgc::identity::IdentityManagerFactory> {
|
||||||
&self.0
|
&self.0
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -542,7 +542,7 @@ impl crate::Context for Context {
|
|||||||
fn init(instance_desc: wgt::InstanceDescriptor) -> Self {
|
fn init(instance_desc: wgt::InstanceDescriptor) -> Self {
|
||||||
Self(wgc::global::Global::new(
|
Self(wgc::global::Global::new(
|
||||||
"wgpu",
|
"wgpu",
|
||||||
wgc::hub::IdentityManagerFactory,
|
wgc::identity::IdentityManagerFactory,
|
||||||
instance_desc,
|
instance_desc,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user