diff --git a/Cargo.lock b/Cargo.lock index 1995cb267..bae74424b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1400,6 +1400,7 @@ dependencies = [ name = "wgpu-native" version = "0.1.0" dependencies = [ + "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "gfx-backend-dx11 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "gfx-backend-dx12 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1411,6 +1412,7 @@ dependencies = [ "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", + "vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "winit 0.18.1 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/gfx-examples/src/framework.rs b/gfx-examples/src/framework.rs index 6d1561637..69df4efbd 100644 --- a/gfx-examples/src/framework.rs +++ b/gfx-examples/src/framework.rs @@ -1,6 +1,7 @@ use log::info; +#[allow(dead_code)] pub fn cast_slice(data: &[T]) -> &[u8] { use std::mem::size_of; use std::slice::from_raw_parts; diff --git a/rustfmt.toml b/rustfmt.toml index e6067ba19..03cbecbde 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -1 +1,2 @@ newline_style = "Native" +spaces_around_ranges = true diff --git a/wgpu-bindings/wgpu.h b/wgpu-bindings/wgpu.h index 29c9aff2e..d23fd06ba 100644 --- a/wgpu-bindings/wgpu.h +++ b/wgpu-bindings/wgpu.h @@ -153,7 +153,9 @@ typedef enum { WGPUVertexFormat_IntR8G8B8A8 = 4, } WGPUVertexFormat; -typedef uint32_t WGPUId; +typedef struct WGPUBufferMapAsyncStatus WGPUBufferMapAsyncStatus; + +typedef struct WGPUId WGPUId; typedef WGPUId WGPUDeviceId; @@ -169,6 +171,10 @@ typedef struct { typedef WGPUId WGPUBufferId; +typedef void (*WGPUBufferMapReadCallback)(WGPUBufferMapAsyncStatus status, const uint8_t *data, uint8_t *userdata); + +typedef void (*WGPUBufferMapWriteCallback)(WGPUBufferMapAsyncStatus status, uint8_t *data, uint8_t *userdata); + typedef WGPUId WGPUCommandBufferId; typedef struct { @@ -553,11 +559,25 @@ WGPUDeviceId wgpu_adapter_create_device(WGPUAdapterId adapter_id, const WGPUDevi void wgpu_buffer_destroy(WGPUBufferId buffer_id); +void wgpu_buffer_map_read_async(WGPUBufferId buffer_id, + uint32_t start, + uint32_t size, + WGPUBufferMapReadCallback callback, + uint8_t *userdata); + +void wgpu_buffer_map_write_async(WGPUBufferId buffer_id, + uint32_t start, + uint32_t size, + WGPUBufferMapWriteCallback callback, + uint8_t *userdata); + void wgpu_buffer_set_sub_data(WGPUBufferId buffer_id, uint32_t start, uint32_t count, const uint8_t *data); +void wgpu_buffer_unmap(WGPUBufferId buffer_id); + void wgpu_command_buffer_copy_buffer_to_buffer(WGPUCommandBufferId command_buffer_id, WGPUBufferId src, uint32_t src_offset, diff --git a/wgpu-native/Cargo.toml b/wgpu-native/Cargo.toml index 17276fe6f..916d806ee 100644 --- a/wgpu-native/Cargo.toml +++ b/wgpu-native/Cargo.toml @@ -22,6 +22,7 @@ remote = ["serde"] metal-auto-capture = ["gfx-backend-metal/auto-capture"] [dependencies] +arrayvec = "0.4" bitflags = "1.0" lazy_static = "1.1.0" log = "0.4" @@ -34,4 +35,5 @@ gfx-backend-dx12 = { version = "0.1.0", optional = true } gfx-backend-metal = { version = "0.1.0", optional = true } #rendy-memory = { git = "https://github.com/rustgd/rendy", rev = "ce7dd7f", features = ["gfx-hal"] } serde = { version = "1.0", features = ["serde_derive"], optional = true } +vec_map = "0.8" winit = { version = "0.18", optional = true } diff --git a/wgpu-native/src/binding_model.rs b/wgpu-native/src/binding_model.rs index f610bdcc5..66eb224e6 100644 --- a/wgpu-native/src/binding_model.rs +++ b/wgpu-native/src/binding_model.rs @@ -1,6 +1,6 @@ use crate::track::TrackerSet; use crate::{ - LifeGuard, WeaklyStored, + LifeGuard, BindGroupLayoutId, BufferId, SamplerId, TextureViewId, }; @@ -50,7 +50,7 @@ pub struct PipelineLayoutDescriptor { pub struct PipelineLayout { pub(crate) raw: B::PipelineLayout, - pub(crate) bind_group_layout_ids: Vec>, + pub(crate) bind_group_layout_ids: Vec, } #[repr(C)] @@ -82,7 +82,7 @@ pub struct BindGroupDescriptor { pub struct BindGroup { pub(crate) raw: B::DescriptorSet, - pub(crate) layout_id: WeaklyStored, + pub(crate) layout_id: BindGroupLayoutId, pub(crate) life_guard: LifeGuard, pub(crate) used: TrackerSet, } diff --git a/wgpu-native/src/command/bind.rs b/wgpu-native/src/command/bind.rs index a9579e9f6..6746a9ffb 100644 --- a/wgpu-native/src/command/bind.rs +++ b/wgpu-native/src/command/bind.rs @@ -1,17 +1,17 @@ use crate::{ - BindGroupHandle, Stored, WeaklyStored, + BindGroupHandle, Stored, BindGroupId, BindGroupLayoutId, PipelineLayoutId, }; pub struct BindGroupPair { - layout_id: WeaklyStored, + layout_id: BindGroupLayoutId, group_id: Stored, } #[derive(Default)] pub struct BindGroupEntry { - expected_layout_id: Option>, + expected_layout_id: Option, provided: Option, } @@ -38,12 +38,12 @@ impl BindGroupEntry { pub fn expect_layout( &mut self, bind_group_layout_id: BindGroupLayoutId, ) -> Option { - let some = Some(WeaklyStored(bind_group_layout_id)); + let some = Some(bind_group_layout_id); if self.expected_layout_id != some { self.expected_layout_id = some; match self.provided { - Some(BindGroupPair { ref layout_id, ref group_id }) - if layout_id.0 == bind_group_layout_id => Some(group_id.value), + Some(BindGroupPair { layout_id, ref group_id }) + if layout_id == bind_group_layout_id => Some(group_id.value), Some(_) | None => None, } } else { @@ -54,7 +54,7 @@ impl BindGroupEntry { #[derive(Default)] pub struct Binder { - pub(crate) pipeline_layout_id: Option>, //TODO: strongly `Stored` + pub(crate) pipeline_layout_id: Option, //TODO: strongly `Stored` pub(crate) entries: Vec, } @@ -70,7 +70,7 @@ impl Binder { ) -> Option { self.ensure_length(index + 1); if self.entries[index].provide(bind_group_id, bind_group) { - self.pipeline_layout_id.as_ref().map(|&WeaklyStored(id)| id) + self.pipeline_layout_id.as_ref().cloned() } else { None } diff --git a/wgpu-native/src/command/compute.rs b/wgpu-native/src/command/compute.rs index 8560c1657..ea2b8a41b 100644 --- a/wgpu-native/src/command/compute.rs +++ b/wgpu-native/src/command/compute.rs @@ -112,18 +112,18 @@ pub extern "C" fn wgpu_compute_pass_set_pipeline( } let pipeline_layout_guard = HUB.pipeline_layouts.read(); - let pipeline_layout = pipeline_layout_guard.get(pipeline.layout_id.0); + let pipeline_layout = pipeline_layout_guard.get(pipeline.layout_id); let bing_group_guard = HUB.bind_groups.read(); pass.binder.pipeline_layout_id = Some(pipeline.layout_id.clone()); pass.binder.ensure_length(pipeline_layout.bind_group_layout_ids.len()); - for (index, (entry, bgl_id)) in pass.binder.entries + for (index, (entry, &bgl_id)) in pass.binder.entries .iter_mut() .zip(&pipeline_layout.bind_group_layout_ids) .enumerate() { - if let Some(bg_id) = entry.expect_layout(bgl_id.0) { + if let Some(bg_id) = entry.expect_layout(bgl_id) { let bind_group = bing_group_guard.get(bg_id); unsafe { pass.raw.bind_compute_descriptor_sets( diff --git a/wgpu-native/src/command/mod.rs b/wgpu-native/src/command/mod.rs index e80cdc1bb..6ba74a3cc 100644 --- a/wgpu-native/src/command/mod.rs +++ b/wgpu-native/src/command/mod.rs @@ -22,7 +22,7 @@ use crate::{ BufferId, CommandBufferId, CommandEncoderId, DeviceId, TextureId, TextureViewId, BufferUsageFlags, TextureUsageFlags, Color, - LifeGuard, Stored, WeaklyStored, + LifeGuard, Stored, CommandBufferHandle, }; #[cfg(feature = "local")] @@ -294,9 +294,9 @@ pub fn command_encoder_begin_render_pass( let fb_key = FramebufferKey { attachments: color_attachments .iter() - .map(|at| WeaklyStored(at.attachment)) + .map(|at| at.attachment) .chain( - depth_stencil_attachment.map(|at| WeaklyStored(at.attachment)), + depth_stencil_attachment.map(|at| at.attachment), ) .collect(), }; @@ -308,7 +308,7 @@ pub fn command_encoder_begin_render_pass( .key() .attachments .iter() - .map(|&WeaklyStored(id)| &view_guard.get(id).raw); + .map(|&id| &view_guard.get(id).raw); unsafe { device @@ -374,7 +374,7 @@ pub extern "C" fn wgpu_command_encoder_begin_render_pass( desc: RenderPassDescriptor, ) -> RenderPassId { let pass = command_encoder_begin_render_pass(command_encoder_id, desc); - HUB.render_passes.register(pass) + HUB.render_passes.register_local(pass) } pub fn command_encoder_begin_compute_pass( @@ -398,5 +398,5 @@ pub extern "C" fn wgpu_command_encoder_begin_compute_pass( command_encoder_id: CommandEncoderId, ) -> ComputePassId { let pass = command_encoder_begin_compute_pass(command_encoder_id); - HUB.compute_passes.register(pass) + HUB.compute_passes.register_local(pass) } diff --git a/wgpu-native/src/command/render.rs b/wgpu-native/src/command/render.rs index 813369784..4fc443a22 100644 --- a/wgpu-native/src/command/render.rs +++ b/wgpu-native/src/command/render.rs @@ -224,18 +224,18 @@ pub extern "C" fn wgpu_render_pass_set_pipeline( } let pipeline_layout_guard = HUB.pipeline_layouts.read(); - let pipeline_layout = pipeline_layout_guard.get(pipeline.layout_id.0); + let pipeline_layout = pipeline_layout_guard.get(pipeline.layout_id); let bing_group_guard = HUB.bind_groups.read(); pass.binder.pipeline_layout_id = Some(pipeline.layout_id.clone()); pass.binder.ensure_length(pipeline_layout.bind_group_layout_ids.len()); - for (index, (entry, bgl_id)) in pass.binder.entries + for (index, (entry, &bgl_id)) in pass.binder.entries .iter_mut() .zip(&pipeline_layout.bind_group_layout_ids) .enumerate() { - if let Some(bg_id) = entry.expect_layout(bgl_id.0) { + if let Some(bg_id) = entry.expect_layout(bgl_id) { let bind_group = bing_group_guard.get(bg_id); unsafe { pass.raw.bind_graphics_descriptor_sets( diff --git a/wgpu-native/src/device.rs b/wgpu-native/src/device.rs index 61542f733..3009dd96d 100644 --- a/wgpu-native/src/device.rs +++ b/wgpu-native/src/device.rs @@ -2,7 +2,7 @@ use crate::{binding_model, command, conv, pipeline, resource, swap_chain}; use crate::hub::HUB; use crate::track::{TrackerSet, TrackPermit}; use crate::{ - LifeGuard, RefCount, Stored, SubmissionIndex, WeaklyStored, + LifeGuard, RefCount, Stored, SubmissionIndex, BufferMapAsyncStatus, BufferMapOperation, }; use crate::{ @@ -15,6 +15,7 @@ use crate::{ ShaderModuleId, CommandEncoderId, RenderPipelineId, ComputePipelineId, }; +use arrayvec::ArrayVec; use back; use hal::backend::FastHashMap; use hal::command::RawCommandBuffer; @@ -34,6 +35,8 @@ use std::collections::hash_map::Entry; use std::sync::atomic::Ordering; +type AttachmentVec = ArrayVec<[T; 5]>; + pub fn all_buffer_stages() -> hal::pso::PipelineStage { use hal::pso::PipelineStage as Ps; Ps::DRAW_INDIRECT | @@ -57,13 +60,13 @@ pub fn all_image_stages() -> hal::pso::PipelineStage { #[derive(Hash, PartialEq)] pub(crate) struct RenderPassKey { - pub attachments: Vec, + pub attachments: AttachmentVec, } impl Eq for RenderPassKey {} #[derive(Hash, PartialEq)] pub(crate) struct FramebufferKey { - pub attachments: Vec>, + pub attachments: AttachmentVec, } impl Eq for FramebufferKey {} @@ -222,7 +225,7 @@ impl DestroyedResources { let mut buffer_guard = HUB.buffers.write(); for buffer_id in self.ready_to_map.drain(..) { - let mut buffer = buffer_guard.get_mut(buffer_id); + let buffer = buffer_guard.get_mut(buffer_id); let mut operation = None; std::mem::swap(&mut operation, &mut buffer.pending_map_operation); match operation { @@ -254,7 +257,7 @@ impl DestroyedResources { pub struct Device { pub(crate) raw: B::Device, - adapter_id: WeaklyStored, + adapter_id: AdapterId, pub(crate) queue_group: hal::QueueGroup, //mem_allocator: Heaps, pub(crate) com_allocator: command::CommandAllocator, @@ -270,7 +273,7 @@ pub struct Device { impl Device { pub(crate) fn new( raw: B::Device, - adapter_id: WeaklyStored, + adapter_id: AdapterId, queue_group: hal::QueueGroup, mem_props: hal::MemoryProperties, ) -> Self { @@ -431,7 +434,7 @@ pub extern "C" fn wgpu_device_create_buffer( ) -> BufferId { let buffer = device_create_buffer(device_id, desc); let ref_count = buffer.life_guard.ref_count.clone(); - let id = HUB.buffers.register(buffer); + let id = HUB.buffers.register_local(buffer); device_track_buffer(device_id, id, ref_count); id } @@ -543,7 +546,7 @@ pub extern "C" fn wgpu_device_create_texture( ) -> TextureId { let texture = device_create_texture(device_id, desc); let ref_count = texture.life_guard.ref_count.clone(); - let id = HUB.textures.register(texture); + let id = HUB.textures.register_local(texture); device_track_texture(device_id, id, ref_count); id } @@ -617,7 +620,7 @@ pub extern "C" fn wgpu_texture_create_view( let view = texture_create_view(texture_id, desc); let texture_id = view.texture_id.value; let ref_count = view.life_guard.ref_count.clone(); - let id = HUB.texture_views.register(view); + let id = HUB.texture_views.register_local(view); device_track_view(texture_id, id, ref_count); id } @@ -671,7 +674,7 @@ pub extern "C" fn wgpu_texture_create_default_view(texture_id: TextureId) -> Tex let view = texture_create_default_view(texture_id); let texture_id = view.texture_id.value; let ref_count = view.life_guard.ref_count.clone(); - let id = HUB.texture_views.register(view); + let id = HUB.texture_views.register_local(view); device_track_view(texture_id, id, ref_count); id } @@ -757,7 +760,7 @@ pub extern "C" fn wgpu_device_create_sampler( device_id: DeviceId, desc: &resource::SamplerDescriptor ) -> SamplerId { let sampler = device_create_sampler(device_id, desc); - HUB.samplers.register(sampler) + HUB.samplers.register_local(sampler) } @@ -799,7 +802,7 @@ pub extern "C" fn wgpu_device_create_bind_group_layout( desc: &binding_model::BindGroupLayoutDescriptor, ) -> BindGroupLayoutId { let layout = device_create_bind_group_layout(device_id, desc); - HUB.bind_group_layouts.register(layout) + HUB.bind_group_layouts.register_local(layout) } pub fn device_create_pipeline_layout( @@ -829,7 +832,6 @@ pub fn device_create_pipeline_layout( bind_group_layout_ids: bind_group_layout_ids .iter() .cloned() - .map(WeaklyStored) .collect(), } } @@ -841,7 +843,7 @@ pub extern "C" fn wgpu_device_create_pipeline_layout( desc: &binding_model::PipelineLayoutDescriptor, ) -> PipelineLayoutId { let layout = device_create_pipeline_layout(device_id, desc); - HUB.pipeline_layouts.register(layout) + HUB.pipeline_layouts.register_local(layout) } pub fn device_create_bind_group( @@ -916,7 +918,7 @@ pub fn device_create_bind_group( binding_model::BindGroup { raw: desc_set, - layout_id: WeaklyStored(desc.layout), + layout_id: desc.layout, life_guard: LifeGuard::new(), used, } @@ -929,7 +931,7 @@ pub extern "C" fn wgpu_device_create_bind_group( desc: &binding_model::BindGroupDescriptor, ) -> BindGroupId { let bind_group = device_create_bind_group(device_id, desc); - HUB.bind_groups.register(bind_group) + HUB.bind_groups.register_local(bind_group) } @@ -957,7 +959,7 @@ pub extern "C" fn wgpu_device_create_shader_module( desc: &pipeline::ShaderModuleDescriptor, ) -> ShaderModuleId { let module = device_create_shader_module(device_id, desc); - HUB.shader_modules.register(module) + HUB.shader_modules.register_local(module) } pub fn device_create_command_encoder( @@ -988,7 +990,7 @@ pub extern "C" fn wgpu_device_create_command_encoder( desc: &command::CommandEncoderDescriptor, ) -> CommandEncoderId { let cmb = device_create_command_encoder(device_id, desc); - HUB.command_buffers.register(cmb) + HUB.command_buffers.register_local(cmb) } #[no_mangle] @@ -1084,7 +1086,7 @@ pub extern "C" fn wgpu_queue_submit( .flat_map(|link| { //TODO: check the epoch surface_guard - .get(link.swap_chain_id.0) + .get(link.swap_chain_id) .swap_chain .as_ref() .map(|swap_chain| ( @@ -1339,7 +1341,7 @@ pub fn device_create_render_pipeline( pipeline::RenderPipeline { raw: pipeline, - layout_id: WeaklyStored(desc.layout), + layout_id: desc.layout, } } @@ -1350,7 +1352,7 @@ pub extern "C" fn wgpu_device_create_render_pipeline( desc: &pipeline::RenderPipelineDescriptor, ) -> RenderPipelineId { let pipeline = device_create_render_pipeline(device_id, desc); - HUB.render_pipelines.register(pipeline) + HUB.render_pipelines.register_local(pipeline) } pub fn device_create_compute_pipeline( @@ -1397,7 +1399,7 @@ pub fn device_create_compute_pipeline( pipeline::ComputePipeline { raw: pipeline, - layout_id: WeaklyStored(desc.layout), + layout_id: desc.layout, } } @@ -1408,7 +1410,7 @@ pub extern "C" fn wgpu_device_create_compute_pipeline( desc: &pipeline::ComputePipelineDescriptor, ) -> ComputePipelineId { let pipeline = device_create_compute_pipeline(device_id, desc); - HUB.compute_pipelines.register(pipeline) + HUB.compute_pipelines.register_local(pipeline) } pub fn device_create_swap_chain( @@ -1425,7 +1427,7 @@ pub fn device_create_swap_chain( let (caps, formats, _present_modes, _composite_alphas) = { let adapter_guard = HUB.adapters.read(); - let adapter = adapter_guard.get(device.adapter_id.0); + let adapter = adapter_guard.get(device.adapter_id); assert!(surface.raw.supports_queue_family(&adapter.queue_families[0])); surface.raw.compatibility(&adapter.physical_device) }; @@ -1556,13 +1558,13 @@ pub fn swap_chain_populate_textures( .unwrap() }; texture.swap_chain_link = Some(swap_chain::SwapChainLink { - swap_chain_id: WeaklyStored(swap_chain_id), //TODO: strongly + swap_chain_id, //TODO: strongly epoch: Mutex::new(0), image_index: i as hal::SwapImageIndex, }); let texture_id = Stored { ref_count: texture.life_guard.ref_count.clone(), - value: HUB.textures.register(texture), + value: HUB.textures.register_local(texture), }; trackers.textures.query( texture_id.value, @@ -1581,7 +1583,7 @@ pub fn swap_chain_populate_textures( }; let view_id = Stored { ref_count: view.life_guard.ref_count.clone(), - value: HUB.texture_views.register(view), + value: HUB.texture_views.register_local(view), }; trackers.views.query( view_id.value, diff --git a/wgpu-native/src/hub.rs b/wgpu-native/src/hub.rs index d7ca81075..e4d50036d 100644 --- a/wgpu-native/src/hub.rs +++ b/wgpu-native/src/hub.rs @@ -7,56 +7,89 @@ use crate::{ SurfaceHandle, }; -use hal::backend::FastHashMap; use lazy_static::lazy_static; use parking_lot::RwLock; #[cfg(feature = "local")] use parking_lot::Mutex; +use vec_map::VecMap; use std::ops; use std::sync::Arc; -//TODO: use Vec instead of HashMap -//TODO: track epochs of indices -pub type Id = u32; +pub(crate) type Index = u32; +pub(crate) type Epoch = u32; +#[derive(Clone, Copy, Debug, Hash, PartialEq)] +pub struct Id(Index, Epoch); + +pub trait NewId { + fn new(index: Index, epoch: Epoch) -> Self; + fn index(&self) -> Index; + fn epoch(&self) -> Epoch; +} + +impl NewId for Id { + fn new(index: Index, epoch: Epoch) -> Self { + Id(index, epoch) + } + + fn index(&self) -> Index { + self.0 + } + + fn epoch(&self) -> Epoch { + self.1 + } +} /// A simple structure to manage identities of objects. #[derive(Default)] pub struct IdentityManager { - last_id: Id, - free: Vec, + free: Vec, + epochs: Vec, } impl IdentityManager { pub fn alloc(&mut self) -> Id { match self.free.pop() { - Some(id) => id, + Some(index) => { + Id(index, self.epochs[index as usize]) + } None => { - self.last_id += 1; - assert_ne!(self.last_id, 0); - self.last_id + let id = Id(self.epochs.len() as Index, 1); + self.epochs.push(id.1); + id } } } - pub fn free(&mut self, id: Id) { - debug_assert!(id <= self.last_id && !self.free.contains(&id)); - self.free.push(id); + pub fn free(&mut self, Id(index, epoch): Id) { + // avoid doing this check in release + if cfg!(debug_assertions) { + assert!(!self.free.contains(&index)); + } + let pe = &mut self.epochs[index as usize]; + assert_eq!(*pe, epoch); + *pe += 1; + self.free.push(index); } } pub struct Storage { //TODO: consider concurrent hashmap? - map: FastHashMap, + map: VecMap<(T, Epoch)>, } impl Storage { pub fn get(&self, id: Id) -> &T { - self.map.get(&id).unwrap() + let (ref value, epoch) = self.map[id.0 as usize]; + assert_eq!(epoch, id.1); + value } pub fn get_mut(&mut self, id: Id) -> &mut T { - self.map.get_mut(&id).unwrap() + let (ref mut value, epoch) = self.map[id.0 as usize]; + assert_eq!(epoch, id.1); + value } } @@ -72,7 +105,7 @@ impl Default for Registry { #[cfg(feature = "local")] identity: Mutex::new(IdentityManager::default()), data: RwLock::new(Storage { - map: FastHashMap::default(), + map: VecMap::new(), }), } } @@ -92,26 +125,26 @@ impl ops::DerefMut for Registry { } impl Registry { - #[cfg(feature = "local")] - pub fn register(&self, value: T) -> Id { - let id = self.identity.lock().alloc(); - let old = self.data.write().map.insert(id, value); + pub fn register(&self, id: Id, value: T) { + let old = self.data.write().map.insert(id.0 as usize, (value, id.1)); assert!(old.is_none()); + } +} + +impl Registry { + #[cfg(feature = "local")] + pub fn register_local(&self, value: T) -> Id { + let id = self.identity.lock().alloc(); + self.register(id, value); id } pub fn unregister(&self, id: Id) -> T { #[cfg(feature = "local")] self.identity.lock().free(id); - self.data.write().map.remove(&id).unwrap() - } -} - -#[cfg(feature = "remote")] -impl Registry { - pub fn register(&self, id: Id, value: T) { - let old = self.data.write().map.insert(id, value); - assert!(old.is_none()); + let (value, epoch) = self.data.write().map.remove(id.0 as usize).unwrap(); + assert_eq!(epoch, id.1); + value } } diff --git a/wgpu-native/src/instance.rs b/wgpu-native/src/instance.rs index 3127ab155..42a973742 100644 --- a/wgpu-native/src/instance.rs +++ b/wgpu-native/src/instance.rs @@ -1,6 +1,5 @@ use crate::hub::HUB; use crate::{ - WeaklyStored, AdapterHandle, DeviceHandle, SurfaceHandle, AdapterId, InstanceId, }; @@ -48,7 +47,7 @@ pub fn create_instance() -> ::back::Instance { #[cfg(feature = "local")] pub extern "C" fn wgpu_create_instance() -> InstanceId { let inst = create_instance(); - HUB.instances.register(inst) + HUB.instances.register_local(inst) } #[cfg(feature = "local")] @@ -62,7 +61,7 @@ pub extern "C" fn wgpu_instance_create_surface_from_winit( .get(instance_id) .create_surface(window); let surface = SurfaceHandle::new(raw); - HUB.surfaces.register(surface) + HUB.surfaces.register_local(surface) } #[allow(unused_variables)] @@ -90,7 +89,7 @@ pub extern "C" fn wgpu_instance_create_surface_from_xlib( window: u64, ) -> SurfaceId { let surface = instance_create_surface_from_xlib(instance_id, display, window); - HUB.surfaces.register(surface) + HUB.surfaces.register_local(surface) } #[allow(unused_variables)] @@ -116,7 +115,7 @@ pub extern "C" fn wgpu_instance_create_surface_from_macos_layer( layer: *mut std::ffi::c_void, ) -> SurfaceId { let surface = instance_create_surface_from_macos_layer(instance_id, layer); - HUB.surfaces.register(surface) + HUB.surfaces.register_local(surface) } #[allow(unused_variables)] @@ -152,7 +151,7 @@ pub extern "C" fn wgpu_instance_create_surface_from_windows_hwnd( hwnd: *mut std::ffi::c_void, ) -> SurfaceId { let surface = instance_create_surface_from_windows_hwnd(instance_id, hinstance, hwnd); - HUB.surfaces.register(surface) + HUB.surfaces.register_local(surface) } pub fn instance_get_adapter( @@ -184,7 +183,7 @@ pub extern "C" fn wgpu_instance_get_adapter( desc: &AdapterDescriptor, ) -> AdapterId { let adapter = instance_get_adapter(instance_id, desc); - HUB.adapters.register(adapter) + HUB.adapters.register_local(adapter) } pub fn adapter_create_device( @@ -195,7 +194,7 @@ pub fn adapter_create_device( let adapter = adapter_guard.get_mut(adapter_id); let (raw, queue_group) = adapter.open_with::<_, hal::General>(1, |_qf| true).unwrap(); let mem_props = adapter.physical_device.memory_properties(); - DeviceHandle::new(raw, WeaklyStored(adapter_id), queue_group, mem_props) + DeviceHandle::new(raw, adapter_id, queue_group, mem_props) } #[cfg(feature = "local")] @@ -205,5 +204,5 @@ pub extern "C" fn wgpu_adapter_create_device( desc: &DeviceDescriptor, ) -> DeviceId { let device = adapter_create_device(adapter_id, desc); - HUB.devices.register(device) + HUB.devices.register_local(device) } diff --git a/wgpu-native/src/lib.rs b/wgpu-native/src/lib.rs index e6b75e027..6f29a6e44 100644 --- a/wgpu-native/src/lib.rs +++ b/wgpu-native/src/lib.rs @@ -100,9 +100,6 @@ struct Stored { ref_count: RefCount, } -#[derive(Clone, Debug, Hash, PartialEq, Eq)] -struct WeaklyStored(T); - #[repr(C)] #[derive(Clone, Copy, Debug)] diff --git a/wgpu-native/src/pipeline.rs b/wgpu-native/src/pipeline.rs index c4566e6c0..3f5d75243 100644 --- a/wgpu-native/src/pipeline.rs +++ b/wgpu-native/src/pipeline.rs @@ -1,6 +1,6 @@ use crate::resource; use crate::{ - ByteArray, PipelineLayoutId, ShaderModuleId, WeaklyStored, + ByteArray, PipelineLayoutId, ShaderModuleId, }; use bitflags::bitflags; @@ -181,7 +181,7 @@ pub struct ComputePipelineDescriptor { pub struct ComputePipeline { pub(crate) raw: B::ComputePipeline, - pub(crate) layout_id: WeaklyStored, + pub(crate) layout_id: PipelineLayoutId, } #[repr(C)] @@ -235,5 +235,5 @@ pub struct RenderPipelineDescriptor { pub struct RenderPipeline { pub(crate) raw: B::GraphicsPipeline, - pub(crate) layout_id: WeaklyStored, + pub(crate) layout_id: PipelineLayoutId, } diff --git a/wgpu-native/src/swap_chain.rs b/wgpu-native/src/swap_chain.rs index e505cf924..89eaddccb 100644 --- a/wgpu-native/src/swap_chain.rs +++ b/wgpu-native/src/swap_chain.rs @@ -1,5 +1,5 @@ use crate::{ - Extent3d, Stored, WeaklyStored, + Extent3d, Stored, DeviceId, SwapChainId, TextureId, TextureViewId, }; use crate::{conv, resource}; @@ -17,7 +17,7 @@ use std::{iter, mem}; pub type SwapImageEpoch = u16; pub(crate) struct SwapChainLink { - pub swap_chain_id: WeaklyStored, //TODO: strongly + pub swap_chain_id: SwapChainId, //TODO: strongly pub epoch: E, pub image_index: hal::SwapImageIndex, } diff --git a/wgpu-native/src/track.rs b/wgpu-native/src/track.rs index 700927d24..dc1f4b6e5 100644 --- a/wgpu-native/src/track.rs +++ b/wgpu-native/src/track.rs @@ -1,19 +1,19 @@ -use crate::hub::{Id, Storage}; +use crate::hub::{NewId, Id, Index, Epoch, Storage}; use crate::resource::{BufferUsageFlags, TextureUsageFlags}; use crate::{ - RefCount, WeaklyStored, + RefCount, BufferId, TextureId, TextureViewId, }; -use std::borrow::Borrow; -use std::collections::hash_map::Entry; -use std::hash::Hash; -use std::mem; -use std::ops::{BitOr, Range}; - use bitflags::bitflags; use hal::backend::FastHashMap; +use std::borrow::Borrow; +use std::collections::hash_map::Entry; +use std::marker::PhantomData; +use std::mem; +use std::ops::{BitOr, Range}; + #[derive(Clone, Debug, PartialEq)] #[allow(unused)] @@ -72,16 +72,19 @@ struct Track { ref_count: RefCount, init: U, last: U, + epoch: Epoch, } //TODO: consider having `I` as an associated type of `U`? pub struct Tracker { - map: FastHashMap, Track>, + map: FastHashMap>, + _phantom: PhantomData, } pub type BufferTracker = Tracker; pub type TextureTracker = Tracker; pub struct DummyTracker { - map: FastHashMap, RefCount>, + map: FastHashMap, + _phantom: PhantomData, } pub type TextureViewTracker = DummyTracker; @@ -102,67 +105,88 @@ impl TrackerSet { } } -impl DummyTracker { +impl DummyTracker { pub fn new() -> Self { DummyTracker { map: FastHashMap::default(), + _phantom: PhantomData, } } /// Remove an id from the tracked map. pub(crate) fn remove(&mut self, id: I) -> bool { - self.map.remove(&WeaklyStored(id)).is_some() + match self.map.remove(&id.index()) { + Some((_, epoch)) => { + assert_eq!(epoch, id.epoch()); + true + } + None => false, + } } /// Get the last usage on a resource. pub(crate) fn query(&mut self, id: I, ref_count: &RefCount) -> bool { - match self.map.entry(WeaklyStored(id)) { + match self.map.entry(id.index()) { Entry::Vacant(e) => { - e.insert(ref_count.clone()); + e.insert((ref_count.clone(), id.epoch())); true } - Entry::Occupied(_) => false, + Entry::Occupied(e) => { + assert_eq!(e.get().1, id.epoch()); + false + } } } /// Consume another tacker. pub fn consume(&mut self, other: &Self) { - for (id, ref_count) in &other.map { - self.query(id.0.clone(), ref_count); + for (&index, &(ref ref_count, epoch)) in &other.map { + self.query(I::new(index, epoch), ref_count); } } } -impl + PartialEq> Tracker { +impl + PartialEq> Tracker { pub fn new() -> Self { Tracker { map: FastHashMap::default(), + _phantom: PhantomData, } } /// Remove an id from the tracked map. pub(crate) fn remove(&mut self, id: I) -> bool { - self.map.remove(&WeaklyStored(id)).is_some() + match self.map.remove(&id.index()) { + Some(track) => { + assert_eq!(track.epoch, id.epoch()); + true + } + None => false, + } } /// Get the last usage on a resource. pub(crate) fn query(&mut self, id: I, ref_count: &RefCount, default: U) -> Query { - match self.map.entry(WeaklyStored(id)) { + match self.map.entry(id.index()) { Entry::Vacant(e) => { e.insert(Track { ref_count: ref_count.clone(), init: default, last: default, + epoch: id.epoch(), }); Query { usage: default, initialized: true, } } - Entry::Occupied(e) => Query { - usage: e.get().last, - initialized: false, - }, + Entry::Occupied(e) => { + assert_eq!(e.get().epoch, id.epoch()); + Query { + usage: e.get().last, + initialized: false, + } + } } } @@ -174,16 +198,18 @@ impl + PartialE usage: U, permit: TrackPermit, ) -> Result, U> { - match self.map.entry(WeaklyStored(id)) { + match self.map.entry(id.index()) { Entry::Vacant(e) => { e.insert(Track { ref_count: ref_count.clone(), init: usage, last: usage, + epoch: id.epoch(), }); Ok(Tracktion::Init) } Entry::Occupied(mut e) => { + assert_eq!(e.get().epoch, id.epoch()); let old = e.get().last; if usage == old { Ok(Tracktion::Keep) @@ -201,37 +227,43 @@ impl + PartialE } /// Consume another tacker, adding it's transitions to `self`. + /// Transitions the current usage to the new one. pub fn consume_by_replace<'a>(&'a mut self, other: &'a Self) -> impl 'a + Iterator)> { - other.map.iter().flat_map(move |(id, new)| { - match self.map.entry(WeaklyStored(id.0.clone())) { + other.map.iter().flat_map(move |(&index, new)| { + match self.map.entry(index) { Entry::Vacant(e) => { e.insert(new.clone()); None } Entry::Occupied(mut e) => { + assert_eq!(e.get().epoch, new.epoch); let old = mem::replace(&mut e.get_mut().last, new.last); if old == new.init { None } else { - Some((id.0.clone(), old..new.last)) + Some((I::new(index, new.epoch), old .. new.last)) } } } }) } + /// Consume another tacker, adding it's transitions to `self`. + /// Extends the current usage without doing any transitions. pub fn consume_by_extend<'a>(&'a mut self, other: &'a Self) -> Result<(), (I, Range)> { - for (id, new) in other.map.iter() { - match self.map.entry(WeaklyStored(id.0.clone())) { + for (&index, new) in other.map.iter() { + match self.map.entry(index) { Entry::Vacant(e) => { e.insert(new.clone()); } Entry::Occupied(mut e) => { + assert_eq!(e.get().epoch, new.epoch); let old = e.get().last; if old != new.last { let extended = old | new.last; if extended.is_exclusive() { - return Err((id.0.clone(), old..new.last)); + let id = I::new(index, new.epoch); + return Err((id, old .. new.last)); } e.get_mut().last = extended; } @@ -243,7 +275,7 @@ impl + PartialE /// Return an iterator over used resources keys. pub fn used<'a>(&'a self) -> impl 'a + Iterator { - self.map.keys().map(|&WeaklyStored(ref id)| id.clone()) + self.map.iter().map(|(&index, track)| I::new(index, track.epoch)) } }