aboutsummaryrefslogtreecommitdiff
path: root/src/command_buffer/traits.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/command_buffer/traits.rs')
-rw-r--r--src/command_buffer/traits.rs528
1 files changed, 0 insertions, 528 deletions
diff --git a/src/command_buffer/traits.rs b/src/command_buffer/traits.rs
deleted file mode 100644
index 5252073..0000000
--- a/src/command_buffer/traits.rs
+++ /dev/null
@@ -1,528 +0,0 @@
-// Copyright (c) 2016 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 crate::buffer::BufferAccess;
-use crate::command_buffer::submit::SubmitAnyBuilder;
-use crate::command_buffer::submit::SubmitCommandBufferBuilder;
-use crate::command_buffer::sys::UnsafeCommandBuffer;
-use crate::command_buffer::CommandBufferInheritance;
-use crate::command_buffer::ImageUninitializedSafe;
-use crate::device::Device;
-use crate::device::DeviceOwned;
-use crate::device::Queue;
-use crate::image::ImageAccess;
-use crate::image::ImageLayout;
-use crate::render_pass::FramebufferAbstract;
-use crate::sync::now;
-use crate::sync::AccessCheckError;
-use crate::sync::AccessError;
-use crate::sync::AccessFlags;
-use crate::sync::FlushError;
-use crate::sync::GpuFuture;
-use crate::sync::NowFuture;
-use crate::sync::PipelineMemoryAccess;
-use crate::sync::PipelineStages;
-use crate::SafeDeref;
-use crate::VulkanObject;
-use std::borrow::Cow;
-use std::error;
-use std::fmt;
-use std::sync::atomic::AtomicBool;
-use std::sync::atomic::Ordering;
-use std::sync::Arc;
-use std::sync::Mutex;
-
-pub unsafe trait PrimaryCommandBuffer: DeviceOwned {
- /// Returns the underlying `UnsafeCommandBuffer` of this command buffer.
- fn inner(&self) -> &UnsafeCommandBuffer;
-
- /// Checks whether this command buffer is allowed to be submitted after the `future` and on
- /// the given queue, and if so locks it.
- ///
- /// If you call this function, then you should call `unlock` afterwards.
- fn lock_submit(
- &self,
- future: &dyn GpuFuture,
- queue: &Queue,
- ) -> Result<(), CommandBufferExecError>;
-
- /// Unlocks the command buffer. Should be called once for each call to `lock_submit`.
- ///
- /// # Safety
- ///
- /// Must not be called if you haven't called `lock_submit` before.
- unsafe fn unlock(&self);
-
- /// Executes this command buffer on a queue.
- ///
- /// This function returns an object that implements the `GpuFuture` trait. See the
- /// documentation of the `sync` module for more information.
- ///
- /// The command buffer is not actually executed until you call `flush()` on the object.
- /// You are encouraged to chain together as many futures as possible before calling `flush()`,
- /// and call `.then_signal_future()` before doing so. Note however that once you called
- /// `execute()` there is no way to cancel the execution, even if you didn't flush yet.
- ///
- /// > **Note**: In the future this function may return `-> impl GpuFuture` instead of a
- /// > concrete type.
- ///
- /// > **Note**: This is just a shortcut for `execute_after(vulkano::sync::now(), queue)`.
- ///
- /// # Panic
- ///
- /// Panics if the device of the command buffer is not the same as the device of the future.
- #[inline]
- fn execute(
- self,
- queue: Arc<Queue>,
- ) -> Result<CommandBufferExecFuture<NowFuture, Self>, CommandBufferExecError>
- where
- Self: Sized + 'static,
- {
- let device = queue.device().clone();
- self.execute_after(now(device), queue)
- }
-
- /// Executes the command buffer after an existing future.
- ///
- /// This function returns an object that implements the `GpuFuture` trait. See the
- /// documentation of the `sync` module for more information.
- ///
- /// The command buffer is not actually executed until you call `flush()` on the object.
- /// You are encouraged to chain together as many futures as possible before calling `flush()`,
- /// and call `.then_signal_future()` before doing so. Note however that once you called
- /// `execute()` there is no way to cancel the execution, even if you didn't flush yet.
- ///
- /// > **Note**: In the future this function may return `-> impl GpuFuture` instead of a
- /// > concrete type.
- ///
- /// This function requires the `'static` lifetime to be on the command buffer. This is because
- /// this function returns a `CommandBufferExecFuture` whose job is to lock resources and keep
- /// them alive while they are in use by the GPU. If `'static` wasn't required, you could call
- /// `std::mem::forget` on that object and "unlock" these resources. For more information about
- /// this problem, search the web for "rust thread scoped leakpocalypse".
- ///
- /// # Panic
- ///
- /// Panics if the device of the command buffer is not the same as the device of the future.
- #[inline]
- fn execute_after<F>(
- self,
- future: F,
- queue: Arc<Queue>,
- ) -> Result<CommandBufferExecFuture<F, Self>, CommandBufferExecError>
- where
- Self: Sized + 'static,
- F: GpuFuture,
- {
- assert_eq!(
- self.device().internal_object(),
- future.device().internal_object()
- );
-
- if !future.queue_change_allowed() {
- assert!(future.queue().unwrap().is_same(&queue));
- }
-
- self.lock_submit(&future, &queue)?;
-
- Ok(CommandBufferExecFuture {
- previous: future,
- command_buffer: self,
- queue,
- submitted: Mutex::new(false),
- finished: AtomicBool::new(false),
- })
- }
-
- fn check_buffer_access(
- &self,
- buffer: &dyn BufferAccess,
- exclusive: bool,
- queue: &Queue,
- ) -> Result<Option<(PipelineStages, AccessFlags)>, AccessCheckError>;
-
- fn check_image_access(
- &self,
- image: &dyn ImageAccess,
- layout: ImageLayout,
- exclusive: bool,
- queue: &Queue,
- ) -> Result<Option<(PipelineStages, AccessFlags)>, AccessCheckError>;
-}
-
-unsafe impl<T> PrimaryCommandBuffer for T
-where
- T: SafeDeref,
- T::Target: PrimaryCommandBuffer,
-{
- #[inline]
- fn inner(&self) -> &UnsafeCommandBuffer {
- (**self).inner()
- }
-
- #[inline]
- fn lock_submit(
- &self,
- future: &dyn GpuFuture,
- queue: &Queue,
- ) -> Result<(), CommandBufferExecError> {
- (**self).lock_submit(future, queue)
- }
-
- #[inline]
- unsafe fn unlock(&self) {
- (**self).unlock();
- }
-
- #[inline]
- fn check_buffer_access(
- &self,
- buffer: &dyn BufferAccess,
- exclusive: bool,
- queue: &Queue,
- ) -> Result<Option<(PipelineStages, AccessFlags)>, AccessCheckError> {
- (**self).check_buffer_access(buffer, exclusive, queue)
- }
-
- #[inline]
- fn check_image_access(
- &self,
- image: &dyn ImageAccess,
- layout: ImageLayout,
- exclusive: bool,
- queue: &Queue,
- ) -> Result<Option<(PipelineStages, AccessFlags)>, AccessCheckError> {
- (**self).check_image_access(image, layout, exclusive, queue)
- }
-}
-
-pub unsafe trait SecondaryCommandBuffer: DeviceOwned {
- /// Returns the underlying `UnsafeCommandBuffer` of this command buffer.
- fn inner(&self) -> &UnsafeCommandBuffer;
-
- /// Checks whether this command buffer is allowed to be recorded to a command buffer,
- /// and if so locks it.
- ///
- /// If you call this function, then you should call `unlock` afterwards.
- fn lock_record(&self) -> Result<(), CommandBufferExecError>;
-
- /// Unlocks the command buffer. Should be called once for each call to `lock_record`.
- ///
- /// # Safety
- ///
- /// Must not be called if you haven't called `lock_record` before.
- unsafe fn unlock(&self);
-
- /// Returns a `CommandBufferInheritance` value describing the properties that the command
- /// buffer inherits from its parent primary command buffer.
- fn inheritance(&self) -> CommandBufferInheritance<&dyn FramebufferAbstract>;
-
- /// Returns the number of buffers accessed by this command buffer.
- fn num_buffers(&self) -> usize;
-
- /// Returns the `index`th buffer of this command buffer, or `None` if out of range.
- ///
- /// The valid range is between 0 and `num_buffers()`.
- fn buffer(&self, index: usize) -> Option<(&dyn BufferAccess, PipelineMemoryAccess)>;
-
- /// Returns the number of images accessed by this command buffer.
- fn num_images(&self) -> usize;
-
- /// Returns the `index`th image of this command buffer, or `None` if out of range.
- ///
- /// The valid range is between 0 and `num_images()`.
- fn image(
- &self,
- index: usize,
- ) -> Option<(
- &dyn ImageAccess,
- PipelineMemoryAccess,
- ImageLayout,
- ImageLayout,
- ImageUninitializedSafe,
- )>;
-}
-
-unsafe impl<T> SecondaryCommandBuffer for T
-where
- T: SafeDeref,
- T::Target: SecondaryCommandBuffer,
-{
- #[inline]
- fn inner(&self) -> &UnsafeCommandBuffer {
- (**self).inner()
- }
-
- #[inline]
- fn lock_record(&self) -> Result<(), CommandBufferExecError> {
- (**self).lock_record()
- }
-
- #[inline]
- unsafe fn unlock(&self) {
- (**self).unlock();
- }
-
- #[inline]
- fn inheritance(&self) -> CommandBufferInheritance<&dyn FramebufferAbstract> {
- (**self).inheritance()
- }
-
- #[inline]
- fn num_buffers(&self) -> usize {
- (**self).num_buffers()
- }
-
- #[inline]
- fn buffer(&self, index: usize) -> Option<(&dyn BufferAccess, PipelineMemoryAccess)> {
- (**self).buffer(index)
- }
-
- #[inline]
- fn num_images(&self) -> usize {
- (**self).num_images()
- }
-
- #[inline]
- fn image(
- &self,
- index: usize,
- ) -> Option<(
- &dyn ImageAccess,
- PipelineMemoryAccess,
- ImageLayout,
- ImageLayout,
- ImageUninitializedSafe,
- )> {
- (**self).image(index)
- }
-}
-
-/// Represents a command buffer being executed by the GPU and the moment when the execution
-/// finishes.
-#[must_use = "Dropping this object will immediately block the thread until the GPU has finished processing the submission"]
-pub struct CommandBufferExecFuture<F, Cb>
-where
- F: GpuFuture,
- Cb: PrimaryCommandBuffer,
-{
- previous: F,
- command_buffer: Cb,
- queue: Arc<Queue>,
- // True if the command buffer 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`.
- submitted: Mutex<bool>,
- finished: AtomicBool,
-}
-
-unsafe impl<F, Cb> GpuFuture for CommandBufferExecFuture<F, Cb>
-where
- F: GpuFuture,
- Cb: PrimaryCommandBuffer,
-{
- #[inline]
- fn cleanup_finished(&mut self) {
- self.previous.cleanup_finished();
- }
-
- unsafe fn build_submission(&self) -> Result<SubmitAnyBuilder, FlushError> {
- Ok(match self.previous.build_submission()? {
- SubmitAnyBuilder::Empty => {
- let mut builder = SubmitCommandBufferBuilder::new();
- builder.add_command_buffer(self.command_buffer.inner());
- SubmitAnyBuilder::CommandBuffer(builder)
- }
- SubmitAnyBuilder::SemaphoresWait(sem) => {
- let mut builder: SubmitCommandBufferBuilder = sem.into();
- builder.add_command_buffer(self.command_buffer.inner());
- SubmitAnyBuilder::CommandBuffer(builder)
- }
- SubmitAnyBuilder::CommandBuffer(mut builder) => {
- // FIXME: add pipeline barrier
- builder.add_command_buffer(self.command_buffer.inner());
- SubmitAnyBuilder::CommandBuffer(builder)
- }
- SubmitAnyBuilder::QueuePresent(_) | SubmitAnyBuilder::BindSparse(_) => {
- unimplemented!() // TODO:
- /*present.submit(); // TODO: wrong
- let mut builder = SubmitCommandBufferBuilder::new();
- builder.add_command_buffer(self.command_buffer.inner());
- SubmitAnyBuilder::CommandBuffer(builder)*/
- }
- })
- }
-
- #[inline]
- fn flush(&self) -> Result<(), FlushError> {
- unsafe {
- let mut submitted = self.submitted.lock().unwrap();
- if *submitted {
- return Ok(());
- }
-
- let queue = self.queue.clone();
-
- match self.build_submission()? {
- SubmitAnyBuilder::Empty => {}
- SubmitAnyBuilder::CommandBuffer(builder) => {
- builder.submit(&queue)?;
- }
- _ => unreachable!(),
- };
-
- // Only write `true` here in order to try again next time if we failed to submit.
- *submitted = true;
- Ok(())
- }
- }
-
- #[inline]
- unsafe fn signal_finished(&self) {
- if self.finished.swap(true, Ordering::SeqCst) == false {
- self.command_buffer.unlock();
- }
-
- self.previous.signal_finished();
- }
-
- #[inline]
- fn queue_change_allowed(&self) -> bool {
- false
- }
-
- #[inline]
- fn queue(&self) -> Option<Arc<Queue>> {
- Some(self.queue.clone())
- }
-
- #[inline]
- fn check_buffer_access(
- &self,
- buffer: &dyn BufferAccess,
- exclusive: bool,
- queue: &Queue,
- ) -> Result<Option<(PipelineStages, AccessFlags)>, AccessCheckError> {
- match self
- .command_buffer
- .check_buffer_access(buffer, exclusive, queue)
- {
- Ok(v) => Ok(v),
- Err(AccessCheckError::Denied(err)) => Err(AccessCheckError::Denied(err)),
- Err(AccessCheckError::Unknown) => {
- self.previous.check_buffer_access(buffer, exclusive, queue)
- }
- }
- }
-
- #[inline]
- fn check_image_access(
- &self,
- image: &dyn ImageAccess,
- layout: ImageLayout,
- exclusive: bool,
- queue: &Queue,
- ) -> Result<Option<(PipelineStages, AccessFlags)>, AccessCheckError> {
- match self
- .command_buffer
- .check_image_access(image, layout, exclusive, queue)
- {
- Ok(v) => Ok(v),
- Err(AccessCheckError::Denied(err)) => Err(AccessCheckError::Denied(err)),
- Err(AccessCheckError::Unknown) => self
- .previous
- .check_image_access(image, layout, exclusive, queue),
- }
- }
-}
-
-unsafe impl<F, Cb> DeviceOwned for CommandBufferExecFuture<F, Cb>
-where
- F: GpuFuture,
- Cb: PrimaryCommandBuffer,
-{
- #[inline]
- fn device(&self) -> &Arc<Device> {
- self.command_buffer.device()
- }
-}
-
-impl<F, Cb> Drop for CommandBufferExecFuture<F, Cb>
-where
- F: GpuFuture,
- Cb: PrimaryCommandBuffer,
-{
- fn drop(&mut self) {
- unsafe {
- if !*self.finished.get_mut() {
- // TODO: handle errors?
- self.flush().unwrap();
- // Block until the queue finished.
- self.queue.wait().unwrap();
- self.command_buffer.unlock();
- self.previous.signal_finished();
- }
- }
- }
-}
-
-/// Error that can happen when attempting to execute a command buffer.
-#[derive(Clone, Debug, PartialEq, Eq)]
-pub enum CommandBufferExecError {
- /// Access to a resource has been denied.
- AccessError {
- error: AccessError,
- command_name: Cow<'static, str>,
- command_param: Cow<'static, str>,
- command_offset: usize,
- },
-
- /// The command buffer or one of the secondary command buffers it executes was created with the
- /// "one time submit" flag, but has already been submitted it the past.
- OneTimeSubmitAlreadySubmitted,
-
- /// The command buffer or one of the secondary command buffers it executes is already in use by
- /// the GPU and was not created with the "concurrent" flag.
- ExclusiveAlreadyInUse,
- // TODO: missing entries (eg. wrong queue family, secondary command buffer)
-}
-
-impl error::Error for CommandBufferExecError {
- #[inline]
- fn source(&self) -> Option<&(dyn error::Error + 'static)> {
- match *self {
- CommandBufferExecError::AccessError { ref error, .. } => Some(error),
- _ => None,
- }
- }
-}
-
-impl fmt::Display for CommandBufferExecError {
- #[inline]
- fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
- write!(
- fmt,
- "{}",
- match *self {
- CommandBufferExecError::AccessError { .. } =>
- "access to a resource has been denied",
- CommandBufferExecError::OneTimeSubmitAlreadySubmitted => {
- "the command buffer or one of the secondary command buffers it executes was \
- created with the \"one time submit\" flag, but has already been submitted in \
- the past"
- }
- CommandBufferExecError::ExclusiveAlreadyInUse => {
- "the command buffer or one of the secondary command buffers it executes is \
- already in use was not created with the \"concurrent\" flag"
- }
- }
- )
- }
-}