From 88dc35c624e3b66df1258c91772021830f9f07e9 Mon Sep 17 00:00:00 2001 From: gents83 Date: Mon, 18 Sep 2023 19:43:21 +0200 Subject: [PATCH] Fixing surface present issue --- deno_webgpu/buffer.rs | 2 +- player/tests/test.rs | 4 +- tests/tests/mem_leaks.rs | 1 - wgpu-core/src/command/clear.rs | 6 +- wgpu-core/src/command/mod.rs | 6 +- wgpu-core/src/command/transfer.rs | 25 +- wgpu-core/src/device/global.rs | 15 +- wgpu-core/src/device/life.rs | 659 +++++++++++------------------- wgpu-core/src/device/mod.rs | 6 +- wgpu-core/src/device/queue.rs | 25 +- wgpu-core/src/device/resource.rs | 8 +- wgpu-core/src/present.rs | 92 ++--- wgpu-core/src/resource.rs | 71 ++-- wgpu-core/src/track/buffer.rs | 1 + wgpu-core/src/track/mod.rs | 11 +- wgpu-core/src/track/stateless.rs | 1 + wgpu-core/src/track/texture.rs | 33 +- wgpu/src/backend/direct.rs | 10 +- 18 files changed, 410 insertions(+), 566 deletions(-) diff --git a/deno_webgpu/buffer.rs b/deno_webgpu/buffer.rs index 7c5f9d58c2..92a88716ae 100644 --- a/deno_webgpu/buffer.rs +++ b/deno_webgpu/buffer.rs @@ -106,7 +106,7 @@ pub async fn op_webgpu_buffer_get_map_async( 2 => wgpu_core::device::HostMap::Write, _ => unreachable!(), }, - callback: wgpu_core::resource::BufferMapCallback::from_rust(callback), + callback: Some(wgpu_core::resource::BufferMapCallback::from_rust(callback)), } )) .err(); diff --git a/player/tests/test.rs b/player/tests/test.rs index e3a2a6a796..a9b93618ac 100644 --- a/player/tests/test.rs +++ b/player/tests/test.rs @@ -113,9 +113,9 @@ impl Test<'_> { expect.offset .. expect.offset+expect.data.len() as wgt::BufferAddress, wgc::resource::BufferMapOperation { host: wgc::device::HostMap::Read, - callback: wgc::resource::BufferMapCallback::from_rust( + callback: Some(wgc::resource::BufferMapCallback::from_rust( Box::new(map_callback) - ), + )), } )) .unwrap(); diff --git a/tests/tests/mem_leaks.rs b/tests/tests/mem_leaks.rs index dd1b93e7af..d55e51fbe4 100644 --- a/tests/tests/mem_leaks.rs +++ b/tests/tests/mem_leaks.rs @@ -251,7 +251,6 @@ fn draw_test_with_reports( assert_eq!(report.bind_groups.num_allocated, 0); assert_eq!(report.bind_group_layouts.num_allocated, 0); assert_eq!(report.pipeline_layouts.num_allocated, 0); - assert_eq!(report.buffers.num_allocated, 0); //surface is still there assert_eq!(report.texture_views.num_allocated, 1); assert_eq!(report.textures.num_allocated, 1); diff --git a/wgpu-core/src/command/clear.rs b/wgpu-core/src/command/clear.rs index 26221d19f3..a2e1bba11d 100644 --- a/wgpu-core/src/command/clear.rs +++ b/wgpu-core/src/command/clear.rs @@ -246,8 +246,8 @@ pub(crate) fn clear_texture( alignments: &hal::Alignments, zero_buffer: &A::Buffer, ) -> Result<(), ClearError> { - let dst_raw = dst_texture - .inner + let dst_inner = dst_texture.inner(); + let dst_raw = dst_inner .as_ref() .unwrap() .as_raw() @@ -290,7 +290,7 @@ pub(crate) fn clear_texture( let dst_barrier = texture_tracker .set_single(dst_texture, selector, clear_usage) .unwrap() - .map(|pending| pending.into_hal(dst_texture)); + .map(|pending| pending.into_hal(dst_inner.as_ref().unwrap())); unsafe { encoder.transition_textures(dst_barrier.into_iter()); } diff --git a/wgpu-core/src/command/mod.rs b/wgpu-core/src/command/mod.rs index 9dc8122a03..672e81bb90 100644 --- a/wgpu-core/src/command/mod.rs +++ b/wgpu-core/src/command/mod.rs @@ -217,7 +217,11 @@ impl CommandBuffer { profiling::scope!("drain_barriers"); let buffer_barriers = base.buffers.drain_transitions(); - let texture_barriers = base.textures.drain_transitions(); + let (transitions, textures) = base.textures.drain_transitions(); + let texture_barriers = transitions + .into_iter() + .enumerate() + .map(|(i, p)| p.into_hal(textures[i].as_ref().unwrap())); unsafe { raw.transition_buffers(buffer_barriers); diff --git a/wgpu-core/src/command/transfer.rs b/wgpu-core/src/command/transfer.rs index 4984e3bebf..98b96e2dda 100644 --- a/wgpu-core/src/command/transfer.rs +++ b/wgpu-core/src/command/transfer.rs @@ -801,8 +801,8 @@ impl Global { .textures .set_single(dst_texture, dst_range, hal::TextureUses::COPY_DST) .ok_or(TransferError::InvalidTexture(destination.texture))?; - let dst_raw = dst_texture - .inner + let dst_inner = dst_texture.inner(); + let dst_raw = dst_inner .as_ref() .unwrap() .as_raw() @@ -812,7 +812,7 @@ impl Global { TransferError::MissingCopyDstUsageFlag(None, Some(destination.texture)).into(), ); } - let dst_barrier = dst_pending.map(|pending| pending.into_hal(dst_texture)); + let dst_barrier = dst_pending.map(|pending| pending.into_hal(dst_inner.as_ref().unwrap())); if !dst_base.aspect.is_one() { return Err(TransferError::CopyAspectNotOne.into()); @@ -932,8 +932,8 @@ impl Global { .textures .set_single(src_texture, src_range, hal::TextureUses::COPY_SRC) .ok_or(TransferError::InvalidTexture(source.texture))?; - let src_raw = src_texture - .inner + let src_inner = src_texture.inner(); + let src_raw = src_inner .as_ref() .unwrap() .as_raw() @@ -954,7 +954,7 @@ impl Global { } .into()); } - let src_barrier = src_pending.map(|pending| pending.into_hal(src_texture)); + let src_barrier = src_pending.map(|pending| pending.into_hal(src_inner.as_ref().unwrap())); let (dst_buffer, dst_pending) = { let buffer_guard = hub.buffers.read(); @@ -1075,9 +1075,11 @@ impl Global { let src_texture = texture_guard .get(source.texture) .map_err(|_| TransferError::InvalidTexture(source.texture))?; + let src_inner = src_texture.inner(); let dst_texture = texture_guard .get(destination.texture) .map_err(|_| TransferError::InvalidTexture(source.texture))?; + let dst_inner = dst_texture.inner(); // src and dst texture format must be copy-compatible // https://gpuweb.github.io/gpuweb/#copy-compatible @@ -1139,8 +1141,7 @@ impl Global { .textures .set_single(src_texture, src_range, hal::TextureUses::COPY_SRC) .ok_or(TransferError::InvalidTexture(source.texture))?; - let src_raw = src_texture - .inner + let src_raw = src_inner .as_ref() .unwrap() .as_raw() @@ -1152,7 +1153,7 @@ impl Global { //TODO: try to avoid this the collection. It's needed because both // `src_pending` and `dst_pending` try to hold `trackers.textures` mutably. let mut barriers: ArrayVec<_, 2> = src_pending - .map(|pending| pending.into_hal(src_texture)) + .map(|pending| pending.into_hal(src_inner.as_ref().unwrap())) .collect(); let dst_pending = cmd_buf_data @@ -1160,8 +1161,7 @@ impl Global { .textures .set_single(dst_texture, dst_range, hal::TextureUses::COPY_DST) .ok_or(TransferError::InvalidTexture(destination.texture))?; - let dst_raw = dst_texture - .inner + let dst_raw = dst_inner .as_ref() .unwrap() .as_raw() @@ -1172,7 +1172,7 @@ impl Global { ); } - barriers.extend(dst_pending.map(|pending| pending.into_hal(dst_texture))); + barriers.extend(dst_pending.map(|pending| pending.into_hal(dst_inner.as_ref().unwrap()))); let hal_copy_size = hal::CopyExtent { width: src_copy_size.width.min(dst_copy_size.width), @@ -1200,6 +1200,7 @@ impl Global { regions, ); } + Ok(()) } } diff --git a/wgpu-core/src/device/global.rs b/wgpu-core/src/device/global.rs index 39b351ae9b..08a31ea685 100644 --- a/wgpu-core/src/device/global.rs +++ b/wgpu-core/src/device/global.rs @@ -748,7 +748,7 @@ impl Global { resource::TextureClearMode::None => SmallVec::new(), }; - match *texture.inner.as_ref().unwrap() { + match *texture.inner().as_ref().unwrap() { resource::TextureInner::Native { ref raw } => { if !raw.is_none() { let temp = queue::TempResource::Texture(texture.clone(), clear_views); @@ -2186,9 +2186,10 @@ impl Global { // User callbacks must not be called while holding buffer_map_async_inner's locks, so we // defer the error callback if it needs to be called immediately (typically when running // into errors). - if let Err((op, err)) = self.buffer_map_async_inner::(buffer_id, range, op) { - op.callback.call(Err(err.clone())); - + if let Err((mut operation, err)) = self.buffer_map_async_inner::(buffer_id, range, op) { + if let Some(callback) = operation.callback.take() { + callback.call(Err(err.clone())); + } return Err(err); } @@ -2370,8 +2371,10 @@ impl Global { } // Note: outside the scope where locks are held when calling the callback - if let Some((operation, status)) = closure? { - operation.callback.call(status); + if let Some((mut operation, status)) = closure? { + if let Some(callback) = operation.callback.take() { + callback.call(status); + } } Ok(()) } diff --git a/wgpu-core/src/device/life.rs b/wgpu-core/src/device/life.rs index a2a2c68a56..22f0b2a5da 100644 --- a/wgpu-core/src/device/life.rs +++ b/wgpu-core/src/device/life.rs @@ -384,41 +384,37 @@ impl LifetimeTracker { self.suspected_resources .render_bundles .retain(|&bundle_id, bundle| { - let is_removed = { - let mut trackers = trackers.lock(); - trackers - .bundles - .remove_abandoned(bundle_id, hub.render_bundles.contains(bundle_id)) - }; - if is_removed { - log::info!("Bundle {:?} is not tracked anymore", bundle_id); - f(&bundle_id); + let mut trackers = trackers.lock(); + let is_removed = trackers + .bundles + .remove_abandoned(bundle_id, hub.render_bundles.contains(bundle_id)); - for v in bundle.used.buffers.used_resources() { - self.suspected_resources - .buffers - .insert(v.as_info().id(), v.clone()); - } - for v in bundle.used.textures.used_resources() { - self.suspected_resources - .textures - .insert(v.as_info().id(), v.clone()); - } - for v in bundle.used.bind_groups.used_resources() { - self.suspected_resources - .bind_groups - .insert(v.as_info().id(), v.clone()); - } - for v in bundle.used.render_pipelines.used_resources() { - self.suspected_resources - .render_pipelines - .insert(v.as_info().id(), v.clone()); - } - for v in bundle.used.query_sets.used_resources() { - self.suspected_resources - .query_sets - .insert(v.as_info().id(), v.clone()); - } + f(&bundle_id); + + for v in bundle.used.buffers.used_resources() { + self.suspected_resources + .buffers + .insert(v.as_info().id(), v.clone()); + } + for v in bundle.used.textures.used_resources() { + self.suspected_resources + .textures + .insert(v.as_info().id(), v.clone()); + } + for v in bundle.used.bind_groups.used_resources() { + self.suspected_resources + .bind_groups + .insert(v.as_info().id(), v.clone()); + } + for v in bundle.used.render_pipelines.used_resources() { + self.suspected_resources + .render_pipelines + .insert(v.as_info().id(), v.clone()); + } + for v in bundle.used.query_sets.used_resources() { + self.suspected_resources + .query_sets + .insert(v.as_info().id(), v.clone()); } !is_removed }); @@ -438,52 +434,48 @@ impl LifetimeTracker { self.suspected_resources .bind_groups .retain(|&bind_group_id, bind_group| { - let is_removed = { - let mut trackers = trackers.lock(); - trackers - .bind_groups - .remove_abandoned(bind_group_id, hub.bind_groups.contains(bind_group_id)) - }; - if is_removed { - log::info!("BindGroup {:?} is not tracked anymore", bind_group_id); - f(&bind_group_id); + let mut trackers = trackers.lock(); + let is_removed = trackers + .bind_groups + .remove_abandoned(bind_group_id, hub.bind_groups.contains(bind_group_id)); - for v in bind_group.used.buffers.used_resources() { - self.suspected_resources - .buffers - .insert(v.as_info().id(), v.clone()); - } - for v in bind_group.used.textures.used_resources() { - self.suspected_resources - .textures - .insert(v.as_info().id(), v.clone()); - } - for v in bind_group.used.views.used_resources() { - self.suspected_resources - .texture_views - .insert(v.as_info().id(), v.clone()); - } - for v in bind_group.used.samplers.used_resources() { - self.suspected_resources - .samplers - .insert(v.as_info().id(), v.clone()); - } + f(&bind_group_id); + for v in bind_group.used.buffers.used_resources() { self.suspected_resources - .bind_group_layouts - .insert(bind_group.layout.as_info().id(), bind_group.layout.clone()); + .buffers + .insert(v.as_info().id(), v.clone()); + } + for v in bind_group.used.textures.used_resources() { + self.suspected_resources + .textures + .insert(v.as_info().id(), v.clone()); + } + for v in bind_group.used.views.used_resources() { + self.suspected_resources + .texture_views + .insert(v.as_info().id(), v.clone()); + } + for v in bind_group.used.samplers.used_resources() { + self.suspected_resources + .samplers + .insert(v.as_info().id(), v.clone()); + } - let submit_index = bind_group.info.submission_index(); - if !submit_indices.contains(&submit_index) { - submit_indices.push(submit_index); - } - self.active - .iter_mut() - .find(|a| a.index == submit_index) - .map_or(&mut self.free_resources, |a| &mut a.last_resources) - .bind_groups - .insert(bind_group_id, bind_group.clone()); + self.suspected_resources + .bind_group_layouts + .insert(bind_group.layout.as_info().id(), bind_group.layout.clone()); + + let submit_index = bind_group.info.submission_index(); + if !submit_indices.contains(&submit_index) { + submit_indices.push(submit_index); } + self.active + .iter_mut() + .find(|a| a.index == submit_index) + .map_or(&mut self.free_resources, |a| &mut a.last_resources) + .bind_groups + .insert(bind_group_id, bind_group.clone()); !is_removed }); submit_indices @@ -502,32 +494,28 @@ impl LifetimeTracker { self.suspected_resources .texture_views .retain(|&view_id, view| { - let is_removed = { - let mut trackers = trackers.lock(); - trackers - .views - .remove_abandoned(view_id, hub.texture_views.contains(view_id)) - }; - if is_removed { - log::info!("TextureView {:?} is not tracked anymore", view_id); - f(&view_id); - - if let Some(parent_texture) = view.parent.as_ref() { - self.suspected_resources - .textures - .insert(parent_texture.as_info().id(), parent_texture.clone()); - } - let submit_index = view.info.submission_index(); - if !submit_indices.contains(&submit_index) { - submit_indices.push(submit_index); - } - self.active - .iter_mut() - .find(|a| a.index == submit_index) - .map_or(&mut self.free_resources, |a| &mut a.last_resources) - .texture_views - .insert(view_id, view.clone()); + let mut trackers = trackers.lock(); + let is_removed = trackers + .views + .remove_abandoned(view_id, hub.texture_views.contains(view_id)); + + f(&view_id); + + if let Some(parent_texture) = view.parent.as_ref() { + self.suspected_resources + .textures + .insert(parent_texture.as_info().id(), parent_texture.clone()); } + let submit_index = view.info.submission_index(); + if !submit_indices.contains(&submit_index) { + submit_indices.push(submit_index); + } + self.active + .iter_mut() + .find(|a| a.index == submit_index) + .map_or(&mut self.free_resources, |a| &mut a.last_resources) + .texture_views + .insert(view_id, view.clone()); !is_removed }); submit_indices @@ -545,37 +533,33 @@ impl LifetimeTracker { self.suspected_resources .textures .retain(|&texture_id, texture| { - let is_removed = { - let mut trackers = trackers.lock(); - trackers - .textures - .remove_abandoned(texture_id, hub.textures.contains(texture_id)) - }; - if is_removed { - log::info!("Texture {:?} is not tracked anymore", texture_id); - f(&texture_id); - - let submit_index = texture.info.submission_index(); - let non_referenced_resources = self - .active - .iter_mut() - .find(|a| a.index == submit_index) - .map_or(&mut self.free_resources, |a| &mut a.last_resources); - - if let &resource::TextureClearMode::RenderPass { - ref clear_views, .. - } = &*texture.clear_mode.read() - { - clear_views.into_iter().for_each(|v| { - non_referenced_resources - .texture_views - .insert(v.as_info().id(), v.clone()); - }); - } - non_referenced_resources - .textures - .insert(texture_id, texture.clone()); + let mut trackers = trackers.lock(); + let is_removed = trackers + .textures + .remove_abandoned(texture_id, hub.textures.contains(texture_id)); + + f(&texture_id); + + let submit_index = texture.info.submission_index(); + let non_referenced_resources = self + .active + .iter_mut() + .find(|a| a.index == submit_index) + .map_or(&mut self.free_resources, |a| &mut a.last_resources); + + if let &resource::TextureClearMode::RenderPass { + ref clear_views, .. + } = &*texture.clear_mode.read() + { + clear_views.into_iter().for_each(|v| { + non_referenced_resources + .texture_views + .insert(v.as_info().id(), v.clone()); + }); } + non_referenced_resources + .textures + .insert(texture_id, texture.clone()); !is_removed }); self @@ -594,27 +578,23 @@ impl LifetimeTracker { self.suspected_resources .samplers .retain(|&sampler_id, sampler| { - let is_removed = { - let mut trackers = trackers.lock(); - trackers - .samplers - .remove_abandoned(sampler_id, hub.samplers.contains(sampler_id)) - }; - if is_removed { - log::info!("Sampler {:?} is not tracked anymore", sampler_id); - f(&sampler_id); + let mut trackers = trackers.lock(); + let is_removed = trackers + .samplers + .remove_abandoned(sampler_id, hub.samplers.contains(sampler_id)); - let submit_index = sampler.info.submission_index(); - if !submit_indices.contains(&submit_index) { - submit_indices.push(submit_index); - } - self.active - .iter_mut() - .find(|a| a.index == submit_index) - .map_or(&mut self.free_resources, |a| &mut a.last_resources) - .samplers - .insert(sampler_id, sampler.clone()); + f(&sampler_id); + + let submit_index = sampler.info.submission_index(); + if !submit_indices.contains(&submit_index) { + submit_indices.push(submit_index); } + self.active + .iter_mut() + .find(|a| a.index == submit_index) + .map_or(&mut self.free_resources, |a| &mut a.last_resources) + .samplers + .insert(sampler_id, sampler.clone()); !is_removed }); submit_indices @@ -633,35 +613,31 @@ impl LifetimeTracker { self.suspected_resources .buffers .retain(|&buffer_id, buffer| { - let is_removed = { - let mut trackers = trackers.lock(); - trackers - .buffers - .remove_abandoned(buffer_id, hub.buffers.contains(buffer_id)) - }; - if is_removed { - log::info!("Buffer {:?} is not tracked anymore", buffer_id); - f(&buffer_id); + let mut trackers = trackers.lock(); + let is_removed = trackers + .buffers + .remove_abandoned(buffer_id, hub.buffers.contains(buffer_id)); - let submit_index = buffer.info.submission_index(); - if !submit_indices.contains(&submit_index) { - submit_indices.push(submit_index); - } - if let resource::BufferMapState::Init { - ref stage_buffer, .. - } = *buffer.map_state.lock() - { - self.free_resources - .buffers - .insert(stage_buffer.as_info().id(), stage_buffer.clone()); - } - self.active - .iter_mut() - .find(|a| a.index == submit_index) - .map_or(&mut self.free_resources, |a| &mut a.last_resources) + f(&buffer_id); + + let submit_index = buffer.info.submission_index(); + if !submit_indices.contains(&submit_index) { + submit_indices.push(submit_index); + } + if let resource::BufferMapState::Init { + ref stage_buffer, .. + } = *buffer.map_state.lock() + { + self.free_resources .buffers - .insert(buffer_id, buffer.clone()); + .insert(stage_buffer.as_info().id(), stage_buffer.clone()); } + self.active + .iter_mut() + .find(|a| a.index == submit_index) + .map_or(&mut self.free_resources, |a| &mut a.last_resources) + .buffers + .insert(buffer_id, buffer.clone()); !is_removed }); submit_indices @@ -679,36 +655,29 @@ impl LifetimeTracker { let mut submit_indices = Vec::new(); self.suspected_resources.compute_pipelines.retain( |&compute_pipeline_id, compute_pipeline| { - let is_removed = { - let mut trackers = trackers.lock(); - trackers.compute_pipelines.remove_abandoned( - compute_pipeline_id, - hub.compute_pipelines.contains(compute_pipeline_id), - ) - }; - if is_removed { - log::info!( - "ComputePipeline {:?} is not tracked anymore", - compute_pipeline_id - ); - f(&compute_pipeline_id); - - self.suspected_resources.pipeline_layouts.insert( - compute_pipeline.layout.as_info().id(), - compute_pipeline.layout.clone(), - ); - - let submit_index = compute_pipeline.info.submission_index(); - if !submit_indices.contains(&submit_index) { - submit_indices.push(submit_index); - } - self.active - .iter_mut() - .find(|a| a.index == submit_index) - .map_or(&mut self.free_resources, |a| &mut a.last_resources) - .compute_pipelines - .insert(compute_pipeline_id, compute_pipeline.clone()); + let mut trackers = trackers.lock(); + let is_removed = trackers.compute_pipelines.remove_abandoned( + compute_pipeline_id, + hub.compute_pipelines.contains(compute_pipeline_id), + ); + + f(&compute_pipeline_id); + + self.suspected_resources.pipeline_layouts.insert( + compute_pipeline.layout.as_info().id(), + compute_pipeline.layout.clone(), + ); + + let submit_index = compute_pipeline.info.submission_index(); + if !submit_indices.contains(&submit_index) { + submit_indices.push(submit_index); } + self.active + .iter_mut() + .find(|a| a.index == submit_index) + .map_or(&mut self.free_resources, |a| &mut a.last_resources) + .compute_pipelines + .insert(compute_pipeline_id, compute_pipeline.clone()); !is_removed }, ); @@ -728,46 +697,35 @@ impl LifetimeTracker { self.suspected_resources .render_pipelines .retain(|&render_pipeline_id, render_pipeline| { - let is_removed = { - let mut trackers = trackers.lock(); - trackers.render_pipelines.remove_abandoned( - render_pipeline_id, - hub.render_pipelines.contains(render_pipeline_id), - ) - }; - if is_removed { - log::info!( - "RenderPipeline {:?} is not tracked anymore", - render_pipeline_id - ); - f(&render_pipeline_id); - - self.suspected_resources.pipeline_layouts.insert( - render_pipeline.layout.as_info().id(), - render_pipeline.layout.clone(), - ); - - let submit_index = render_pipeline.info.submission_index(); - if !submit_indices.contains(&submit_index) { - submit_indices.push(submit_index); - } - self.active - .iter_mut() - .find(|a| a.index == submit_index) - .map_or(&mut self.free_resources, |a| &mut a.last_resources) - .render_pipelines - .insert(render_pipeline_id, render_pipeline.clone()); + let mut trackers = trackers.lock(); + let is_removed = trackers.render_pipelines.remove_abandoned( + render_pipeline_id, + hub.render_pipelines.contains(render_pipeline_id), + ); + + f(&render_pipeline_id); + + self.suspected_resources.pipeline_layouts.insert( + render_pipeline.layout.as_info().id(), + render_pipeline.layout.clone(), + ); + + let submit_index = render_pipeline.info.submission_index(); + if !submit_indices.contains(&submit_index) { + submit_indices.push(submit_index); } + self.active + .iter_mut() + .find(|a| a.index == submit_index) + .map_or(&mut self.free_resources, |a| &mut a.last_resources) + .render_pipelines + .insert(render_pipeline_id, render_pipeline.clone()); !is_removed }); submit_indices } - fn triage_suspected_pipeline_layouts( - &mut self, - pipeline_submit_indices: &[u64], - mut f: F, - ) -> &mut Self + fn triage_suspected_pipeline_layouts(&mut self, mut f: F) -> &mut Self where F: FnMut(&id::PipelineLayoutId), { @@ -775,63 +733,22 @@ impl LifetimeTracker { .pipeline_layouts .retain(|pipeline_layout_id, pipeline_layout| { //Note: this has to happen after all the suspected pipelines are destroyed + f(pipeline_layout_id); - let mut num_ref_in_nonreferenced_resources = 0; - pipeline_submit_indices.iter().for_each(|submit_index| { - let resources = self - .active - .iter() - .find(|a| a.index == *submit_index) - .map_or(&self.free_resources, |a| &a.last_resources); - - resources.compute_pipelines.iter().for_each(|(_id, p)| { - if p.layout.as_info().id() == *pipeline_layout_id { - num_ref_in_nonreferenced_resources += 1; - } - }); - resources.render_pipelines.iter().for_each(|(_id, p)| { - if p.layout.as_info().id() == *pipeline_layout_id { - num_ref_in_nonreferenced_resources += 1; - } - }); - }); - - if pipeline_layout.ref_count() == (1 + num_ref_in_nonreferenced_resources) { - log::debug!( - "PipelineLayout {:?} is not tracked anymore", - pipeline_layout_id - ); - - f(pipeline_layout_id); - - for bgl in &pipeline_layout.bind_group_layouts { - self.suspected_resources - .bind_group_layouts - .insert(bgl.as_info().id(), bgl.clone()); - } - self.free_resources - .pipeline_layouts - .insert(*pipeline_layout_id, pipeline_layout.clone()); - - return false; - } else { - log::info!( - "PipelineLayout {:?} is still referenced from {}", - pipeline_layout_id, - pipeline_layout.ref_count() - ); + for bgl in &pipeline_layout.bind_group_layouts { + self.suspected_resources + .bind_group_layouts + .insert(bgl.as_info().id(), bgl.clone()); } - true + self.free_resources + .pipeline_layouts + .insert(*pipeline_layout_id, pipeline_layout.clone()); + false }); self } - fn triage_suspected_bind_group_layouts( - &mut self, - bind_group_submit_indices: &[u64], - pipeline_submit_indices: &[u64], - mut f: F, - ) -> &mut Self + fn triage_suspected_bind_group_layouts(&mut self, mut f: F) -> &mut Self where F: FnMut(&id::BindGroupLayoutId), { @@ -841,80 +758,12 @@ impl LifetimeTracker { //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 // encounter could drop the refcount to 0. - let mut num_ref_in_nonreferenced_resources = 0; - bind_group_submit_indices.iter().for_each(|submit_index| { - let resources = self - .active - .iter() - .find(|a| a.index == *submit_index) - .map_or(&self.free_resources, |a| &a.last_resources); - - resources.bind_groups.iter().for_each(|(_id, b)| { - if b.layout.as_info().id() == *bind_group_layout_id { - num_ref_in_nonreferenced_resources += 1; - } - }); - resources.bind_group_layouts.iter().for_each(|(id, _b)| { - if id == bind_group_layout_id { - num_ref_in_nonreferenced_resources += 1; - } - }); - }); - pipeline_submit_indices.iter().for_each(|submit_index| { - let resources = self - .active - .iter() - .find(|a| a.index == *submit_index) - .map_or(&self.free_resources, |a| &a.last_resources); - - resources.compute_pipelines.iter().for_each(|(_id, p)| { - p.layout.bind_group_layouts.iter().for_each(|b| { - if b.as_info().id() == *bind_group_layout_id { - num_ref_in_nonreferenced_resources += 1; - } - }); - }); - resources.render_pipelines.iter().for_each(|(_id, p)| { - p.layout.bind_group_layouts.iter().for_each(|b| { - if b.as_info().id() == *bind_group_layout_id { - num_ref_in_nonreferenced_resources += 1; - } - }); - }); - resources.pipeline_layouts.iter().for_each(|(_id, p)| { - p.bind_group_layouts.iter().for_each(|b| { - if b.as_info().id() == *bind_group_layout_id { - num_ref_in_nonreferenced_resources += 1; - } - }); - }); - }); - - //Note: this has to happen after all the suspected pipelines are destroyed - if bind_group_layout.ref_count() == (1 + num_ref_in_nonreferenced_resources) { - // If This layout points to a compatible one, go over the latter - // to decrement the ref count and potentially destroy it. - //bgl_to_check = bind_group_layout.compatible_layout; - - log::debug!( - "BindGroupLayout {:?} is not tracked anymore", - bind_group_layout_id - ); - f(bind_group_layout_id); + f(bind_group_layout_id); - self.free_resources - .bind_group_layouts - .insert(*bind_group_layout_id, bind_group_layout.clone()); - - return false; - } else { - log::info!( - "BindGroupLayout {:?} is still referenced from {}", - bind_group_layout_id, - bind_group_layout.ref_count() - ); - } - true + self.free_resources + .bind_group_layouts + .insert(*bind_group_layout_id, bind_group_layout.clone()); + false }, ); self @@ -929,28 +778,23 @@ impl LifetimeTracker { self.suspected_resources .query_sets .retain(|&query_set_id, query_set| { - let is_removed = { - let mut trackers = trackers.lock(); - trackers - .query_sets - .remove_abandoned(query_set_id, hub.query_sets.contains(query_set_id)) - }; - if is_removed { - log::info!("QuerySet {:?} is not tracked anymore", query_set_id); - // #[cfg(feature = "trace")] - // trace.map(|t| t.add(trace::Action::DestroyComputePipeline(id))); - - let submit_index = query_set.info.submission_index(); - if !submit_indices.contains(&submit_index) { - submit_indices.push(submit_index); - } - self.active - .iter_mut() - .find(|a| a.index == submit_index) - .map_or(&mut self.free_resources, |a| &mut a.last_resources) - .query_sets - .insert(query_set_id, query_set.clone()); + let mut trackers = trackers.lock(); + let is_removed = trackers + .query_sets + .remove_abandoned(query_set_id, hub.query_sets.contains(query_set_id)); + // #[cfg(feature = "trace")] + // trace.map(|t| t.add(trace::Action::DestroyComputePipeline(id))); + + let submit_index = query_set.info.submission_index(); + if !submit_indices.contains(&submit_index) { + submit_indices.push(submit_index); } + self.active + .iter_mut() + .find(|a| a.index == submit_index) + .map_or(&mut self.free_resources, |a| &mut a.last_resources) + .query_sets + .insert(query_set_id, query_set.clone()); !is_removed }); submit_indices @@ -1009,45 +853,36 @@ impl LifetimeTracker { t.add(trace::Action::DestroyRenderBundle(*_id)); } }); - let compute_pipeline_indices = - self.triage_suspected_compute_pipelines(hub, trackers, |_id| { - #[cfg(feature = "trace")] - if let Some(ref mut t) = trace { - t.add(trace::Action::DestroyComputePipeline(*_id)); - } - }); - let render_pipeline_indices = - self.triage_suspected_render_pipelines(hub, trackers, |_id| { - #[cfg(feature = "trace")] - if let Some(ref mut t) = trace { - t.add(trace::Action::DestroyRenderPipeline(*_id)); - } - }); - let mut pipeline_submit_indices = Vec::new(); - pipeline_submit_indices.extend(compute_pipeline_indices); - pipeline_submit_indices.extend(render_pipeline_indices); - let bind_group_submit_indices = self.triage_suspected_bind_groups(hub, trackers, |_id| { + self.triage_suspected_compute_pipelines(hub, trackers, |_id| { + #[cfg(feature = "trace")] + if let Some(ref mut t) = trace { + t.add(trace::Action::DestroyComputePipeline(*_id)); + } + }); + self.triage_suspected_render_pipelines(hub, trackers, |_id| { + #[cfg(feature = "trace")] + if let Some(ref mut t) = trace { + t.add(trace::Action::DestroyRenderPipeline(*_id)); + } + }); + self.triage_suspected_bind_groups(hub, trackers, |_id| { #[cfg(feature = "trace")] if let Some(ref mut t) = trace { t.add(trace::Action::DestroyBindGroup(*_id)); } }); - self.triage_suspected_pipeline_layouts(&pipeline_submit_indices, |_id| { + self.triage_suspected_pipeline_layouts(|_id| { #[cfg(feature = "trace")] if let Some(ref mut t) = trace { t.add(trace::Action::DestroyPipelineLayout(*_id)); } }); - self.triage_suspected_bind_group_layouts( - &bind_group_submit_indices, - &pipeline_submit_indices, - |_id| { - #[cfg(feature = "trace")] - if let Some(ref mut t) = trace { - t.add(trace::Action::DestroyBindGroupLayout(*_id)); - } - }, - ); + self.triage_suspected_bind_group_layouts(|_id| { + #[cfg(feature = "trace")] + if let Some(ref mut t) = trace { + t.add(trace::Action::DestroyBindGroupLayout(*_id)); + } + }); self.triage_suspected_samplers(hub, trackers, |_id| { #[cfg(feature = "trace")] if let Some(ref mut t) = trace { diff --git a/wgpu-core/src/device/mod.rs b/wgpu-core/src/device/mod.rs index 1836dd646f..ae53e83f1d 100644 --- a/wgpu-core/src/device/mod.rs +++ b/wgpu-core/src/device/mod.rs @@ -184,8 +184,10 @@ impl UserClosures { // Mappings _must_ be fired before submissions, as the spec requires all mapping callbacks that are registered before // a on_submitted_work_done callback to be fired before the on_submitted_work_done callback. - for (operation, status) in self.mappings { - operation.callback.call(status); + for (mut operation, status) in self.mappings { + if let Some(callback) = operation.callback.take() { + callback.call(status); + } } for closure in self.submissions { closure.call(); diff --git a/wgpu-core/src/device/queue.rs b/wgpu-core/src/device/queue.rs index 8f103a9ae6..9b6cd33fb4 100644 --- a/wgpu-core/src/device/queue.rs +++ b/wgpu-core/src/device/queue.rs @@ -794,8 +794,8 @@ impl Global { dst.info .use_at(device.active_submission_index.load(Ordering::Relaxed) + 1); - let dst_raw = dst - .inner + let dst_inner = dst.inner(); + let dst_raw = dst_inner .as_ref() .unwrap() .as_raw() @@ -880,7 +880,9 @@ impl Global { .set_single(&dst, selector, hal::TextureUses::COPY_DST) .ok_or(TransferError::InvalidTexture(destination.texture))?; unsafe { - encoder.transition_textures(transition.map(|pending| pending.into_hal(&dst))); + encoder.transition_textures( + transition.map(|pending| pending.into_hal(dst_inner.as_ref().unwrap())), + ); encoder.transition_buffers(iter::once(barrier)); encoder.copy_buffer_to_texture(inner_buffer.as_ref().unwrap(), dst_raw, regions); } @@ -1211,7 +1213,7 @@ impl Global { } for texture in cmd_buf_trackers.textures.used_resources() { let id = texture.info.id(); - let should_extend = match *texture.inner.as_ref().unwrap() { + let should_extend = match *texture.inner().as_ref().unwrap() { TextureInner::Native { raw: None } => { return Err(QueueSubmitError::DestroyedTexture(id)); } @@ -1364,7 +1366,11 @@ impl Global { trackers .textures .set_from_usage_scope(&used_surface_textures); - let texture_barriers = trackers.textures.drain_transitions(); + let (transitions, textures) = trackers.textures.drain_transitions(); + let texture_barriers = transitions + .into_iter() + .enumerate() + .map(|(i, p)| p.into_hal(textures[i].as_ref().unwrap())); let present = unsafe { baked.encoder.transition_textures(texture_barriers); baked.encoder.end_encoding().unwrap() @@ -1392,7 +1398,7 @@ impl Global { used_surface_textures.set_size(texture_guard.len()); for (&id, texture) in pending_writes.dst_textures.iter() { - match *texture.inner.as_ref().unwrap() { + match *texture.inner().as_ref().unwrap() { TextureInner::Native { raw: None } => { return Err(QueueSubmitError::DestroyedTexture(id)); } @@ -1414,8 +1420,11 @@ impl Global { trackers .textures .set_from_usage_scope(&used_surface_textures); - let texture_barriers = trackers.textures.drain_transitions(); - + let (transitions, textures) = trackers.textures.drain_transitions(); + let texture_barriers = transitions + .into_iter() + .enumerate() + .map(|(i, p)| p.into_hal(textures[i].as_ref().unwrap())); unsafe { pending_writes .command_encoder diff --git a/wgpu-core/src/device/resource.rs b/wgpu-core/src/device/resource.rs index 105d8c7f62..de2a7c966d 100644 --- a/wgpu-core/src/device/resource.rs +++ b/wgpu-core/src/device/resource.rs @@ -534,9 +534,9 @@ impl Device { debug_assert_eq!(self_id.backend(), A::VARIANT); Texture { - inner: Some(resource::TextureInner::Native { + inner: RwLock::new(Some(resource::TextureInner::Native { raw: Some(hal_texture), - }), + })), device: self.clone(), desc: desc.map_label(|_| ()), hal_usage, @@ -768,8 +768,8 @@ impl Device { texture: &Arc>, desc: &resource::TextureViewDescriptor, ) -> Result, resource::CreateTextureViewError> { - let texture_raw = texture - .inner + let inner = texture.inner(); + let texture_raw = inner .as_ref() .unwrap() .as_raw() diff --git a/wgpu-core/src/present.rs b/wgpu-core/src/present.rs index 4a88b05753..76db63472a 100644 --- a/wgpu-core/src/present.rs +++ b/wgpu-core/src/present.rs @@ -11,10 +11,7 @@ extract it from the hub. use std::{ borrow::Borrow, - sync::{ - atomic::{AtomicBool, Ordering}, - Arc, - }, + sync::atomic::{AtomicBool, Ordering}, }; #[cfg(feature = "trace")] @@ -203,11 +200,11 @@ impl Global { let mut presentation = surface.presentation.lock(); let present = presentation.as_mut().unwrap(); let texture = resource::Texture { - inner: Some(resource::TextureInner::Surface { - raw: ast.texture, + inner: RwLock::new(Some(resource::TextureInner::Surface { + raw: Some(ast.texture), parent_id: surface_id, has_work: AtomicBool::new(false), - }), + })), device: device.clone(), desc: texture_desc, hal_usage, @@ -310,35 +307,34 @@ impl Global { let texture = hub.textures.unregister(texture_id); if let Some(texture) = texture { - if let Ok(mut texture) = Arc::try_unwrap(texture) { - texture.clear_mode.write().destroy_clear_views(device.raw()); - - let suf = A::get_surface(&surface); - match texture.inner.take().unwrap() { - resource::TextureInner::Surface { - raw, - parent_id, - has_work, - } => { - if surface_id != parent_id { - log::error!("Presented frame is from a different surface"); - Err(hal::SurfaceError::Lost) - } else if !has_work.load(Ordering::Relaxed) { - log::error!("No work has been submitted for this frame"); - unsafe { suf.unwrap().raw.discard_texture(raw) }; - Err(hal::SurfaceError::Outdated) - } else { - unsafe { - queue.raw.as_ref().unwrap().present(&suf.unwrap().raw, raw) - } + let suf = A::get_surface(&surface); + let mut inner = texture.inner_mut(); + let inner = inner.as_mut().unwrap(); + + match *inner { + resource::TextureInner::Surface { + ref mut raw, + ref parent_id, + ref has_work, + } => { + if surface_id != *parent_id { + log::error!("Presented frame is from a different surface"); + Err(hal::SurfaceError::Lost) + } else if !has_work.load(Ordering::Relaxed) { + log::error!("No work has been submitted for this frame"); + unsafe { suf.unwrap().raw.discard_texture(raw.take().unwrap()) }; + Err(hal::SurfaceError::Outdated) + } else { + unsafe { + queue + .raw + .as_ref() + .unwrap() + .present(&suf.unwrap().raw, raw.take().unwrap()) } } - resource::TextureInner::Native { .. } => unreachable!(), } - } else { - Err(hal::SurfaceError::Other( - "Surface cannot be destroyed because is still in use", - )) + _ => unreachable!(), } } else { Err(hal::SurfaceError::Outdated) //TODO? @@ -402,26 +398,20 @@ impl Global { let texture = hub.textures.unregister(texture_id); if let Some(texture) = texture { - if let Ok(mut texture) = Arc::try_unwrap(texture) { - texture.clear_mode.write().destroy_clear_views(device.raw()); - - let suf = A::get_surface(&surface); - match texture.inner.take().unwrap() { - resource::TextureInner::Surface { - raw, - parent_id, - has_work: _, - } => { - if surface_id == parent_id { - unsafe { suf.unwrap().raw.discard_texture(raw) }; - } else { - log::warn!("Surface texture is outdated"); - } + let suf = A::get_surface(&surface); + match *texture.inner_mut().as_mut().take().as_mut().unwrap() { + &mut resource::TextureInner::Surface { + ref mut raw, + ref parent_id, + has_work: _, + } => { + if surface_id == *parent_id { + unsafe { suf.unwrap().raw.discard_texture(raw.take().unwrap()) }; + } else { + log::warn!("Surface texture is outdated"); } - resource::TextureInner::Native { .. } => unreachable!(), } - } else { - return Err(SurfaceError::StillReferenced); + _ => unreachable!(), } } } diff --git a/wgpu-core/src/resource.rs b/wgpu-core/src/resource.rs index bb28ce805e..5fcaff1c90 100644 --- a/wgpu-core/src/resource.rs +++ b/wgpu-core/src/resource.rs @@ -20,7 +20,7 @@ use crate::{ }; use hal::CommandEncoder; -use parking_lot::{Mutex, RwLock}; +use parking_lot::{Mutex, RwLock, RwLockReadGuard, RwLockWriteGuard}; use smallvec::SmallVec; use thiserror::Error; @@ -242,7 +242,7 @@ unsafe impl Send for BufferMapCallbackC {} pub struct BufferMapCallback { // We wrap this so creating the enum in the C variant can be unsafe, // allowing our call function to be safe. - inner: Option, + inner: BufferMapCallbackInner, } #[cfg(any( @@ -279,7 +279,7 @@ impl Debug for BufferMapCallbackInner { impl BufferMapCallback { pub fn from_rust(callback: BufferMapCallbackCallback) -> Self { Self { - inner: Some(BufferMapCallbackInner::Rust { callback }), + inner: BufferMapCallbackInner::Rust { callback }, } } @@ -292,17 +292,17 @@ impl BufferMapCallback { /// invoked, which may happen at an unspecified time. pub unsafe fn from_c(inner: BufferMapCallbackC) -> Self { Self { - inner: Some(BufferMapCallbackInner::C { inner }), + inner: BufferMapCallbackInner::C { inner }, } } - pub(crate) fn call(mut self, result: BufferAccessResult) { - match self.inner.take() { - Some(BufferMapCallbackInner::Rust { callback }) => { + pub(crate) fn call(self, result: BufferAccessResult) { + match self.inner { + BufferMapCallbackInner::Rust { callback } => { callback(result); } // SAFETY: the contract of the call to from_c says that this unsafe is sound. - Some(BufferMapCallbackInner::C { inner }) => unsafe { + BufferMapCallbackInner::C { inner } => unsafe { let status = match result { Ok(()) => BufferMapAsyncStatus::Success, Err(BufferAccessError::Device(_)) => BufferMapAsyncStatus::ContextLost, @@ -331,17 +331,6 @@ impl BufferMapCallback { (inner.callback)(status, inner.user_data); }, - None => { - panic!("Map callback invoked twice"); - } - } - } -} - -impl Drop for BufferMapCallback { - fn drop(&mut self) { - if self.inner.is_some() { - panic!("Map callback was leaked"); } } } @@ -349,7 +338,7 @@ impl Drop for BufferMapCallback { #[derive(Debug)] pub struct BufferMapOperation { pub host: HostMap, - pub callback: BufferMapCallback, + pub callback: Option, } #[derive(Clone, Debug, Error)] @@ -585,8 +574,10 @@ impl Buffer { } // Note: outside the scope where locks are held when calling the callback - if let Some((operation, status)) = map_closure { - operation.callback.call(status); + if let Some((mut operation, status)) = map_closure { + if let Some(callback) = operation.callback.take() { + callback.call(status); + } } Ok(()) @@ -688,7 +679,7 @@ pub(crate) enum TextureInner { raw: Option, }, Surface { - raw: A::SurfaceTexture, + raw: Option, parent_id: SurfaceId, has_work: AtomicBool, }, @@ -698,8 +689,10 @@ impl TextureInner { pub fn as_raw(&self) -> Option<&A::Texture> { match *self { Self::Native { raw: Some(ref tex) } => Some(tex), - Self::Native { raw: None } => None, - Self::Surface { ref raw, .. } => Some(raw.borrow()), + Self::Surface { + raw: Some(ref tex), .. + } => Some(tex.borrow()), + _ => None, } } } @@ -720,20 +713,9 @@ pub enum TextureClearMode { None, } -impl TextureClearMode { - pub(crate) fn destroy_clear_views(&mut self, device: &A::Device) { - if let TextureClearMode::Surface { ref mut clear_view } = *self { - unsafe { - let view = clear_view.take().unwrap(); - hal::Device::destroy_texture_view(device, view); - } - } - } -} - #[derive(Debug)] pub struct Texture { - pub(crate) inner: Option>, + pub(crate) inner: RwLock>>, pub(crate) device: Arc>, pub(crate) desc: wgt::TextureDescriptor<(), Vec>, pub(crate) hal_usage: hal::TextureUses, @@ -768,10 +750,10 @@ impl Drop for Texture { } _ => {} }; - if self.inner.is_none() { + if self.inner.read().is_none() { return; } - let inner = self.inner.take().unwrap(); + let inner = self.inner.write().take().unwrap(); if let TextureInner::Native { raw: Some(raw) } = inner { unsafe { self.device.raw().destroy_texture(raw); @@ -781,6 +763,12 @@ impl Drop for Texture { } impl Texture { + pub(crate) fn inner<'a>(&'a self) -> RwLockReadGuard<'a, Option>> { + self.inner.read() + } + pub(crate) fn inner_mut<'a>(&'a self) -> RwLockWriteGuard<'a, Option>> { + self.inner.write() + } pub(crate) fn get_clear_view<'a>( clear_mode: &'a TextureClearMode, desc: &'a wgt::TextureDescriptor<(), Vec>, @@ -824,9 +812,8 @@ impl Global { let hub = A::hub(self); let texture = { hub.textures.try_get(id).ok().flatten() }; - let hal_texture = texture - .as_ref() - .and_then(|tex| tex.inner.as_ref().unwrap().as_raw()); + let inner = texture.as_ref().unwrap().inner(); + let hal_texture = inner.as_ref().unwrap().as_raw(); hal_texture_callback(hal_texture); } diff --git a/wgpu-core/src/track/buffer.rs b/wgpu-core/src/track/buffer.rs index 973684419b..a5c972283f 100644 --- a/wgpu-core/src/track/buffer.rs +++ b/wgpu-core/src/track/buffer.rs @@ -580,6 +580,7 @@ impl BufferTracker { let min_ref_count = if is_in_registry { 3 } else { 2 }; if existing_ref_count <= min_ref_count { self.metadata.remove(index); + log::info!("Buffer {:?} is not tracked anymore", id,); return true; } else { log::info!( diff --git a/wgpu-core/src/track/mod.rs b/wgpu-core/src/track/mod.rs index f51d736a1f..7d85712596 100644 --- a/wgpu-core/src/track/mod.rs +++ b/wgpu-core/src/track/mod.rs @@ -130,6 +130,8 @@ pub(crate) struct PendingTransition { pub usage: ops::Range, } +pub(crate) type PendingTransitionList = Vec>; + impl PendingTransition { /// Produce the hal barrier corresponding to the transition. pub fn into_hal<'a, A: HalApi>( @@ -148,14 +150,9 @@ impl PendingTransition { /// Produce the hal barrier corresponding to the transition. pub fn into_hal<'a, A: HalApi>( self, - tex: &'a resource::Texture, + tex: &'a resource::TextureInner, ) -> hal::TextureBarrier<'a, A> { - let texture = tex - .inner - .as_ref() - .unwrap() - .as_raw() - .expect("Texture is destroyed"); + let texture = tex.as_raw().expect("Texture is destroyed"); // These showing up in a barrier is always a bug strict_assert_ne!(self.usage.start, hal::TextureUses::UNKNOWN); diff --git a/wgpu-core/src/track/stateless.rs b/wgpu-core/src/track/stateless.rs index f565932f8b..3ed5e73415 100644 --- a/wgpu-core/src/track/stateless.rs +++ b/wgpu-core/src/track/stateless.rs @@ -189,6 +189,7 @@ impl> StatelessTracker { let min_ref_count = if is_in_registry { 3 } else { 2 }; if existing_ref_count <= min_ref_count { self.metadata.remove(index); + log::info!("{} {:?} is not tracked anymore", T::TYPE, id,); return true; } else { log::info!( diff --git a/wgpu-core/src/track/texture.rs b/wgpu-core/src/track/texture.rs index a90888a86d..146d0970cd 100644 --- a/wgpu-core/src/track/texture.rs +++ b/wgpu-core/src/track/texture.rs @@ -19,21 +19,22 @@ * will treat the contents as junk. !*/ -use super::{range::RangedStates, PendingTransition}; +use super::{range::RangedStates, PendingTransition, PendingTransitionList}; use crate::{ hal_api::HalApi, id::{TextureId, TypedId}, - resource::{Resource, Texture}, + resource::{Resource, Texture, TextureInner}, track::{ invalid_resource_state, skip_barrier, ResourceMetadata, ResourceMetadataProvider, ResourceUses, UsageConflict, }, }; -use hal::{TextureBarrier, TextureUses}; +use hal::TextureUses; use arrayvec::ArrayVec; use naga::FastHashMap; +use parking_lot::RwLockReadGuard; use wgt::{strict_assert, strict_assert_eq}; use std::{borrow::Cow, iter, marker::PhantomData, ops::Range, sync::Arc, vec::Drain}; @@ -437,13 +438,24 @@ impl TextureTracker { self.metadata.owned_resources() } - /// Drains all currently pending transitions. - pub fn drain_transitions(&mut self) -> impl Iterator> { - let texture_barriers = self.temp.drain(..).map(|pending| { - let tex = unsafe { self.metadata.get_resource_unchecked(pending.id as _) }; - pending.into_hal(tex) - }); - texture_barriers + /// Drain all currently pending transitions. + pub fn drain_transitions<'a>( + &'a mut self, + ) -> ( + PendingTransitionList, + Vec>>>, + ) { + let mut textures = Vec::new(); + let transitions = self + .temp + .drain(..) + .map(|pending| { + let tex = unsafe { self.metadata.get_resource_unchecked(pending.id as _) }; + textures.push(tex.inner()); + pending + }) + .collect(); + (transitions, textures) } /// Inserts a single texture and a state into the resource tracker. @@ -707,6 +719,7 @@ impl TextureTracker { self.start_set.complex.remove(&index); self.end_set.complex.remove(&index); self.metadata.remove(index); + log::info!("Texture {:?} is not tracked anymore", id,); return true; } else { log::info!( diff --git a/wgpu/src/backend/direct.rs b/wgpu/src/backend/direct.rs index 2273e4f884..12a057be92 100644 --- a/wgpu/src/backend/direct.rs +++ b/wgpu/src/backend/direct.rs @@ -1505,10 +1505,12 @@ impl crate::Context for Context { MapMode::Read => wgc::device::HostMap::Read, MapMode::Write => wgc::device::HostMap::Write, }, - callback: wgc::resource::BufferMapCallback::from_rust(Box::new(|status| { - let res = status.map_err(|_| crate::BufferAsyncError); - callback(res); - })), + callback: Some(wgc::resource::BufferMapCallback::from_rust(Box::new( + |status| { + let res = status.map_err(|_| crate::BufferAsyncError); + callback(res); + }, + ))), }; let global = &self.0;