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