mirror of
https://github.com/gfx-rs/wgpu.git
synced 2025-12-08 21:26:17 +00:00
hal/vulkan: use different indexes for acquire and present
This commit is contained in:
parent
c5efc89b08
commit
83badd52ab
@ -573,25 +573,29 @@ impl super::Device {
|
|||||||
let images =
|
let images =
|
||||||
unsafe { functor.get_swapchain_images(raw) }.map_err(super::map_host_device_oom_err)?;
|
unsafe { functor.get_swapchain_images(raw) }.map_err(super::map_host_device_oom_err)?;
|
||||||
|
|
||||||
// NOTE: It's important that we define at least images.len() wait
|
// NOTE: It's important that we define the same number of acquire/present semaphores
|
||||||
// semaphores, since we prospectively need to provide the call to
|
// as we will need to index into them with the image index.
|
||||||
// acquire the next image with an unsignaled semaphore.
|
let acquire_semaphores = (0..=images.len())
|
||||||
let surface_semaphores = (0..=images.len())
|
|
||||||
.map(|i| {
|
.map(|i| {
|
||||||
super::SwapchainImageSemaphores::new(&self.shared, i)
|
super::SwapchainAcquireSemaphore::new(&self.shared, i)
|
||||||
.map(Mutex::new)
|
.map(Mutex::new)
|
||||||
.map(Arc::new)
|
.map(Arc::new)
|
||||||
})
|
})
|
||||||
.collect::<Result<Vec<_>, _>>()?;
|
.collect::<Result<Vec<_>, _>>()?;
|
||||||
|
|
||||||
|
let present_semaphores = (0..=images.len())
|
||||||
|
.map(|i| Arc::new(Mutex::new(super::SwapchainPresentSemaphores::new(i))))
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
Ok(super::Swapchain {
|
Ok(super::Swapchain {
|
||||||
raw,
|
raw,
|
||||||
functor,
|
functor,
|
||||||
device: Arc::clone(&self.shared),
|
device: Arc::clone(&self.shared),
|
||||||
images,
|
images,
|
||||||
config: config.clone(),
|
config: config.clone(),
|
||||||
surface_semaphores,
|
acquire_semaphores,
|
||||||
next_semaphore_index: 0,
|
next_acquire_index: 0,
|
||||||
|
present_semaphores,
|
||||||
next_present_time: None,
|
next_present_time: None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@ -188,9 +188,18 @@ impl super::Swapchain {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// We cannot take this by value, as the function returns `self`.
|
// We cannot take this by value, as the function returns `self`.
|
||||||
for semaphore in self.surface_semaphores.drain(..) {
|
for semaphore in self.acquire_semaphores.drain(..) {
|
||||||
let arc_removed = Arc::into_inner(semaphore).expect(
|
let arc_removed = Arc::into_inner(semaphore).expect(
|
||||||
"Trying to destroy a SurfaceSemaphores that is still in use by a SurfaceTexture",
|
"Trying to destroy a SurfaceAcquireSemaphores that is still in use by a SurfaceTexture",
|
||||||
|
);
|
||||||
|
let mutex_removed = arc_removed.into_inner();
|
||||||
|
|
||||||
|
unsafe { mutex_removed.destroy(device) };
|
||||||
|
}
|
||||||
|
|
||||||
|
for semaphore in self.present_semaphores.drain(..) {
|
||||||
|
let arc_removed = Arc::into_inner(semaphore).expect(
|
||||||
|
"Trying to destroy a SurfacePresentSemaphores that is still in use by a SurfaceTexture",
|
||||||
);
|
);
|
||||||
let mutex_removed = arc_removed.into_inner();
|
let mutex_removed = arc_removed.into_inner();
|
||||||
|
|
||||||
@ -1074,9 +1083,9 @@ impl crate::Surface for super::Surface {
|
|||||||
timeout_ns = u64::MAX;
|
timeout_ns = u64::MAX;
|
||||||
}
|
}
|
||||||
|
|
||||||
let swapchain_semaphores_arc = swapchain.get_surface_semaphores();
|
let acquire_semaphore_arc = swapchain.get_acquire_semaphore();
|
||||||
// Nothing should be using this, so we don't block, but panic if we fail to lock.
|
// Nothing should be using this, so we don't block, but panic if we fail to lock.
|
||||||
let locked_swapchain_semaphores = swapchain_semaphores_arc
|
let acquire_semaphore_guard = acquire_semaphore_arc
|
||||||
.try_lock()
|
.try_lock()
|
||||||
.expect("Failed to lock a SwapchainSemaphores.");
|
.expect("Failed to lock a SwapchainSemaphores.");
|
||||||
|
|
||||||
@ -1095,7 +1104,7 @@ impl crate::Surface for super::Surface {
|
|||||||
// `vkAcquireNextImageKHR` again.
|
// `vkAcquireNextImageKHR` again.
|
||||||
swapchain.device.wait_for_fence(
|
swapchain.device.wait_for_fence(
|
||||||
fence,
|
fence,
|
||||||
locked_swapchain_semaphores.previously_used_submission_index,
|
acquire_semaphore_guard.previously_used_submission_index,
|
||||||
timeout_ns,
|
timeout_ns,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
@ -1105,7 +1114,7 @@ impl crate::Surface for super::Surface {
|
|||||||
swapchain.functor.acquire_next_image(
|
swapchain.functor.acquire_next_image(
|
||||||
swapchain.raw,
|
swapchain.raw,
|
||||||
timeout_ns,
|
timeout_ns,
|
||||||
locked_swapchain_semaphores.acquire,
|
acquire_semaphore_guard.acquire,
|
||||||
vk::Fence::null(),
|
vk::Fence::null(),
|
||||||
)
|
)
|
||||||
} {
|
} {
|
||||||
@ -1129,12 +1138,12 @@ impl crate::Surface for super::Surface {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
log::error!("Got swapchain image {index}");
|
drop(acquire_semaphore_guard);
|
||||||
|
|
||||||
drop(locked_swapchain_semaphores);
|
|
||||||
// We only advance the surface semaphores if we successfully acquired an image, otherwise
|
// We only advance the surface semaphores if we successfully acquired an image, otherwise
|
||||||
// we should try to re-acquire using the same semaphores.
|
// we should try to re-acquire using the same semaphores.
|
||||||
swapchain.advance_surface_semaphores();
|
swapchain.advance_acquire_semaphore();
|
||||||
|
|
||||||
|
let present_semaphore_arc = swapchain.get_present_semaphores(index);
|
||||||
|
|
||||||
// special case for Intel Vulkan returning bizarre values (ugh)
|
// special case for Intel Vulkan returning bizarre values (ugh)
|
||||||
if swapchain.device.vendor_id == crate::auxil::db::intel::VENDOR && index > 0x100 {
|
if swapchain.device.vendor_id == crate::auxil::db::intel::VENDOR && index > 0x100 {
|
||||||
@ -1158,7 +1167,8 @@ impl crate::Surface for super::Surface {
|
|||||||
},
|
},
|
||||||
identity,
|
identity,
|
||||||
},
|
},
|
||||||
surface_semaphores: swapchain_semaphores_arc,
|
acquire_semaphores: acquire_semaphore_arc,
|
||||||
|
present_semaphores: present_semaphore_arc,
|
||||||
};
|
};
|
||||||
Ok(Some(crate::AcquiredSurfaceTexture {
|
Ok(Some(crate::AcquiredSurfaceTexture {
|
||||||
texture,
|
texture,
|
||||||
|
|||||||
@ -178,9 +178,9 @@ pub struct Instance {
|
|||||||
shared: Arc<InstanceShared>,
|
shared: Arc<InstanceShared>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The semaphores needed to use one image in a swapchain.
|
/// Semaphore used to acquire a swapchain image.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct SwapchainImageSemaphores {
|
struct SwapchainAcquireSemaphore {
|
||||||
/// A semaphore that is signaled when this image is safe for us to modify.
|
/// A semaphore that is signaled when this image is safe for us to modify.
|
||||||
///
|
///
|
||||||
/// When [`vkAcquireNextImageKHR`] returns the index of the next swapchain
|
/// When [`vkAcquireNextImageKHR`] returns the index of the next swapchain
|
||||||
@ -209,10 +209,70 @@ struct SwapchainImageSemaphores {
|
|||||||
/// wait. We set this flag when this image is acquired, and clear it the
|
/// wait. We set this flag when this image is acquired, and clear it the
|
||||||
/// first time it's passed to [`Queue::submit`] as a surface texture.
|
/// first time it's passed to [`Queue::submit`] as a surface texture.
|
||||||
///
|
///
|
||||||
/// [`acquire`]: SwapchainImageSemaphores::acquire
|
/// Additionally, semaphores can only be waited on once, so we need to ensure
|
||||||
|
/// that we only actually pass this semaphore to the first submission that
|
||||||
|
/// uses that image.
|
||||||
|
///
|
||||||
|
/// [`acquire`]: SwapchainAcquireSemaphore::acquire
|
||||||
/// [`Queue::submit`]: crate::Queue::submit
|
/// [`Queue::submit`]: crate::Queue::submit
|
||||||
should_wait_for_acquire: bool,
|
should_wait_for_acquire: bool,
|
||||||
|
|
||||||
|
/// The fence value of the last command submission that wrote to this image.
|
||||||
|
///
|
||||||
|
/// The next time we try to acquire this image, we'll block until
|
||||||
|
/// this submission finishes, proving that [`acquire`] is ready to
|
||||||
|
/// pass to `vkAcquireNextImageKHR` again.
|
||||||
|
///
|
||||||
|
/// [`acquire`]: SwapchainAcquireSemaphore::acquire
|
||||||
|
previously_used_submission_index: crate::FenceValue,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SwapchainAcquireSemaphore {
|
||||||
|
fn new(device: &DeviceShared, index: usize) -> Result<Self, crate::DeviceError> {
|
||||||
|
Ok(Self {
|
||||||
|
acquire: device
|
||||||
|
.new_binary_semaphore(&format!("SwapchainImageSemaphore: Index {index} acquire"))?,
|
||||||
|
should_wait_for_acquire: true,
|
||||||
|
previously_used_submission_index: 0,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sets the fence value which the next acquire will wait for. This prevents
|
||||||
|
/// the semaphore from being used while the previous submission is still in flight.
|
||||||
|
fn set_used_fence_value(&mut self, value: crate::FenceValue) {
|
||||||
|
self.previously_used_submission_index = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return the semaphore that commands drawing to this image should wait for, if any.
|
||||||
|
///
|
||||||
|
/// This only returns `Some` once per acquisition; see
|
||||||
|
/// [`SwapchainAcquireSemaphore::should_wait_for_acquire`] for details.
|
||||||
|
fn get_acquire_wait_semaphore(&mut self) -> Option<vk::Semaphore> {
|
||||||
|
if self.should_wait_for_acquire {
|
||||||
|
self.should_wait_for_acquire = false;
|
||||||
|
Some(self.acquire)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Indicates the cpu-side usage of this semaphore has finished for the frame,
|
||||||
|
/// so reset internal state to be ready for the next frame.
|
||||||
|
fn end_semaphore_usage(&mut self) {
|
||||||
|
// Reset the acquire semaphore, so that the next time we acquire this
|
||||||
|
// image, we can wait for it again.
|
||||||
|
self.should_wait_for_acquire = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn destroy(&self, device: &ash::Device) {
|
||||||
|
unsafe {
|
||||||
|
device.destroy_semaphore(self.acquire, None);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct SwapchainPresentSemaphores {
|
||||||
/// A pool of semaphores for ordering presentation after drawing.
|
/// A pool of semaphores for ordering presentation after drawing.
|
||||||
///
|
///
|
||||||
/// The first [`present_index`] semaphores in this vector are:
|
/// The first [`present_index`] semaphores in this vector are:
|
||||||
@ -244,64 +304,33 @@ struct SwapchainImageSemaphores {
|
|||||||
/// by the next present call. Any semaphores beyond that index were created
|
/// by the next present call. Any semaphores beyond that index were created
|
||||||
/// for prior presents and are simply being retained for recycling.
|
/// for prior presents and are simply being retained for recycling.
|
||||||
///
|
///
|
||||||
/// [`present_index`]: SwapchainImageSemaphores::present_index
|
/// [`present_index`]: SwapchainPresentSemaphores::present_index
|
||||||
/// [`vkQueuePresentKHR`]: https://registry.khronos.org/vulkan/specs/1.3-extensions/html/vkspec.html#vkQueuePresentKHR
|
/// [`vkQueuePresentKHR`]: https://registry.khronos.org/vulkan/specs/1.3-extensions/html/vkspec.html#vkQueuePresentKHR
|
||||||
/// [`vkQueueSubmit`]: https://registry.khronos.org/vulkan/specs/1.3-extensions/html/vkspec.html#vkQueueSubmit
|
/// [`vkQueueSubmit`]: https://registry.khronos.org/vulkan/specs/1.3-extensions/html/vkspec.html#vkQueueSubmit
|
||||||
present: Vec<vk::Semaphore>,
|
present: Vec<vk::Semaphore>,
|
||||||
|
|
||||||
/// The number of semaphores in [`present`] to be signalled for this submission.
|
/// The number of semaphores in [`present`] to be signalled for this submission.
|
||||||
///
|
///
|
||||||
/// [`present`]: SwapchainImageSemaphores::present
|
/// [`present`]: SwapchainPresentSemaphores::present
|
||||||
present_index: usize,
|
present_index: usize,
|
||||||
|
|
||||||
/// The fence value of the last command submission that wrote to this image.
|
|
||||||
///
|
|
||||||
/// The next time we try to acquire this image, we'll block until
|
|
||||||
/// this submission finishes, proving that [`acquire`] is ready to
|
|
||||||
/// pass to `vkAcquireNextImageKHR` again.
|
|
||||||
///
|
|
||||||
/// [`acquire`]: SwapchainImageSemaphores::acquire
|
|
||||||
previously_used_submission_index: crate::FenceValue,
|
|
||||||
|
|
||||||
/// Which image this semaphore set is used for.
|
/// Which image this semaphore set is used for.
|
||||||
frame_index: usize,
|
frame_index: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SwapchainImageSemaphores {
|
impl SwapchainPresentSemaphores {
|
||||||
fn new(device: &DeviceShared, frame_index: usize) -> Result<Self, crate::DeviceError> {
|
pub fn new(frame_index: usize) -> Self {
|
||||||
Ok(Self {
|
Self {
|
||||||
acquire: device.new_binary_semaphore(&format!(
|
|
||||||
"SwapchainImageSemaphore: Image {frame_index} acquire"
|
|
||||||
))?,
|
|
||||||
should_wait_for_acquire: true,
|
|
||||||
present: Vec::new(),
|
present: Vec::new(),
|
||||||
present_index: 0,
|
present_index: 0,
|
||||||
previously_used_submission_index: 0,
|
|
||||||
frame_index,
|
frame_index,
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn set_used_fence_value(&mut self, value: crate::FenceValue) {
|
|
||||||
self.previously_used_submission_index = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return the semaphore that commands drawing to this image should wait for, if any.
|
|
||||||
///
|
|
||||||
/// This only returns `Some` once per acquisition; see
|
|
||||||
/// [`SwapchainImageSemaphores::should_wait_for_acquire`] for details.
|
|
||||||
fn get_acquire_wait_semaphore(&mut self) -> Option<vk::Semaphore> {
|
|
||||||
if self.should_wait_for_acquire {
|
|
||||||
self.should_wait_for_acquire = false;
|
|
||||||
Some(self.acquire)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return a semaphore that a submission that writes to this image should
|
/// Return the semaphore that the next submission that writes to this image should
|
||||||
/// signal when it's done.
|
/// signal when it's done.
|
||||||
///
|
///
|
||||||
/// See [`SwapchainImageSemaphores::present`] for details.
|
/// See [`SwapchainPresentSemaphores::present`] for details.
|
||||||
fn get_submit_signal_semaphore(
|
fn get_submit_signal_semaphore(
|
||||||
&mut self,
|
&mut self,
|
||||||
device: &DeviceShared,
|
device: &DeviceShared,
|
||||||
@ -324,29 +353,29 @@ impl SwapchainImageSemaphores {
|
|||||||
Ok(sem)
|
Ok(sem)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Indicates the cpu-side usage of this semaphore has finished for the frame,
|
||||||
|
/// so reset internal state to be ready for the next frame.
|
||||||
|
fn end_semaphore_usage(&mut self) {
|
||||||
|
// Reset the index to 0, so that the next time we get a semaphore, we
|
||||||
|
// start from the beginning of the list.
|
||||||
|
self.present_index = 0;
|
||||||
|
}
|
||||||
|
|
||||||
/// Return the semaphores that a presentation of this image should wait on.
|
/// Return the semaphores that a presentation of this image should wait on.
|
||||||
///
|
///
|
||||||
/// Return a slice of semaphores that the call to [`vkQueueSubmit`] that
|
/// Return a slice of semaphores that the call to [`vkQueueSubmit`] that
|
||||||
/// ends this image's acquisition should wait for. See
|
/// ends this image's acquisition should wait for. See
|
||||||
/// [`SwapchainImageSemaphores::present`] for details.
|
/// [`SwapchainPresentSemaphores::present`] for details.
|
||||||
///
|
///
|
||||||
/// Reset `self` to be ready for the next acquisition cycle.
|
/// Reset `self` to be ready for the next acquisition cycle.
|
||||||
///
|
///
|
||||||
/// [`vkQueueSubmit`]: https://registry.khronos.org/vulkan/specs/1.3-extensions/html/vkspec.html#vkQueueSubmit
|
/// [`vkQueueSubmit`]: https://registry.khronos.org/vulkan/specs/1.3-extensions/html/vkspec.html#vkQueueSubmit
|
||||||
fn get_present_wait_semaphores(&mut self) -> &[vk::Semaphore] {
|
fn get_present_wait_semaphores(&mut self) -> Vec<vk::Semaphore> {
|
||||||
let old_index = self.present_index;
|
self.present[0..self.present_index].to_vec()
|
||||||
|
|
||||||
// Since this marks the end of this acquire/draw/present cycle, take the
|
|
||||||
// opportunity to reset `self` in preparation for the next acquisition.
|
|
||||||
self.present_index = 0;
|
|
||||||
self.should_wait_for_acquire = true;
|
|
||||||
|
|
||||||
&self.present[0..old_index]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn destroy(&self, device: &ash::Device) {
|
unsafe fn destroy(&self, device: &ash::Device) {
|
||||||
unsafe {
|
unsafe {
|
||||||
device.destroy_semaphore(self.acquire, None);
|
|
||||||
for sem in &self.present {
|
for sem in &self.present {
|
||||||
device.destroy_semaphore(*sem, None);
|
device.destroy_semaphore(*sem, None);
|
||||||
}
|
}
|
||||||
@ -360,16 +389,44 @@ struct Swapchain {
|
|||||||
device: Arc<DeviceShared>,
|
device: Arc<DeviceShared>,
|
||||||
images: Vec<vk::Image>,
|
images: Vec<vk::Image>,
|
||||||
config: crate::SurfaceConfiguration,
|
config: crate::SurfaceConfiguration,
|
||||||
/// One wait semaphore per swapchain image. This will be associated with the
|
|
||||||
/// surface texture, and later collected during submission.
|
/// Semaphores used between image acquisition and the first submission
|
||||||
|
/// that uses that image. This is indexed using [`next_acquire_index`].
|
||||||
///
|
///
|
||||||
/// We need this to be `Arc<Mutex<>>` because we need to be able to pass this
|
/// Because we need to provide this to [`vkAcquireNextImageKHR`], we haven't
|
||||||
/// data into the surface texture, so submit/present can use it.
|
/// received the swapchain image index for the frame yet, so we cannot use
|
||||||
surface_semaphores: Vec<Arc<Mutex<SwapchainImageSemaphores>>>,
|
/// that to index it.
|
||||||
/// The index of the next semaphore to use. Ideally we would use the same
|
///
|
||||||
/// index as the image index, but we need to specify the semaphore as an argument
|
/// Before we pass this to [`vkAcquireNextImageKHR`], we ensure that we wait on
|
||||||
/// to the acquire_next_image function which is what tells us which image to use.
|
/// the submission indicated by [`previously_used_submission_index`]. This enusres
|
||||||
next_semaphore_index: usize,
|
/// the semaphore is no longer in use before we use it.
|
||||||
|
///
|
||||||
|
/// [`next_acquire_index`]: Swapchain::next_acquire_index
|
||||||
|
/// [`vkAcquireNextImageKHR`]: https://registry.khronos.org/vulkan/specs/1.3-extensions/html/vkspec.html#vkAcquireNextImageKHR
|
||||||
|
/// [`previously_used_submission_index`]: SwapchainAcquireSemaphore::previously_used_submission_index
|
||||||
|
acquire_semaphores: Vec<Arc<Mutex<SwapchainAcquireSemaphore>>>,
|
||||||
|
/// The index of the next acquire semaphore to use.
|
||||||
|
///
|
||||||
|
/// This is incremented each time we acquire a new image, and wraps around
|
||||||
|
/// to 0 when it reaches the end of [`acquire_semaphores`].
|
||||||
|
///
|
||||||
|
/// [`acquire_semaphores`]: Swapchain::acquire_semaphores
|
||||||
|
next_acquire_index: usize,
|
||||||
|
|
||||||
|
/// Semaphore sets used between all submissions that write to an image and
|
||||||
|
/// the presentation of that image.
|
||||||
|
///
|
||||||
|
/// This is indexed by the swapchain image index returned by
|
||||||
|
/// [`vkAcquireNextImageKHR`].
|
||||||
|
///
|
||||||
|
/// We know it is safe to use these semaphores because use them
|
||||||
|
/// _after_ the acquire semaphore. Because the acquire semaphore
|
||||||
|
/// has been signaled, the previous presentation using that image
|
||||||
|
/// is known-finished, so this semaphore is no longer in use.
|
||||||
|
///
|
||||||
|
/// [`vkAcquireNextImageKHR`]: https://registry.khronos.org/vulkan/specs/1.3-extensions/html/vkspec.html#vkAcquireNextImageKHR
|
||||||
|
present_semaphores: Vec<Arc<Mutex<SwapchainPresentSemaphores>>>,
|
||||||
|
|
||||||
/// The present timing information which will be set in the next call to [`present()`](crate::Queue::present()).
|
/// The present timing information which will be set in the next call to [`present()`](crate::Queue::present()).
|
||||||
///
|
///
|
||||||
/// # Safety
|
/// # Safety
|
||||||
@ -380,13 +437,20 @@ struct Swapchain {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Swapchain {
|
impl Swapchain {
|
||||||
fn advance_surface_semaphores(&mut self) {
|
/// Mark the current frame finished, advancing to the next acquire semaphore.
|
||||||
let semaphore_count = self.surface_semaphores.len();
|
fn advance_acquire_semaphore(&mut self) {
|
||||||
self.next_semaphore_index = (self.next_semaphore_index + 1) % semaphore_count;
|
let semaphore_count = self.acquire_semaphores.len();
|
||||||
|
self.next_acquire_index = (self.next_acquire_index + 1) % semaphore_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_surface_semaphores(&self) -> Arc<Mutex<SwapchainImageSemaphores>> {
|
/// Get the next acquire semaphore that should be used with this swapchain.
|
||||||
self.surface_semaphores[self.next_semaphore_index].clone()
|
fn get_acquire_semaphore(&self) -> Arc<Mutex<SwapchainAcquireSemaphore>> {
|
||||||
|
self.acquire_semaphores[self.next_acquire_index].clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the set of present semaphores that should be used with the given image index.
|
||||||
|
fn get_present_semaphores(&self, index: u32) -> Arc<Mutex<SwapchainPresentSemaphores>> {
|
||||||
|
self.present_semaphores[index as usize].clone()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -448,7 +512,8 @@ impl Surface {
|
|||||||
pub struct SurfaceTexture {
|
pub struct SurfaceTexture {
|
||||||
index: u32,
|
index: u32,
|
||||||
texture: Texture,
|
texture: Texture,
|
||||||
surface_semaphores: Arc<Mutex<SwapchainImageSemaphores>>,
|
acquire_semaphores: Arc<Mutex<SwapchainAcquireSemaphore>>,
|
||||||
|
present_semaphores: Arc<Mutex<SwapchainPresentSemaphores>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl crate::DynSurfaceTexture for SurfaceTexture {}
|
impl crate::DynSurfaceTexture for SurfaceTexture {}
|
||||||
@ -1384,9 +1449,10 @@ impl crate::Queue for Queue {
|
|||||||
let mut check = HashSet::with_capacity(surface_textures.len());
|
let mut check = HashSet::with_capacity(surface_textures.len());
|
||||||
// We compare the Arcs by pointer, as Eq isn't well defined for SurfaceSemaphores.
|
// We compare the Arcs by pointer, as Eq isn't well defined for SurfaceSemaphores.
|
||||||
for st in surface_textures {
|
for st in surface_textures {
|
||||||
check.insert(Arc::as_ptr(&st.surface_semaphores));
|
check.insert(Arc::as_ptr(&st.acquire_semaphores) as usize);
|
||||||
|
check.insert(Arc::as_ptr(&st.present_semaphores) as usize);
|
||||||
}
|
}
|
||||||
check.len() == surface_textures.len()
|
check.len() == surface_textures.len() * 2
|
||||||
},
|
},
|
||||||
"More than one surface texture is being used from the same swapchain. This will cause a deadlock in release."
|
"More than one surface texture is being used from the same swapchain. This will cause a deadlock in release."
|
||||||
);
|
);
|
||||||
@ -1394,26 +1460,33 @@ impl crate::Queue for Queue {
|
|||||||
let locked_swapchain_semaphores = surface_textures
|
let locked_swapchain_semaphores = surface_textures
|
||||||
.iter()
|
.iter()
|
||||||
.map(|st| {
|
.map(|st| {
|
||||||
st.surface_semaphores
|
let acquire = st
|
||||||
|
.acquire_semaphores
|
||||||
.try_lock()
|
.try_lock()
|
||||||
.expect("Failed to lock surface semaphore.")
|
.expect("Failed to lock surface acquire semaphore");
|
||||||
|
let present = st
|
||||||
|
.present_semaphores
|
||||||
|
.try_lock()
|
||||||
|
.expect("Failed to lock surface present semaphore");
|
||||||
|
|
||||||
|
(acquire, present)
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
for mut swapchain_semaphore in locked_swapchain_semaphores {
|
for (mut acquire_semaphore, mut present_semaphores) in locked_swapchain_semaphores {
|
||||||
swapchain_semaphore.set_used_fence_value(signal_value);
|
acquire_semaphore.set_used_fence_value(signal_value);
|
||||||
|
|
||||||
// If we're the first submission to operate on this image, wait on
|
// If we're the first submission to operate on this image, wait on
|
||||||
// its acquire semaphore, to make sure the presentation engine is
|
// its acquire semaphore, to make sure the presentation engine is
|
||||||
// done with it.
|
// done with it.
|
||||||
if let Some(sem) = swapchain_semaphore.get_acquire_wait_semaphore() {
|
if let Some(sem) = acquire_semaphore.get_acquire_wait_semaphore() {
|
||||||
wait_stage_masks.push(vk::PipelineStageFlags::TOP_OF_PIPE);
|
wait_stage_masks.push(vk::PipelineStageFlags::TOP_OF_PIPE);
|
||||||
wait_semaphores.push(sem);
|
wait_semaphores.push(sem);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get a semaphore to signal when we're done writing to this surface
|
// Get a semaphore to signal when we're done writing to this surface
|
||||||
// image. Presentation of this image will wait for this.
|
// image. Presentation of this image will wait for this.
|
||||||
let signal_semaphore = swapchain_semaphore.get_submit_signal_semaphore(&self.device)?;
|
let signal_semaphore = present_semaphores.get_submit_signal_semaphore(&self.device)?;
|
||||||
signal_semaphores.push_binary(signal_semaphore);
|
signal_semaphores.push_binary(signal_semaphore);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1488,14 +1561,28 @@ impl crate::Queue for Queue {
|
|||||||
) -> Result<(), crate::SurfaceError> {
|
) -> Result<(), crate::SurfaceError> {
|
||||||
let mut swapchain = surface.swapchain.write();
|
let mut swapchain = surface.swapchain.write();
|
||||||
let ssc = swapchain.as_mut().unwrap();
|
let ssc = swapchain.as_mut().unwrap();
|
||||||
let mut swapchain_semaphores = texture.surface_semaphores.lock();
|
let mut acquire_semaphore = texture.acquire_semaphores.lock();
|
||||||
|
let mut present_semaphores = texture.present_semaphores.lock();
|
||||||
|
|
||||||
|
let wait_semaphores = present_semaphores.get_present_wait_semaphores();
|
||||||
|
|
||||||
|
// Reset the acquire and present semaphores internal state
|
||||||
|
// to be ready for the next frame.
|
||||||
|
//
|
||||||
|
// We do this before the actual call to present to ensure that
|
||||||
|
// even if this method errors and early outs, we have reset
|
||||||
|
// the state for next frame.
|
||||||
|
acquire_semaphore.end_semaphore_usage();
|
||||||
|
present_semaphores.end_semaphore_usage();
|
||||||
|
|
||||||
|
drop(acquire_semaphore);
|
||||||
|
|
||||||
let swapchains = [ssc.raw];
|
let swapchains = [ssc.raw];
|
||||||
let image_indices = [texture.index];
|
let image_indices = [texture.index];
|
||||||
let vk_info = vk::PresentInfoKHR::default()
|
let vk_info = vk::PresentInfoKHR::default()
|
||||||
.swapchains(&swapchains)
|
.swapchains(&swapchains)
|
||||||
.image_indices(&image_indices)
|
.image_indices(&image_indices)
|
||||||
.wait_semaphores(swapchain_semaphores.get_present_wait_semaphores());
|
.wait_semaphores(&wait_semaphores);
|
||||||
|
|
||||||
let mut display_timing;
|
let mut display_timing;
|
||||||
let present_times;
|
let present_times;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user