mirror of
https://github.com/gfx-rs/wgpu.git
synced 2025-02-17 01:12:41 +00:00
Handle frame acquisition failure internally
This commit is contained in:
parent
175e992149
commit
d37ecdf248
@ -1911,19 +1911,7 @@ pub fn device_create_swap_chain<B: GfxBackend>(
|
||||
suf.compatibility(&adapter.raw.physical_device)
|
||||
};
|
||||
let num_frames = *caps.image_count.start(); //TODO: configure?
|
||||
let usage = conv::map_texture_usage(desc.usage, hal::format::Aspects::COLOR);
|
||||
let mut config = hal::SwapchainConfig::new(
|
||||
desc.width,
|
||||
desc.height,
|
||||
conv::map_texture_format(desc.format),
|
||||
num_frames, //TODO: configure?
|
||||
);
|
||||
//TODO: check for supported
|
||||
config.composite_alpha = hal::window::CompositeAlpha::OPAQUE;
|
||||
config.present_mode = match desc.present_mode {
|
||||
swap_chain::PresentMode::NoVsync => hal::PresentMode::Immediate,
|
||||
swap_chain::PresentMode::Vsync => hal::PresentMode::Fifo,
|
||||
};
|
||||
let config = desc.to_hal(num_frames);
|
||||
|
||||
if let Some(formats) = formats {
|
||||
assert!(
|
||||
@ -1960,9 +1948,9 @@ pub fn device_create_swap_chain<B: GfxBackend>(
|
||||
);
|
||||
}
|
||||
unsafe { old.command_pool.reset(false) };
|
||||
(Some(old.raw), old.sem_available, old.command_pool)
|
||||
(old.raw, old.sem_available, old.command_pool)
|
||||
}
|
||||
_ => unsafe {
|
||||
None => unsafe {
|
||||
let sem_available = device.raw.create_semaphore().unwrap();
|
||||
let command_pool = device
|
||||
.raw
|
||||
@ -1979,7 +1967,7 @@ pub fn device_create_swap_chain<B: GfxBackend>(
|
||||
let suf = B::get_surface_mut(surface);
|
||||
device
|
||||
.raw
|
||||
.create_swapchain(suf, config.with_image_usage(usage), old_raw)
|
||||
.create_swapchain(suf, config, old_raw)
|
||||
.unwrap()
|
||||
};
|
||||
|
||||
@ -1988,7 +1976,11 @@ pub fn device_create_swap_chain<B: GfxBackend>(
|
||||
|
||||
let mut trackers = device.trackers.lock();
|
||||
let mut swap_chain = swap_chain::SwapChain {
|
||||
raw: raw_swap_chain,
|
||||
raw: Some(raw_swap_chain),
|
||||
surface_id: Stored {
|
||||
value: surface_id,
|
||||
ref_count: surface.ref_count.clone(),
|
||||
},
|
||||
device_id: Stored {
|
||||
value: device_id,
|
||||
ref_count: device.life_guard.ref_count.clone(),
|
||||
|
@ -8,10 +8,11 @@ use crate::{
|
||||
Backend,
|
||||
Device,
|
||||
DeviceId,
|
||||
RefCount,
|
||||
SwapChainId,
|
||||
};
|
||||
#[cfg(not(feature = "remote"))]
|
||||
use crate::{gfx_select, SurfaceId};
|
||||
use crate::{gfx_select, LifeGuard, SurfaceId};
|
||||
|
||||
#[cfg(not(feature = "remote"))]
|
||||
use bitflags::bitflags;
|
||||
@ -59,6 +60,7 @@ type GfxSurface<B> = <B as hal::Backend>::Surface;
|
||||
#[derive(Debug)]
|
||||
pub struct Surface {
|
||||
pub(crate) swap_chain: Option<SwapChainId>,
|
||||
pub(crate) ref_count: RefCount,
|
||||
pub(crate) vulkan: Option<GfxSurface<backend::Vulkan>>,
|
||||
#[cfg(any(target_os = "ios", target_os = "macos"))]
|
||||
pub(crate) metal: GfxSurface<backend::Metal>,
|
||||
@ -158,10 +160,12 @@ pub fn wgpu_create_surface(raw_handle: raw_window_handle::RawWindowHandle) -> Su
|
||||
use raw_window_handle::RawWindowHandle as Rwh;
|
||||
|
||||
let instance = &GLOBAL.instance;
|
||||
let ref_count = LifeGuard::new().ref_count;
|
||||
let surface = match raw_handle {
|
||||
#[cfg(target_os = "ios")]
|
||||
Rwh::IOS(h) => Surface {
|
||||
swap_chain: None,
|
||||
ref_count,
|
||||
vulkan: None,
|
||||
metal: instance
|
||||
.metal
|
||||
@ -170,6 +174,7 @@ pub fn wgpu_create_surface(raw_handle: raw_window_handle::RawWindowHandle) -> Su
|
||||
#[cfg(target_os = "macos")]
|
||||
Rwh::MacOS(h) => Surface {
|
||||
swap_chain: None,
|
||||
ref_count,
|
||||
vulkan: instance
|
||||
.vulkan
|
||||
.as_ref()
|
||||
@ -181,6 +186,7 @@ pub fn wgpu_create_surface(raw_handle: raw_window_handle::RawWindowHandle) -> Su
|
||||
#[cfg(all(unix, not(target_os = "ios"), not(target_os = "macos")))]
|
||||
Rwh::X11(h) => Surface {
|
||||
swap_chain: None,
|
||||
ref_count,
|
||||
vulkan: instance
|
||||
.vulkan
|
||||
.as_ref()
|
||||
@ -189,6 +195,7 @@ pub fn wgpu_create_surface(raw_handle: raw_window_handle::RawWindowHandle) -> Su
|
||||
#[cfg(all(unix, not(target_os = "ios"), not(target_os = "macos")))]
|
||||
Rwh::Wayland(h) => Surface {
|
||||
swap_chain: None,
|
||||
ref_count,
|
||||
vulkan: instance
|
||||
.vulkan
|
||||
.as_ref()
|
||||
@ -197,6 +204,7 @@ pub fn wgpu_create_surface(raw_handle: raw_window_handle::RawWindowHandle) -> Su
|
||||
#[cfg(windows)]
|
||||
Rwh::Windows(h) => Surface {
|
||||
swap_chain: None,
|
||||
ref_count,
|
||||
vulkan: instance
|
||||
.vulkan
|
||||
.as_ref()
|
||||
@ -235,6 +243,7 @@ pub extern "C" fn wgpu_create_surface_from_xlib(
|
||||
pub extern "C" fn wgpu_create_surface_from_metal_layer(layer: *mut std::ffi::c_void) -> SurfaceId {
|
||||
let surface = Surface {
|
||||
swap_chain: None,
|
||||
ref_count: LifeGuard::new().ref_count,
|
||||
vulkan: None, //TODO: currently requires `NSView`
|
||||
metal: GLOBAL
|
||||
.instance
|
||||
|
@ -8,9 +8,12 @@ use crate::{
|
||||
Extent3d,
|
||||
Stored,
|
||||
SwapChainId,
|
||||
SurfaceId,
|
||||
TextureId,
|
||||
TextureViewId,
|
||||
};
|
||||
#[cfg(not(feature = "remote"))]
|
||||
use crate::hub::GLOBAL;
|
||||
|
||||
use hal::{self, Device as _, Swapchain as _};
|
||||
use log::{trace, warn};
|
||||
@ -56,13 +59,16 @@ pub(crate) struct Frame<B: hal::Backend> {
|
||||
//TODO: does it need a ref-counted lifetime?
|
||||
#[derive(Debug)]
|
||||
pub struct SwapChain<B: hal::Backend> {
|
||||
pub(crate) raw: B::Swapchain,
|
||||
//Note: it's only an option because we may need to move it out
|
||||
// and then put a new swapchain back in.
|
||||
pub(crate) raw: Option<B::Swapchain>,
|
||||
pub(crate) surface_id: Stored<SurfaceId>,
|
||||
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,
|
||||
#[cfg_attr(not(not(feature = "remote")), allow(dead_code))] //TODO: remove
|
||||
#[cfg_attr(feature = "remote", allow(dead_code))] //TODO: remove
|
||||
pub(crate) command_pool: hal::CommandPool<B, hal::General>,
|
||||
}
|
||||
|
||||
@ -84,6 +90,23 @@ pub struct SwapChainDescriptor {
|
||||
}
|
||||
|
||||
impl SwapChainDescriptor {
|
||||
pub(crate) fn to_hal(&self, num_frames: u32) -> hal::window::SwapchainConfig {
|
||||
let mut config = hal::SwapchainConfig::new(
|
||||
self.width,
|
||||
self.height,
|
||||
conv::map_texture_format(self.format),
|
||||
num_frames,
|
||||
);
|
||||
//TODO: check for supported
|
||||
config.image_usage = conv::map_texture_usage(self.usage, hal::format::Aspects::COLOR);
|
||||
config.composite_alpha = hal::window::CompositeAlpha::OPAQUE;
|
||||
config.present_mode = match self.present_mode {
|
||||
PresentMode::NoVsync => hal::PresentMode::Immediate,
|
||||
PresentMode::Vsync => hal::PresentMode::Fifo,
|
||||
};
|
||||
config
|
||||
}
|
||||
|
||||
pub fn to_texture_desc(&self) -> resource::TextureDescriptor {
|
||||
resource::TextureDescriptor {
|
||||
size: Extent3d {
|
||||
@ -108,10 +131,14 @@ pub struct SwapChainOutput {
|
||||
pub view_id: TextureViewId,
|
||||
}
|
||||
|
||||
pub fn swap_chain_get_next_texture<B: GfxBackend>(swap_chain_id: SwapChainId) -> SwapChainOutput {
|
||||
pub fn swap_chain_get_next_texture<B: GfxBackend>(
|
||||
swap_chain_id: SwapChainId
|
||||
) -> SwapChainOutput {
|
||||
let hub = B::hub();
|
||||
let mut token = Token::root();
|
||||
|
||||
#[cfg(not(feature = "remote"))]
|
||||
let (mut surface_guard, mut token) = GLOBAL.surfaces.write(&mut token);
|
||||
let (device_guard, mut token) = hub.devices.read(&mut token);
|
||||
let (mut swap_chain_guard, _) = hub.swap_chains.write(&mut token);
|
||||
let swap_chain = &mut swap_chain_guard[swap_chain_id];
|
||||
@ -120,31 +147,73 @@ pub fn swap_chain_get_next_texture<B: GfxBackend>(swap_chain_id: SwapChainId) ->
|
||||
let image_index = unsafe {
|
||||
swap_chain
|
||||
.raw
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.acquire_image(!0, Some(&swap_chain.sem_available), None)
|
||||
}
|
||||
.ok();
|
||||
};
|
||||
|
||||
#[cfg(not(feature = "remote"))]
|
||||
{
|
||||
//use crate::device::device_create_swap_chain_textures}
|
||||
if image_index.is_none() {
|
||||
if image_index.is_err() {
|
||||
warn!("acquire_image failed, re-creating");
|
||||
unimplemented!()
|
||||
//let textures = device_create_swap_chain(device_id, swap_chain_id, &descriptor, &mut token);
|
||||
//swap_chain_populate_textures(swap_chain_id, textures, &mut token); //TODO?
|
||||
//TODO: remove this once gfx-rs stops destroying the old swapchain
|
||||
device.raw.wait_idle().unwrap();
|
||||
let (mut texture_guard, mut token) = hub.textures.write(&mut token);
|
||||
let (mut texture_view_guard, _) = hub.texture_views.write(&mut token);
|
||||
let mut trackers = device.trackers.lock();
|
||||
|
||||
let old_raw = swap_chain.raw.take();
|
||||
let config = swap_chain.desc.to_hal(swap_chain.frames.len() as u32);
|
||||
let surface = &mut surface_guard[swap_chain.surface_id.value];
|
||||
|
||||
let (raw, images) = unsafe {
|
||||
let suf = B::get_surface_mut(surface);
|
||||
device
|
||||
.raw
|
||||
.create_swapchain(suf, config, old_raw)
|
||||
.unwrap()
|
||||
};
|
||||
swap_chain.raw = Some(raw);
|
||||
for (frame, image) in swap_chain.frames.iter_mut().zip(images) {
|
||||
let texture = &mut texture_guard[frame.texture_id.value];
|
||||
let view_raw = unsafe {
|
||||
device
|
||||
.raw
|
||||
.create_image_view(
|
||||
&image,
|
||||
hal::image::ViewKind::D2,
|
||||
conv::map_texture_format(texture.format),
|
||||
hal::format::Swizzle::NO,
|
||||
texture.full_range.clone(),
|
||||
)
|
||||
.unwrap()
|
||||
};
|
||||
texture.raw = image;
|
||||
trackers.textures.reset(
|
||||
frame.texture_id.value,
|
||||
texture.full_range.clone(),
|
||||
resource::TextureUsage::UNINITIALIZED,
|
||||
);
|
||||
let old_view = mem::replace(&mut texture_view_guard[frame.view_id.value].raw, view_raw);
|
||||
unsafe {
|
||||
device.raw.destroy_image_view(old_view);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let image_index = match image_index {
|
||||
Some((index, suboptimal)) => {
|
||||
Ok((index, suboptimal)) => {
|
||||
if suboptimal.is_some() {
|
||||
warn!("acquire_image: sub-optimal");
|
||||
}
|
||||
index
|
||||
}
|
||||
None => unsafe {
|
||||
Err(_) => unsafe {
|
||||
swap_chain
|
||||
.raw
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.acquire_image(!0, Some(&swap_chain.sem_available), None)
|
||||
.unwrap()
|
||||
.0
|
||||
@ -266,7 +335,7 @@ pub fn swap_chain_present<B: GfxBackend>(swap_chain_id: SwapChainId) {
|
||||
let queue = &mut device.queue_group.queues[0];
|
||||
queue.submit(submission, Some(&frame.fence));
|
||||
queue.present(
|
||||
iter::once((&swap_chain.raw, image_index)),
|
||||
iter::once((swap_chain.raw.as_ref().unwrap(), image_index)),
|
||||
iter::once(&frame.sem_present),
|
||||
)
|
||||
};
|
||||
|
@ -223,6 +223,27 @@ impl<S: ResourceState> ResourceTracker<S> {
|
||||
.is_none()
|
||||
}
|
||||
|
||||
/// Resets a resource to the specified usage.
|
||||
#[cfg(not(feature = "remote"))]
|
||||
pub fn reset(
|
||||
&mut self,
|
||||
id: S::Id,
|
||||
selector: S::Selector,
|
||||
default: S::Usage,
|
||||
) {
|
||||
let mut state = S::default();
|
||||
match state.change(id, selector, default, None) {
|
||||
Ok(()) => (),
|
||||
Err(_) => unreachable!(),
|
||||
}
|
||||
|
||||
let (index, epoch, backend) = id.unzip();
|
||||
debug_assert_eq!(backend, self.backend);
|
||||
let res = self.map.get_mut(&index).unwrap();
|
||||
assert_eq!(res.epoch, epoch);
|
||||
res.state = state;
|
||||
}
|
||||
|
||||
/// Query the usage of a resource selector.
|
||||
///
|
||||
/// Returns `Some(Usage)` only if this usage is consistent
|
||||
|
Loading…
Reference in New Issue
Block a user