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 //! Low level implementation of buffers.
11 //!
12 //! This module contains low-level wrappers around the Vulkan buffer types. All
13 //! other buffer types of this library, and all custom buffer types
14 //! that you create must wrap around the types in this module.
15 
16 use super::{Buffer, BufferCreateFlags, BufferError, BufferMemory, BufferUsage};
17 use crate::{
18     device::{Device, DeviceOwned},
19     macros::impl_id_counter,
20     memory::{
21         allocator::{AllocationType, DeviceLayout, MemoryAlloc},
22         is_aligned, DedicatedTo, ExternalMemoryHandleTypes, MemoryAllocateFlags,
23         MemoryPropertyFlags, MemoryRequirements,
24     },
25     sync::Sharing,
26     DeviceSize, RequiresOneOf, Version, VulkanError, VulkanObject,
27 };
28 use smallvec::SmallVec;
29 use std::{mem::MaybeUninit, num::NonZeroU64, ptr, sync::Arc};
30 
31 /// A raw buffer, with no memory backing it.
32 ///
33 /// This is the basic buffer type, a direct translation of a `VkBuffer` object, but it is mostly
34 /// useless in this form. After creating a raw buffer, you must call `bind_memory` to make a
35 /// complete buffer object.
36 #[derive(Debug)]
37 pub struct RawBuffer {
38     handle: ash::vk::Buffer,
39     device: Arc<Device>,
40     id: NonZeroU64,
41 
42     flags: BufferCreateFlags,
43     size: DeviceSize,
44     usage: BufferUsage,
45     sharing: Sharing<SmallVec<[u32; 4]>>,
46     external_memory_handle_types: ExternalMemoryHandleTypes,
47 
48     memory_requirements: MemoryRequirements,
49 }
50 
51 impl RawBuffer {
52     /// Creates a new `RawBuffer`.
53     ///
54     /// # Panics
55     ///
56     /// - Panics if `create_info.sharing` is [`Concurrent`](Sharing::Concurrent) with less than 2
57     ///   items.
58     /// - Panics if `create_info.size` is zero.
59     /// - Panics if `create_info.usage` is empty.
60     #[inline]
new( device: Arc<Device>, mut create_info: BufferCreateInfo, ) -> Result<Self, BufferError>61     pub fn new(
62         device: Arc<Device>,
63         mut create_info: BufferCreateInfo,
64     ) -> Result<Self, BufferError> {
65         match &mut create_info.sharing {
66             Sharing::Exclusive => (),
67             Sharing::Concurrent(queue_family_indices) => {
68                 // VUID-VkBufferCreateInfo-sharingMode-01419
69                 queue_family_indices.sort_unstable();
70                 queue_family_indices.dedup();
71             }
72         }
73 
74         Self::validate_new(&device, &create_info)?;
75 
76         unsafe { Ok(Self::new_unchecked(device, create_info)?) }
77     }
78 
validate_new(device: &Device, create_info: &BufferCreateInfo) -> Result<(), BufferError>79     fn validate_new(device: &Device, create_info: &BufferCreateInfo) -> Result<(), BufferError> {
80         let &BufferCreateInfo {
81             flags,
82             ref sharing,
83             size,
84             usage,
85             external_memory_handle_types,
86             _ne: _,
87         } = create_info;
88 
89         // VUID-VkBufferCreateInfo-flags-parameter
90         flags.validate_device(device)?;
91 
92         // VUID-VkBufferCreateInfo-usage-parameter
93         usage.validate_device(device)?;
94 
95         // VUID-VkBufferCreateInfo-usage-requiredbitmask
96         assert!(!usage.is_empty());
97 
98         // VUID-VkBufferCreateInfo-size-00912
99         assert!(size != 0);
100 
101         /* Enable when sparse binding is properly handled
102         if let Some(sparse_level) = sparse {
103             // VUID-VkBufferCreateInfo-flags-00915
104             if !device.enabled_features().sparse_binding {
105                 return Err(BufferError::RequirementNotMet {
106                     required_for: "`create_info.sparse` is `Some`",
107                     requires_one_of: RequiresOneOf {
108                         features: &["sparse_binding"],
109                         ..Default::default()
110                     },
111                 });
112             }
113 
114             // VUID-VkBufferCreateInfo-flags-00916
115             if sparse_level.sparse_residency && !device.enabled_features().sparse_residency_buffer {
116                 return Err(BufferError::RequirementNotMet {
117                     required_for: "`create_info.sparse` is `Some(sparse_level)`, where \
118                         `sparse_level` contains `BufferCreateFlags::SPARSE_RESIDENCY`",
119                     requires_one_of: RequiresOneOf {
120                         features: &["sparse_residency_buffer"],
121                         ..Default::default()
122                     },
123                 });
124             }
125 
126             // VUID-VkBufferCreateInfo-flags-00917
127             if sparse_level.sparse_aliased && !device.enabled_features().sparse_residency_aliased {
128                 return Err(BufferError::RequirementNotMet {
129                     required_for: "`create_info.sparse` is `Some(sparse_level)`, where \
130                         `sparse_level` contains `BufferCreateFlags::SPARSE_ALIASED`",
131                     requires_one_of: RequiresOneOf {
132                         features: &["sparse_residency_aliased"],
133                         ..Default::default()
134                     },
135                 });
136             }
137 
138             // VUID-VkBufferCreateInfo-flags-00918
139         }
140         */
141 
142         match sharing {
143             Sharing::Exclusive => (),
144             Sharing::Concurrent(queue_family_indices) => {
145                 // VUID-VkBufferCreateInfo-sharingMode-00914
146                 assert!(queue_family_indices.len() >= 2);
147 
148                 for &queue_family_index in queue_family_indices.iter() {
149                     // VUID-VkBufferCreateInfo-sharingMode-01419
150                     if queue_family_index
151                         >= device.physical_device().queue_family_properties().len() as u32
152                     {
153                         return Err(BufferError::SharingQueueFamilyIndexOutOfRange {
154                             queue_family_index,
155                             queue_family_count: device
156                                 .physical_device()
157                                 .queue_family_properties()
158                                 .len() as u32,
159                         });
160                     }
161                 }
162             }
163         }
164 
165         if let Some(max_buffer_size) = device.physical_device().properties().max_buffer_size {
166             // VUID-VkBufferCreateInfo-size-06409
167             if size > max_buffer_size {
168                 return Err(BufferError::MaxBufferSizeExceeded {
169                     size,
170                     max: max_buffer_size,
171                 });
172             }
173         }
174 
175         if !external_memory_handle_types.is_empty() {
176             if !(device.api_version() >= Version::V1_1
177                 || device.enabled_extensions().khr_external_memory)
178             {
179                 return Err(BufferError::RequirementNotMet {
180                     required_for: "`create_info.external_memory_handle_types` is not empty",
181                     requires_one_of: RequiresOneOf {
182                         api_version: Some(Version::V1_1),
183                         device_extensions: &["khr_external_memory"],
184                         ..Default::default()
185                     },
186                 });
187             }
188 
189             // VUID-VkExternalMemoryBufferCreateInfo-handleTypes-parameter
190             external_memory_handle_types.validate_device(device)?;
191 
192             // VUID-VkBufferCreateInfo-pNext-00920
193             // TODO:
194         }
195 
196         Ok(())
197     }
198 
199     #[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
new_unchecked( device: Arc<Device>, create_info: BufferCreateInfo, ) -> Result<Self, VulkanError>200     pub unsafe fn new_unchecked(
201         device: Arc<Device>,
202         create_info: BufferCreateInfo,
203     ) -> Result<Self, VulkanError> {
204         let &BufferCreateInfo {
205             flags,
206             ref sharing,
207             size,
208             usage,
209             external_memory_handle_types,
210             _ne: _,
211         } = &create_info;
212 
213         let (sharing_mode, queue_family_index_count, p_queue_family_indices) = match sharing {
214             Sharing::Exclusive => (ash::vk::SharingMode::EXCLUSIVE, 0, &[] as _),
215             Sharing::Concurrent(queue_family_indices) => (
216                 ash::vk::SharingMode::CONCURRENT,
217                 queue_family_indices.len() as u32,
218                 queue_family_indices.as_ptr(),
219             ),
220         };
221 
222         let mut create_info_vk = ash::vk::BufferCreateInfo {
223             flags: flags.into(),
224             size,
225             usage: usage.into(),
226             sharing_mode,
227             queue_family_index_count,
228             p_queue_family_indices,
229             ..Default::default()
230         };
231         let mut external_memory_info_vk = None;
232 
233         if !external_memory_handle_types.is_empty() {
234             let _ = external_memory_info_vk.insert(ash::vk::ExternalMemoryBufferCreateInfo {
235                 handle_types: external_memory_handle_types.into(),
236                 ..Default::default()
237             });
238         }
239 
240         if let Some(next) = external_memory_info_vk.as_mut() {
241             next.p_next = create_info_vk.p_next;
242             create_info_vk.p_next = next as *const _ as *const _;
243         }
244 
245         let handle = {
246             let fns = device.fns();
247             let mut output = MaybeUninit::uninit();
248             (fns.v1_0.create_buffer)(
249                 device.handle(),
250                 &create_info_vk,
251                 ptr::null(),
252                 output.as_mut_ptr(),
253             )
254             .result()
255             .map_err(VulkanError::from)?;
256             output.assume_init()
257         };
258 
259         Ok(Self::from_handle(device, handle, create_info))
260     }
261 
262     /// Creates a new `RawBuffer` from a raw object handle.
263     ///
264     /// # Safety
265     ///
266     /// - `handle` must be a valid Vulkan object handle created from `device`.
267     /// - `handle` must refer to a buffer that has not yet had memory bound to it.
268     /// - `create_info` must match the info used to create the object.
269     #[inline]
from_handle( device: Arc<Device>, handle: ash::vk::Buffer, create_info: BufferCreateInfo, ) -> Self270     pub unsafe fn from_handle(
271         device: Arc<Device>,
272         handle: ash::vk::Buffer,
273         create_info: BufferCreateInfo,
274     ) -> Self {
275         let BufferCreateInfo {
276             flags,
277             size,
278             usage,
279             sharing,
280             external_memory_handle_types,
281             _ne: _,
282         } = create_info;
283 
284         let mut memory_requirements = Self::get_memory_requirements(&device, handle);
285 
286         debug_assert!(memory_requirements.layout.size() >= size);
287         debug_assert!(memory_requirements.memory_type_bits != 0);
288 
289         // We have to manually enforce some additional requirements for some buffer types.
290         let properties = device.physical_device().properties();
291         if usage.intersects(BufferUsage::UNIFORM_TEXEL_BUFFER | BufferUsage::STORAGE_TEXEL_BUFFER) {
292             memory_requirements.layout = memory_requirements
293                 .layout
294                 .align_to(properties.min_texel_buffer_offset_alignment)
295                 .unwrap();
296         }
297 
298         if usage.intersects(BufferUsage::STORAGE_BUFFER) {
299             memory_requirements.layout = memory_requirements
300                 .layout
301                 .align_to(properties.min_storage_buffer_offset_alignment)
302                 .unwrap();
303         }
304 
305         if usage.intersects(BufferUsage::UNIFORM_BUFFER) {
306             memory_requirements.layout = memory_requirements
307                 .layout
308                 .align_to(properties.min_uniform_buffer_offset_alignment)
309                 .unwrap();
310         }
311 
312         RawBuffer {
313             handle,
314             device,
315             id: Self::next_id(),
316             flags,
317             size,
318             usage,
319             sharing,
320             external_memory_handle_types,
321             memory_requirements,
322         }
323     }
324 
get_memory_requirements(device: &Device, handle: ash::vk::Buffer) -> MemoryRequirements325     fn get_memory_requirements(device: &Device, handle: ash::vk::Buffer) -> MemoryRequirements {
326         let info_vk = ash::vk::BufferMemoryRequirementsInfo2 {
327             buffer: handle,
328             ..Default::default()
329         };
330 
331         let mut memory_requirements2_vk = ash::vk::MemoryRequirements2::default();
332         let mut memory_dedicated_requirements_vk = None;
333 
334         if device.api_version() >= Version::V1_1
335             || device.enabled_extensions().khr_dedicated_allocation
336         {
337             debug_assert!(
338                 device.api_version() >= Version::V1_1
339                     || device.enabled_extensions().khr_get_memory_requirements2
340             );
341 
342             let next = memory_dedicated_requirements_vk
343                 .insert(ash::vk::MemoryDedicatedRequirements::default());
344 
345             next.p_next = memory_requirements2_vk.p_next;
346             memory_requirements2_vk.p_next = next as *mut _ as *mut _;
347         }
348 
349         unsafe {
350             let fns = device.fns();
351 
352             if device.api_version() >= Version::V1_1
353                 || device.enabled_extensions().khr_get_memory_requirements2
354             {
355                 if device.api_version() >= Version::V1_1 {
356                     (fns.v1_1.get_buffer_memory_requirements2)(
357                         device.handle(),
358                         &info_vk,
359                         &mut memory_requirements2_vk,
360                     );
361                 } else {
362                     (fns.khr_get_memory_requirements2
363                         .get_buffer_memory_requirements2_khr)(
364                         device.handle(),
365                         &info_vk,
366                         &mut memory_requirements2_vk,
367                     );
368                 }
369             } else {
370                 (fns.v1_0.get_buffer_memory_requirements)(
371                     device.handle(),
372                     handle,
373                     &mut memory_requirements2_vk.memory_requirements,
374                 );
375             }
376         }
377 
378         MemoryRequirements {
379             layout: DeviceLayout::from_size_alignment(
380                 memory_requirements2_vk.memory_requirements.size,
381                 memory_requirements2_vk.memory_requirements.alignment,
382             )
383             .unwrap(),
384             memory_type_bits: memory_requirements2_vk.memory_requirements.memory_type_bits,
385             prefers_dedicated_allocation: memory_dedicated_requirements_vk
386                 .map_or(false, |dreqs| dreqs.prefers_dedicated_allocation != 0),
387             requires_dedicated_allocation: memory_dedicated_requirements_vk
388                 .map_or(false, |dreqs| dreqs.requires_dedicated_allocation != 0),
389         }
390     }
391 
id(&self) -> NonZeroU64392     pub(crate) fn id(&self) -> NonZeroU64 {
393         self.id
394     }
395 
396     /// Binds device memory to this buffer.
bind_memory( self, allocation: MemoryAlloc, ) -> Result<Buffer, (BufferError, RawBuffer, MemoryAlloc)>397     pub fn bind_memory(
398         self,
399         allocation: MemoryAlloc,
400     ) -> Result<Buffer, (BufferError, RawBuffer, MemoryAlloc)> {
401         if let Err(err) = self.validate_bind_memory(&allocation) {
402             return Err((err, self, allocation));
403         }
404 
405         unsafe { self.bind_memory_unchecked(allocation) }
406             .map_err(|(err, buffer, allocation)| (err.into(), buffer, allocation))
407     }
408 
validate_bind_memory(&self, allocation: &MemoryAlloc) -> Result<(), BufferError>409     fn validate_bind_memory(&self, allocation: &MemoryAlloc) -> Result<(), BufferError> {
410         assert_ne!(allocation.allocation_type(), AllocationType::NonLinear);
411 
412         let memory_requirements = &self.memory_requirements;
413         let memory = allocation.device_memory();
414         let memory_offset = allocation.offset();
415         let memory_type = &self
416             .device
417             .physical_device()
418             .memory_properties()
419             .memory_types[memory.memory_type_index() as usize];
420 
421         // VUID-VkBindBufferMemoryInfo-commonparent
422         assert_eq!(self.device(), memory.device());
423 
424         // VUID-VkBindBufferMemoryInfo-buffer-07459
425         // Ensured by taking ownership of `RawBuffer`.
426 
427         // VUID-VkBindBufferMemoryInfo-buffer-01030
428         // Currently ensured by not having sparse binding flags, but this needs to be checked once
429         // those are enabled.
430 
431         // VUID-VkBindBufferMemoryInfo-memoryOffset-01031
432         // Assume that `allocation` was created correctly.
433 
434         // VUID-VkBindBufferMemoryInfo-memory-01035
435         if memory_requirements.memory_type_bits & (1 << memory.memory_type_index()) == 0 {
436             return Err(BufferError::MemoryTypeNotAllowed {
437                 provided_memory_type_index: memory.memory_type_index(),
438                 allowed_memory_type_bits: memory_requirements.memory_type_bits,
439             });
440         }
441 
442         // VUID-VkBindBufferMemoryInfo-memoryOffset-01036
443         if !is_aligned(memory_offset, memory_requirements.layout.alignment()) {
444             return Err(BufferError::MemoryAllocationNotAligned {
445                 allocation_offset: memory_offset,
446                 required_alignment: memory_requirements.layout.alignment(),
447             });
448         }
449 
450         // VUID-VkBindBufferMemoryInfo-size-01037
451         if allocation.size() < memory_requirements.layout.size() {
452             return Err(BufferError::MemoryAllocationTooSmall {
453                 allocation_size: allocation.size(),
454                 required_size: memory_requirements.layout.size(),
455             });
456         }
457 
458         if let Some(dedicated_to) = memory.dedicated_to() {
459             // VUID-VkBindBufferMemoryInfo-memory-01508
460             match dedicated_to {
461                 DedicatedTo::Buffer(id) if id == self.id => {}
462                 _ => return Err(BufferError::DedicatedAllocationMismatch),
463             }
464             debug_assert!(memory_offset == 0); // This should be ensured by the allocator
465         } else {
466             // VUID-VkBindBufferMemoryInfo-buffer-01444
467             if memory_requirements.requires_dedicated_allocation {
468                 return Err(BufferError::DedicatedAllocationRequired);
469             }
470         }
471 
472         // VUID-VkBindBufferMemoryInfo-None-01899
473         if memory_type
474             .property_flags
475             .intersects(MemoryPropertyFlags::PROTECTED)
476         {
477             return Err(BufferError::MemoryProtectedMismatch {
478                 buffer_protected: false,
479                 memory_protected: true,
480             });
481         }
482 
483         // VUID-VkBindBufferMemoryInfo-memory-02726
484         if !memory.export_handle_types().is_empty()
485             && !memory
486                 .export_handle_types()
487                 .intersects(self.external_memory_handle_types)
488         {
489             return Err(BufferError::MemoryExternalHandleTypesDisjoint {
490                 buffer_handle_types: self.external_memory_handle_types,
491                 memory_export_handle_types: memory.export_handle_types(),
492             });
493         }
494 
495         if let Some(handle_type) = memory.imported_handle_type() {
496             // VUID-VkBindBufferMemoryInfo-memory-02985
497             if !ExternalMemoryHandleTypes::from(handle_type)
498                 .intersects(self.external_memory_handle_types)
499             {
500                 return Err(BufferError::MemoryImportedHandleTypeNotEnabled {
501                     buffer_handle_types: self.external_memory_handle_types,
502                     memory_imported_handle_type: handle_type,
503                 });
504             }
505         }
506 
507         // VUID-VkBindBufferMemoryInfo-bufferDeviceAddress-03339
508         if !self.device.enabled_extensions().ext_buffer_device_address
509             && self.usage.intersects(BufferUsage::SHADER_DEVICE_ADDRESS)
510             && !memory
511                 .flags()
512                 .intersects(MemoryAllocateFlags::DEVICE_ADDRESS)
513         {
514             return Err(BufferError::MemoryBufferDeviceAddressNotSupported);
515         }
516 
517         Ok(())
518     }
519 
520     #[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
bind_memory_unchecked( self, allocation: MemoryAlloc, ) -> Result<Buffer, (VulkanError, RawBuffer, MemoryAlloc)>521     pub unsafe fn bind_memory_unchecked(
522         self,
523         allocation: MemoryAlloc,
524     ) -> Result<Buffer, (VulkanError, RawBuffer, MemoryAlloc)> {
525         let memory = allocation.device_memory();
526         let memory_offset = allocation.offset();
527 
528         let fns = self.device.fns();
529 
530         let result = if self.device.api_version() >= Version::V1_1
531             || self.device.enabled_extensions().khr_bind_memory2
532         {
533             let bind_infos_vk = [ash::vk::BindBufferMemoryInfo {
534                 buffer: self.handle,
535                 memory: memory.handle(),
536                 memory_offset,
537                 ..Default::default()
538             }];
539 
540             if self.device.api_version() >= Version::V1_1 {
541                 (fns.v1_1.bind_buffer_memory2)(
542                     self.device.handle(),
543                     bind_infos_vk.len() as u32,
544                     bind_infos_vk.as_ptr(),
545                 )
546             } else {
547                 (fns.khr_bind_memory2.bind_buffer_memory2_khr)(
548                     self.device.handle(),
549                     bind_infos_vk.len() as u32,
550                     bind_infos_vk.as_ptr(),
551                 )
552             }
553         } else {
554             (fns.v1_0.bind_buffer_memory)(
555                 self.device.handle(),
556                 self.handle,
557                 memory.handle(),
558                 memory_offset,
559             )
560         }
561         .result();
562 
563         if let Err(err) = result {
564             return Err((VulkanError::from(err), self, allocation));
565         }
566 
567         Ok(Buffer::from_raw(self, BufferMemory::Normal(allocation)))
568     }
569 
570     /// Returns the memory requirements for this buffer.
memory_requirements(&self) -> &MemoryRequirements571     pub fn memory_requirements(&self) -> &MemoryRequirements {
572         &self.memory_requirements
573     }
574 
575     /// Returns the flags the buffer was created with.
576     #[inline]
flags(&self) -> BufferCreateFlags577     pub fn flags(&self) -> BufferCreateFlags {
578         self.flags
579     }
580 
581     /// Returns the size of the buffer in bytes.
582     #[inline]
size(&self) -> DeviceSize583     pub fn size(&self) -> DeviceSize {
584         self.size
585     }
586 
587     /// Returns the usage the buffer was created with.
588     #[inline]
usage(&self) -> BufferUsage589     pub fn usage(&self) -> BufferUsage {
590         self.usage
591     }
592 
593     /// Returns the sharing the buffer was created with.
594     #[inline]
sharing(&self) -> &Sharing<SmallVec<[u32; 4]>>595     pub fn sharing(&self) -> &Sharing<SmallVec<[u32; 4]>> {
596         &self.sharing
597     }
598 
599     /// Returns the external memory handle types that are supported with this buffer.
600     #[inline]
external_memory_handle_types(&self) -> ExternalMemoryHandleTypes601     pub fn external_memory_handle_types(&self) -> ExternalMemoryHandleTypes {
602         self.external_memory_handle_types
603     }
604 }
605 
606 impl Drop for RawBuffer {
607     #[inline]
drop(&mut self)608     fn drop(&mut self) {
609         unsafe {
610             let fns = self.device.fns();
611             (fns.v1_0.destroy_buffer)(self.device.handle(), self.handle, ptr::null());
612         }
613     }
614 }
615 
616 unsafe impl VulkanObject for RawBuffer {
617     type Handle = ash::vk::Buffer;
618 
619     #[inline]
handle(&self) -> Self::Handle620     fn handle(&self) -> Self::Handle {
621         self.handle
622     }
623 }
624 
625 unsafe impl DeviceOwned for RawBuffer {
626     #[inline]
device(&self) -> &Arc<Device>627     fn device(&self) -> &Arc<Device> {
628         &self.device
629     }
630 }
631 
632 impl_id_counter!(RawBuffer);
633 
634 /// Parameters to create a new [`Buffer`].
635 #[derive(Clone, Debug)]
636 pub struct BufferCreateInfo {
637     /// Flags to enable.
638     ///
639     /// The default value is [`BufferCreateFlags::empty()`].
640     pub flags: BufferCreateFlags,
641 
642     /// Whether the buffer can be shared across multiple queues, or is limited to a single queue.
643     ///
644     /// The default value is [`Sharing::Exclusive`].
645     pub sharing: Sharing<SmallVec<[u32; 4]>>,
646 
647     /// The size in bytes of the buffer.
648     ///
649     /// The default value is `0`, which must be overridden.
650     pub size: DeviceSize,
651 
652     /// How the buffer is going to be used.
653     ///
654     /// The default value is [`BufferUsage::empty()`], which must be overridden.
655     pub usage: BufferUsage,
656 
657     /// The external memory handle types that are going to be used with the buffer.
658     ///
659     /// If this value is not empty, then the device API version must be at least 1.1, or the
660     /// [`khr_external_memory`] extension must be enabled on the device.
661     ///
662     /// The default value is [`ExternalMemoryHandleTypes::empty()`].
663     ///
664     /// [`khr_external_memory`]: crate::device::DeviceExtensions::khr_external_memory
665     pub external_memory_handle_types: ExternalMemoryHandleTypes,
666 
667     pub _ne: crate::NonExhaustive,
668 }
669 
670 impl Default for BufferCreateInfo {
671     #[inline]
default() -> Self672     fn default() -> Self {
673         Self {
674             flags: BufferCreateFlags::empty(),
675             sharing: Sharing::Exclusive,
676             size: 0,
677             usage: BufferUsage::empty(),
678             external_memory_handle_types: ExternalMemoryHandleTypes::empty(),
679             _ne: crate::NonExhaustive(()),
680         }
681     }
682 }
683 
684 #[cfg(test)]
685 mod tests {
686     use super::{BufferCreateInfo, BufferUsage, RawBuffer};
687     use crate::device::{Device, DeviceOwned};
688 
689     #[test]
create()690     fn create() {
691         let (device, _) = gfx_dev_and_queue!();
692         let buf = RawBuffer::new(
693             device.clone(),
694             BufferCreateInfo {
695                 size: 128,
696                 usage: BufferUsage::TRANSFER_DST,
697                 ..Default::default()
698             },
699         )
700         .unwrap();
701         let reqs = buf.memory_requirements();
702 
703         assert!(reqs.layout.size() >= 128);
704         assert_eq!(buf.size(), 128);
705         assert_eq!(&**buf.device() as *const Device, &*device as *const Device);
706     }
707 
708     /* Re-enable when sparse binding is properly implemented
709     #[test]
710     fn missing_feature_sparse_binding() {
711         let (device, _) = gfx_dev_and_queue!();
712         match RawBuffer::new(
713             device,
714             BufferCreateInfo {
715                 size: 128,
716                 sparse: Some(BufferCreateFlags::empty()),
717                 usage: BufferUsage::transfer_dst,
718                 ..Default::default()
719             },
720         ) {
721             Err(BufferError::RequirementNotMet {
722                 requires_one_of: RequiresOneOf { features, .. },
723                 ..
724             }) if features.contains(&"sparse_binding") => (),
725             _ => panic!(),
726         }
727     }
728 
729     #[test]
730     fn missing_feature_sparse_residency() {
731         let (device, _) = gfx_dev_and_queue!(sparse_binding);
732         match RawBuffer::new(
733             device,
734             BufferCreateInfo {
735                 size: 128,
736                 sparse: Some(BufferCreateFlags {
737                     sparse_residency: true,
738                     sparse_aliased: false,
739                     ..Default::default()
740                 }),
741                 usage: BufferUsage::transfer_dst,
742                 ..Default::default()
743             },
744         ) {
745             Err(BufferError::RequirementNotMet {
746                 requires_one_of: RequiresOneOf { features, .. },
747                 ..
748             }) if features.contains(&"sparse_residency_buffer") => (),
749             _ => panic!(),
750         }
751     }
752 
753     #[test]
754     fn missing_feature_sparse_aliased() {
755         let (device, _) = gfx_dev_and_queue!(sparse_binding);
756         match RawBuffer::new(
757             device,
758             BufferCreateInfo {
759                 size: 128,
760                 sparse: Some(BufferCreateFlags {
761                     sparse_residency: false,
762                     sparse_aliased: true,
763                     ..Default::default()
764                 }),
765                 usage: BufferUsage::transfer_dst,
766                 ..Default::default()
767             },
768         ) {
769             Err(BufferError::RequirementNotMet {
770                 requires_one_of: RequiresOneOf { features, .. },
771                 ..
772             }) if features.contains(&"sparse_residency_aliased") => (),
773             _ => panic!(),
774         }
775     }
776     */
777 
778     #[test]
create_empty_buffer()779     fn create_empty_buffer() {
780         let (device, _) = gfx_dev_and_queue!();
781 
782         assert_should_panic!({
783             RawBuffer::new(
784                 device,
785                 BufferCreateInfo {
786                     size: 0,
787                     usage: BufferUsage::TRANSFER_DST,
788                     ..Default::default()
789                 },
790             )
791         });
792     }
793 }
794