Support more than one frame in flight

This commit is contained in:
Dzmitry Malyshau 2020-09-08 01:06:45 -04:00
parent cbaf5ba24e
commit 871cc90b09
3 changed files with 440 additions and 438 deletions

820
Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -4378,9 +4378,9 @@ pub unsafe extern "C" fn gfxCreateSwapchainKHR(
let swapchain = Swapchain { let swapchain = Swapchain {
gpu, gpu,
surface: info.surface, surface: info.surface,
count: info.minImageCount as u8, count: info.minImageCount,
current_index: 0, current_index: 0,
active: None, active: Vec::new(),
lazy_framebuffers: Mutex::new(Vec::with_capacity(1)), lazy_framebuffers: Mutex::new(Vec::with_capacity(1)),
}; };
*pSwapchain = Handle::new(swapchain); *pSwapchain = Handle::new(swapchain);
@ -4419,7 +4419,7 @@ pub unsafe extern "C" fn gfxGetSwapchainImagesKHR(
debug_assert!(!pSwapchainImageCount.is_null()); debug_assert!(!pSwapchainImageCount.is_null());
let swapchain_image_count = &mut *pSwapchainImageCount; let swapchain_image_count = &mut *pSwapchainImageCount;
let available_images = swapchain.count as u32; let available_images = swapchain.count;
if pSwapchainImages.is_null() { if pSwapchainImages.is_null() {
// If NULL the number of presentable images is returned. // If NULL the number of presentable images is returned.
@ -4427,7 +4427,7 @@ pub unsafe extern "C" fn gfxGetSwapchainImagesKHR(
} else { } else {
*swapchain_image_count = available_images.min(*swapchain_image_count); *swapchain_image_count = available_images.min(*swapchain_image_count);
for frame in 0..*swapchain_image_count as u8 { for frame in 0..*swapchain_image_count {
*pSwapchainImages.offset(frame as isize) = *pSwapchainImages.offset(frame as isize) =
Handle::new(Image::SwapchainFrame { swapchain, frame }); Handle::new(Image::SwapchainFrame { swapchain, frame });
} }
@ -4663,17 +4663,12 @@ pub unsafe extern "C" fn gfxAcquireNextImageKHR(
sem.is_fake = true; sem.is_fake = true;
} }
if let Some(_old_frame) = swapchain.active.take() {
warn!(
"Swapchain frame {} was not presented!",
swapchain.current_index
);
}
match swapchain.surface.acquire_image(timeout) { match swapchain.surface.acquire_image(timeout) {
Ok((frame, suboptimal)) => { Ok((frame, suboptimal)) => {
swapchain.current_index = (swapchain.current_index + 1) % swapchain.count; let index = (swapchain.current_index + 1) % swapchain.count;
swapchain.active = Some(frame); swapchain.active.push((index, frame));
*pImageIndex = swapchain.current_index as u32; *pImageIndex = index;
swapchain.current_index = index;
match suboptimal { match suboptimal {
Some(_) => VkResult::VK_SUBOPTIMAL_KHR, Some(_) => VkResult::VK_SUBOPTIMAL_KHR,
None => VkResult::VK_SUCCESS, None => VkResult::VK_SUCCESS,
@ -4704,16 +4699,17 @@ pub unsafe extern "C" fn gfxQueuePresentKHR(
); );
} }
for (swapchain, index) in swapchain_slice.iter().zip(index_slice) { for (swapchain, &index) in swapchain_slice.iter().zip(index_slice) {
let sc = swapchain.as_mut().unwrap(); let sc = swapchain.as_mut().unwrap();
let frame = sc.active.take().expect("Frame was not acquired properly!"); let active_pos = sc
if sc.current_index == *index as u8 { .active
let sem = wait_semaphores.first().map(|s| &s.raw); .iter()
if let Err(_) = queue.present(&mut *sc.surface, frame, sem) { .position(|&(frame, _)| frame == index)
return VkResult::VK_ERROR_SURFACE_LOST_KHR; .expect("Frame was not acquired properly!");
} let frame = sc.active.swap_remove(active_pos).1;
} else { let sem = wait_semaphores.first().map(|s| &s.raw);
warn!("Swapchain frame {} is stale, can't be presented.", *index); if let Err(_) = queue.present(&mut *sc.surface, frame, sem) {
return VkResult::VK_ERROR_SURFACE_LOST_KHR;
} }
for framebuffer in sc.lazy_framebuffers.lock().drain(..) { for framebuffer in sc.lazy_framebuffers.lock().drain(..) {
sc.gpu.device.destroy_framebuffer(framebuffer) sc.gpu.device.destroy_framebuffer(framebuffer)

View file

@ -117,7 +117,7 @@ pub enum Image<B: hal::Backend> {
}, },
SwapchainFrame { SwapchainFrame {
swapchain: VkSwapchainKHR, swapchain: VkSwapchainKHR,
frame: u8, frame: hal::window::SwapImageIndex,
}, },
} }
@ -137,7 +137,7 @@ pub enum ImageView {
Native(<B as hal::Backend>::ImageView), Native(<B as hal::Backend>::ImageView),
SwapchainFrame { SwapchainFrame {
swapchain: VkSwapchainKHR, swapchain: VkSwapchainKHR,
frame: u8, frame: hal::window::SwapImageIndex,
}, },
} }
@ -194,11 +194,12 @@ impl Framebuffer {
frame, frame,
} => { } => {
use std::borrow::Borrow; use std::borrow::Borrow;
debug_assert_eq!(frame, swapchain.current_index);
swapchain swapchain
.active .active
.as_ref() .iter()
.find(|&&(index, _)| index == frame)
.expect("Swapchain frame isn't acquired") .expect("Swapchain frame isn't acquired")
.1
.borrow() .borrow()
} }
}); });
@ -246,9 +247,12 @@ pub type VkSwapchainKHR = Handle<Swapchain<B>>;
pub struct Swapchain<B: hal::Backend> { pub struct Swapchain<B: hal::Backend> {
gpu: VkDevice, gpu: VkDevice,
surface: VkSurfaceKHR, surface: VkSurfaceKHR,
count: u8, count: hal::window::SwapImageIndex,
current_index: u8, current_index: hal::window::SwapImageIndex,
active: Option<<B::Surface as hal::window::PresentationSurface<B>>::SwapchainImage>, active: Vec<(
hal::window::SwapImageIndex,
<B::Surface as hal::window::PresentationSurface<B>>::SwapchainImage,
)>,
lazy_framebuffers: parking_lot::Mutex<Vec<<B as hal::Backend>::Framebuffer>>, lazy_framebuffers: parking_lot::Mutex<Vec<<B as hal::Backend>::Framebuffer>>,
} }