Assert on swapchain output usage before presenting

This commit is contained in:
Dzmitry Malyshau
2019-05-03 10:45:39 -04:00
parent f015eb22d8
commit 1c350cc4af
3 changed files with 33 additions and 12 deletions

View File

@@ -155,6 +155,7 @@ pub struct CommandEncoderDescriptor {
pub extern "C" fn wgpu_command_encoder_finish(
command_encoder_id: CommandEncoderId,
) -> CommandBufferId {
//TODO: actually close the last recorded command buffer
HUB.command_buffers.write()[command_encoder_id].is_recording = false; //TODO: check for the old value
command_encoder_id
}

View File

@@ -51,7 +51,17 @@ use log::{info, trace};
//use rendy_memory::{allocator, Config, Heaps};
use parking_lot::Mutex;
use std::{collections::hash_map::Entry, ffi, iter, ptr, slice, sync::atomic::Ordering};
use std::{
collections::hash_map::Entry,
ffi,
iter,
ptr,
slice,
sync::atomic::Ordering,
};
#[cfg(feature = "local")]
use std::sync::atomic::AtomicBool;
pub const MAX_COLOR_TARGETS: usize = 4;
@@ -1271,17 +1281,17 @@ pub extern "C" fn wgpu_queue_submit(
let wait_semaphores = swap_chain_links.into_iter().flat_map(|link| {
let swap_chain = surface_guard[link.swap_chain_id].swap_chain.as_ref()?;
let frame = &swap_chain.frames[link.image_index as usize];
let mut wait_for_epoch = frame.wait_for_epoch.lock();
let current_epoch = *wait_for_epoch.as_ref()?;
if link.epoch < current_epoch {
None
} else {
debug_assert_eq!(link.epoch, current_epoch);
*wait_for_epoch = None;
if frame.need_waiting.swap(false, Ordering::Relaxed) {
assert_eq!(frame.acquired_epoch, Some(link.epoch),
"{}. Image index {} with epoch {} != current epoch {:?}",
"Attempting to rendering to a swapchain output that has already been presented",
link.image_index, link.epoch, frame.acquired_epoch);
Some((
&frame.sem_available,
hal::pso::PipelineStage::COLOR_ATTACHMENT_OUTPUT,
))
} else {
None
}
});
@@ -1798,7 +1808,8 @@ pub fn swap_chain_populate_textures(
fence: device.raw.create_fence(true).unwrap(),
sem_available: device.raw.create_semaphore().unwrap(),
sem_present: device.raw.create_semaphore().unwrap(),
wait_for_epoch: Mutex::new(None),
acquired_epoch: None,
need_waiting: AtomicBool::new(false),
comb: swap_chain.command_pool.acquire_command_buffer(),
});
}

View File

@@ -16,7 +16,9 @@ use hal::{self, Device as _, Swapchain as _};
use log::{trace, warn};
use parking_lot::Mutex;
use std::{iter, mem};
use std::{
iter, mem, sync::atomic::{AtomicBool, Ordering},
};
pub type SwapImageEpoch = u16;
@@ -54,7 +56,8 @@ pub(crate) struct Frame<B: hal::Backend> {
pub fence: B::Fence,
pub sem_available: B::Semaphore,
pub sem_present: B::Semaphore,
pub wait_for_epoch: Mutex<Option<SwapImageEpoch>>,
pub acquired_epoch: Option<SwapImageEpoch>,
pub need_waiting: AtomicBool,
pub comb: hal::command::CommandBuffer<B, hal::General, hal::command::MultiShot>,
}
@@ -153,13 +156,15 @@ pub extern "C" fn wgpu_swap_chain_get_next_texture(swap_chain_id: SwapChainId) -
device.raw.wait_for_fence(&frame.fence, !0).unwrap();
}
mem::swap(&mut frame.sem_available, &mut swap_chain.sem_available);
frame.need_waiting.store(true, Ordering::Release);
let frame_epoch = HUB.textures.read()[frame.texture_id.value]
.placement
.as_swap_chain()
.bump_epoch();
*frame.wait_for_epoch.lock() = Some(frame_epoch);
assert_eq!(frame.acquired_epoch, None, "Last swapchain output hasn't been presented");
frame.acquired_epoch =Some(frame_epoch);
SwapChainOutput {
texture_id: frame.texture_id.value,
@@ -174,6 +179,10 @@ pub extern "C" fn wgpu_swap_chain_present(swap_chain_id: SwapChainId) {
let image_index = swap_chain.acquired.remove(0);
let frame = &mut swap_chain.frames[image_index as usize];
let epoch = frame.acquired_epoch.take();
assert!(epoch.is_some(), "Presented frame (image {}) was not acquired", image_index);
assert!(!frame.need_waiting.load(Ordering::Acquire),
"No rendering work has been submitted for the presented frame (image {})", image_index);
let mut device_guard = HUB.devices.write();
let device = &mut device_guard[swap_chain.device_id.value];