mirror of
https://github.com/gfx-rs/wgpu.git
synced 2026-04-22 03:02:01 -04:00
Remove the outdated frame concept in favor of aggressive swapchain re-creation
This commit is contained in:
@@ -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
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user