diff --git a/wgpu-core/src/command/mod.rs b/wgpu-core/src/command/mod.rs index 4f373c22b8..877ddb17c8 100644 --- a/wgpu-core/src/command/mod.rs +++ b/wgpu-core/src/command/mod.rs @@ -136,7 +136,7 @@ pub struct CommandBuffer { pub(crate) device_id: Stored, pub(crate) life_guard: LifeGuard, pub(crate) trackers: TrackerSet, - pub(crate) used_swap_chain: Option<(Stored, B::Framebuffer)>, + pub(crate) used_swap_chain: Option<(Stored, B::Framebuffer)>, pub(crate) features: Features, } @@ -263,13 +263,17 @@ impl Global { ) -> id::CommandBufferId { let hub = B::hub(self); let mut token = Token::root(); + let (swap_chain_guard, mut token) = hub.swap_chains.read(&mut token); //TODO: actually close the last recorded command buffer let (mut comb_guard, _) = hub.command_buffers.write(&mut token); let comb = &mut comb_guard[encoder_id]; assert!(comb.is_recording); comb.is_recording = false; // stop tracking the swapchain image, if used - if let Some((ref view_id, _)) = comb.used_swap_chain { + if let Some((ref sc_id, _)) = comb.used_swap_chain { + let view_id = swap_chain_guard[sc_id.value].acquired_view_id + .as_ref() + .expect("Used swap chain frame has already presented"); comb.trackers.views.remove(view_id.value); } log::debug!("Command buffer {:?} {:#?}", encoder_id, comb.trackers); diff --git a/wgpu-core/src/command/render.rs b/wgpu-core/src/command/render.rs index 29a3609a09..c7b43696d5 100644 --- a/wgpu-core/src/command/render.rs +++ b/wgpu-core/src/command/render.rs @@ -325,7 +325,7 @@ impl Global { let base_trackers = &cmb.trackers; let mut extent = None; - let mut used_swap_chain_image = None::>; + let mut used_swap_chain = None::>; let sample_count = color_attachments .get(0) @@ -430,15 +430,12 @@ impl Global { }; old_layout .. hal::image::Layout::ColorAttachmentOptimal } - TextureViewInner::SwapChain { .. } => { - if let Some((ref view_id, _)) = cmb.used_swap_chain { - assert_eq!(view_id.value, at.attachment); + TextureViewInner::SwapChain { ref source_id, .. } => { + if let Some((ref sc_id, _)) = cmb.used_swap_chain { + assert_eq!(source_id.value, sc_id.value); } else { - assert!(used_swap_chain_image.is_none()); - used_swap_chain_image = Some(Stored { - value: at.attachment, - ref_count: view.life_guard.add_ref(), - }); + assert!(used_swap_chain.is_none()); + used_swap_chain = Some(source_id.clone()); } let end = hal::image::Layout::Present; @@ -490,15 +487,12 @@ impl Global { }; old_layout .. hal::image::Layout::ColorAttachmentOptimal } - TextureViewInner::SwapChain { .. } => { - if let Some((ref view_id, _)) = cmb.used_swap_chain { - assert_eq!(view_id.value, resolve_target); + TextureViewInner::SwapChain { ref source_id, .. } => { + if let Some((ref sc_id, _)) = cmb.used_swap_chain { + assert_eq!(source_id.value, sc_id.value); } else { - assert!(used_swap_chain_image.is_none()); - used_swap_chain_image = Some(Stored { - value: resolve_target, - ref_count: view.life_guard.add_ref(), - }); + assert!(used_swap_chain.is_none()); + used_swap_chain = Some(source_id.clone()); } let end = hal::image::Layout::Present; @@ -624,8 +618,8 @@ impl Global { depth_stencil: depth_stencil_attachment.map(|at| at.attachment), }; - let framebuffer = match used_swap_chain_image.take() { - Some(view_id) => { + let framebuffer = match used_swap_chain.take() { + Some(sc_id) => { assert!(cmb.used_swap_chain.is_none()); // Always create a new framebuffer and delete it after presentation. let attachments = fb_key.all().map(|&id| match view_guard[id].inner { @@ -638,7 +632,7 @@ impl Global { .create_framebuffer(&render_pass, attachments, extent.unwrap()) .unwrap() }; - cmb.used_swap_chain = Some((view_id, framebuffer)); + cmb.used_swap_chain = Some((sc_id, framebuffer)); &mut cmb.used_swap_chain.as_mut().unwrap().1 } None => { diff --git a/wgpu-core/src/device/mod.rs b/wgpu-core/src/device/mod.rs index 4b5f35846b..26272748c9 100644 --- a/wgpu-core/src/device/mod.rs +++ b/wgpu-core/src/device/mod.rs @@ -31,6 +31,7 @@ use hal::{ use parking_lot::{Mutex, MutexGuard}; use rendy_descriptor::{DescriptorAllocator, DescriptorRanges}; use rendy_memory::{Block, Heaps}; +use smallvec::SmallVec; use std::{ collections::hash_map::Entry, @@ -668,7 +669,7 @@ impl> Global { texture.life_guard.ref_count.take(); texture.device_id.value }; - + let (device_guard, mut token) = hub.devices.read(&mut token); device_guard[device_id] .lock_life(&mut token) @@ -1309,16 +1310,16 @@ impl> Global { .submission_index .fetch_add(1, Ordering::Relaxed); - let (swap_chain_guard, mut token) = hub.swap_chains.read(&mut token); + let (mut swap_chain_guard, mut token) = hub.swap_chains.write(&mut token); let (mut command_buffer_guard, mut token) = hub.command_buffers.write(&mut token); let (bind_group_guard, mut token) = hub.bind_groups.read(&mut token); let (buffer_guard, mut token) = hub.buffers.read(&mut token); let (texture_guard, mut token) = hub.textures.read(&mut token); - let (mut texture_view_guard, mut token) = hub.texture_views.write(&mut token); + let (texture_view_guard, mut token) = hub.texture_views.read(&mut token); let (sampler_guard, _) = hub.samplers.read(&mut token); //Note: locking the trackers has to be done after the storages - let mut signal_semaphores = Vec::new(); + let mut signal_swapchain_semaphores = SmallVec::<[_; 1]>::new(); let mut trackers = device.trackers.lock(); //TODO: if multiple command buffers are submitted, we can re-use the last @@ -1329,21 +1330,12 @@ impl> Global { for &cmb_id in command_buffer_ids { let comb = &mut command_buffer_guard[cmb_id]; - if let Some((view_id, fbo)) = comb.used_swap_chain.take() { - match texture_view_guard[view_id.value].inner { - resource::TextureViewInner::Native { .. } => unreachable!(), - resource::TextureViewInner::SwapChain { - ref source_id, - ref mut framebuffers, - .. - } => { - if framebuffers.is_empty() { - let sem = &swap_chain_guard[source_id.value].semaphore; - signal_semaphores.push(sem); - } - framebuffers.push(fbo); - } - }; + if let Some((sc_id, fbo)) = comb.used_swap_chain.take() { + let sc = &mut swap_chain_guard[sc_id.value]; + if sc.acquired_framebuffers.is_empty() { + signal_swapchain_semaphores.push(sc_id.value); + } + sc.acquired_framebuffers.push(fbo); } // optimize the tracked states @@ -1405,12 +1397,15 @@ impl> Global { // now prepare the GPU submission let fence = device.raw.create_fence(false).unwrap(); - let submission = hal::queue::Submission::<_, _, Vec<&B::Semaphore>> { + let submission = hal::queue::Submission { command_buffers: command_buffer_ids .iter() .flat_map(|&cmb_id| &command_buffer_guard[cmb_id].raw), wait_semaphores: Vec::new(), - signal_semaphores, + signal_semaphores: signal_swapchain_semaphores + .into_iter() + .map(|sc_id| &swap_chain_guard[sc_id].semaphore), + }; unsafe { @@ -1853,6 +1848,7 @@ impl> Global { num_frames, semaphore: device.raw.create_semaphore().unwrap(), acquired_view_id: None, + acquired_framebuffers: Vec::new(), }; swap_chain_guard.insert(sc_id, swap_chain); sc_id diff --git a/wgpu-core/src/hub.rs b/wgpu-core/src/hub.rs index 208ed5ad97..285865c1c5 100644 --- a/wgpu-core/src/hub.rs +++ b/wgpu-core/src/hub.rs @@ -165,6 +165,7 @@ impl Access> for Surface {} impl Access> for Root {} impl Access> for Surface {} impl Access> for Adapter {} +impl Access> for Root {} impl Access> for Device {} impl Access> for Root {} impl Access> for Device {} diff --git a/wgpu-core/src/resource.rs b/wgpu-core/src/resource.rs index 1456fbb449..083a4240b7 100644 --- a/wgpu-core/src/resource.rs +++ b/wgpu-core/src/resource.rs @@ -14,7 +14,6 @@ use crate::{ use hal; use rendy_memory::MemoryBlock; -use smallvec::SmallVec; #[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; @@ -307,7 +306,6 @@ pub(crate) enum TextureViewInner { SwapChain { image: >::SwapchainImage, source_id: Stored, - framebuffers: SmallVec<[B::Framebuffer; 1]>, }, } diff --git a/wgpu-core/src/swap_chain.rs b/wgpu-core/src/swap_chain.rs index b760de378a..90a5e0b535 100644 --- a/wgpu-core/src/swap_chain.rs +++ b/wgpu-core/src/swap_chain.rs @@ -45,8 +45,6 @@ use crate::{ use hal::{self, device::Device as _, queue::CommandQueue as _, window::PresentationSurface as _}; -use smallvec::SmallVec; - const FRAME_TIMEOUT_MS: u64 = 1000; pub const DESIRED_NUM_FRAMES: u32 = 3; @@ -59,6 +57,7 @@ pub struct SwapChain { pub(crate) num_frames: hal::window::SwapImageIndex, pub(crate) semaphore: B::Semaphore, pub(crate) acquired_view_id: Option>, + pub(crate) acquired_framebuffers: Vec, } #[repr(C)] @@ -169,7 +168,6 @@ impl> Global { value: swap_chain_id, ref_count: sc.life_guard.add_ref(), }, - framebuffers: SmallVec::new(), }, format: sc.desc.format, extent: hal::image::Extent { @@ -218,13 +216,9 @@ impl> Global { .take() .expect("Swap chain image is not acquired"); let (view, _) = hub.texture_views.unregister(view_id.value, &mut token); - let (image, framebuffers) = match view.inner { + let image = match view.inner { resource::TextureViewInner::Native { .. } => unreachable!(), - resource::TextureViewInner::SwapChain { - image, - framebuffers, - .. - } => (image, framebuffers), + resource::TextureViewInner::SwapChain { image, .. } => image, }; let err = unsafe { @@ -235,7 +229,7 @@ impl> Global { log::warn!("present failed: {:?}", e); } - for fbo in framebuffers { + for fbo in sc.acquired_framebuffers.drain(..) { unsafe { device.raw.destroy_framebuffer(fbo); }