From cfe3da1c6f4e30af0b0239a58cd793450044dca6 Mon Sep 17 00:00:00 2001 From: Dzmitry Malyshau Date: Fri, 22 Feb 2019 18:42:14 -0500 Subject: [PATCH] Remove the outdated frame concept in favor of aggressive swapchain re-creation --- wgpu-native/src/device.rs | 37 +++--------- wgpu-native/src/swap_chain.rs | 103 ++++++++++++++++++---------------- 2 files changed, 63 insertions(+), 77 deletions(-) diff --git a/wgpu-native/src/device.rs b/wgpu-native/src/device.rs index fad6eb6342..0bee3e49d3 100644 --- a/wgpu-native/src/device.rs +++ b/wgpu-native/src/device.rs @@ -22,7 +22,7 @@ use hal::{self, Device as _Device, Surface as _Surface, }; -use log::trace; +use log::{info, trace}; //use rendy_memory::{allocator, Config, Heaps}; use parking_lot::{Mutex}; @@ -1343,8 +1343,9 @@ pub fn device_create_swap_chain( device_id: DeviceId, surface_id: SurfaceId, desc: &swap_chain::SwapChainDescriptor, - outdated: swap_chain::OutdatedFrame, ) -> Vec> { + info!("creating swap chain {:?}", desc); + let device_guard = HUB.devices.read(); let device = device_guard.get(device_id); let mut surface_guard = HUB.surfaces.write(); @@ -1357,6 +1358,7 @@ pub fn device_create_swap_chain( surface.raw.compatibility(&adapter.physical_device) }; let num_frames = caps.image_count.start; //TODO: configure? + let usage = conv::map_texture_usage(desc.usage, hal::format::Aspects::COLOR); let config = hal::SwapchainConfig::new( desc.width, desc.height, @@ -1364,7 +1366,6 @@ pub fn device_create_swap_chain( num_frames, //TODO: configure? ); - let usage = conv::map_texture_usage(desc.usage, hal::format::Aspects::COLOR); if let Some(formats) = formats { assert!(formats.contains(&config.format), "Requested format {:?} is not in supported list: {:?}", @@ -1380,9 +1381,6 @@ pub fn device_create_swap_chain( let (old_raw, sem_available, command_pool) = match surface.swap_chain.take() { Some(mut old) => { assert_eq!(old.device_id.value, device_id); - let mut destroyed = device.destroyed.lock(); - destroyed.add(ResourceId::Texture(old.outdated.texture_id.value), old.outdated.texture_id.ref_count); - destroyed.add(ResourceId::TextureView(old.outdated.view_id.value), old.outdated.view_id.ref_count); unsafe { old.command_pool.reset() }; @@ -1417,10 +1415,10 @@ pub fn device_create_swap_chain( value: device_id, ref_count: device.life_guard.ref_count.clone(), }, + desc: desc.clone(), frames: Vec::with_capacity(num_frames as usize), acquired: Vec::with_capacity(1), //TODO: get it from gfx-hal? sem_available, - outdated, command_pool, }); @@ -1451,7 +1449,7 @@ pub fn device_create_swap_chain( } #[cfg(feature = "local")] -fn swap_chain_populate_textures( +pub fn swap_chain_populate_textures( swap_chain_id: SwapChainId, textures: Vec>, ) { @@ -1531,28 +1529,7 @@ pub extern "C" fn wgpu_device_create_swap_chain( surface_id: SurfaceId, desc: &swap_chain::SwapChainDescriptor, ) -> SwapChainId { - let outdated = { - let outdated_texture = device_create_texture(device_id, &desc.to_texture_desc()); - let texture_id = Stored { - ref_count: outdated_texture.life_guard.ref_count.clone(), - value: HUB.textures.register(outdated_texture), - }; - device_track_texture(device_id, texture_id.value, texture_id.ref_count.clone()); - - let outdated_view = texture_create_default_view(texture_id.value); - let view_id = Stored { - ref_count: outdated_view.life_guard.ref_count.clone(), - value: HUB.texture_views.register(outdated_view), - }; - device_track_view(texture_id.value, view_id.value, view_id.ref_count.clone()); - - swap_chain::OutdatedFrame { - texture_id, - view_id, - } - }; - - let textures = device_create_swap_chain(device_id, surface_id, desc, outdated); + let textures = device_create_swap_chain(device_id, surface_id, desc); swap_chain_populate_textures(surface_id, textures); surface_id } diff --git a/wgpu-native/src/swap_chain.rs b/wgpu-native/src/swap_chain.rs index ea44857f8f..e505cf9247 100644 --- a/wgpu-native/src/swap_chain.rs +++ b/wgpu-native/src/swap_chain.rs @@ -45,26 +45,20 @@ pub(crate) struct Frame { pub comb: hal::command::CommandBuffer, } -pub struct OutdatedFrame { - pub(crate) texture_id: Stored, - pub(crate) view_id: Stored, -} - -const OUTDATED_IMAGE_INDEX: u32 = !0; //TODO: does it need a ref-counted lifetime? - pub struct SwapChain { pub(crate) raw: B::Swapchain, pub(crate) device_id: Stored, + pub(crate) desc: SwapChainDescriptor, pub(crate) frames: Vec>, pub(crate) acquired: Vec, pub(crate) sem_available: B::Semaphore, - pub(crate) outdated: OutdatedFrame, #[cfg_attr(not(feature = "local"), allow(dead_code))] //TODO: remove pub(crate) command_pool: hal::CommandPool, } #[repr(C)] +#[derive(Clone, Debug)] pub struct SwapChainDescriptor { pub usage: resource::TextureUsageFlags, pub format: resource::TextureFormat, @@ -98,51 +92,72 @@ pub struct SwapChainOutput { pub extern "C" fn wgpu_swap_chain_get_next_texture( swap_chain_id: SwapChainId, ) -> SwapChainOutput { + let (image_index, device_id, descriptor) = { + let mut surface_guard = HUB.surfaces.write(); + let swap_chain = surface_guard + .get_mut(swap_chain_id) + .swap_chain + .as_mut() + .unwrap(); + let sync = hal::FrameSync::Semaphore(&swap_chain.sem_available); + let result = unsafe { + swap_chain.raw.acquire_image(!0, sync) + }; + (result.ok(), swap_chain.device_id.value, swap_chain.desc.clone()) + }; + + #[cfg(not(feature = "local"))] + let _ = descriptor; + #[cfg(feature = "local")] + { + use crate::device::{device_create_swap_chain, swap_chain_populate_textures}; + if image_index.is_none() { + warn!("acquire_image failed, re-creating"); + let textures = device_create_swap_chain(device_id, swap_chain_id, &descriptor); + swap_chain_populate_textures(swap_chain_id, textures); + } + } + let mut surface_guard = HUB.surfaces.write(); let swap_chain = surface_guard .get_mut(swap_chain_id) .swap_chain .as_mut() .unwrap(); + + let image_index = match image_index { + Some(index) => index, + None => { + let sync = hal::FrameSync::Semaphore(&swap_chain.sem_available); + unsafe { swap_chain.raw.acquire_image(!0, sync) }.unwrap() + } + }; + let device_guard = HUB.devices.read(); - let device = device_guard.get(swap_chain.device_id.value); + let device = device_guard.get(device_id); assert_ne!(swap_chain.acquired.len(), swap_chain.acquired.capacity(), "Unable to acquire any more swap chain images before presenting"); + swap_chain.acquired.push(image_index); - match { - let sync = hal::FrameSync::Semaphore(&swap_chain.sem_available); - unsafe { swap_chain.raw.acquire_image(!0, sync) } - } { - Ok(image_index) => { - swap_chain.acquired.push(image_index); - let frame = &mut swap_chain.frames[image_index as usize]; - unsafe { - device.raw.wait_for_fence(&frame.fence, !0).unwrap(); - } + let frame = &mut swap_chain.frames[image_index as usize]; + unsafe { + device.raw.wait_for_fence(&frame.fence, !0).unwrap(); + } + mem::swap(&mut frame.sem_available, &mut swap_chain.sem_available); - mem::swap(&mut frame.sem_available, &mut swap_chain.sem_available); + match HUB.textures + .read() + .get(frame.texture_id.value) + .swap_chain_link + { + Some(ref link) => *link.epoch.lock() += 1, + None => unreachable!(), + } - let texture_guard = HUB.textures.read(); - let texture = texture_guard.get(frame.texture_id.value); - match texture.swap_chain_link { - Some(ref link) => *link.epoch.lock() += 1, - None => unreachable!(), - } - - SwapChainOutput { - texture_id: frame.texture_id.value, - view_id: frame.view_id.value, - } - } - Err(e) => { - warn!("acquire_image failed: {:?}", e); - swap_chain.acquired.push(OUTDATED_IMAGE_INDEX); - SwapChainOutput { - texture_id: swap_chain.outdated.texture_id.value, - view_id: swap_chain.outdated.view_id.value, - } - } + SwapChainOutput { + texture_id: frame.texture_id.value, + view_id: frame.view_id.value, } } @@ -158,13 +173,7 @@ pub extern "C" fn wgpu_swap_chain_present( .unwrap(); let image_index = swap_chain.acquired.remove(0); - let frame = match swap_chain.frames.get_mut(image_index as usize) { - Some(frame) => frame, - None => { - assert_eq!(image_index, OUTDATED_IMAGE_INDEX); - return - } - }; + let frame = &mut swap_chain.frames[image_index as usize]; let mut device_guard = HUB.devices.write(); let device = device_guard.get_mut(swap_chain.device_id.value);