Remove the outdated frame concept in favor of aggressive swapchain re-creation

This commit is contained in:
Dzmitry Malyshau
2019-02-22 18:42:14 -05:00
parent 9df7cc4a8e
commit cfe3da1c6f
2 changed files with 63 additions and 77 deletions

View File

@@ -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<resource::Texture<back::Backend>> {
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<resource::Texture<back::Backend>>,
) {
@@ -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
}

View File

@@ -45,26 +45,20 @@ pub(crate) struct Frame<B: hal::Backend> {
pub comb: hal::command::CommandBuffer<B, hal::General, hal::command::MultiShot>,
}
pub struct OutdatedFrame {
pub(crate) texture_id: Stored<TextureId>,
pub(crate) view_id: Stored<TextureViewId>,
}
const OUTDATED_IMAGE_INDEX: u32 = !0;
//TODO: does it need a ref-counted lifetime?
pub struct SwapChain<B: hal::Backend> {
pub(crate) raw: B::Swapchain,
pub(crate) device_id: Stored<DeviceId>,
pub(crate) desc: SwapChainDescriptor,
pub(crate) frames: Vec<Frame<B>>,
pub(crate) acquired: Vec<hal::SwapImageIndex>,
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<B, hal::General>,
}
#[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);