diff options
Diffstat (limited to 'src/command_buffer/validity/copy_buffer.rs')
-rw-r--r-- | src/command_buffer/validity/copy_buffer.rs | 103 |
1 files changed, 103 insertions, 0 deletions
diff --git a/src/command_buffer/validity/copy_buffer.rs b/src/command_buffer/validity/copy_buffer.rs new file mode 100644 index 0000000..3691860 --- /dev/null +++ b/src/command_buffer/validity/copy_buffer.rs @@ -0,0 +1,103 @@ +// 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::TypedBufferAccess; +use crate::device::Device; +use crate::device::DeviceOwned; +use crate::DeviceSize; +use crate::VulkanObject; +use std::cmp; +use std::error; +use std::fmt; + +/// Checks whether a copy buffer command is valid. +/// +/// # Panic +/// +/// - Panics if the source and destination were not created with `device`. +/// +pub fn check_copy_buffer<S, D, T>( + device: &Device, + source: &S, + destination: &D, +) -> Result<CheckCopyBuffer, CheckCopyBufferError> +where + S: ?Sized + TypedBufferAccess<Content = T>, + D: ?Sized + TypedBufferAccess<Content = T>, + T: ?Sized, +{ + assert_eq!( + source.inner().buffer.device().internal_object(), + device.internal_object() + ); + assert_eq!( + destination.inner().buffer.device().internal_object(), + device.internal_object() + ); + + if !source.inner().buffer.usage().transfer_source { + return Err(CheckCopyBufferError::SourceMissingTransferUsage); + } + + if !destination.inner().buffer.usage().transfer_destination { + return Err(CheckCopyBufferError::DestinationMissingTransferUsage); + } + + let copy_size = cmp::min(source.size(), destination.size()); + + if source.conflict_key() == destination.conflict_key() { + return Err(CheckCopyBufferError::OverlappingRanges); + } else { + debug_assert!(destination.conflict_key() != source.conflict_key()); + } + + Ok(CheckCopyBuffer { copy_size }) +} + +/// Information returned if `check_copy_buffer` succeeds. +pub struct CheckCopyBuffer { + /// Size of the transfer in bytes. + /// + /// If the size of the source and destination are not equal, then the value is equal to the + /// smallest of the two. + pub copy_size: DeviceSize, +} + +/// Error that can happen from `check_copy_buffer`. +#[derive(Debug, Copy, Clone)] +pub enum CheckCopyBufferError { + /// The source buffer is missing the transfer source usage. + SourceMissingTransferUsage, + /// The destination buffer is missing the transfer destination usage. + DestinationMissingTransferUsage, + /// The source and destination are overlapping. + OverlappingRanges, +} + +impl error::Error for CheckCopyBufferError {} + +impl fmt::Display for CheckCopyBufferError { + #[inline] + fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { + write!( + fmt, + "{}", + match *self { + CheckCopyBufferError::SourceMissingTransferUsage => { + "the source buffer is missing the transfer source usage" + } + CheckCopyBufferError::DestinationMissingTransferUsage => { + "the destination buffer is missing the transfer destination usage" + } + CheckCopyBufferError::OverlappingRanges => + "the source and destination are overlapping", + } + ) + } +} |