mirror of
https://github.com/gfx-rs/wgpu.git
synced 2026-04-22 03:02:01 -04:00
Simplify ResourceMaps (#4880)
* Remove the abstractions in resource maps ResourceMaps had a rather convoluted system for erasing types that isn't needed anywhere except in one place in the triage_resource function. Everywhere else we are always dealing with specific types so using a member of the resource maps is simpler than going through an abstraction. More importantly there was a constraint that all contents of the resource maps implement the Resource trait which got in the way of some of the ongoing buffer snatching changes. This commit simplifies this by removing the abstraction. Each resource type has its hash map directly in ResourceMaps and it is easier to have different requirements and behaviors depending on the type of the each resource.
This commit is contained in:
@@ -521,6 +521,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
device
|
||||
.lock_life()
|
||||
.suspected_resources
|
||||
.buffers
|
||||
.insert(buffer_id, buffer);
|
||||
}
|
||||
|
||||
@@ -784,6 +785,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
device
|
||||
.lock_life()
|
||||
.suspected_resources
|
||||
.textures
|
||||
.insert(texture_id, texture.clone());
|
||||
}
|
||||
}
|
||||
@@ -861,6 +863,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
view.device
|
||||
.lock_life()
|
||||
.suspected_resources
|
||||
.texture_views
|
||||
.insert(texture_view_id, view.clone());
|
||||
|
||||
if wait {
|
||||
@@ -931,6 +934,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
.device
|
||||
.lock_life()
|
||||
.suspected_resources
|
||||
.samplers
|
||||
.insert(sampler_id, sampler.clone());
|
||||
}
|
||||
}
|
||||
@@ -1017,6 +1021,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
.device
|
||||
.lock_life()
|
||||
.suspected_resources
|
||||
.bind_group_layouts
|
||||
.insert(bind_group_layout_id, layout.clone());
|
||||
}
|
||||
}
|
||||
@@ -1080,6 +1085,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
.device
|
||||
.lock_life()
|
||||
.suspected_resources
|
||||
.pipeline_layouts
|
||||
.insert(pipeline_layout_id, layout.clone());
|
||||
}
|
||||
}
|
||||
@@ -1154,6 +1160,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
.device
|
||||
.lock_life()
|
||||
.suspected_resources
|
||||
.bind_groups
|
||||
.insert(bind_group_id, bind_group.clone());
|
||||
}
|
||||
}
|
||||
@@ -1448,6 +1455,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
.device
|
||||
.lock_life()
|
||||
.suspected_resources
|
||||
.render_bundles
|
||||
.insert(render_bundle_id, bundle.clone());
|
||||
}
|
||||
}
|
||||
@@ -1517,6 +1525,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
device
|
||||
.lock_life()
|
||||
.suspected_resources
|
||||
.query_sets
|
||||
.insert(query_set_id, query_set.clone());
|
||||
}
|
||||
}
|
||||
@@ -1653,10 +1662,12 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
let mut life_lock = device.lock_life();
|
||||
life_lock
|
||||
.suspected_resources
|
||||
.render_pipelines
|
||||
.insert(render_pipeline_id, pipeline.clone());
|
||||
|
||||
life_lock
|
||||
.suspected_resources
|
||||
.pipeline_layouts
|
||||
.insert(layout_id, pipeline.layout.clone());
|
||||
}
|
||||
}
|
||||
@@ -1788,9 +1799,11 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
let mut life_lock = device.lock_life();
|
||||
life_lock
|
||||
.suspected_resources
|
||||
.compute_pipelines
|
||||
.insert(compute_pipeline_id, pipeline.clone());
|
||||
life_lock
|
||||
.suspected_resources
|
||||
.pipeline_layouts
|
||||
.insert(layout_id, pipeline.layout.clone());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,111 +14,107 @@ use crate::{
|
||||
TextureViewId,
|
||||
},
|
||||
pipeline::{ComputePipeline, RenderPipeline},
|
||||
resource::{
|
||||
self, Buffer, QuerySet, Resource, ResourceType, Sampler, StagingBuffer, Texture,
|
||||
TextureView,
|
||||
},
|
||||
resource::{self, Buffer, QuerySet, Resource, Sampler, StagingBuffer, Texture, TextureView},
|
||||
track::{ResourceTracker, Tracker},
|
||||
FastHashMap, SubmissionIndex,
|
||||
};
|
||||
use smallvec::SmallVec;
|
||||
|
||||
use parking_lot::Mutex;
|
||||
use std::sync::Arc;
|
||||
use thiserror::Error;
|
||||
use wgt::WasmNotSendSync;
|
||||
|
||||
use std::{any::Any, sync::Arc};
|
||||
|
||||
pub(crate) trait ResourceMap: Any + WasmNotSendSync {
|
||||
fn as_any(&self) -> &dyn Any;
|
||||
fn as_any_mut(&mut self) -> &mut dyn Any;
|
||||
fn clear_map(&mut self);
|
||||
fn extend_map(&mut self, maps: &mut ResourceMaps);
|
||||
}
|
||||
|
||||
impl<Id, R> ResourceMap for FastHashMap<Id, Arc<R>>
|
||||
where
|
||||
Id: id::TypedId,
|
||||
R: Resource<Id>,
|
||||
{
|
||||
fn as_any(&self) -> &dyn Any {
|
||||
self
|
||||
}
|
||||
fn as_any_mut(&mut self) -> &mut dyn Any {
|
||||
self
|
||||
}
|
||||
fn clear_map(&mut self) {
|
||||
self.clear()
|
||||
}
|
||||
fn extend_map(&mut self, r: &mut ResourceMaps) {
|
||||
if let Some(other) = r.maps.get_mut(R::TYPE) {
|
||||
if let Some(other) = other.as_any_mut().downcast_mut::<Self>() {
|
||||
self.extend(other.drain());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A struct that keeps lists of resources that are no longer needed by the user.
|
||||
#[derive(Default)]
|
||||
pub(crate) struct ResourceMaps {
|
||||
pub(crate) maps: FastHashMap<ResourceType, Box<dyn ResourceMap>>,
|
||||
pub(crate) struct ResourceMaps<A: HalApi> {
|
||||
pub buffers: FastHashMap<BufferId, Arc<Buffer<A>>>,
|
||||
pub staging_buffers: FastHashMap<StagingBufferId, Arc<StagingBuffer<A>>>,
|
||||
pub textures: FastHashMap<TextureId, Arc<Texture<A>>>,
|
||||
pub texture_views: FastHashMap<TextureViewId, Arc<TextureView<A>>>,
|
||||
pub samplers: FastHashMap<SamplerId, Arc<Sampler<A>>>,
|
||||
pub bind_groups: FastHashMap<BindGroupId, Arc<BindGroup<A>>>,
|
||||
pub bind_group_layouts: FastHashMap<BindGroupLayoutId, Arc<BindGroupLayout<A>>>,
|
||||
pub render_pipelines: FastHashMap<RenderPipelineId, Arc<RenderPipeline<A>>>,
|
||||
pub compute_pipelines: FastHashMap<ComputePipelineId, Arc<ComputePipeline<A>>>,
|
||||
pub pipeline_layouts: FastHashMap<PipelineLayoutId, Arc<PipelineLayout<A>>>,
|
||||
pub render_bundles: FastHashMap<RenderBundleId, Arc<RenderBundle<A>>>,
|
||||
pub query_sets: FastHashMap<QuerySetId, Arc<QuerySet<A>>>,
|
||||
}
|
||||
|
||||
impl ResourceMaps {
|
||||
fn add_type<Id, R>(&mut self) -> &mut Self
|
||||
where
|
||||
Id: id::TypedId,
|
||||
R: Resource<Id>,
|
||||
{
|
||||
let map = FastHashMap::<Id, Arc<R>>::default();
|
||||
self.maps.insert(R::TYPE, Box::new(map));
|
||||
self
|
||||
}
|
||||
fn map_mut<Id, R>(&mut self) -> &mut FastHashMap<Id, Arc<R>>
|
||||
where
|
||||
Id: id::TypedId,
|
||||
R: Resource<Id>,
|
||||
{
|
||||
let map = self
|
||||
.maps
|
||||
.entry(R::TYPE)
|
||||
.or_insert_with(|| Box::<FastHashMap<Id, Arc<R>>>::default());
|
||||
let any_map = map.as_mut().as_any_mut();
|
||||
let map = any_map.downcast_mut::<FastHashMap<Id, Arc<R>>>().unwrap();
|
||||
map
|
||||
}
|
||||
pub(crate) fn new<A: HalApi>() -> Self {
|
||||
let mut maps = Self::default();
|
||||
maps.add_type::<BufferId, Buffer<A>>();
|
||||
maps.add_type::<StagingBufferId, StagingBuffer<A>>();
|
||||
maps.add_type::<TextureId, Texture<A>>();
|
||||
maps.add_type::<TextureViewId, TextureView<A>>();
|
||||
maps.add_type::<SamplerId, Sampler<A>>();
|
||||
maps.add_type::<BindGroupId, BindGroup<A>>();
|
||||
maps.add_type::<BindGroupLayoutId, BindGroupLayout<A>>();
|
||||
maps.add_type::<RenderPipelineId, RenderPipeline<A>>();
|
||||
maps.add_type::<ComputePipelineId, ComputePipeline<A>>();
|
||||
maps.add_type::<PipelineLayoutId, PipelineLayout<A>>();
|
||||
maps.add_type::<RenderBundleId, RenderBundle<A>>();
|
||||
maps.add_type::<QuerySetId, QuerySet<A>>();
|
||||
maps
|
||||
impl<A: HalApi> ResourceMaps<A> {
|
||||
pub(crate) fn new() -> Self {
|
||||
ResourceMaps {
|
||||
buffers: FastHashMap::default(),
|
||||
staging_buffers: FastHashMap::default(),
|
||||
textures: FastHashMap::default(),
|
||||
texture_views: FastHashMap::default(),
|
||||
samplers: FastHashMap::default(),
|
||||
bind_groups: FastHashMap::default(),
|
||||
bind_group_layouts: FastHashMap::default(),
|
||||
render_pipelines: FastHashMap::default(),
|
||||
compute_pipelines: FastHashMap::default(),
|
||||
pipeline_layouts: FastHashMap::default(),
|
||||
render_bundles: FastHashMap::default(),
|
||||
query_sets: FastHashMap::default(),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn clear(&mut self) {
|
||||
self.maps.iter_mut().for_each(|(_t, map)| map.clear_map());
|
||||
let ResourceMaps {
|
||||
buffers,
|
||||
staging_buffers,
|
||||
textures,
|
||||
texture_views,
|
||||
samplers,
|
||||
bind_groups,
|
||||
bind_group_layouts,
|
||||
render_pipelines,
|
||||
compute_pipelines,
|
||||
pipeline_layouts,
|
||||
render_bundles,
|
||||
query_sets,
|
||||
} = self;
|
||||
buffers.clear();
|
||||
staging_buffers.clear();
|
||||
textures.clear();
|
||||
texture_views.clear();
|
||||
samplers.clear();
|
||||
bind_groups.clear();
|
||||
bind_group_layouts.clear();
|
||||
render_pipelines.clear();
|
||||
compute_pipelines.clear();
|
||||
pipeline_layouts.clear();
|
||||
render_bundles.clear();
|
||||
query_sets.clear();
|
||||
}
|
||||
|
||||
pub(crate) fn extend(&mut self, mut other: Self) {
|
||||
self.maps.iter_mut().for_each(|(_t, map)| {
|
||||
map.extend_map(&mut other);
|
||||
});
|
||||
}
|
||||
pub(crate) fn insert<Id, R>(&mut self, id: Id, r: Arc<R>) -> &mut Self
|
||||
where
|
||||
Id: id::TypedId,
|
||||
R: Resource<Id>,
|
||||
{
|
||||
self.map_mut().insert(id, r);
|
||||
self
|
||||
let ResourceMaps {
|
||||
buffers,
|
||||
staging_buffers,
|
||||
textures,
|
||||
texture_views,
|
||||
samplers,
|
||||
bind_groups,
|
||||
bind_group_layouts,
|
||||
render_pipelines,
|
||||
compute_pipelines,
|
||||
pipeline_layouts,
|
||||
render_bundles,
|
||||
query_sets,
|
||||
} = self;
|
||||
buffers.extend(other.buffers.drain());
|
||||
staging_buffers.extend(other.staging_buffers.drain());
|
||||
textures.extend(other.textures.drain());
|
||||
texture_views.extend(other.texture_views.drain());
|
||||
samplers.extend(other.samplers.drain());
|
||||
bind_groups.extend(other.bind_groups.drain());
|
||||
bind_group_layouts.extend(other.bind_group_layouts.drain());
|
||||
render_pipelines.extend(other.render_pipelines.drain());
|
||||
compute_pipelines.extend(other.compute_pipelines.drain());
|
||||
pipeline_layouts.extend(other.pipeline_layouts.drain());
|
||||
render_bundles.extend(other.render_bundles.drain());
|
||||
query_sets.extend(other.query_sets.drain());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -140,7 +136,7 @@ struct ActiveSubmission<A: HalApi> {
|
||||
/// This includes things like temporary resources and resources that are
|
||||
/// used by submitted commands but have been dropped by the user (meaning that
|
||||
/// this submission is their last reference.)
|
||||
last_resources: ResourceMaps,
|
||||
last_resources: ResourceMaps<A>,
|
||||
|
||||
/// Buffers to be mapped once this submission has completed.
|
||||
mapped: Vec<Arc<Buffer<A>>>,
|
||||
@@ -214,7 +210,7 @@ pub(crate) struct LifetimeTracker<A: HalApi> {
|
||||
|
||||
/// Resources whose user handle has died (i.e. drop/destroy has been called)
|
||||
/// and will likely be ready for destruction soon.
|
||||
pub suspected_resources: ResourceMaps,
|
||||
pub suspected_resources: ResourceMaps<A>,
|
||||
|
||||
/// Resources used by queue submissions still in flight. One entry per
|
||||
/// submission, with older submissions appearing before younger.
|
||||
@@ -229,7 +225,7 @@ pub(crate) struct LifetimeTracker<A: HalApi> {
|
||||
/// These are freed by `LifeTracker::cleanup`, which is called from periodic
|
||||
/// maintenance functions like `Global::device_poll`, and when a device is
|
||||
/// destroyed.
|
||||
free_resources: ResourceMaps,
|
||||
free_resources: ResourceMaps<A>,
|
||||
|
||||
/// Buffers the user has asked us to map, and which are not used by any
|
||||
/// queue submission still in flight.
|
||||
@@ -253,9 +249,9 @@ impl<A: HalApi> LifetimeTracker<A> {
|
||||
mapped: Vec::new(),
|
||||
future_suspected_buffers: Vec::new(),
|
||||
future_suspected_textures: Vec::new(),
|
||||
suspected_resources: ResourceMaps::new::<A>(),
|
||||
suspected_resources: ResourceMaps::new(),
|
||||
active: Vec::new(),
|
||||
free_resources: ResourceMaps::new::<A>(),
|
||||
free_resources: ResourceMaps::new(),
|
||||
ready_to_map: Vec::new(),
|
||||
work_done_closures: SmallVec::new(),
|
||||
device_lost_closure: None,
|
||||
@@ -274,17 +270,19 @@ impl<A: HalApi> LifetimeTracker<A> {
|
||||
temp_resources: impl Iterator<Item = TempResource<A>>,
|
||||
encoders: Vec<EncoderInFlight<A>>,
|
||||
) {
|
||||
let mut last_resources = ResourceMaps::new::<A>();
|
||||
let mut last_resources = ResourceMaps::new();
|
||||
for res in temp_resources {
|
||||
match res {
|
||||
TempResource::Buffer(raw) => {
|
||||
last_resources.insert(raw.as_info().id(), raw);
|
||||
last_resources.buffers.insert(raw.as_info().id(), raw);
|
||||
}
|
||||
TempResource::StagingBuffer(raw) => {
|
||||
last_resources.insert(raw.as_info().id(), raw);
|
||||
last_resources
|
||||
.staging_buffers
|
||||
.insert(raw.as_info().id(), raw);
|
||||
}
|
||||
TempResource::Texture(raw) => {
|
||||
last_resources.insert(raw.as_info().id(), raw);
|
||||
last_resources.textures.insert(raw.as_info().id(), raw);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -300,10 +298,12 @@ impl<A: HalApi> LifetimeTracker<A> {
|
||||
|
||||
pub fn post_submit(&mut self) {
|
||||
for v in self.future_suspected_buffers.drain(..).take(1) {
|
||||
self.suspected_resources.insert(v.as_info().id(), v);
|
||||
self.suspected_resources.buffers.insert(v.as_info().id(), v);
|
||||
}
|
||||
for v in self.future_suspected_textures.drain(..).take(1) {
|
||||
self.suspected_resources.insert(v.as_info().id(), v);
|
||||
self.suspected_resources
|
||||
.textures
|
||||
.insert(v.as_info().id(), v);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -379,13 +379,13 @@ impl<A: HalApi> LifetimeTracker<A> {
|
||||
.map_or(&mut self.free_resources, |a| &mut a.last_resources);
|
||||
match temp_resource {
|
||||
TempResource::Buffer(raw) => {
|
||||
resources.insert(raw.as_info().id(), raw);
|
||||
resources.buffers.insert(raw.as_info().id(), raw);
|
||||
}
|
||||
TempResource::StagingBuffer(raw) => {
|
||||
resources.insert(raw.as_info().id(), raw);
|
||||
resources.staging_buffers.insert(raw.as_info().id(), raw);
|
||||
}
|
||||
TempResource::Texture(raw) => {
|
||||
resources.insert(raw.as_info().id(), raw);
|
||||
resources.textures.insert(raw.as_info().id(), raw);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -408,8 +408,9 @@ impl<A: HalApi> LifetimeTracker<A> {
|
||||
fn triage_resources<Id, R, T>(
|
||||
resources_map: &mut FastHashMap<Id, Arc<R>>,
|
||||
active: &mut [ActiveSubmission<A>],
|
||||
free_resources: &mut ResourceMaps,
|
||||
free_resources: &mut ResourceMaps<A>,
|
||||
trackers: &mut impl ResourceTracker<Id, R>,
|
||||
get_resource_map: impl Fn(&mut ResourceMaps<A>) -> &mut FastHashMap<Id, Arc<R>>,
|
||||
mut on_remove: T,
|
||||
) -> Vec<Arc<R>>
|
||||
where
|
||||
@@ -429,7 +430,7 @@ impl<A: HalApi> LifetimeTracker<A> {
|
||||
if is_removed {
|
||||
on_remove(&id, resource);
|
||||
removed_resources.push(resource.clone());
|
||||
non_referenced_resources.insert(id, resource.clone());
|
||||
get_resource_map(non_referenced_resources).insert(id, resource.clone());
|
||||
}
|
||||
!is_removed
|
||||
});
|
||||
@@ -442,12 +443,13 @@ impl<A: HalApi> LifetimeTracker<A> {
|
||||
#[cfg(feature = "trace")] trace: &mut Option<&mut trace::Trace>,
|
||||
) -> &mut Self {
|
||||
let mut trackers = trackers.lock();
|
||||
let resource_map = self.suspected_resources.map_mut();
|
||||
let resource_map = &mut self.suspected_resources.render_bundles;
|
||||
let mut removed_resources = Self::triage_resources(
|
||||
resource_map,
|
||||
self.active.as_mut_slice(),
|
||||
&mut self.free_resources,
|
||||
&mut trackers.bundles,
|
||||
|maps| &mut maps.render_bundles,
|
||||
|_bundle_id, _bundle| {
|
||||
#[cfg(feature = "trace")]
|
||||
if let Some(ref mut t) = *trace {
|
||||
@@ -457,19 +459,27 @@ impl<A: HalApi> LifetimeTracker<A> {
|
||||
);
|
||||
removed_resources.drain(..).for_each(|bundle| {
|
||||
for v in bundle.used.buffers.write().drain_resources() {
|
||||
self.suspected_resources.insert(v.as_info().id(), v);
|
||||
self.suspected_resources.buffers.insert(v.as_info().id(), v);
|
||||
}
|
||||
for v in bundle.used.textures.write().drain_resources() {
|
||||
self.suspected_resources.insert(v.as_info().id(), v);
|
||||
self.suspected_resources
|
||||
.textures
|
||||
.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);
|
||||
self.suspected_resources
|
||||
.bind_groups
|
||||
.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);
|
||||
self.suspected_resources
|
||||
.render_pipelines
|
||||
.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);
|
||||
self.suspected_resources
|
||||
.query_sets
|
||||
.insert(v.as_info().id(), v);
|
||||
}
|
||||
});
|
||||
self
|
||||
@@ -481,12 +491,13 @@ impl<A: HalApi> LifetimeTracker<A> {
|
||||
#[cfg(feature = "trace")] trace: &mut Option<&mut trace::Trace>,
|
||||
) -> &mut Self {
|
||||
let mut trackers = trackers.lock();
|
||||
let resource_map = self.suspected_resources.map_mut();
|
||||
let resource_map = &mut self.suspected_resources.bind_groups;
|
||||
let mut removed_resource = Self::triage_resources(
|
||||
resource_map,
|
||||
self.active.as_mut_slice(),
|
||||
&mut self.free_resources,
|
||||
&mut trackers.bind_groups,
|
||||
|maps| &mut maps.bind_groups,
|
||||
|_bind_group_id, _bind_group| {
|
||||
#[cfg(feature = "trace")]
|
||||
if let Some(ref mut t) = *trace {
|
||||
@@ -496,16 +507,22 @@ impl<A: HalApi> LifetimeTracker<A> {
|
||||
);
|
||||
removed_resource.drain(..).for_each(|bind_group| {
|
||||
for v in bind_group.used.buffers.drain_resources() {
|
||||
self.suspected_resources.insert(v.as_info().id(), v);
|
||||
self.suspected_resources.buffers.insert(v.as_info().id(), v);
|
||||
}
|
||||
for v in bind_group.used.textures.drain_resources() {
|
||||
self.suspected_resources.insert(v.as_info().id(), v);
|
||||
self.suspected_resources
|
||||
.textures
|
||||
.insert(v.as_info().id(), v);
|
||||
}
|
||||
for v in bind_group.used.views.drain_resources() {
|
||||
self.suspected_resources.insert(v.as_info().id(), v);
|
||||
self.suspected_resources
|
||||
.texture_views
|
||||
.insert(v.as_info().id(), v);
|
||||
}
|
||||
for v in bind_group.used.samplers.drain_resources() {
|
||||
self.suspected_resources.insert(v.as_info().id(), v);
|
||||
self.suspected_resources
|
||||
.samplers
|
||||
.insert(v.as_info().id(), v);
|
||||
}
|
||||
//Releasing safely unused resources to decrement refcount
|
||||
bind_group.used_buffer_ranges.write().clear();
|
||||
@@ -513,6 +530,7 @@ impl<A: HalApi> LifetimeTracker<A> {
|
||||
bind_group.dynamic_binding_info.write().clear();
|
||||
|
||||
self.suspected_resources
|
||||
.bind_group_layouts
|
||||
.insert(bind_group.layout.as_info().id(), bind_group.layout.clone());
|
||||
});
|
||||
self
|
||||
@@ -524,12 +542,13 @@ impl<A: HalApi> LifetimeTracker<A> {
|
||||
#[cfg(feature = "trace")] trace: &mut Option<&mut trace::Trace>,
|
||||
) -> &mut Self {
|
||||
let mut trackers = trackers.lock();
|
||||
let resource_map = self.suspected_resources.map_mut();
|
||||
let resource_map = &mut self.suspected_resources.texture_views;
|
||||
let mut removed_resources = Self::triage_resources(
|
||||
resource_map,
|
||||
self.active.as_mut_slice(),
|
||||
&mut self.free_resources,
|
||||
&mut trackers.views,
|
||||
|maps| &mut maps.texture_views,
|
||||
|_texture_view_id, _texture_view| {
|
||||
#[cfg(feature = "trace")]
|
||||
if let Some(ref mut t) = *trace {
|
||||
@@ -541,6 +560,7 @@ impl<A: HalApi> LifetimeTracker<A> {
|
||||
let mut lock = texture_view.parent.write();
|
||||
if let Some(parent_texture) = lock.take() {
|
||||
self.suspected_resources
|
||||
.textures
|
||||
.insert(parent_texture.as_info().id(), parent_texture);
|
||||
}
|
||||
});
|
||||
@@ -553,12 +573,13 @@ impl<A: HalApi> LifetimeTracker<A> {
|
||||
#[cfg(feature = "trace")] trace: &mut Option<&mut trace::Trace>,
|
||||
) -> &mut Self {
|
||||
let mut trackers = trackers.lock();
|
||||
let resource_map = self.suspected_resources.map_mut();
|
||||
let resource_map = &mut self.suspected_resources.textures;
|
||||
Self::triage_resources(
|
||||
resource_map,
|
||||
self.active.as_mut_slice(),
|
||||
&mut self.free_resources,
|
||||
&mut trackers.textures,
|
||||
|maps| &mut maps.textures,
|
||||
|_texture_id, _texture| {
|
||||
#[cfg(feature = "trace")]
|
||||
if let Some(ref mut t) = *trace {
|
||||
@@ -575,12 +596,13 @@ impl<A: HalApi> LifetimeTracker<A> {
|
||||
#[cfg(feature = "trace")] trace: &mut Option<&mut trace::Trace>,
|
||||
) -> &mut Self {
|
||||
let mut trackers = trackers.lock();
|
||||
let resource_map = self.suspected_resources.map_mut();
|
||||
let resource_map = &mut self.suspected_resources.samplers;
|
||||
Self::triage_resources(
|
||||
resource_map,
|
||||
self.active.as_mut_slice(),
|
||||
&mut self.free_resources,
|
||||
&mut trackers.samplers,
|
||||
|maps| &mut maps.samplers,
|
||||
|_sampler_id, _sampler| {
|
||||
#[cfg(feature = "trace")]
|
||||
if let Some(ref mut t) = *trace {
|
||||
@@ -597,12 +619,13 @@ impl<A: HalApi> LifetimeTracker<A> {
|
||||
#[cfg(feature = "trace")] trace: &mut Option<&mut trace::Trace>,
|
||||
) -> &mut Self {
|
||||
let mut trackers = trackers.lock();
|
||||
let resource_map = self.suspected_resources.map_mut();
|
||||
let resource_map = &mut self.suspected_resources.buffers;
|
||||
let mut removed_resources = Self::triage_resources(
|
||||
resource_map,
|
||||
self.active.as_mut_slice(),
|
||||
&mut self.free_resources,
|
||||
&mut trackers.buffers,
|
||||
|maps| &mut maps.buffers,
|
||||
|_buffer_id, _buffer| {
|
||||
#[cfg(feature = "trace")]
|
||||
if let Some(ref mut t) = *trace {
|
||||
@@ -616,6 +639,7 @@ impl<A: HalApi> LifetimeTracker<A> {
|
||||
} = *buffer.map_state.lock()
|
||||
{
|
||||
self.free_resources
|
||||
.buffers
|
||||
.insert(stage_buffer.as_info().id(), stage_buffer.clone());
|
||||
}
|
||||
});
|
||||
@@ -628,12 +652,13 @@ impl<A: HalApi> LifetimeTracker<A> {
|
||||
#[cfg(feature = "trace")] trace: &mut Option<&mut trace::Trace>,
|
||||
) -> &mut Self {
|
||||
let mut trackers = trackers.lock();
|
||||
let resource_map = self.suspected_resources.map_mut();
|
||||
let resource_map = &mut self.suspected_resources.compute_pipelines;
|
||||
let mut removed_resources = Self::triage_resources(
|
||||
resource_map,
|
||||
self.active.as_mut_slice(),
|
||||
&mut self.free_resources,
|
||||
&mut trackers.compute_pipelines,
|
||||
|maps| &mut maps.compute_pipelines,
|
||||
|_compute_pipeline_id, _compute_pipeline| {
|
||||
#[cfg(feature = "trace")]
|
||||
if let Some(ref mut t) = *trace {
|
||||
@@ -642,7 +667,7 @@ impl<A: HalApi> LifetimeTracker<A> {
|
||||
},
|
||||
);
|
||||
removed_resources.drain(..).for_each(|compute_pipeline| {
|
||||
self.suspected_resources.insert(
|
||||
self.suspected_resources.pipeline_layouts.insert(
|
||||
compute_pipeline.layout.as_info().id(),
|
||||
compute_pipeline.layout.clone(),
|
||||
);
|
||||
@@ -656,12 +681,13 @@ impl<A: HalApi> LifetimeTracker<A> {
|
||||
#[cfg(feature = "trace")] trace: &mut Option<&mut trace::Trace>,
|
||||
) -> &mut Self {
|
||||
let mut trackers = trackers.lock();
|
||||
let resource_map = self.suspected_resources.map_mut();
|
||||
let resource_map = &mut self.suspected_resources.render_pipelines;
|
||||
let mut removed_resources = Self::triage_resources(
|
||||
resource_map,
|
||||
self.active.as_mut_slice(),
|
||||
&mut self.free_resources,
|
||||
&mut trackers.render_pipelines,
|
||||
|maps| &mut maps.render_pipelines,
|
||||
|_render_pipeline_id, _render_pipeline| {
|
||||
#[cfg(feature = "trace")]
|
||||
if let Some(ref mut t) = *trace {
|
||||
@@ -670,7 +696,7 @@ impl<A: HalApi> LifetimeTracker<A> {
|
||||
},
|
||||
);
|
||||
removed_resources.drain(..).for_each(|render_pipeline| {
|
||||
self.suspected_resources.insert(
|
||||
self.suspected_resources.pipeline_layouts.insert(
|
||||
render_pipeline.layout.as_info().id(),
|
||||
render_pipeline.layout.clone(),
|
||||
);
|
||||
@@ -684,7 +710,7 @@ impl<A: HalApi> LifetimeTracker<A> {
|
||||
) -> &mut Self {
|
||||
let mut removed_resources = Vec::new();
|
||||
self.suspected_resources
|
||||
.map_mut::<PipelineLayoutId, PipelineLayout<A>>()
|
||||
.pipeline_layouts
|
||||
.retain(|_pipeline_layout_id, pipeline_layout| {
|
||||
#[cfg(feature = "trace")]
|
||||
if let Some(ref mut t) = *trace {
|
||||
@@ -696,6 +722,7 @@ impl<A: HalApi> LifetimeTracker<A> {
|
||||
removed_resources.drain(..).for_each(|pipeline_layout| {
|
||||
for bgl in &pipeline_layout.bind_group_layouts {
|
||||
self.suspected_resources
|
||||
.bind_group_layouts
|
||||
.insert(bgl.as_info().id(), bgl.clone());
|
||||
}
|
||||
});
|
||||
@@ -706,9 +733,8 @@ impl<A: HalApi> LifetimeTracker<A> {
|
||||
&mut self,
|
||||
#[cfg(feature = "trace")] trace: &mut Option<&mut trace::Trace>,
|
||||
) -> &mut Self {
|
||||
self.suspected_resources
|
||||
.map_mut::<BindGroupLayoutId, BindGroupLayout<A>>()
|
||||
.retain(|bind_group_layout_id, bind_group_layout| {
|
||||
self.suspected_resources.bind_group_layouts.retain(
|
||||
|bind_group_layout_id, bind_group_layout| {
|
||||
//Note: this has to happen after all the suspected pipelines are destroyed
|
||||
//Note: nothing else can bump the refcount since the guard is locked exclusively
|
||||
//Note: same BGL can appear multiple times in the list, but only the last
|
||||
@@ -718,20 +744,23 @@ impl<A: HalApi> LifetimeTracker<A> {
|
||||
t.add(trace::Action::DestroyBindGroupLayout(*bind_group_layout_id));
|
||||
}
|
||||
self.free_resources
|
||||
.bind_group_layouts
|
||||
.insert(*bind_group_layout_id, bind_group_layout.clone());
|
||||
false
|
||||
});
|
||||
},
|
||||
);
|
||||
self
|
||||
}
|
||||
|
||||
fn triage_suspected_query_sets(&mut self, trackers: &Mutex<Tracker<A>>) -> &mut Self {
|
||||
let mut trackers = trackers.lock();
|
||||
let resource_map = self.suspected_resources.map_mut();
|
||||
let resource_map = &mut self.suspected_resources.query_sets;
|
||||
Self::triage_resources(
|
||||
resource_map,
|
||||
self.active.as_mut_slice(),
|
||||
&mut self.free_resources,
|
||||
&mut trackers.query_sets,
|
||||
|maps| &mut maps.query_sets,
|
||||
|_query_set_id, _query_set| {},
|
||||
);
|
||||
self
|
||||
@@ -739,9 +768,10 @@ impl<A: HalApi> LifetimeTracker<A> {
|
||||
|
||||
fn triage_suspected_staging_buffers(&mut self) -> &mut Self {
|
||||
self.suspected_resources
|
||||
.map_mut::<StagingBufferId, StagingBuffer<A>>()
|
||||
.staging_buffers
|
||||
.retain(|staging_buffer_id, staging_buffer| {
|
||||
self.free_resources
|
||||
.staging_buffers
|
||||
.insert(*staging_buffer_id, staging_buffer.clone());
|
||||
false
|
||||
});
|
||||
@@ -899,7 +929,9 @@ impl<A: HalApi> LifetimeTracker<A> {
|
||||
if is_removed {
|
||||
*buffer.map_state.lock() = resource::BufferMapState::Idle;
|
||||
log::trace!("Buffer ready to map {:?} is not tracked anymore", buffer_id);
|
||||
self.free_resources.insert(buffer_id, buffer.clone());
|
||||
self.free_resources
|
||||
.buffers
|
||||
.insert(buffer_id, buffer.clone());
|
||||
} else {
|
||||
let mapping = match std::mem::replace(
|
||||
&mut *buffer.map_state.lock(),
|
||||
|
||||
@@ -1153,8 +1153,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
// a temporary one, since the chains are not finished.
|
||||
let mut temp_suspected = device.temp_suspected.lock();
|
||||
{
|
||||
let mut suspected =
|
||||
temp_suspected.replace(ResourceMaps::new::<A>()).unwrap();
|
||||
let mut suspected = temp_suspected.replace(ResourceMaps::new()).unwrap();
|
||||
suspected.clear();
|
||||
}
|
||||
|
||||
@@ -1224,7 +1223,11 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
unsafe { device.raw().unmap_buffer(raw_buf) }
|
||||
.map_err(DeviceError::from)?;
|
||||
}
|
||||
temp_suspected.as_mut().unwrap().insert(id, buffer.clone());
|
||||
temp_suspected
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.buffers
|
||||
.insert(id, buffer.clone());
|
||||
} else {
|
||||
match *buffer.map_state.lock() {
|
||||
BufferMapState::Idle => (),
|
||||
@@ -1246,7 +1249,11 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
};
|
||||
texture.info.use_at(submit_index);
|
||||
if texture.is_unique() {
|
||||
temp_suspected.as_mut().unwrap().insert(id, texture.clone());
|
||||
temp_suspected
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.textures
|
||||
.insert(id, texture.clone());
|
||||
}
|
||||
if should_extend {
|
||||
unsafe {
|
||||
@@ -1262,6 +1269,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
temp_suspected
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.texture_views
|
||||
.insert(texture_view.as_info().id(), texture_view.clone());
|
||||
}
|
||||
}
|
||||
@@ -1281,6 +1289,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
temp_suspected
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.bind_groups
|
||||
.insert(bg.as_info().id(), bg.clone());
|
||||
}
|
||||
}
|
||||
@@ -1291,7 +1300,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
{
|
||||
compute_pipeline.info.use_at(submit_index);
|
||||
if compute_pipeline.is_unique() {
|
||||
temp_suspected.as_mut().unwrap().insert(
|
||||
temp_suspected.as_mut().unwrap().compute_pipelines.insert(
|
||||
compute_pipeline.as_info().id(),
|
||||
compute_pipeline.clone(),
|
||||
);
|
||||
@@ -1302,7 +1311,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
{
|
||||
render_pipeline.info.use_at(submit_index);
|
||||
if render_pipeline.is_unique() {
|
||||
temp_suspected.as_mut().unwrap().insert(
|
||||
temp_suspected.as_mut().unwrap().render_pipelines.insert(
|
||||
render_pipeline.as_info().id(),
|
||||
render_pipeline.clone(),
|
||||
);
|
||||
@@ -1314,6 +1323,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
temp_suspected
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.query_sets
|
||||
.insert(query_set.as_info().id(), query_set.clone());
|
||||
}
|
||||
}
|
||||
@@ -1334,6 +1344,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
temp_suspected
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.render_bundles
|
||||
.insert(bundle.as_info().id(), bundle.clone());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -119,7 +119,7 @@ pub struct Device<A: HalApi> {
|
||||
life_tracker: Mutex<LifetimeTracker<A>>,
|
||||
/// Temporary storage for resource management functions. Cleared at the end
|
||||
/// of every call (unless an error occurs).
|
||||
pub(crate) temp_suspected: Mutex<Option<ResourceMaps>>,
|
||||
pub(crate) temp_suspected: Mutex<Option<ResourceMaps<A>>>,
|
||||
pub(crate) alignments: hal::Alignments,
|
||||
pub(crate) limits: wgt::Limits,
|
||||
pub(crate) features: wgt::Features,
|
||||
@@ -260,7 +260,7 @@ impl<A: HalApi> Device<A> {
|
||||
valid: AtomicBool::new(true),
|
||||
trackers: Mutex::new(Tracker::new()),
|
||||
life_tracker: Mutex::new(life::LifetimeTracker::new()),
|
||||
temp_suspected: Mutex::new(Some(life::ResourceMaps::new::<A>())),
|
||||
temp_suspected: Mutex::new(Some(life::ResourceMaps::new())),
|
||||
#[cfg(feature = "trace")]
|
||||
trace: Mutex::new(trace_path.and_then(|path| match trace::Trace::new(path) {
|
||||
Ok(mut trace) => {
|
||||
@@ -324,7 +324,7 @@ impl<A: HalApi> Device<A> {
|
||||
let temp_suspected = self
|
||||
.temp_suspected
|
||||
.lock()
|
||||
.replace(ResourceMaps::new::<A>())
|
||||
.replace(ResourceMaps::new())
|
||||
.unwrap();
|
||||
|
||||
let mut life_tracker = self.lock_life();
|
||||
@@ -404,7 +404,7 @@ impl<A: HalApi> Device<A> {
|
||||
let mut temp_suspected = self
|
||||
.temp_suspected
|
||||
.lock()
|
||||
.replace(ResourceMaps::new::<A>())
|
||||
.replace(ResourceMaps::new())
|
||||
.unwrap();
|
||||
temp_suspected.clear();
|
||||
// As the tracker is cleared/dropped, we need to consider all the resources
|
||||
@@ -412,42 +412,58 @@ impl<A: HalApi> Device<A> {
|
||||
{
|
||||
for resource in trackers.buffers.used_resources() {
|
||||
if resource.is_unique() {
|
||||
temp_suspected.insert(resource.as_info().id(), resource.clone());
|
||||
temp_suspected
|
||||
.buffers
|
||||
.insert(resource.as_info().id(), resource.clone());
|
||||
}
|
||||
}
|
||||
for resource in trackers.textures.used_resources() {
|
||||
if resource.is_unique() {
|
||||
temp_suspected.insert(resource.as_info().id(), resource.clone());
|
||||
temp_suspected
|
||||
.textures
|
||||
.insert(resource.as_info().id(), resource.clone());
|
||||
}
|
||||
}
|
||||
for resource in trackers.views.used_resources() {
|
||||
if resource.is_unique() {
|
||||
temp_suspected.insert(resource.as_info().id(), resource.clone());
|
||||
temp_suspected
|
||||
.texture_views
|
||||
.insert(resource.as_info().id(), resource.clone());
|
||||
}
|
||||
}
|
||||
for resource in trackers.bind_groups.used_resources() {
|
||||
if resource.is_unique() {
|
||||
temp_suspected.insert(resource.as_info().id(), resource.clone());
|
||||
temp_suspected
|
||||
.bind_groups
|
||||
.insert(resource.as_info().id(), resource.clone());
|
||||
}
|
||||
}
|
||||
for resource in trackers.samplers.used_resources() {
|
||||
if resource.is_unique() {
|
||||
temp_suspected.insert(resource.as_info().id(), resource.clone());
|
||||
temp_suspected
|
||||
.samplers
|
||||
.insert(resource.as_info().id(), resource.clone());
|
||||
}
|
||||
}
|
||||
for resource in trackers.compute_pipelines.used_resources() {
|
||||
if resource.is_unique() {
|
||||
temp_suspected.insert(resource.as_info().id(), resource.clone());
|
||||
temp_suspected
|
||||
.compute_pipelines
|
||||
.insert(resource.as_info().id(), resource.clone());
|
||||
}
|
||||
}
|
||||
for resource in trackers.render_pipelines.used_resources() {
|
||||
if resource.is_unique() {
|
||||
temp_suspected.insert(resource.as_info().id(), resource.clone());
|
||||
temp_suspected
|
||||
.render_pipelines
|
||||
.insert(resource.as_info().id(), resource.clone());
|
||||
}
|
||||
}
|
||||
for resource in trackers.query_sets.used_resources() {
|
||||
if resource.is_unique() {
|
||||
temp_suspected.insert(resource.as_info().id(), resource.clone());
|
||||
temp_suspected
|
||||
.query_sets
|
||||
.insert(resource.as_info().id(), resource.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user