1 // Copyright (c) 2016 The vulkano developers
2 // Licensed under the Apache License, Version 2.0
3 // <LICENSE-APACHE or
4 // https://www.apache.org/licenses/LICENSE-2.0> or the MIT
5 // license <LICENSE-MIT or https://opensource.org/licenses/MIT>,
6 // at your option. All files in the project carrying such
7 // notice may not be copied, modified, or distributed except
8 // according to those terms.
9
10 use crate::buffer::TypedBufferAccess;
11 use crate::device::Device;
12 use crate::device::DeviceOwned;
13 use crate::DeviceSize;
14 use crate::VulkanObject;
15 use std::cmp;
16 use std::error;
17 use std::fmt;
18
19 /// Checks whether a copy buffer command is valid.
20 ///
21 /// # Panic
22 ///
23 /// - Panics if the source and destination were not created with `device`.
24 ///
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,25 pub fn check_copy_buffer<S, D, T>(
26 device: &Device,
27 source: &S,
28 destination: &D,
29 ) -> Result<CheckCopyBuffer, CheckCopyBufferError>
30 where
31 S: ?Sized + TypedBufferAccess<Content = T>,
32 D: ?Sized + TypedBufferAccess<Content = T>,
33 T: ?Sized,
34 {
35 assert_eq!(
36 source.inner().buffer.device().internal_object(),
37 device.internal_object()
38 );
39 assert_eq!(
40 destination.inner().buffer.device().internal_object(),
41 device.internal_object()
42 );
43
44 if !source.inner().buffer.usage().transfer_source {
45 return Err(CheckCopyBufferError::SourceMissingTransferUsage);
46 }
47
48 if !destination.inner().buffer.usage().transfer_destination {
49 return Err(CheckCopyBufferError::DestinationMissingTransferUsage);
50 }
51
52 let copy_size = cmp::min(source.size(), destination.size());
53
54 if source.conflict_key() == destination.conflict_key() {
55 return Err(CheckCopyBufferError::OverlappingRanges);
56 } else {
57 debug_assert!(destination.conflict_key() != source.conflict_key());
58 }
59
60 Ok(CheckCopyBuffer { copy_size })
61 }
62
63 /// Information returned if `check_copy_buffer` succeeds.
64 pub struct CheckCopyBuffer {
65 /// Size of the transfer in bytes.
66 ///
67 /// If the size of the source and destination are not equal, then the value is equal to the
68 /// smallest of the two.
69 pub copy_size: DeviceSize,
70 }
71
72 /// Error that can happen from `check_copy_buffer`.
73 #[derive(Debug, Copy, Clone)]
74 pub enum CheckCopyBufferError {
75 /// The source buffer is missing the transfer source usage.
76 SourceMissingTransferUsage,
77 /// The destination buffer is missing the transfer destination usage.
78 DestinationMissingTransferUsage,
79 /// The source and destination are overlapping.
80 OverlappingRanges,
81 }
82
83 impl error::Error for CheckCopyBufferError {}
84
85 impl fmt::Display for CheckCopyBufferError {
86 #[inline]
fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error>87 fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
88 write!(
89 fmt,
90 "{}",
91 match *self {
92 CheckCopyBufferError::SourceMissingTransferUsage => {
93 "the source buffer is missing the transfer source usage"
94 }
95 CheckCopyBufferError::DestinationMissingTransferUsage => {
96 "the destination buffer is missing the transfer destination usage"
97 }
98 CheckCopyBufferError::OverlappingRanges =>
99 "the source and destination are overlapping",
100 }
101 )
102 }
103 }
104