diff --git a/wgpu-core/src/binding_model.rs b/wgpu-core/src/binding_model.rs index 2a4e3084a7..29c8ccf131 100644 --- a/wgpu-core/src/binding_model.rs +++ b/wgpu-core/src/binding_model.rs @@ -15,6 +15,7 @@ use crate::{ use arrayvec::ArrayVec; +use parking_lot::RwLock; #[cfg(feature = "replay")] use serde::Deserialize; #[cfg(feature = "trace")] @@ -847,9 +848,9 @@ pub struct BindGroup { pub(crate) layout: Arc>, pub(crate) info: ResourceInfo, pub(crate) used: BindGroupStates, - pub(crate) used_buffer_ranges: Vec>, - pub(crate) used_texture_ranges: Vec>, - pub(crate) dynamic_binding_info: Vec, + pub(crate) used_buffer_ranges: RwLock>>, + pub(crate) used_texture_ranges: RwLock>>, + pub(crate) dynamic_binding_info: RwLock>, /// Actual binding sizes for buffers that don't have `min_binding_size` /// specified in BGL. Listed in the order of iteration of `BGL.entries`. pub(crate) late_buffer_binding_sizes: Vec, @@ -877,16 +878,17 @@ impl BindGroup { offsets: &[wgt::DynamicOffset], limits: &wgt::Limits, ) -> Result<(), BindError> { - if self.dynamic_binding_info.len() != offsets.len() { + if self.dynamic_binding_info.read().len() != offsets.len() { return Err(BindError::MismatchedDynamicOffsetCount { group: bind_group_index, - expected: self.dynamic_binding_info.len(), + expected: self.dynamic_binding_info.read().len(), actual: offsets.len(), }); } for (idx, (info, &offset)) in self .dynamic_binding_info + .read() .iter() .zip(offsets.iter()) .enumerate() diff --git a/wgpu-core/src/command/bundle.rs b/wgpu-core/src/command/bundle.rs index e476a5ecf8..8f453605d4 100644 --- a/wgpu-core/src/command/bundle.rs +++ b/wgpu-core/src/command/bundle.rs @@ -318,10 +318,10 @@ impl RenderBundleEncoder { next_dynamic_offset = offsets_range.end; let offsets = &base.dynamic_offsets[offsets_range.clone()]; - if bind_group.dynamic_binding_info.len() != offsets.len() { + if bind_group.dynamic_binding_info.read().len() != offsets.len() { return Err(RenderCommandError::InvalidDynamicOffsetCount { actual: offsets.len(), - expected: bind_group.dynamic_binding_info.len(), + expected: bind_group.dynamic_binding_info.read().len(), }) .map_pass_err(scope); } @@ -330,7 +330,7 @@ impl RenderBundleEncoder { for (offset, info) in offsets .iter() .map(|offset| *offset as wgt::BufferAddress) - .zip(bind_group.dynamic_binding_info.iter()) + .zip(bind_group.dynamic_binding_info.read().iter()) { let (alignment, limit_name) = buffer_binding_type_alignment(&device.limits, info.binding_type); @@ -342,8 +342,8 @@ impl RenderBundleEncoder { } } - buffer_memory_init_actions.extend_from_slice(&bind_group.used_buffer_ranges); - texture_memory_init_actions.extend_from_slice(&bind_group.used_texture_ranges); + buffer_memory_init_actions.extend_from_slice(&bind_group.used_buffer_ranges.read()); + texture_memory_init_actions.extend_from_slice(&bind_group.used_texture_ranges.read()); state.set_bind_group(index, bind_group_guard.get(bind_group_id).as_ref().unwrap(), &bind_group.layout, offsets_range); unsafe { diff --git a/wgpu-core/src/command/compute.rs b/wgpu-core/src/command/compute.rs index 2c8d8a5146..341743985f 100644 --- a/wgpu-core/src/command/compute.rs +++ b/wgpu-core/src/command/compute.rs @@ -505,16 +505,20 @@ impl Global { .map_pass_err(scope)?; buffer_memory_init_actions.extend( - bind_group.used_buffer_ranges.iter().filter_map(|action| { - action - .buffer - .initialization_status - .read() - .check_action(action) - }), + bind_group + .used_buffer_ranges + .read() + .iter() + .filter_map(|action| { + action + .buffer + .initialization_status + .read() + .check_action(action) + }), ); - for action in bind_group.used_texture_ranges.iter() { + for action in bind_group.used_texture_ranges.read().iter() { pending_discard_init_fixups .extend(texture_memory_actions.register_init_action(action)); } diff --git a/wgpu-core/src/command/render.rs b/wgpu-core/src/command/render.rs index cbb657f548..346ef24363 100644 --- a/wgpu-core/src/command/render.rs +++ b/wgpu-core/src/command/render.rs @@ -1424,15 +1424,19 @@ impl Global { // is held to the bind group itself. buffer_memory_init_actions.extend( - bind_group.used_buffer_ranges.iter().filter_map(|action| { - action - .buffer - .initialization_status - .read() - .check_action(action) - }), + bind_group + .used_buffer_ranges + .read() + .iter() + .filter_map(|action| { + action + .buffer + .initialization_status + .read() + .check_action(action) + }), ); - for action in bind_group.used_texture_ranges.iter() { + for action in bind_group.used_texture_ranges.read().iter() { info.pending_discard_init_fixups .extend(texture_memory_actions.register_init_action(action)); } diff --git a/wgpu-core/src/device/life.rs b/wgpu-core/src/device/life.rs index bbcb0eb643..e8bf3be8ed 100644 --- a/wgpu-core/src/device/life.rs +++ b/wgpu-core/src/device/life.rs @@ -418,33 +418,37 @@ impl LifetimeTracker { } impl LifetimeTracker { - fn triage_resources( + fn triage_resources( resources_map: &mut HashMap>, active: &mut [ActiveSubmission], free_resources: &mut ResourceMaps, trackers: &mut impl ResourceTracker, registry: &Registry, - mut f: F, + count_fn: F, + mut on_remove: T, ) -> Vec> where Id: id::TypedId, R: Resource, - F: FnMut(&Id, &Arc), + F: Fn(u64, &[ActiveSubmission], &Id) -> usize, + T: FnMut(&Id, &Arc), { let mut removed_resources = Vec::new(); resources_map.retain(|&id, resource| { let submit_index = resource.as_info().submission_index(); + let mut count = 1; + count += count_fn(submit_index, active, &id); + count += registry.contains(id) as usize; + let non_referenced_resources = active .iter_mut() .find(|a| a.index == submit_index) .map_or(&mut *free_resources, |a| &mut a.last_resources); - - let mut count = 1; - count += registry.contains(id) as usize; count += non_referenced_resources.contains::(&id) as usize; + let is_removed = trackers.remove_abandoned(id, count); if is_removed { - f(&id, resource); + on_remove(&id, resource); removed_resources.push(resource.clone()); non_referenced_resources.insert(id, resource.clone()); } @@ -467,6 +471,7 @@ impl LifetimeTracker { &mut self.free_resources, &mut trackers.bundles, &hub.render_bundles, + |_submit_index, _active, _id| 0, |_bundle_id, _bundle| { #[cfg(feature = "trace")] if let Some(ref mut t) = *trace { @@ -476,19 +481,19 @@ impl LifetimeTracker { ); removed_resources.drain(..).for_each(|bundle| { for v in bundle.used.buffers.write().drain_resources() { - self.suspected_resources.insert(v.as_info().id(), v.clone()); + self.suspected_resources.insert(v.as_info().id(), v); } for v in bundle.used.textures.write().drain_resources() { - self.suspected_resources.insert(v.as_info().id(), v.clone()); + self.suspected_resources.insert(v.as_info().id(), v); } for v in bundle.used.bind_groups.write().drain_resources() { - self.suspected_resources.insert(v.as_info().id(), v.clone()); + self.suspected_resources.insert(v.as_info().id(), v); } for v in bundle.used.render_pipelines.write().drain_resources() { - self.suspected_resources.insert(v.as_info().id(), v.clone()); + self.suspected_resources.insert(v.as_info().id(), v); } for v in bundle.used.query_sets.write().drain_resources() { - self.suspected_resources.insert(v.as_info().id(), v.clone()); + self.suspected_resources.insert(v.as_info().id(), v); } }); self @@ -508,6 +513,7 @@ impl LifetimeTracker { &mut self.free_resources, &mut trackers.bind_groups, &hub.bind_groups, + |_submit_index, _active, _id| 0, |_bind_group_id, _bind_group| { #[cfg(feature = "trace")] if let Some(ref mut t) = *trace { @@ -528,6 +534,10 @@ impl LifetimeTracker { for v in bind_group.used.samplers.drain_resources() { self.suspected_resources.insert(v.as_info().id(), v); } + //Releasing safely unused resources to decrement refcount + bind_group.used_buffer_ranges.write().clear(); + bind_group.used_texture_ranges.write().clear(); + bind_group.dynamic_binding_info.write().clear(); self.suspected_resources .insert(bind_group.layout.as_info().id(), bind_group.layout.clone()); @@ -549,6 +559,7 @@ impl LifetimeTracker { &mut self.free_resources, &mut trackers.views, &hub.texture_views, + |_submit_index, _active, _id| 0, |_texture_view_id, _texture_view| { #[cfg(feature = "trace")] if let Some(ref mut t) = *trace { @@ -580,6 +591,7 @@ impl LifetimeTracker { &mut self.free_resources, &mut trackers.textures, &hub.textures, + |_submit_index, _active, _id| 0, |_texture_id, _texture| { #[cfg(feature = "trace")] if let Some(ref mut t) = *trace { @@ -604,6 +616,7 @@ impl LifetimeTracker { &mut self.free_resources, &mut trackers.samplers, &hub.samplers, + |_submit_index, _active, _id| 0, |_sampler_id, _sampler| { #[cfg(feature = "trace")] if let Some(ref mut t) = *trace { @@ -628,6 +641,19 @@ impl LifetimeTracker { &mut self.free_resources, &mut trackers.buffers, &hub.buffers, + |submit_index, active, buffer_id| { + let mut count = 0; + let mapped = active + .iter() + .find(|a| a.index == submit_index) + .map_or(&self.mapped, |a| &a.mapped); + mapped.iter().for_each(|b| { + if b.as_info().id() == *buffer_id { + count += 1; + } + }); + count + }, |_buffer_id, _buffer| { #[cfg(feature = "trace")] if let Some(ref mut t) = *trace { @@ -661,6 +687,7 @@ impl LifetimeTracker { &mut self.free_resources, &mut trackers.compute_pipelines, &hub.compute_pipelines, + |_submit_index, _active, _id| 0, |_compute_pipeline_id, _compute_pipeline| { #[cfg(feature = "trace")] if let Some(ref mut t) = *trace { @@ -691,6 +718,7 @@ impl LifetimeTracker { &mut self.free_resources, &mut trackers.render_pipelines, &hub.render_pipelines, + |_submit_index, _active, _id| 0, |_render_pipeline_id, _render_pipeline| { #[cfg(feature = "trace")] if let Some(ref mut t) = *trace { @@ -767,6 +795,7 @@ impl LifetimeTracker { &mut self.free_resources, &mut trackers.query_sets, &hub.query_sets, + |_submit_index, _active, _id| 0, |_query_set_id, _query_set| {}, ); self diff --git a/wgpu-core/src/device/resource.rs b/wgpu-core/src/device/resource.rs index 50a25a203c..c6a3514703 100644 --- a/wgpu-core/src/device/resource.rs +++ b/wgpu-core/src/device/resource.rs @@ -2049,9 +2049,9 @@ impl Device { layout: layout.clone(), info: ResourceInfo::new(desc.label.borrow_or_default()), used, - used_buffer_ranges, - used_texture_ranges, - dynamic_binding_info, + used_buffer_ranges: RwLock::new(used_buffer_ranges), + used_texture_ranges: RwLock::new(used_texture_ranges), + dynamic_binding_info: RwLock::new(dynamic_binding_info), // collect in the order of BGL iteration late_buffer_binding_sizes: layout .entries