diff options
Diffstat (limited to 'src/sync/future/join.rs')
-rw-r--r-- | src/sync/future/join.rs | 268 |
1 files changed, 0 insertions, 268 deletions
diff --git a/src/sync/future/join.rs b/src/sync/future/join.rs deleted file mode 100644 index c45a764..0000000 --- a/src/sync/future/join.rs +++ /dev/null @@ -1,268 +0,0 @@ -// Copyright (c) 2017 The vulkano developers -// Licensed under the Apache License, Version 2.0 -// <LICENSE-APACHE or -// https://www.apache.org/licenses/LICENSE-2.0> or the MIT -// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, -// at your option. All files in the project carrying such -// notice may not be copied, modified, or distributed except -// according to those terms. - -use std::sync::Arc; - -use crate::buffer::BufferAccess; -use crate::command_buffer::submit::SubmitAnyBuilder; -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::VulkanObject; - -/// Joins two futures together. -// TODO: handle errors -#[inline] -pub fn join<F, S>(first: F, second: S) -> JoinFuture<F, S> -where - F: GpuFuture, - S: GpuFuture, -{ - assert_eq!( - first.device().internal_object(), - second.device().internal_object() - ); - - if !first.queue_change_allowed() && !second.queue_change_allowed() { - assert!(first.queue().unwrap().is_same(&second.queue().unwrap())); - } - - JoinFuture { - first: first, - second: second, - } -} - -/// Two futures joined into one. -#[must_use] -pub struct JoinFuture<A, B> { - first: A, - second: B, -} - -unsafe impl<A, B> DeviceOwned for JoinFuture<A, B> -where - A: DeviceOwned, - B: DeviceOwned, -{ - #[inline] - fn device(&self) -> &Arc<Device> { - let device = self.first.device(); - debug_assert_eq!( - self.second.device().internal_object(), - device.internal_object() - ); - device - } -} - -unsafe impl<A, B> GpuFuture for JoinFuture<A, B> -where - A: GpuFuture, - B: GpuFuture, -{ - #[inline] - fn cleanup_finished(&mut self) { - self.first.cleanup_finished(); - self.second.cleanup_finished(); - } - - #[inline] - fn flush(&self) -> Result<(), FlushError> { - // Since each future remembers whether it has been flushed, there's no safety issue here - // if we call this function multiple times. - self.first.flush()?; - self.second.flush()?; - Ok(()) - } - - #[inline] - unsafe fn build_submission(&self) -> Result<SubmitAnyBuilder, FlushError> { - // TODO: review this function - let first = self.first.build_submission()?; - let second = self.second.build_submission()?; - - // In some cases below we have to submit previous command buffers already, this s done by flushing previous. - // Since the implementation should remember being flushed it's safe to call build_submission multiple times - Ok(match (first, second) { - (SubmitAnyBuilder::Empty, b) => b, - (a, SubmitAnyBuilder::Empty) => a, - (SubmitAnyBuilder::SemaphoresWait(mut a), SubmitAnyBuilder::SemaphoresWait(b)) => { - a.merge(b); - SubmitAnyBuilder::SemaphoresWait(a) - } - (SubmitAnyBuilder::SemaphoresWait(a), SubmitAnyBuilder::CommandBuffer(b)) => { - self.second.flush()?; - SubmitAnyBuilder::SemaphoresWait(a) - } - (SubmitAnyBuilder::CommandBuffer(a), SubmitAnyBuilder::SemaphoresWait(b)) => { - self.first.flush()?; - SubmitAnyBuilder::SemaphoresWait(b) - } - (SubmitAnyBuilder::SemaphoresWait(a), SubmitAnyBuilder::QueuePresent(b)) => { - self.second.flush()?; - SubmitAnyBuilder::SemaphoresWait(a) - } - (SubmitAnyBuilder::QueuePresent(a), SubmitAnyBuilder::SemaphoresWait(b)) => { - self.first.flush()?; - SubmitAnyBuilder::SemaphoresWait(b) - } - (SubmitAnyBuilder::SemaphoresWait(a), SubmitAnyBuilder::BindSparse(b)) => { - self.second.flush()?; - SubmitAnyBuilder::SemaphoresWait(a) - } - (SubmitAnyBuilder::BindSparse(a), SubmitAnyBuilder::SemaphoresWait(b)) => { - self.first.flush()?; - SubmitAnyBuilder::SemaphoresWait(b) - } - (SubmitAnyBuilder::CommandBuffer(a), SubmitAnyBuilder::CommandBuffer(b)) => { - // TODO: we may want to add debug asserts here - let new = a.merge(b); - SubmitAnyBuilder::CommandBuffer(new) - } - (SubmitAnyBuilder::QueuePresent(a), SubmitAnyBuilder::QueuePresent(b)) => { - self.first.flush()?; - self.second.flush()?; - SubmitAnyBuilder::Empty - } - (SubmitAnyBuilder::CommandBuffer(a), SubmitAnyBuilder::QueuePresent(b)) => { - unimplemented!() - } - (SubmitAnyBuilder::QueuePresent(a), SubmitAnyBuilder::CommandBuffer(b)) => { - unimplemented!() - } - (SubmitAnyBuilder::BindSparse(a), SubmitAnyBuilder::QueuePresent(b)) => { - unimplemented!() - } - (SubmitAnyBuilder::QueuePresent(a), SubmitAnyBuilder::BindSparse(b)) => { - unimplemented!() - } - (SubmitAnyBuilder::BindSparse(a), SubmitAnyBuilder::CommandBuffer(b)) => { - unimplemented!() - } - (SubmitAnyBuilder::CommandBuffer(a), SubmitAnyBuilder::BindSparse(b)) => { - unimplemented!() - } - (SubmitAnyBuilder::BindSparse(mut a), SubmitAnyBuilder::BindSparse(b)) => { - match a.merge(b) { - Ok(()) => SubmitAnyBuilder::BindSparse(a), - Err(_) => { - // TODO: this happens if both bind sparse have been given a fence already - // annoying, but not impossible, to handle - unimplemented!() - } - } - } - }) - } - - #[inline] - unsafe fn signal_finished(&self) { - self.first.signal_finished(); - self.second.signal_finished(); - } - - #[inline] - fn queue_change_allowed(&self) -> bool { - self.first.queue_change_allowed() && self.second.queue_change_allowed() - } - - #[inline] - fn queue(&self) -> Option<Arc<Queue>> { - match (self.first.queue(), self.second.queue()) { - (Some(q1), Some(q2)) => { - if q1.is_same(&q2) { - Some(q1) - } else if self.first.queue_change_allowed() { - Some(q2) - } else if self.second.queue_change_allowed() { - Some(q1) - } else { - None - } - } - (Some(q), None) => Some(q), - (None, Some(q)) => Some(q), - (None, None) => None, - } - } - - #[inline] - fn check_buffer_access( - &self, - buffer: &dyn BufferAccess, - exclusive: bool, - queue: &Queue, - ) -> Result<Option<(PipelineStages, AccessFlags)>, AccessCheckError> { - let first = self.first.check_buffer_access(buffer, exclusive, queue); - let second = self.second.check_buffer_access(buffer, exclusive, queue); - debug_assert!( - !exclusive || !(first.is_ok() && second.is_ok()), - "Two futures gave exclusive access to the same resource" - ); - match (first, second) { - (v, Err(AccessCheckError::Unknown)) => v, - (Err(AccessCheckError::Unknown), v) => v, - (Err(AccessCheckError::Denied(e1)), Err(AccessCheckError::Denied(e2))) => { - Err(AccessCheckError::Denied(e1)) - } // TODO: which one? - (Ok(_), Err(AccessCheckError::Denied(_))) - | (Err(AccessCheckError::Denied(_)), Ok(_)) => panic!( - "Contradictory information \ - between two futures" - ), - (Ok(None), Ok(None)) => Ok(None), - (Ok(Some(a)), Ok(None)) | (Ok(None), Ok(Some(a))) => Ok(Some(a)), - (Ok(Some((a1, a2))), Ok(Some((b1, b2)))) => Ok(Some((a1 | b1, a2 | b2))), - } - } - - #[inline] - fn check_image_access( - &self, - image: &dyn ImageAccess, - layout: ImageLayout, - exclusive: bool, - queue: &Queue, - ) -> Result<Option<(PipelineStages, AccessFlags)>, AccessCheckError> { - let first = self - .first - .check_image_access(image, layout, exclusive, queue); - let second = self - .second - .check_image_access(image, layout, exclusive, queue); - debug_assert!( - !exclusive || !(first.is_ok() && second.is_ok()), - "Two futures gave exclusive access to the same resource" - ); - match (first, second) { - (v, Err(AccessCheckError::Unknown)) => v, - (Err(AccessCheckError::Unknown), v) => v, - (Err(AccessCheckError::Denied(e1)), Err(AccessCheckError::Denied(e2))) => { - Err(AccessCheckError::Denied(e1)) - } // TODO: which one? - (Ok(_), Err(AccessCheckError::Denied(_))) - | (Err(AccessCheckError::Denied(_)), Ok(_)) => panic!( - "Contradictory information \ - between two futures" - ), - (Ok(None), Ok(None)) => Ok(None), - (Ok(Some(a)), Ok(None)) | (Ok(None), Ok(Some(a))) => Ok(Some(a)), - (Ok(Some((a1, a2))), Ok(Some((b1, b2)))) => Ok(Some((a1 | b1, a2 | b2))), - } - } -} |