diff --git a/wgpu-core/src/device/queue.rs b/wgpu-core/src/device/queue.rs index 45a396fc1dc..5f44af58750 100644 --- a/wgpu-core/src/device/queue.rs +++ b/wgpu-core/src/device/queue.rs @@ -22,8 +22,9 @@ use crate::{ resource_log, track, FastHashMap, SubmissionIndex, }; -use hal::{CommandEncoder as _, Device as _, Queue as _, RawSet as _}; +use hal::{CommandEncoder as _, Device as _, Queue as _}; use parking_lot::Mutex; +use smallvec::SmallVec; use std::{ iter, mem, ptr, @@ -227,20 +228,6 @@ impl PendingWrites { .push(TempResource::StagingBuffer(buffer)); } - #[must_use] - fn pre_submit(&mut self) -> Option<&A::CommandBuffer> { - self.dst_buffers.clear(); - self.dst_textures.clear(); - if self.is_active { - let cmd_buf = unsafe { self.command_encoder.end_encoding().unwrap() }; - self.is_active = false; - self.executing_command_buffers.push(cmd_buf); - self.executing_command_buffers.last() - } else { - None - } - } - #[must_use] fn post_submit( &mut self, @@ -1116,15 +1103,12 @@ impl Global { + 1; let mut active_executions = Vec::new(); - // SAFETY: We're constructing this during the submission phase, - // where all resources it uses are guaranteed to outlive this - // short-lived set. - let mut submit_surface_textures = A::SubmitSurfaceTextureSet::new(); - let mut used_surface_textures = track::TextureUsageScope::new(); let snatch_guard = device.snatchable_lock.read(); + let mut submit_surface_textures = SmallVec::<[_; 2]>::new(); + { let mut command_buffer_guard = hub.command_buffers.write(); @@ -1231,9 +1215,7 @@ impl Global { has_work.store(true, Ordering::Relaxed); if let Some(raw) = raw { - unsafe { - submit_surface_textures.insert(raw); - } + submit_surface_textures.push(raw); } true @@ -1434,9 +1416,7 @@ impl Global { has_work.store(true, Ordering::Relaxed); if let Some(raw) = raw { - unsafe { - submit_surface_textures.insert(raw); - } + submit_surface_textures.push(raw); } unsafe { @@ -1468,8 +1448,18 @@ impl Global { } } - let refs = pending_writes - .pre_submit() + pending_writes.dst_buffers.clear(); + + let refs = if pending_writes.is_active { + let cmd_buf = unsafe { pending_writes.command_encoder.end_encoding().unwrap() }; + pending_writes.is_active = false; + pending_writes.executing_command_buffers.push(cmd_buf); + pending_writes.executing_command_buffers.last() + } else { + None + }; + + let refs = refs .into_iter() .chain( active_executions @@ -1487,6 +1477,9 @@ impl Global { .map_err(DeviceError::from)?; } + // We clear this here, since dst_textures is in use during the call to submit. + pending_writes.dst_textures.clear(); + profiling::scope!("cleanup"); if let Some(pending_execution) = pending_writes.post_submit( device.command_allocator.lock().as_mut().unwrap(), diff --git a/wgpu-core/src/resource.rs b/wgpu-core/src/resource.rs index 0d337d12c00..85073842fcb 100644 --- a/wgpu-core/src/resource.rs +++ b/wgpu-core/src/resource.rs @@ -399,7 +399,7 @@ impl Drop for Buffer { } impl Buffer { - pub(crate) fn raw(&self, guard: &SnatchGuard) -> Option<&A::Buffer> { + pub(crate) fn raw<'snatch>(&self, guard: &'snatch SnatchGuard) -> Option<&'snatch A::Buffer> { self.raw.get(guard) } diff --git a/wgpu-core/src/snatch.rs b/wgpu-core/src/snatch.rs index 54983120c82..eba4b3f7a8f 100644 --- a/wgpu-core/src/snatch.rs +++ b/wgpu-core/src/snatch.rs @@ -25,8 +25,15 @@ impl Snatchable { } } - /// Get read access to the value. Requires a the snatchable lock's read guard. - pub fn get(&self, _guard: &SnatchGuard) -> Option<&T> { + /// Get read access to the value. Requires a the snatchable lock's read + /// guard. + /// + /// Note that this returns a reference with a lifetime matching + /// `SnatchGuard`, which ensures that the returned reference doesn't outlive + /// the guard it's indirectly projected from. It is very important that the + /// resource doesn't use the incorrect snatch guard, since that could result + /// in the resource being modified while it's in use. + pub fn get<'snatch>(&self, _guard: &'snatch SnatchGuard) -> Option<&'snatch T> { unsafe { (*self.value.get()).as_ref() } } diff --git a/wgpu-hal/examples/halmark/main.rs b/wgpu-hal/examples/halmark/main.rs index 22df88e3203..a16887be42e 100644 --- a/wgpu-hal/examples/halmark/main.rs +++ b/wgpu-hal/examples/halmark/main.rs @@ -3,8 +3,7 @@ extern crate wgpu_hal as hal; use hal::{ - Adapter as _, CommandEncoder as _, Device as _, Instance as _, Queue as _, RawSet as _, - Surface as _, + Adapter as _, CommandEncoder as _, Device as _, Instance as _, Queue as _, Surface as _, }; use raw_window_handle::{HasDisplayHandle, HasWindowHandle}; use winit::{ @@ -490,7 +489,7 @@ impl Example { let fence = unsafe { let mut fence = device.create_fence().unwrap(); let init_cmd = cmd_encoder.end_encoding().unwrap(); - let surface_textures = A::SubmitSurfaceTextureSet::new(); + let surface_textures = Vec::new(); queue .submit( &[&init_cmd], @@ -547,7 +546,7 @@ impl Example { unsafe { { let ctx = &mut self.contexts[self.context_index]; - let surface_textures = A::SubmitSurfaceTextureSet::new(); + let surface_textures = Vec::new(); self.queue .submit( &[], @@ -740,8 +739,8 @@ impl Example { } else { None }; - let mut surface_textures = A::SubmitSurfaceTextureSet::new(); - surface_textures.insert(&surface_tex); + let mut surface_textures = Vec::new(); + surface_textures.push(&surface_tex); self.queue .submit(&[&cmd_buf], &surface_textures, fence_param) .unwrap(); diff --git a/wgpu-hal/examples/ray-traced-triangle/main.rs b/wgpu-hal/examples/ray-traced-triangle/main.rs index dcdbba156cf..6a6c6bc6b52 100644 --- a/wgpu-hal/examples/ray-traced-triangle/main.rs +++ b/wgpu-hal/examples/ray-traced-triangle/main.rs @@ -1,8 +1,7 @@ extern crate wgpu_hal as hal; use hal::{ - Adapter as _, CommandEncoder as _, Device as _, Instance as _, Queue as _, RawSet as _, - Surface as _, + Adapter as _, CommandEncoder as _, Device as _, Instance as _, Queue as _, Surface as _, }; use raw_window_handle::{HasDisplayHandle, HasWindowHandle}; @@ -755,7 +754,7 @@ impl Example { let fence = unsafe { let mut fence = device.create_fence().unwrap(); let init_cmd = cmd_encoder.end_encoding().unwrap(); - let surface_textures = A::SubmitSurfaceTextureSet::new(); + let surface_textures = Vec::new(); queue .submit( &[&init_cmd], @@ -966,8 +965,8 @@ impl Example { } else { None }; - let mut surface_textures = A::SubmitSurfaceTextureSet::new(); - surface_textures.insert(&surface_tex); + let mut surface_textures = Vec::new(); + surface_textures.push(&surface_tex); self.queue .submit(&[&cmd_buf], &surface_textures, fence_param) .unwrap(); @@ -1008,7 +1007,7 @@ impl Example { unsafe { { let ctx = &mut self.contexts[self.context_index]; - let surface_textures = A::SubmitSurfaceTextureSet::new(); + let surface_textures = Vec::new(); self.queue .submit( &[], diff --git a/wgpu-hal/src/dx12/mod.rs b/wgpu-hal/src/dx12/mod.rs index d3875649c12..e9343e830f9 100644 --- a/wgpu-hal/src/dx12/mod.rs +++ b/wgpu-hal/src/dx12/mod.rs @@ -84,7 +84,6 @@ impl crate::Api for Api { type ComputePipeline = ComputePipeline; type AccelerationStructure = AccelerationStructure; - type SubmitSurfaceTextureSet = (); } // Limited by D3D12's root signature size of 64. Each element takes 1 or 2 entries. @@ -878,7 +877,7 @@ impl crate::Queue for Queue { unsafe fn submit( &self, command_buffers: &[&CommandBuffer], - _surface_textures: &(), + _surface_textures: &[&Texture], signal_fence: Option<(&mut Fence, crate::FenceValue)>, ) -> Result<(), crate::DeviceError> { let mut temp_lists = self.temp_lists.lock(); diff --git a/wgpu-hal/src/empty.rs b/wgpu-hal/src/empty.rs index 253989b9cfa..d58e779b96a 100644 --- a/wgpu-hal/src/empty.rs +++ b/wgpu-hal/src/empty.rs @@ -37,7 +37,6 @@ impl crate::Api for Api { type ShaderModule = Resource; type RenderPipeline = Resource; type ComputePipeline = Resource; - type SubmitSurfaceTextureSet = (); } impl crate::Instance for Context { @@ -105,7 +104,7 @@ impl crate::Queue for Context { unsafe fn submit( &self, command_buffers: &[&Resource], - surface_textures: &(), + surface_textures: &[&Resource], signal_fence: Option<(&mut Resource, crate::FenceValue)>, ) -> DeviceResult<()> { Ok(()) diff --git a/wgpu-hal/src/gles/mod.rs b/wgpu-hal/src/gles/mod.rs index 97e2036570f..701b13fb572 100644 --- a/wgpu-hal/src/gles/mod.rs +++ b/wgpu-hal/src/gles/mod.rs @@ -161,7 +161,6 @@ impl crate::Api for Api { type ShaderModule = ShaderModule; type RenderPipeline = RenderPipeline; type ComputePipeline = ComputePipeline; - type SubmitSurfaceTextureSet = (); } bitflags::bitflags! { diff --git a/wgpu-hal/src/gles/queue.rs b/wgpu-hal/src/gles/queue.rs index 1d51a591761..6ec553bd296 100644 --- a/wgpu-hal/src/gles/queue.rs +++ b/wgpu-hal/src/gles/queue.rs @@ -1748,7 +1748,7 @@ impl crate::Queue for super::Queue { unsafe fn submit( &self, command_buffers: &[&super::CommandBuffer], - _surface_textures: &(), + _surface_textures: &[&super::Texture], signal_fence: Option<(&mut super::Fence, crate::FenceValue)>, ) -> Result<(), crate::DeviceError> { let shared = Arc::clone(&self.shared); diff --git a/wgpu-hal/src/lib.rs b/wgpu-hal/src/lib.rs index 1a462c54ad2..fd4d9edaeea 100644 --- a/wgpu-hal/src/lib.rs +++ b/wgpu-hal/src/lib.rs @@ -214,7 +214,6 @@ pub trait Api: Clone + fmt::Debug + Sized { type ComputePipeline: fmt::Debug + WasmNotSendSync; type AccelerationStructure: fmt::Debug + WasmNotSendSync + 'static; - type SubmitSurfaceTextureSet: RawSet; } pub trait Instance: Sized + WasmNotSendSync { @@ -419,7 +418,7 @@ pub trait Queue: WasmNotSendSync { unsafe fn submit( &self, command_buffers: &[&A::CommandBuffer], - surface_textures: &A::SubmitSurfaceTextureSet, + surface_textures: &[&A::SurfaceTexture], signal_fence: Option<(&mut A::Fence, FenceValue)>, ) -> Result<(), DeviceError>; unsafe fn present( @@ -722,25 +721,6 @@ bitflags!( } ); -pub trait RawSet { - /// Construct a new set unsafely. - fn new() -> Self; - - /// Insert a value into the raw set. - /// - /// The caller is responsible for ensuring that the set doesn't outlive the - /// values it contains. The exact requirements depends on which set is being - /// constructed. - unsafe fn insert(&mut self, value: &T); -} - -/// Provide a default implementation for () for backends which do not need to -/// track any raw resources so they can easily be stubbed out. -impl RawSet for () { - fn new() -> Self {} - unsafe fn insert(&mut self, _: &T) {} -} - bitflags!( /// Texture format capability flags. #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] diff --git a/wgpu-hal/src/metal/mod.rs b/wgpu-hal/src/metal/mod.rs index d11fd6a7b24..298f60faac9 100644 --- a/wgpu-hal/src/metal/mod.rs +++ b/wgpu-hal/src/metal/mod.rs @@ -68,7 +68,6 @@ impl crate::Api for Api { type ComputePipeline = ComputePipeline; type AccelerationStructure = AccelerationStructure; - type SubmitSurfaceTextureSet = (); } pub struct Instance { @@ -369,7 +368,7 @@ impl crate::Queue for Queue { unsafe fn submit( &self, command_buffers: &[&CommandBuffer], - _surface_textures: &(), + _surface_textures: &[&SurfaceTexture], signal_fence: Option<(&mut Fence, crate::FenceValue)>, ) -> Result<(), crate::DeviceError> { objc::rc::autoreleasepool(|| { diff --git a/wgpu-hal/src/vulkan/mod.rs b/wgpu-hal/src/vulkan/mod.rs index ac7abf948b2..787ebd72677 100644 --- a/wgpu-hal/src/vulkan/mod.rs +++ b/wgpu-hal/src/vulkan/mod.rs @@ -48,9 +48,6 @@ use ash::{ vk, }; use parking_lot::{Mutex, RwLock}; -use smallvec::SmallVec; - -use crate::RawSet; const MILLIS_TO_NANOS: u64 = 1_000_000; const MAX_TOTAL_ATTACHMENTS: usize = crate::MAX_COLOR_ATTACHMENTS * 2 + 1; @@ -83,23 +80,6 @@ impl crate::Api for Api { type ShaderModule = ShaderModule; type RenderPipeline = RenderPipeline; type ComputePipeline = ComputePipeline; - type SubmitSurfaceTextureSet = SubmitSurfaceTextureSet; -} - -pub struct SubmitSurfaceTextureSet { - semaphores: SmallVec<[vk::Semaphore; 2]>, -} - -impl RawSet for SubmitSurfaceTextureSet { - fn new() -> Self { - Self { - semaphores: SmallVec::new(), - } - } - - unsafe fn insert(&mut self, texture: &SurfaceTexture) { - self.semaphores.push(texture.wait_semaphore); - } } struct DebugUtils { @@ -610,7 +590,7 @@ impl crate::Queue for Queue { unsafe fn submit( &self, command_buffers: &[&CommandBuffer], - surface_textures: &SubmitSurfaceTextureSet, + surface_textures: &[&SurfaceTexture], signal_fence: Option<(&mut Fence, crate::FenceValue)>, ) -> Result<(), crate::DeviceError> { let mut fence_raw = vk::Fence::null(); @@ -620,9 +600,9 @@ impl crate::Queue for Queue { let mut signal_semaphores = ArrayVec::<_, 2>::new(); let mut signal_values = ArrayVec::<_, 2>::new(); - for &wait in &surface_textures.semaphores { + for &surface_texture in surface_textures { wait_stage_masks.push(vk::PipelineStageFlags::TOP_OF_PIPE); - wait_semaphores.push(wait); + wait_semaphores.push(surface_texture.wait_semaphore); } let old_index = self.relay_index.load(Ordering::Relaxed);