aboutsummaryrefslogtreecommitdiff
path: root/src/sync/future/semaphore_signal.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/sync/future/semaphore_signal.rs')
-rw-r--r--src/sync/future/semaphore_signal.rs204
1 files changed, 134 insertions, 70 deletions
diff --git a/src/sync/future/semaphore_signal.rs b/src/sync/future/semaphore_signal.rs
index 829860b..f31d37a 100644
--- a/src/sync/future/semaphore_signal.rs
+++ b/src/sync/future/semaphore_signal.rs
@@ -7,29 +7,28 @@
// notice may not be copied, modified, or distributed except
// according to those terms.
-use std::sync::atomic::AtomicBool;
-use std::sync::atomic::Ordering;
-use std::sync::Arc;
-use std::sync::Mutex;
-
-use crate::buffer::BufferAccess;
-use crate::command_buffer::submit::SubmitAnyBuilder;
-use crate::command_buffer::submit::SubmitCommandBufferBuilder;
-use crate::command_buffer::submit::SubmitSemaphoresWaitBuilder;
-use crate::device::Device;
-use crate::device::DeviceOwned;
-use crate::device::Queue;
-use crate::image::ImageAccess;
-use crate::image::ImageLayout;
-use crate::sync::AccessCheckError;
-use crate::sync::AccessFlags;
-use crate::sync::FlushError;
-use crate::sync::GpuFuture;
-use crate::sync::PipelineStages;
-use crate::sync::Semaphore;
+use super::{AccessCheckError, FlushError, GpuFuture, SubmitAnyBuilder};
+use crate::{
+ buffer::Buffer,
+ command_buffer::{SemaphoreSubmitInfo, SubmitInfo},
+ device::{Device, DeviceOwned, Queue},
+ image::{sys::Image, ImageLayout},
+ swapchain::Swapchain,
+ sync::{future::AccessError, semaphore::Semaphore, PipelineStages},
+ DeviceSize,
+};
+use parking_lot::Mutex;
+use smallvec::smallvec;
+use std::{
+ ops::Range,
+ sync::{
+ atomic::{AtomicBool, Ordering},
+ Arc,
+ },
+ thread,
+};
/// Builds a new semaphore signal future.
-#[inline]
pub fn then_signal_semaphore<F>(future: F) -> SemaphoreSignalFuture<F>
where
F: GpuFuture,
@@ -40,7 +39,7 @@ where
SemaphoreSignalFuture {
previous: future,
- semaphore: Semaphore::from_pool(device).unwrap(),
+ semaphore: Arc::new(Semaphore::from_pool(device).unwrap()),
wait_submitted: Mutex::new(false),
finished: AtomicBool::new(false),
}
@@ -54,7 +53,7 @@ where
F: GpuFuture,
{
previous: F,
- semaphore: Semaphore,
+ semaphore: Arc<Semaphore>,
// True if the signaling command has already been submitted.
// If flush is called multiple times, we want to block so that only one flushing is executed.
// Therefore we use a `Mutex<bool>` and not an `AtomicBool`.
@@ -66,58 +65,120 @@ unsafe impl<F> GpuFuture for SemaphoreSignalFuture<F>
where
F: GpuFuture,
{
- #[inline]
fn cleanup_finished(&mut self) {
self.previous.cleanup_finished();
}
- #[inline]
unsafe fn build_submission(&self) -> Result<SubmitAnyBuilder, FlushError> {
// Flushing the signaling part, since it must always be submitted before the waiting part.
self.flush()?;
+ let sem = smallvec![self.semaphore.clone()];
- let mut sem = SubmitSemaphoresWaitBuilder::new();
- sem.add_wait_semaphore(&self.semaphore);
Ok(SubmitAnyBuilder::SemaphoresWait(sem))
}
fn flush(&self) -> Result<(), FlushError> {
unsafe {
- let mut wait_submitted = self.wait_submitted.lock().unwrap();
+ let mut wait_submitted = self.wait_submitted.lock();
if *wait_submitted {
return Ok(());
}
- let queue = self.previous.queue().unwrap().clone();
+ let queue = self.previous.queue().unwrap();
match self.previous.build_submission()? {
SubmitAnyBuilder::Empty => {
- let mut builder = SubmitCommandBufferBuilder::new();
- builder.add_signal_semaphore(&self.semaphore);
- builder.submit(&queue)?;
+ queue.with(|mut q| {
+ q.submit_unchecked(
+ [SubmitInfo {
+ signal_semaphores: vec![SemaphoreSubmitInfo::semaphore(
+ self.semaphore.clone(),
+ )],
+ ..Default::default()
+ }],
+ None,
+ )
+ })?;
}
- SubmitAnyBuilder::SemaphoresWait(sem) => {
- let mut builder: SubmitCommandBufferBuilder = sem.into();
- builder.add_signal_semaphore(&self.semaphore);
- builder.submit(&queue)?;
+ SubmitAnyBuilder::SemaphoresWait(semaphores) => {
+ queue.with(|mut q| {
+ q.submit_unchecked(
+ [SubmitInfo {
+ wait_semaphores: semaphores
+ .into_iter()
+ .map(|semaphore| {
+ SemaphoreSubmitInfo {
+ // TODO: correct stages ; hard
+ stages: PipelineStages::ALL_COMMANDS,
+ ..SemaphoreSubmitInfo::semaphore(semaphore)
+ }
+ })
+ .collect(),
+ signal_semaphores: vec![SemaphoreSubmitInfo::semaphore(
+ self.semaphore.clone(),
+ )],
+ ..Default::default()
+ }],
+ None,
+ )
+ })?;
}
- SubmitAnyBuilder::CommandBuffer(mut builder) => {
- debug_assert_eq!(builder.num_signal_semaphores(), 0);
- builder.add_signal_semaphore(&self.semaphore);
- builder.submit(&queue)?;
+ SubmitAnyBuilder::CommandBuffer(mut submit_info, fence) => {
+ debug_assert!(submit_info.signal_semaphores.is_empty());
+
+ submit_info
+ .signal_semaphores
+ .push(SemaphoreSubmitInfo::semaphore(self.semaphore.clone()));
+
+ queue.with(|mut q| {
+ q.submit_with_future(submit_info, fence, &self.previous, &queue)
+ })?;
}
- SubmitAnyBuilder::BindSparse(_) => {
+ SubmitAnyBuilder::BindSparse(_, _) => {
unimplemented!() // TODO: how to do that?
/*debug_assert_eq!(builder.num_signal_semaphores(), 0);
builder.add_signal_semaphore(&self.semaphore);
builder.submit(&queue)?;*/
}
- SubmitAnyBuilder::QueuePresent(present) => {
- present.submit(&queue)?;
- let mut builder = SubmitCommandBufferBuilder::new();
- builder.add_signal_semaphore(&self.semaphore);
- builder.submit(&queue)?; // FIXME: problematic because if we return an error and flush() is called again, then we'll submit the present twice
+ SubmitAnyBuilder::QueuePresent(present_info) => {
+ // VUID-VkPresentIdKHR-presentIds-04999
+ for swapchain_info in &present_info.swapchain_infos {
+ if swapchain_info.present_id.map_or(false, |present_id| {
+ !swapchain_info.swapchain.try_claim_present_id(present_id)
+ }) {
+ return Err(FlushError::PresentIdLessThanOrEqual);
+ }
+
+ match self.previous.check_swapchain_image_acquired(
+ &swapchain_info.swapchain,
+ swapchain_info.image_index,
+ true,
+ ) {
+ Ok(_) => (),
+ Err(AccessCheckError::Unknown) => {
+ return Err(AccessError::SwapchainImageNotAcquired.into())
+ }
+ Err(AccessCheckError::Denied(e)) => return Err(e.into()),
+ }
+ }
+
+ queue.with(|mut q| {
+ q.present_unchecked(present_info)?
+ .map(|r| r.map(|_| ()))
+ .fold(Ok(()), Result::and)?;
+ // FIXME: problematic because if we return an error and flush() is called again, then we'll submit the present twice
+ q.submit_unchecked(
+ [SubmitInfo {
+ signal_semaphores: vec![SemaphoreSubmitInfo::semaphore(
+ self.semaphore.clone(),
+ )],
+ ..Default::default()
+ }],
+ None,
+ )?;
+ Ok::<_, FlushError>(())
+ })?;
}
};
@@ -127,46 +188,52 @@ where
}
}
- #[inline]
unsafe fn signal_finished(&self) {
- debug_assert!(*self.wait_submitted.lock().unwrap());
+ debug_assert!(*self.wait_submitted.lock());
self.finished.store(true, Ordering::SeqCst);
self.previous.signal_finished();
}
- #[inline]
fn queue_change_allowed(&self) -> bool {
true
}
- #[inline]
fn queue(&self) -> Option<Arc<Queue>> {
self.previous.queue()
}
- #[inline]
fn check_buffer_access(
&self,
- buffer: &dyn BufferAccess,
+ buffer: &Buffer,
+ range: Range<DeviceSize>,
exclusive: bool,
queue: &Queue,
- ) -> Result<Option<(PipelineStages, AccessFlags)>, AccessCheckError> {
+ ) -> Result<(), AccessCheckError> {
self.previous
- .check_buffer_access(buffer, exclusive, queue)
- .map(|_| None)
+ .check_buffer_access(buffer, range, exclusive, queue)
}
- #[inline]
fn check_image_access(
&self,
- image: &dyn ImageAccess,
- layout: ImageLayout,
+ image: &Image,
+ range: Range<DeviceSize>,
exclusive: bool,
+ expected_layout: ImageLayout,
queue: &Queue,
- ) -> Result<Option<(PipelineStages, AccessFlags)>, AccessCheckError> {
+ ) -> Result<(), AccessCheckError> {
self.previous
- .check_image_access(image, layout, exclusive, queue)
- .map(|_| None)
+ .check_image_access(image, range, exclusive, expected_layout, queue)
+ }
+
+ #[inline]
+ fn check_swapchain_image_acquired(
+ &self,
+ swapchain: &Swapchain,
+ image_index: u32,
+ _before: bool,
+ ) -> Result<(), AccessCheckError> {
+ self.previous
+ .check_swapchain_image_acquired(swapchain, image_index, false)
}
}
@@ -174,7 +241,6 @@ unsafe impl<F> DeviceOwned for SemaphoreSignalFuture<F>
where
F: GpuFuture,
{
- #[inline]
fn device(&self) -> &Arc<Device> {
self.semaphore.device()
}
@@ -185,14 +251,12 @@ where
F: GpuFuture,
{
fn drop(&mut self) {
- unsafe {
- if !*self.finished.get_mut() {
- // TODO: handle errors?
- self.flush().unwrap();
- // Block until the queue finished.
- self.queue().unwrap().wait().unwrap();
- self.previous.signal_finished();
- }
+ if !*self.finished.get_mut() && !thread::panicking() {
+ // TODO: handle errors?
+ self.flush().unwrap();
+ // Block until the queue finished.
+ self.queue().unwrap().with(|mut q| q.wait_idle()).unwrap();
+ unsafe { self.previous.signal_finished() };
}
}
}