Use strong type

This commit is contained in:
psincf 2019-04-26 23:04:36 +02:00
parent 1e177d0813
commit 44cf64495a
5 changed files with 195 additions and 79 deletions

View File

@ -99,8 +99,8 @@ impl CommandBufferHandle {
base: &mut TrackerSet,
head: &TrackerSet,
stitch: Stitch,
buffer_guard: &Storage<BufferHandle>,
texture_guard: &Storage<TextureHandle>,
buffer_guard: &Storage<BufferHandle, crate::BufferId>,
texture_guard: &Storage<TextureHandle, crate::TextureId>,
) {
let buffer_barriers =
base.buffers

View File

@ -802,7 +802,7 @@ pub fn texture_create_view(
}
}
pub fn device_track_view(texture_id: TextureId, view_id: BufferId, ref_count: RefCount) {
pub fn device_track_view(texture_id: TextureId, view_id: TextureViewId, ref_count: RefCount) {
let device_id = HUB.textures.read()[texture_id].device_id.value;
let query = HUB.devices.read()[device_id]
.trackers

View File

@ -87,107 +87,112 @@ impl IdentityManager {
}
}
pub struct Storage<T> {
pub struct Storage<T, I:'static + ToId> {
//TODO: consider concurrent hashmap?
map: VecMap<(T, Epoch)>,
_phantom: std::marker::PhantomData<&'static I>,
}
impl<T> ops::Index<Id> for Storage<T> {
impl<T, I:ToId> ops::Index<I> for Storage<T, I> {
type Output = T;
fn index(&self, id: Id) -> &T {
let (ref value, epoch) = self.map[id.0 as usize];
assert_eq!(epoch, id.1);
fn index(&self, id: I) -> &T {
let (ref value, epoch) = self.map[id.id().0 as usize];
assert_eq!(epoch, id.id().1);
value
}
}
impl<T> ops::IndexMut<Id> for Storage<T> {
fn index_mut(&mut self, id: Id) -> &mut T {
let (ref mut value, epoch) = self.map[id.0 as usize];
assert_eq!(epoch, id.1);
impl<T, I:ToId> ops::IndexMut<I> for Storage<T, I> {
fn index_mut(&mut self, id: I) -> &mut T {
let (ref mut value, epoch) = self.map[id.id().0 as usize];
assert_eq!(epoch, id.id().1);
value
}
}
impl<T> Storage<T> {
pub fn contains(&self, id: Id) -> bool {
match self.map.get(id.0 as usize) {
Some(&(_, epoch)) if epoch == id.1 => true,
impl<T, I:ToId> Storage<T, I> {
pub fn contains(&self, id: I) -> bool {
match self.map.get(id.id().0 as usize) {
Some(&(_, epoch)) if epoch == id.id().1 => true,
_ => false,
}
}
}
pub struct Registry<T> {
use crate::ToId;
pub struct Registry<T, I: 'static + ToId + From<Id>> {
#[cfg(feature = "local")]
identity: Mutex<IdentityManager>,
data: RwLock<Storage<T>>,
data: RwLock<Storage<T, I>>,
_phantom: std::marker::PhantomData<&'static I>,
}
impl<T> Default for Registry<T> {
impl<T, I: ToId + From<Id>> Default for Registry<T, I> {
fn default() -> Self {
Registry {
#[cfg(feature = "local")]
identity: Mutex::new(IdentityManager::default()),
data: RwLock::new(Storage { map: VecMap::new() }),
data: RwLock::new(Storage { map: VecMap::new(), _phantom: std::marker::PhantomData }),
_phantom: std::marker::PhantomData,
}
}
}
impl<T> ops::Deref for Registry<T> {
type Target = RwLock<Storage<T>>;
impl<T, I: ToId + From<Id>> ops::Deref for Registry<T, I> {
type Target = RwLock<Storage<T, I>>;
fn deref(&self) -> &Self::Target {
&self.data
}
}
impl<T> ops::DerefMut for Registry<T> {
impl<T, I: ToId + From<Id>> ops::DerefMut for Registry<T, I> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.data
}
}
impl<T> Registry<T> {
pub fn register(&self, id: Id, value: T) {
let old = self.data.write().map.insert(id.0 as usize, (value, id.1));
impl<T, I: ToId + From<Id> + Clone> Registry<T, I> {
pub fn register(&self, id: I, value: T) {
let old = self.data.write().map.insert(id.id().0 as usize, (value, id.id().1));
assert!(old.is_none());
}
#[cfg(feature = "local")]
pub fn register_local(&self, value: T) -> Id {
let id = self.identity.lock().alloc();
self.register(id, value);
pub fn register_local(&self, value: T) -> I {
let raw_id = self.identity.lock().alloc();
let id:I = raw_id.into();
self.register(id.clone(), value);
id
}
pub fn unregister(&self, id: Id) -> T {
pub fn unregister(&self, id: I) -> T {
#[cfg(feature = "local")]
self.identity.lock().free(id);
let (value, epoch) = self.data.write().map.remove(id.0 as usize).unwrap();
assert_eq!(epoch, id.1);
self.identity.lock().free(id.id());
let (value, epoch) = self.data.write().map.remove(id.id().0 as usize).unwrap();
assert_eq!(epoch, id.id().1);
value
}
}
use crate::*;
#[derive(Default)]
pub struct Hub {
pub instances: Arc<Registry<InstanceHandle>>,
pub adapters: Arc<Registry<AdapterHandle>>,
pub devices: Arc<Registry<DeviceHandle>>,
pub pipeline_layouts: Arc<Registry<PipelineLayoutHandle>>,
pub bind_group_layouts: Arc<Registry<BindGroupLayoutHandle>>,
pub bind_groups: Arc<Registry<BindGroupHandle>>,
pub shader_modules: Arc<Registry<ShaderModuleHandle>>,
pub command_buffers: Arc<Registry<CommandBufferHandle>>,
pub render_pipelines: Arc<Registry<RenderPipelineHandle>>,
pub compute_pipelines: Arc<Registry<ComputePipelineHandle>>,
pub render_passes: Arc<Registry<RenderPassHandle>>,
pub compute_passes: Arc<Registry<ComputePassHandle>>,
pub buffers: Arc<Registry<BufferHandle>>,
pub textures: Arc<Registry<TextureHandle>>,
pub texture_views: Arc<Registry<TextureViewHandle>>,
pub samplers: Arc<Registry<SamplerHandle>>,
pub surfaces: Arc<Registry<SurfaceHandle>>,
pub instances: Arc<Registry<InstanceHandle, InstanceId>>,
pub adapters: Arc<Registry<AdapterHandle, AdapterId>>,
pub devices: Arc<Registry<DeviceHandle, DeviceId>>,
pub pipeline_layouts: Arc<Registry<PipelineLayoutHandle, PipelineLayoutId>>,
pub bind_group_layouts: Arc<Registry<BindGroupLayoutHandle, BindGroupLayoutId>>,
pub bind_groups: Arc<Registry<BindGroupHandle, BindGroupId>>,
pub shader_modules: Arc<Registry<ShaderModuleHandle, ShaderModuleId>>,
pub command_buffers: Arc<Registry<CommandBufferHandle, CommandBufferId>>,
pub render_pipelines: Arc<Registry<RenderPipelineHandle, RenderPipelineId>>,
pub compute_pipelines: Arc<Registry<ComputePipelineHandle, ComputePipelineId>>,
pub render_passes: Arc<Registry<RenderPassHandle, RenderPassId>>,
pub compute_passes: Arc<Registry<ComputePassHandle, ComputePassId>>,
pub buffers: Arc<Registry<BufferHandle, BufferId>>,
pub textures: Arc<Registry<TextureHandle, TextureId>>,
pub texture_views: Arc<Registry<TextureViewHandle, TextureViewId>>,
pub samplers: Arc<Registry<SamplerHandle, SamplerId>>,
pub surfaces: Arc<Registry<SurfaceHandle, SurfaceId>>,
}
lazy_static! {

View File

@ -166,46 +166,157 @@ pub struct ByteArray {
pub length: usize,
}
pub type InstanceId = hub::Id;
macro_rules! transparent {
($i:item) => (
#[repr(transparent)]
#[derive(Clone, Copy, Debug, Hash, PartialEq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
$i
)
}
pub trait ToId {
fn id(&self) -> hub::Id;
}
macro_rules! to_id {
($i:ident) => (
impl ToId for $i {
fn id(&self) -> hub::Id {
self.0
}
}
)
}
macro_rules! from_id {
($i:ident) => (
impl From<hub::Id> for $i {
fn from(id:hub::Id) -> $i {
$i(id)
}
}
)
}
use hub::{Index, Epoch, NewId, Id};
macro_rules! new_id {
($i:ident) => (
impl NewId for $i {
fn new(index: Index, epoch: Epoch) -> Self {
let id = Id::new(index, epoch);
$i(id)
}
fn index(&self) -> Index {
(self.id()).index()
}
fn epoch(&self) -> Epoch {
(self.id()).epoch()
}
}
)
}
transparent!(pub struct InstanceId(hub::Id););
to_id!(InstanceId);
from_id!(InstanceId);
type InstanceHandle = back::Instance;
pub type AdapterId = hub::Id;
transparent!(pub struct AdapterId(hub::Id););
to_id!(AdapterId);
from_id!(AdapterId);
type AdapterHandle = hal::Adapter<back::Backend>;
pub type DeviceId = hub::Id;
transparent!(pub struct DeviceId(hub::Id););
to_id!(DeviceId);
from_id!(DeviceId);
type DeviceHandle = Device<back::Backend>;
//transparent!(pub struct QueueId(DeviceId););
pub type QueueId = DeviceId;
pub type BufferId = hub::Id;
transparent!(pub struct BufferId(hub::Id););
to_id!(BufferId);
from_id!(BufferId);
new_id!(BufferId);
type BufferHandle = Buffer<back::Backend>;
// Resource
pub type TextureViewId = hub::Id;
transparent!(pub struct TextureViewId(hub::Id););
to_id!(TextureViewId);
from_id!(TextureViewId);
new_id!(TextureViewId);
type TextureViewHandle = TextureView<back::Backend>;
pub type TextureId = hub::Id;
transparent!(pub struct TextureId(hub::Id););
to_id!(TextureId);
from_id!(TextureId);
new_id!(TextureId);
type TextureHandle = Texture<back::Backend>;
pub type SamplerId = hub::Id;
transparent!(pub struct SamplerId(hub::Id););
to_id!(SamplerId);
from_id!(SamplerId);
type SamplerHandle = Sampler<back::Backend>;
// Binding model
pub type BindGroupLayoutId = hub::Id;
transparent!(pub struct BindGroupLayoutId(hub::Id););
to_id!(BindGroupLayoutId);
from_id!(BindGroupLayoutId);
type BindGroupLayoutHandle = BindGroupLayout<back::Backend>;
pub type PipelineLayoutId = hub::Id;
transparent!(pub struct PipelineLayoutId(hub::Id););
to_id!(PipelineLayoutId);
from_id!(PipelineLayoutId);
type PipelineLayoutHandle = PipelineLayout<back::Backend>;
pub type BindGroupId = hub::Id;
transparent!(pub struct BindGroupId(hub::Id););
to_id!(BindGroupId);
from_id!(BindGroupId);
type BindGroupHandle = BindGroup<back::Backend>;
// Pipeline
pub type InputStateId = hub::Id;
pub type ShaderModuleId = hub::Id;
transparent!(pub struct InputStateId(hub::Id););
to_id!(InputStateId);
from_id!(InputStateId);
transparent!(pub struct ShaderModuleId(hub::Id););
to_id!(ShaderModuleId);
from_id!(ShaderModuleId);
type ShaderModuleHandle = ShaderModule<back::Backend>;
pub type RenderPipelineId = hub::Id;
transparent!(pub struct RenderPipelineId(hub::Id););
to_id!(RenderPipelineId);
from_id!(RenderPipelineId);
type RenderPipelineHandle = RenderPipeline<back::Backend>;
pub type ComputePipelineId = hub::Id;
transparent!(pub struct ComputePipelineId(hub::Id););
to_id!(ComputePipelineId);
from_id!(ComputePipelineId);
type ComputePipelineHandle = ComputePipeline<back::Backend>;
// Command
pub type CommandBufferId = hub::Id;
transparent!(pub struct CommandBufferId(hub::Id););
to_id!(CommandBufferId);
from_id!(CommandBufferId);
type CommandBufferHandle = CommandBuffer<back::Backend>;
//transparent!(pub struct CommandEncoderId(CommandBufferId););
pub type CommandEncoderId = CommandBufferId;
pub type RenderPassId = hub::Id;
transparent!(pub struct RenderPassId(hub::Id););
to_id!(RenderPassId);
from_id!(RenderPassId);
type RenderPassHandle = RenderPass<back::Backend>;
pub type ComputePassId = hub::Id;
transparent!(pub struct ComputePassId(hub::Id););
to_id!(ComputePassId);
from_id!(ComputePassId);
type ComputePassHandle = ComputePass<back::Backend>;
// Swap chain
pub type SurfaceId = hub::Id;
transparent!(pub struct SurfaceId(hub::Id););
to_id!(SurfaceId);
from_id!(SurfaceId);
type SurfaceHandle = Surface<back::Backend>;
//transparent!(pub struct SwapChainId(SurfaceId););
pub type SwapChainId = SurfaceId;

View File

@ -276,37 +276,37 @@ impl<I: NewId, U: Copy + GenericUsage + BitOr<Output = U> + PartialEq> Tracker<I
}
}
impl<U: Copy + GenericUsage + BitOr<Output = U> + PartialEq> Tracker<Id, U> {
impl<I: crate::ToId + NewId + Clone, U: Copy + GenericUsage + BitOr<Output = U> + PartialEq> Tracker<I, U> {
fn _get_with_usage<'a, T: 'a + Borrow<RefCount>>(
&mut self,
storage: &'a Storage<T>,
id: Id,
storage: &'a Storage<T, I>,
id: I,
usage: U,
permit: TrackPermit,
) -> Result<(&'a T, Tracktion<U>), U> {
let item = &storage[id];
let item = &storage[id.clone()];
self.transit(id, item.borrow(), usage, permit)
.map(|tracktion| (item, tracktion))
}
pub(crate) fn get_with_extended_usage<'a, T: 'a + Borrow<RefCount>>(
&mut self,
storage: &'a Storage<T>,
id: Id,
storage: &'a Storage<T, I>,
id: I,
usage: U,
) -> Result<&'a T, U> {
let item = &storage[id];
let item = &storage[id.clone()];
self.transit(id, item.borrow(), usage, TrackPermit::EXTEND)
.map(|_tracktion| item)
}
pub(crate) fn get_with_replaced_usage<'a, T: 'a + Borrow<RefCount>>(
&mut self,
storage: &'a Storage<T>,
id: Id,
storage: &'a Storage<T, I>,
id: I,
usage: U,
) -> Result<(&'a T, Option<U>), U> {
let item = &storage[id];
let item = &storage[id.clone()];
self.transit(id, item.borrow(), usage, TrackPermit::REPLACE)
.map(|tracktion| {
(