1use super::{Buffer, BufferCreateFlags, BufferMemory, BufferUsage};
8use crate::{
9 buffer::ExternalBufferInfo,
10 device::{Device, DeviceOwned},
11 instance::InstanceOwnedDebugWrapper,
12 macros::impl_id_counter,
13 memory::{
14 allocator::AllocationType, is_aligned, DedicatedTo, ExternalMemoryHandleTypes,
15 MemoryAllocateFlags, MemoryPropertyFlags, MemoryRequirements, ResourceMemory,
16 },
17 sync::Sharing,
18 DeviceSize, Requires, RequiresAllOf, RequiresOneOf, Validated, ValidationError, Version,
19 VulkanError, VulkanObject,
20};
21use smallvec::SmallVec;
22use std::{marker::PhantomData, mem::MaybeUninit, num::NonZeroU64, ptr, sync::Arc};
23
24#[derive(Debug)]
30pub struct RawBuffer {
31 handle: ash::vk::Buffer,
32 device: InstanceOwnedDebugWrapper<Arc<Device>>,
33 id: NonZeroU64,
34
35 flags: BufferCreateFlags,
36 size: DeviceSize,
37 usage: BufferUsage,
38 sharing: Sharing<SmallVec<[u32; 4]>>,
39 external_memory_handle_types: ExternalMemoryHandleTypes,
40
41 memory_requirements: MemoryRequirements,
42 needs_destruction: bool,
43}
44
45impl RawBuffer {
46 #[inline]
55 pub fn new(
56 device: Arc<Device>,
57 create_info: BufferCreateInfo,
58 ) -> Result<Self, Validated<VulkanError>> {
59 Self::validate_new(&device, &create_info)?;
60
61 Ok(unsafe { Self::new_unchecked(device, create_info) }?)
62 }
63
64 fn validate_new(
65 device: &Device,
66 create_info: &BufferCreateInfo,
67 ) -> Result<(), Box<ValidationError>> {
68 create_info
69 .validate(device)
70 .map_err(|err| err.add_context("create_info"))?;
71
72 Ok(())
78 }
79
80 #[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
81 pub unsafe fn new_unchecked(
82 device: Arc<Device>,
83 create_info: BufferCreateInfo,
84 ) -> Result<Self, VulkanError> {
85 let mut extensions_vk = create_info.to_vk_extensions();
86 let create_info_vk = create_info.to_vk(&mut extensions_vk);
87
88 let handle = {
89 let fns = device.fns();
90 let mut output = MaybeUninit::uninit();
91 unsafe {
92 (fns.v1_0.create_buffer)(
93 device.handle(),
94 &create_info_vk,
95 ptr::null(),
96 output.as_mut_ptr(),
97 )
98 }
99 .result()
100 .map_err(VulkanError::from)?;
101 unsafe { output.assume_init() }
102 };
103
104 Ok(unsafe { Self::from_handle(device, handle, create_info) })
105 }
106
107 #[inline]
116 pub unsafe fn from_handle(
117 device: Arc<Device>,
118 handle: ash::vk::Buffer,
119 create_info: BufferCreateInfo,
120 ) -> Self {
121 unsafe { Self::from_handle_with_destruction(device, handle, create_info, true) }
122 }
123
124 #[inline]
136 pub unsafe fn from_handle_borrowed(
137 device: Arc<Device>,
138 handle: ash::vk::Buffer,
139 create_info: BufferCreateInfo,
140 ) -> Self {
141 unsafe { Self::from_handle_with_destruction(device, handle, create_info, false) }
142 }
143
144 unsafe fn from_handle_with_destruction(
145 device: Arc<Device>,
146 handle: ash::vk::Buffer,
147 create_info: BufferCreateInfo,
148 needs_destruction: bool,
149 ) -> Self {
150 let BufferCreateInfo {
151 flags,
152 size,
153 usage,
154 sharing,
155 external_memory_handle_types,
156 _ne: _,
157 } = create_info;
158
159 let mut memory_requirements = Self::get_memory_requirements(&device, handle);
160
161 debug_assert!(memory_requirements.layout.size() >= size);
162 debug_assert!(memory_requirements.memory_type_bits != 0);
163
164 let properties = device.physical_device().properties();
166 if usage.intersects(BufferUsage::UNIFORM_TEXEL_BUFFER | BufferUsage::STORAGE_TEXEL_BUFFER) {
167 memory_requirements.layout = memory_requirements
168 .layout
169 .align_to(properties.min_texel_buffer_offset_alignment)
170 .unwrap();
171 }
172
173 if usage.intersects(BufferUsage::STORAGE_BUFFER) {
174 memory_requirements.layout = memory_requirements
175 .layout
176 .align_to(properties.min_storage_buffer_offset_alignment)
177 .unwrap();
178 }
179
180 if usage.intersects(BufferUsage::UNIFORM_BUFFER) {
181 memory_requirements.layout = memory_requirements
182 .layout
183 .align_to(properties.min_uniform_buffer_offset_alignment)
184 .unwrap();
185 }
186
187 RawBuffer {
188 handle,
189 device: InstanceOwnedDebugWrapper(device),
190 id: Self::next_id(),
191 flags,
192 size,
193 usage,
194 sharing,
195 external_memory_handle_types,
196 memory_requirements,
197 needs_destruction,
198 }
199 }
200
201 fn get_memory_requirements(device: &Device, handle: ash::vk::Buffer) -> MemoryRequirements {
202 let info_vk = ash::vk::BufferMemoryRequirementsInfo2::default().buffer(handle);
203
204 let mut memory_requirements2_extensions_vk =
205 MemoryRequirements::to_mut_vk2_extensions(device);
206 let mut memory_requirements2_vk =
207 MemoryRequirements::to_mut_vk2(&mut memory_requirements2_extensions_vk);
208
209 let fns = device.fns();
210
211 if device.api_version() >= Version::V1_1
212 || device.enabled_extensions().khr_get_memory_requirements2
213 {
214 if device.api_version() >= Version::V1_1 {
215 unsafe {
216 (fns.v1_1.get_buffer_memory_requirements2)(
217 device.handle(),
218 &info_vk,
219 &mut memory_requirements2_vk,
220 )
221 };
222 } else {
223 unsafe {
224 (fns.khr_get_memory_requirements2
225 .get_buffer_memory_requirements2_khr)(
226 device.handle(),
227 &info_vk,
228 &mut memory_requirements2_vk,
229 )
230 };
231 }
232 } else {
233 unsafe {
234 (fns.v1_0.get_buffer_memory_requirements)(
235 device.handle(),
236 handle,
237 &mut memory_requirements2_vk.memory_requirements,
238 )
239 };
240 }
241
242 let memory_requirements2_vk = ash::vk::MemoryRequirements2 {
244 _marker: PhantomData,
245 ..memory_requirements2_vk
246 };
247
248 MemoryRequirements::from_vk2(
249 &memory_requirements2_vk,
250 &memory_requirements2_extensions_vk,
251 )
252 }
253
254 #[inline]
256 pub fn bind_memory(
257 self,
258 allocation: ResourceMemory,
259 ) -> Result<Buffer, (Validated<VulkanError>, RawBuffer, ResourceMemory)> {
260 if let Err(err) = self.validate_bind_memory(&allocation) {
261 return Err((err.into(), self, allocation));
262 }
263
264 unsafe { self.bind_memory_unchecked(allocation) }
265 .map_err(|(err, buffer, allocation)| (err.into(), buffer, allocation))
266 }
267
268 fn validate_bind_memory(
269 &self,
270 allocation: &ResourceMemory,
271 ) -> Result<(), Box<ValidationError>> {
272 if self.flags().intersects(BufferCreateFlags::SPARSE_BINDING) {
273 return Err(Box::new(ValidationError {
274 context: "self.flags()".into(),
275 problem: "contains `BufferCreateFlags::SPARSE_BINDING`".into(),
276 vuids: &["VUID-VkBindBufferMemoryInfo-buffer-01030"],
277 ..Default::default()
278 }));
279 }
280
281 assert_ne!(allocation.allocation_type(), AllocationType::NonLinear);
282
283 let physical_device = self.device().physical_device();
284
285 let memory_requirements = &self.memory_requirements;
286 let memory = allocation.device_memory();
287 let memory_offset = allocation.offset();
288 let memory_type =
289 &physical_device.memory_properties().memory_types[memory.memory_type_index() as usize];
290
291 assert_eq!(self.device(), memory.device());
293
294 if memory_requirements.memory_type_bits & (1 << memory.memory_type_index()) == 0 {
301 return Err(Box::new(ValidationError {
302 problem: "`allocation.device_memory().memory_type_index()` is not a bit set in \
303 `self.memory_requirements().memory_type_bits`"
304 .into(),
305 vuids: &["VUID-VkBindBufferMemoryInfo-memory-01035"],
306 ..Default::default()
307 }));
308 }
309
310 if !is_aligned(memory_offset, memory_requirements.layout.alignment()) {
311 return Err(Box::new(ValidationError {
312 problem: "`allocation.offset()` is not aligned according to \
313 `self.memory_requirements().layout.alignment()`"
314 .into(),
315 vuids: &["VUID-VkBindBufferMemoryInfo-memoryOffset-01036"],
316 ..Default::default()
317 }));
318 }
319
320 if allocation.size() < memory_requirements.layout.size() {
321 return Err(Box::new(ValidationError {
322 problem: "`allocation.size()` is less than \
323 `self.memory_requirements().layout.size()`"
324 .into(),
325 vuids: &["VUID-VkBindBufferMemoryInfo-size-01037"],
326 ..Default::default()
327 }));
328 }
329
330 if let Some(dedicated_to) = memory.dedicated_to() {
331 match dedicated_to {
332 DedicatedTo::Buffer(id) if id == self.id => {}
333 _ => {
334 return Err(Box::new(ValidationError {
335 problem: "`allocation.device_memory()` is a dedicated allocation, but \
336 it is not dedicated to this buffer"
337 .into(),
338 vuids: &["VUID-VkBindBufferMemoryInfo-memory-01508"],
339 ..Default::default()
340 }));
341 }
342 }
343 debug_assert!(memory_offset == 0); } else {
345 if memory_requirements.requires_dedicated_allocation {
346 return Err(Box::new(ValidationError {
347 problem: "`self.memory_requirements().requires_dedicated_allocation` is \
348 `true`, but `allocation.device_memory()` is not a dedicated allocation"
349 .into(),
350 vuids: &["VUID-VkBindBufferMemoryInfo-buffer-01444"],
351 ..Default::default()
352 }));
353 }
354 }
355
356 if memory_type
357 .property_flags
358 .intersects(MemoryPropertyFlags::PROTECTED)
359 {
360 return Err(Box::new(ValidationError {
361 problem: "the `property_flags` of the memory type of \
362 `allocation.device_memory()` contains `MemoryPropertyFlags::PROTECTED`"
363 .into(),
364 vuids: &["VUID-VkBindBufferMemoryInfo-None-01899"],
365 ..Default::default()
366 }));
367 }
368
369 if !memory.export_handle_types().is_empty() {
370 if !self
371 .external_memory_handle_types
372 .intersects(memory.export_handle_types())
373 {
374 return Err(Box::new(ValidationError {
375 problem:
376 "`allocation.device_memory().export_handle_types()` is not empty, but \
377 it does not share at least one handle type with \
378 `self.external_memory_handle_types()`"
379 .into(),
380 vuids: &["VUID-VkBindBufferMemoryInfo-memory-02726"],
381 ..Default::default()
382 }));
383 }
384
385 for handle_type in memory.export_handle_types() {
386 let external_buffer_properties = unsafe {
387 physical_device.external_buffer_properties_unchecked(ExternalBufferInfo {
388 flags: self.flags,
389 usage: self.usage,
390 handle_type,
391 _ne: crate::NonExhaustive(()),
392 })
393 };
394
395 if external_buffer_properties
396 .external_memory_properties
397 .dedicated_only
398 && !memory.is_dedicated()
399 {
400 return Err(Box::new(ValidationError {
401 problem: format!(
402 "`allocation.device_memory().export_handle_types()` has the `{:?}` \
403 flag set, which requires a dedicated allocation as returned by \
404 `PhysicalDevice::external_buffer_properties`, but \
405 `allocation.device_memory()` is not a dedicated allocation",
406 handle_type,
407 )
408 .into(),
409 vuids: &["VUID-VkMemoryAllocateInfo-pNext-00639"],
410 ..Default::default()
411 }));
412 }
413
414 if !external_buffer_properties
415 .external_memory_properties
416 .exportable
417 {
418 return Err(Box::new(ValidationError {
419 problem: format!(
420 "`allocation.device_memory().export_handle_types()` has the `{:?}` \
421 flag set, but the flag is not supported for exporting, as returned by \
422 `PhysicalDevice::external_buffer_properties`",
423 handle_type,
424 )
425 .into(),
426 vuids: &["VUID-VkExportMemoryAllocateInfo-handleTypes-00656"],
427 ..Default::default()
428 }));
429 }
430
431 if !external_buffer_properties
432 .external_memory_properties
433 .compatible_handle_types
434 .contains(memory.export_handle_types())
435 {
436 return Err(Box::new(ValidationError {
437 problem: format!(
438 "`allocation.device_memory().export_handle_types()` has the `{:?}` \
439 flag set, but the flag is not compatible with the other flags set, as \
440 returned by `PhysicalDevice::external_buffer_properties`",
441 handle_type,
442 )
443 .into(),
444 vuids: &["VUID-VkExportMemoryAllocateInfo-handleTypes-00656"],
445 ..Default::default()
446 }));
447 }
448 }
449 }
450
451 if let Some(handle_type) = memory.imported_handle_type() {
452 if !self.external_memory_handle_types.contains_enum(handle_type) {
453 return Err(Box::new(ValidationError {
454 problem: "`allocation.device_memory()` is imported, but \
455 `self.external_memory_handle_types()` does not contain the imported \
456 handle type"
457 .into(),
458 vuids: &["VUID-VkBindBufferMemoryInfo-memory-02985"],
459 ..Default::default()
460 }));
461 }
462 }
463
464 if !self.device.enabled_extensions().ext_buffer_device_address
465 && self.usage.intersects(BufferUsage::SHADER_DEVICE_ADDRESS)
466 && !memory
467 .flags()
468 .intersects(MemoryAllocateFlags::DEVICE_ADDRESS)
469 {
470 return Err(Box::new(ValidationError {
471 problem: "`self.usage()` contains `BufferUsage::SHADER_DEVICE_ADDRESS`, but \
472 `allocation.device_memory().flags()` does not contain \
473 `MemoryAllocateFlags::DEVICE_ADDRESS`"
474 .into(),
475 vuids: &["VUID-VkBindBufferMemoryInfo-bufferDeviceAddress-03339"],
476 ..Default::default()
477 }));
478 }
479
480 Ok(())
481 }
482
483 #[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
484 pub unsafe fn bind_memory_unchecked(
485 self,
486 allocation: ResourceMemory,
487 ) -> Result<Buffer, (VulkanError, RawBuffer, ResourceMemory)> {
488 let bind_info_vk = allocation.to_vk_bind_buffer_memory_info(self.handle());
489
490 let fns = self.device.fns();
491
492 let result = if self.device.api_version() >= Version::V1_1
493 || self.device.enabled_extensions().khr_bind_memory2
494 {
495 let bind_infos_vk = [bind_info_vk];
496
497 if self.device.api_version() >= Version::V1_1 {
498 unsafe {
499 (fns.v1_1.bind_buffer_memory2)(
500 self.device.handle(),
501 bind_infos_vk.len() as u32,
502 bind_infos_vk.as_ptr(),
503 )
504 }
505 } else {
506 unsafe {
507 (fns.khr_bind_memory2.bind_buffer_memory2_khr)(
508 self.device.handle(),
509 bind_infos_vk.len() as u32,
510 bind_infos_vk.as_ptr(),
511 )
512 }
513 }
514 } else {
515 unsafe {
516 (fns.v1_0.bind_buffer_memory)(
517 self.device.handle(),
518 bind_info_vk.buffer,
519 bind_info_vk.memory,
520 bind_info_vk.memory_offset,
521 )
522 }
523 }
524 .result();
525
526 if let Err(err) = result {
527 return Err((VulkanError::from(err), self, allocation));
528 }
529
530 Ok(Buffer::from_raw(self, BufferMemory::Normal(allocation)))
531 }
532
533 pub unsafe fn assume_bound(self) -> Buffer {
551 let memory = if self.flags().intersects(BufferCreateFlags::SPARSE_BINDING) {
552 BufferMemory::Sparse
553 } else {
554 BufferMemory::External
555 };
556
557 Buffer::from_raw(self, memory)
558 }
559
560 pub fn memory_requirements(&self) -> &MemoryRequirements {
562 &self.memory_requirements
563 }
564
565 #[inline]
567 pub fn flags(&self) -> BufferCreateFlags {
568 self.flags
569 }
570
571 #[inline]
573 pub fn size(&self) -> DeviceSize {
574 self.size
575 }
576
577 #[inline]
579 pub fn usage(&self) -> BufferUsage {
580 self.usage
581 }
582
583 #[inline]
585 pub fn sharing(&self) -> &Sharing<SmallVec<[u32; 4]>> {
586 &self.sharing
587 }
588
589 #[inline]
591 pub fn external_memory_handle_types(&self) -> ExternalMemoryHandleTypes {
592 self.external_memory_handle_types
593 }
594}
595
596impl Drop for RawBuffer {
597 #[inline]
598 fn drop(&mut self) {
599 if self.needs_destruction {
600 let fns = self.device.fns();
601 unsafe { (fns.v1_0.destroy_buffer)(self.device.handle(), self.handle, ptr::null()) };
602 }
603 }
604}
605
606unsafe impl VulkanObject for RawBuffer {
607 type Handle = ash::vk::Buffer;
608
609 #[inline]
610 fn handle(&self) -> Self::Handle {
611 self.handle
612 }
613}
614
615unsafe impl DeviceOwned for RawBuffer {
616 #[inline]
617 fn device(&self) -> &Arc<Device> {
618 &self.device
619 }
620}
621
622impl_id_counter!(RawBuffer);
623
624#[derive(Clone, Debug)]
626pub struct BufferCreateInfo {
627 pub flags: BufferCreateFlags,
631
632 pub sharing: Sharing<SmallVec<[u32; 4]>>,
636
637 pub size: DeviceSize,
646
647 pub usage: BufferUsage,
651
652 pub external_memory_handle_types: ExternalMemoryHandleTypes,
661
662 pub _ne: crate::NonExhaustive,
663}
664
665impl Default for BufferCreateInfo {
666 #[inline]
667 fn default() -> Self {
668 Self {
669 flags: BufferCreateFlags::empty(),
670 sharing: Sharing::Exclusive,
671 size: 0,
672 usage: BufferUsage::empty(),
673 external_memory_handle_types: ExternalMemoryHandleTypes::empty(),
674 _ne: crate::NonExhaustive(()),
675 }
676 }
677}
678
679impl BufferCreateInfo {
680 pub(crate) fn validate(&self, device: &Device) -> Result<(), Box<ValidationError>> {
681 let &Self {
682 flags,
683 ref sharing,
684 size,
685 usage,
686 external_memory_handle_types,
687 _ne: _,
688 } = self;
689
690 flags.validate_device(device).map_err(|err| {
691 err.add_context("flags")
692 .set_vuids(&["VUID-VkBufferCreateInfo-flags-parameter"])
693 })?;
694
695 usage.validate_device(device).map_err(|err| {
696 err.add_context("usage")
697 .set_vuids(&["VUID-VkBufferCreateInfo-usage-parameter"])
698 })?;
699
700 if usage.is_empty() {
701 return Err(Box::new(ValidationError {
702 context: "usage".into(),
703 problem: "is empty".into(),
704 vuids: &["VUID-VkBufferCreateInfo-usage-requiredbitmask"],
705 ..Default::default()
706 }));
707 }
708
709 if size == 0 {
710 return Err(Box::new(ValidationError {
711 context: "size".into(),
712 problem: "is zero".into(),
713 vuids: &["VUID-VkBufferCreateInfo-size-00912"],
714 ..Default::default()
715 }));
716 }
717
718 match sharing {
719 Sharing::Exclusive => (),
720 Sharing::Concurrent(queue_family_indices) => {
721 if queue_family_indices.len() < 2 {
722 return Err(Box::new(ValidationError {
723 context: "sharing".into(),
724 problem: "is `Sharing::Concurrent`, but contains less than 2 elements"
725 .into(),
726 vuids: &["VUID-VkBufferCreateInfo-sharingMode-00914"],
727 ..Default::default()
728 }));
729 }
730
731 let queue_family_count =
732 device.physical_device().queue_family_properties().len() as u32;
733
734 for (index, &queue_family_index) in queue_family_indices.iter().enumerate() {
735 if queue_family_indices[..index].contains(&queue_family_index) {
736 return Err(Box::new(ValidationError {
737 context: "queue_family_indices".into(),
738 problem: format!(
739 "the queue family index in the list at index {} is contained in \
740 the list more than once",
741 index,
742 )
743 .into(),
744 vuids: &["VUID-VkBufferCreateInfo-sharingMode-01419"],
745 ..Default::default()
746 }));
747 }
748
749 if queue_family_index >= queue_family_count {
750 return Err(Box::new(ValidationError {
751 context: format!("sharing[{}]", index).into(),
752 problem: "is not less than the number of queue families in the device"
753 .into(),
754 vuids: &["VUID-VkBufferCreateInfo-sharingMode-01419"],
755 ..Default::default()
756 }));
757 }
758 }
759 }
760 }
761
762 if flags.intersects(BufferCreateFlags::SPARSE_BINDING) {
763 if !device.enabled_features().sparse_binding {
764 return Err(Box::new(ValidationError {
765 context: "flags".into(),
766 problem: "contains `BufferCreateFlags::SPARSE_BINDING`".into(),
767 requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::DeviceFeature(
768 "sparse_binding",
769 )])]),
770 vuids: &["VUID-VkBufferCreateInfo-flags-00915"],
771 }));
772 }
773 }
774
775 if flags.intersects(BufferCreateFlags::SPARSE_RESIDENCY) {
776 if !flags.intersects(BufferCreateFlags::SPARSE_BINDING) {
777 return Err(Box::new(ValidationError {
778 context: "flags".into(),
779 problem: "contains `BufferCreateFlags::SPARSE_RESIDENCY`, but does not also \
780 contain `BufferCreateFlags::SPARSE_BINDING`"
781 .into(),
782 vuids: &["VUID-VkBufferCreateInfo-flags-00918"],
783 ..Default::default()
784 }));
785 }
786
787 if !device.enabled_features().sparse_residency_buffer {
788 return Err(Box::new(ValidationError {
789 context: "flags".into(),
790 problem: "contains `BufferCreateFlags::SPARSE_RESIDENCY`".into(),
791 requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::DeviceFeature(
792 "sparse_residency_buffer",
793 )])]),
794 vuids: &["VUID-VkBufferCreateInfo-flags-00916"],
795 }));
796 }
797 }
798
799 if let Some(max_buffer_size) = device.physical_device().properties().max_buffer_size {
800 if size > max_buffer_size {
801 return Err(Box::new(ValidationError {
802 context: "size".into(),
803 problem: "exceeds the `max_buffer_size` limit".into(),
804 vuids: &["VUID-VkBufferCreateInfo-size-06409"],
805 ..Default::default()
806 }));
807 }
808 }
809
810 if !external_memory_handle_types.is_empty() {
811 if !(device.api_version() >= Version::V1_1
812 || device.enabled_extensions().khr_external_memory)
813 {
814 return Err(Box::new(ValidationError {
815 context: "external_memory_handle_types".into(),
816 problem: "is not empty".into(),
817 requires_one_of: RequiresOneOf(&[
818 RequiresAllOf(&[Requires::APIVersion(Version::V1_1)]),
819 RequiresAllOf(&[Requires::DeviceExtension("khr_external_memory")]),
820 ]),
821 ..Default::default()
822 }));
823 }
824
825 external_memory_handle_types
826 .validate_device(device)
827 .map_err(|err| {
828 err.add_context("external_memory_handle_types")
829 .set_vuids(&["VUID-VkExternalMemoryBufferCreateInfo-handleTypes-parameter"])
830 })?;
831
832 }
835
836 Ok(())
837 }
838
839 pub(crate) fn to_vk<'a>(
840 &'a self,
841 extensions_vk: &'a mut BufferCreateInfoExtensionsVk,
842 ) -> ash::vk::BufferCreateInfo<'a> {
843 let &Self {
844 flags,
845 ref sharing,
846 size,
847 usage,
848 external_memory_handle_types: _,
849 _ne: _,
850 } = self;
851
852 let (sharing_mode_vk, queue_family_indices) = sharing.to_vk();
853
854 let mut val_vk = ash::vk::BufferCreateInfo::default()
855 .flags(flags.into())
856 .size(size)
857 .usage(usage.into())
858 .sharing_mode(sharing_mode_vk)
859 .queue_family_indices(queue_family_indices);
860
861 let BufferCreateInfoExtensionsVk { external_memory_vk } = extensions_vk;
862
863 if let Some(next) = external_memory_vk {
864 val_vk = val_vk.push_next(next);
865 }
866
867 val_vk
868 }
869
870 pub(crate) fn to_vk_extensions(&self) -> BufferCreateInfoExtensionsVk {
871 let &Self {
872 external_memory_handle_types,
873 ..
874 } = self;
875
876 let external_memory_vk = (!external_memory_handle_types.is_empty()).then(|| {
877 ash::vk::ExternalMemoryBufferCreateInfo::default()
878 .handle_types(external_memory_handle_types.into())
879 });
880
881 BufferCreateInfoExtensionsVk { external_memory_vk }
882 }
883}
884
885pub(crate) struct BufferCreateInfoExtensionsVk {
886 pub(crate) external_memory_vk: Option<ash::vk::ExternalMemoryBufferCreateInfo<'static>>,
887}
888
889#[cfg(test)]
890mod tests {
891 use super::{BufferCreateInfo, BufferUsage, RawBuffer};
892 use crate::device::DeviceOwned;
893
894 #[test]
895 fn create() {
896 let (device, _) = gfx_dev_and_queue!();
897 let buf = RawBuffer::new(
898 device.clone(),
899 BufferCreateInfo {
900 size: 128,
901 usage: BufferUsage::TRANSFER_DST,
902 ..Default::default()
903 },
904 )
905 .unwrap();
906 let reqs = buf.memory_requirements();
907
908 assert!(reqs.layout.size() >= 128);
909 assert_eq!(buf.size(), 128);
910 assert_eq!(buf.device(), &device);
911 }
912
913 #[test]
984 fn create_empty_buffer() {
985 let (device, _) = gfx_dev_and_queue!();
986
987 if RawBuffer::new(
988 device,
989 BufferCreateInfo {
990 size: 0,
991 usage: BufferUsage::TRANSFER_DST,
992 ..Default::default()
993 },
994 )
995 .is_ok()
996 {
997 panic!()
998 }
999 }
1000}