1pub(crate) use self::properties::DevicePropertiesFfi;
100use self::{physical::PhysicalDevice, queue::DeviceQueueInfo};
101pub use self::{
102 properties::DeviceProperties,
103 queue::{Queue, QueueFamilyProperties, QueueFlags, QueueGuard},
104};
105pub use crate::fns::DeviceFunctions;
106use crate::{
107 acceleration_structure::{
108 AccelerationStructureBuildGeometryInfo, AccelerationStructureBuildSizesInfo,
109 AccelerationStructureBuildType, AccelerationStructureGeometries,
110 },
111 buffer::BufferCreateInfo,
112 descriptor_set::layout::{DescriptorSetLayoutCreateInfo, DescriptorSetLayoutSupport},
113 image::{sys::ImageCreateInfoExtensionsVk, ImageCreateFlags, ImageCreateInfo, ImageTiling},
114 instance::{Instance, InstanceOwned, InstanceOwnedDebugWrapper},
115 macros::{impl_id_counter, vulkan_bitflags},
116 memory::{ExternalMemoryHandleType, MemoryFdProperties, MemoryRequirements},
117 Requires, RequiresAllOf, RequiresOneOf, Validated, ValidationError, Version, VulkanError,
118 VulkanObject,
119};
120use ash::vk::Handle;
121use parking_lot::Mutex;
122use smallvec::{smallvec, SmallVec};
123use std::{
124 ffi::{c_char, CString},
125 fmt::{Debug, Error as FmtError, Formatter},
126 fs::File,
127 marker::PhantomData,
128 mem::MaybeUninit,
129 num::NonZeroU64,
130 ops::Deref,
131 ptr, slice,
132 sync::{
133 atomic::{AtomicU32, Ordering},
134 Arc,
135 },
136};
137
138pub mod physical;
139pub mod private_data;
140pub(crate) mod properties;
141mod queue;
142
143include!(concat!(env!("OUT_DIR"), "/device_extensions.rs"));
145include!(concat!(env!("OUT_DIR"), "/features.rs"));
146
147pub struct Device {
149 handle: ash::vk::Device,
150 physical_device: InstanceOwnedDebugWrapper<Arc<PhysicalDevice>>,
152 id: NonZeroU64,
153
154 enabled_extensions: DeviceExtensions,
155 enabled_features: DeviceFeatures,
156 physical_devices: SmallVec<[InstanceOwnedDebugWrapper<Arc<PhysicalDevice>>; 2]>,
157
158 api_version: Version,
161 fns: DeviceFunctions,
162 active_queue_family_indices: SmallVec<[u32; 2]>,
163
164 pub(crate) allocation_count: AtomicU32,
167 fence_pool: Mutex<Vec<ash::vk::Fence>>,
168 semaphore_pool: Mutex<Vec<ash::vk::Semaphore>>,
169 event_pool: Mutex<Vec<ash::vk::Event>>,
170}
171
172impl Device {
173 #[inline]
175 pub fn new(
176 physical_device: Arc<PhysicalDevice>,
177 create_info: DeviceCreateInfo,
178 ) -> Result<(Arc<Device>, impl ExactSizeIterator<Item = Arc<Queue>>), Validated<VulkanError>>
179 {
180 Self::validate_new(&physical_device, &create_info)?;
181
182 Ok(unsafe { Self::new_unchecked(physical_device, create_info) }?)
183 }
184
185 fn validate_new(
186 physical_device: &PhysicalDevice,
187 create_info: &DeviceCreateInfo,
188 ) -> Result<(), Box<ValidationError>> {
189 create_info
190 .validate(physical_device)
191 .map_err(|err| err.add_context("create_info"))?;
192
193 let &DeviceCreateInfo {
194 queue_create_infos: _,
195 enabled_extensions: _,
196 enabled_features: _,
197 ref physical_devices,
198 private_data_slot_request_count: _,
199 _ne: _,
200 } = create_info;
201
202 if !physical_devices.is_empty()
203 && !physical_devices
204 .iter()
205 .any(|p| p.as_ref() == physical_device)
206 {
207 return Err(Box::new(ValidationError {
208 problem: "`create_info.physical_devices` is not empty, but does not contain \
209 `physical_device`"
210 .into(),
211 vuids: &["VUID-VkDeviceGroupDeviceCreateInfo-physicalDeviceCount-00377"],
212 ..Default::default()
213 }));
214 }
215
216 Ok(())
217 }
218
219 #[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
220 pub unsafe fn new_unchecked(
221 physical_device: Arc<PhysicalDevice>,
222 mut create_info: DeviceCreateInfo,
223 ) -> Result<(Arc<Device>, impl ExactSizeIterator<Item = Arc<Queue>>), VulkanError> {
224 create_info.enabled_extensions.enable_dependencies(
226 physical_device.api_version(),
227 physical_device.supported_extensions(),
228 );
229
230 if physical_device
232 .supported_extensions()
233 .khr_portability_subset
234 {
235 create_info.enabled_extensions.khr_portability_subset = true;
236 }
237
238 macro_rules! enable_extension_required_features {
239 (
240 $extension:ident,
241 $feature_to_enable:ident $(,)?
242 ) => {
243 if create_info.enabled_extensions.$extension {
244 assert!(
245 physical_device.supported_features().$feature_to_enable,
246 "The device extension `{}` is enabled, and it requires the `{}` device \
247 feature to be also enabled, but the device does not support the required \
248 feature. This is a bug in the Vulkan driver for this device.",
249 stringify!($extension),
250 stringify!($feature_to_enable),
251 );
252 create_info.enabled_features.$feature_to_enable = true;
253 }
254 };
255 }
256
257 if physical_device.api_version() >= Version::V1_1 {
258 enable_extension_required_features!(khr_shader_draw_parameters, shader_draw_parameters);
260 }
261
262 if physical_device.api_version() >= Version::V1_2 {
263 enable_extension_required_features!(khr_draw_indirect_count, draw_indirect_count);
265
266 enable_extension_required_features!(
268 khr_sampler_mirror_clamp_to_edge,
269 sampler_mirror_clamp_to_edge,
270 );
271
272 enable_extension_required_features!(ext_descriptor_indexing, descriptor_indexing);
274
275 enable_extension_required_features!(ext_sampler_filter_minmax, sampler_filter_minmax);
277
278 enable_extension_required_features!(
280 ext_shader_viewport_index_layer,
281 shader_output_layer,
282 );
283 enable_extension_required_features!(
284 ext_shader_viewport_index_layer,
285 shader_output_layer,
286 );
287 }
288
289 macro_rules! enable_feature_required_features {
290 (
291 $feature:ident,
292 $feature_to_enable:ident $(,)?
293 ) => {
294 if create_info.enabled_features.$feature {
295 assert!(
296 physical_device.supported_features().$feature_to_enable,
297 "The device feature `{}` is enabled, and it requires the `{}` feature \
298 to be also enabled, but the device does not support the required feature. \
299 This is a bug in the Vulkan driver for this device.",
300 stringify!($feature),
301 stringify!($feature_to_enable),
302 );
303 create_info.enabled_features.$feature_to_enable = true;
304 }
305 };
306 }
307
308 enable_feature_required_features!(variable_pointers, variable_pointers_storage_buffer);
310
311 enable_feature_required_features!(multiview_geometry_shader, multiview);
313
314 enable_feature_required_features!(multiview_tessellation_shader, multiview);
316
317 enable_feature_required_features!(multiview_mesh_shader, multiview);
319
320 enable_feature_required_features!(
322 primitive_fragment_shading_rate_mesh_shader,
323 primitive_fragment_shading_rate,
324 );
325
326 enable_feature_required_features!(
328 ray_tracing_pipeline_shader_group_handle_capture_replay_mixed,
329 ray_tracing_pipeline_shader_group_handle_capture_replay,
330 );
331
332 enable_feature_required_features!(robust_buffer_access2, robust_buffer_access);
334
335 let handle = {
336 let has_khr_get_physical_device_properties2 = physical_device.instance().api_version()
337 >= Version::V1_1
338 || physical_device
339 .instance()
340 .enabled_extensions()
341 .khr_get_physical_device_properties2;
342
343 let mut features_ffi = DeviceFeaturesFfi::default();
344 features_ffi.make_chain(
345 physical_device.api_version(),
346 &create_info.enabled_extensions,
347 physical_device.instance().enabled_extensions(),
348 );
349 features_ffi.write(&create_info.enabled_features);
350
351 let (features_vk, features2_vk) = if has_khr_get_physical_device_properties2 {
353 (None, Some(features_ffi.head_as_mut()))
354 } else {
355 (Some(&features_ffi.head_as_ref().features), None)
356 };
357
358 let create_info_fields2_vk = create_info.to_vk_fields2();
359 let create_info_fields1_vk =
360 create_info.to_vk_fields1(&create_info_fields2_vk, features_vk);
361 let mut create_info_extensions =
362 create_info.to_vk_extensions(&create_info_fields1_vk, features2_vk);
363 let create_info_vk =
364 create_info.to_vk(&create_info_fields1_vk, &mut create_info_extensions);
365
366 let fns = physical_device.instance().fns();
367
368 let mut output = MaybeUninit::uninit();
369 unsafe {
370 (fns.v1_0.create_device)(
371 physical_device.handle(),
372 &create_info_vk,
373 ptr::null(),
374 output.as_mut_ptr(),
375 )
376 }
377 .result()
378 .map_err(VulkanError::from)?;
379 unsafe { output.assume_init() }
380 };
381
382 Ok(unsafe { Self::from_handle(physical_device, handle, create_info) })
383 }
384
385 pub unsafe fn from_handle(
392 physical_device: Arc<PhysicalDevice>,
393 handle: ash::vk::Device,
394 create_info: DeviceCreateInfo,
395 ) -> (Arc<Device>, impl ExactSizeIterator<Item = Arc<Queue>>) {
396 let DeviceCreateInfo {
397 queue_create_infos,
398 enabled_features,
399 enabled_extensions,
400 physical_devices,
401 private_data_slot_request_count: _,
402 _ne: _,
403 } = create_info;
404
405 let api_version = physical_device.api_version();
406 let fns = DeviceFunctions::load(|name| {
407 unsafe {
408 (physical_device.instance().fns().v1_0.get_device_proc_addr)(handle, name.as_ptr())
409 }
410 .map_or(ptr::null(), |func| func as _)
411 });
412
413 let mut active_queue_family_indices: SmallVec<[_; 2]> =
414 SmallVec::with_capacity(queue_create_infos.len());
415 let mut queues_to_get: SmallVec<[_; 2]> = SmallVec::with_capacity(queue_create_infos.len());
416
417 for queue_create_info in &queue_create_infos {
418 let &QueueCreateInfo {
419 flags,
420 queue_family_index,
421 ref queues,
422 _ne: _,
423 } = queue_create_info;
424
425 active_queue_family_indices.push(queue_family_index);
426 queues_to_get.extend((0..queues.len() as u32).map(move |queue_index| {
427 DeviceQueueInfo {
428 flags,
429 queue_family_index,
430 queue_index,
431 ..Default::default()
432 }
433 }));
434 }
435
436 active_queue_family_indices.sort_unstable();
437 active_queue_family_indices.dedup();
438
439 let physical_devices = if physical_devices.is_empty() {
440 smallvec![physical_device.clone()]
441 } else {
442 physical_devices
443 };
444
445 let device = Arc::new(Device {
446 handle,
447 physical_device: InstanceOwnedDebugWrapper(physical_device),
448 id: Self::next_id(),
449
450 enabled_extensions,
451 enabled_features,
452 physical_devices: physical_devices
453 .into_iter()
454 .map(InstanceOwnedDebugWrapper)
455 .collect(),
456
457 api_version,
458 fns,
459 active_queue_family_indices,
460
461 allocation_count: AtomicU32::new(0),
462 fence_pool: Mutex::new(Vec::new()),
463 semaphore_pool: Mutex::new(Vec::new()),
464 event_pool: Mutex::new(Vec::new()),
465 });
466
467 let queues_iter = {
468 let device = device.clone();
469 queues_to_get
470 .into_iter()
471 .map(move |queue_info| unsafe { Queue::new(device.clone(), queue_info) })
472 };
473
474 (device, queues_iter)
475 }
476
477 #[inline]
483 pub fn api_version(&self) -> Version {
484 self.api_version
485 }
486
487 #[inline]
489 pub fn fns(&self) -> &DeviceFunctions {
490 &self.fns
491 }
492
493 #[inline]
495 pub fn physical_device(&self) -> &Arc<PhysicalDevice> {
496 &self.physical_device
497 }
498
499 #[inline]
506 pub fn physical_devices(&self) -> &[Arc<PhysicalDevice>] {
507 InstanceOwnedDebugWrapper::cast_slice_inner(&self.physical_devices)
508 }
509
510 #[inline]
513 pub fn device_mask(&self) -> u32 {
514 (1 << self.physical_devices.len() as u32) - 1
515 }
516
517 #[inline]
519 pub fn instance(&self) -> &Arc<Instance> {
520 self.physical_device.instance()
521 }
522
523 #[inline]
525 pub fn active_queue_family_indices(&self) -> &[u32] {
526 &self.active_queue_family_indices
527 }
528
529 #[inline]
534 pub fn enabled_extensions(&self) -> &DeviceExtensions {
535 &self.enabled_extensions
536 }
537
538 #[inline]
543 pub fn enabled_features(&self) -> &DeviceFeatures {
544 &self.enabled_features
545 }
546
547 #[inline]
551 pub fn allocation_count(&self) -> u32 {
552 self.allocation_count.load(Ordering::Acquire)
553 }
554
555 pub(crate) fn fence_pool(&self) -> &Mutex<Vec<ash::vk::Fence>> {
556 &self.fence_pool
557 }
558
559 pub(crate) fn semaphore_pool(&self) -> &Mutex<Vec<ash::vk::Semaphore>> {
560 &self.semaphore_pool
561 }
562
563 pub(crate) fn event_pool(&self) -> &Mutex<Vec<ash::vk::Event>> {
564 &self.event_pool
565 }
566
567 #[inline]
571 pub fn acceleration_structure_build_sizes(
572 &self,
573 build_type: AccelerationStructureBuildType,
574 build_info: &AccelerationStructureBuildGeometryInfo,
575 max_primitive_counts: &[u32],
576 ) -> Result<AccelerationStructureBuildSizesInfo, Box<ValidationError>> {
577 self.validate_acceleration_structure_build_sizes(
578 build_type,
579 build_info,
580 max_primitive_counts,
581 )?;
582
583 Ok(unsafe {
584 self.acceleration_structure_build_sizes_unchecked(
585 build_type,
586 build_info,
587 max_primitive_counts,
588 )
589 })
590 }
591
592 fn validate_acceleration_structure_build_sizes(
593 &self,
594 build_type: AccelerationStructureBuildType,
595 build_info: &AccelerationStructureBuildGeometryInfo,
596 max_primitive_counts: &[u32],
597 ) -> Result<(), Box<ValidationError>> {
598 if !self.enabled_extensions().khr_acceleration_structure {
599 return Err(Box::new(ValidationError {
600 requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::DeviceExtension(
601 "khr_acceleration_structure",
602 )])]),
603 ..Default::default()
604 }));
605 }
606
607 if !self.enabled_features().acceleration_structure {
608 return Err(Box::new(ValidationError {
609 requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::DeviceFeature(
610 "acceleration_structure",
611 )])]),
612 vuids: &[
613 "VUID-vkGetAccelerationStructureBuildSizesKHR-accelerationStructure-08933",
614 ],
615 ..Default::default()
616 }));
617 }
618
619 build_type.validate_device(self).map_err(|err| {
620 err.add_context("build_type")
621 .set_vuids(&["VUID-vkGetAccelerationStructureBuildSizesKHR-buildType-parameter"])
622 })?;
623
624 build_info
626 .validate(self)
627 .map_err(|err| err.add_context("build_info"))?;
628
629 let max_primitive_count = self
630 .physical_device()
631 .properties()
632 .max_primitive_count
633 .unwrap();
634 let max_instance_count = self
635 .physical_device()
636 .properties()
637 .max_instance_count
638 .unwrap();
639
640 let geometry_count = match &build_info.geometries {
641 AccelerationStructureGeometries::Triangles(geometries) => {
642 for (index, &primitive_count) in max_primitive_counts.iter().enumerate() {
643 if primitive_count as u64 > max_primitive_count {
644 return Err(Box::new(ValidationError {
645 context: format!("max_primitive_counts[{}]", index).into(),
646 problem: "exceeds the `max_primitive_count` limit".into(),
647 vuids: &["VUID-VkAccelerationStructureBuildGeometryInfoKHR-type-03795"],
648 ..Default::default()
649 }));
650 }
651 }
652
653 geometries.len()
654 }
655 AccelerationStructureGeometries::Aabbs(geometries) => {
656 for (index, &primitive_count) in max_primitive_counts.iter().enumerate() {
657 if primitive_count as u64 > max_primitive_count {
658 return Err(Box::new(ValidationError {
659 context: format!("max_primitive_counts[{}]", index).into(),
660 problem: "exceeds the `max_primitive_count` limit".into(),
661 vuids: &["VUID-VkAccelerationStructureBuildGeometryInfoKHR-type-03794"],
662 ..Default::default()
663 }));
664 }
665 }
666
667 geometries.len()
668 }
669 AccelerationStructureGeometries::Instances(_) => {
670 for (index, &instance_count) in max_primitive_counts.iter().enumerate() {
671 if instance_count as u64 > max_instance_count {
672 return Err(Box::new(ValidationError {
673 context: format!("max_primitive_counts[{}]", index).into(),
674 problem: "exceeds the `max_instance_count` limit".into(),
675 vuids: &[
676 "VUID-vkGetAccelerationStructureBuildSizesKHR-pBuildInfo-03785",
677 ],
678 ..Default::default()
679 }));
680 }
681 }
682
683 1
684 }
685 };
686
687 if max_primitive_counts.len() != geometry_count {
688 return Err(Box::new(ValidationError {
689 problem: "`build_info.geometries` and `max_primitive_counts` \
690 do not have the same length"
691 .into(),
692 vuids: &["VUID-vkGetAccelerationStructureBuildSizesKHR-pBuildInfo-03619"],
693 ..Default::default()
694 }));
695 }
696
697 Ok(())
698 }
699
700 #[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
701 pub unsafe fn acceleration_structure_build_sizes_unchecked(
702 &self,
703 build_type: AccelerationStructureBuildType,
704 build_info: &AccelerationStructureBuildGeometryInfo,
705 max_primitive_counts: &[u32],
706 ) -> AccelerationStructureBuildSizesInfo {
707 let build_info_fields1_vk = build_info.to_vk_fields1();
708 let build_info_vk = build_info.to_vk(&build_info_fields1_vk);
709
710 let mut build_sizes_info_vk = AccelerationStructureBuildSizesInfo::to_mut_vk();
711
712 let fns = self.fns();
713 unsafe {
714 (fns.khr_acceleration_structure
715 .get_acceleration_structure_build_sizes_khr)(
716 self.handle,
717 build_type.into(),
718 &build_info_vk,
719 max_primitive_counts.as_ptr(),
720 &mut build_sizes_info_vk,
721 )
722 };
723
724 AccelerationStructureBuildSizesInfo::from_vk(&build_sizes_info_vk)
725 }
726
727 #[inline]
730 pub fn acceleration_structure_is_compatible(
731 &self,
732 version_data: &[u8; 2 * ash::vk::UUID_SIZE],
733 ) -> Result<bool, Box<ValidationError>> {
734 self.validate_acceleration_structure_is_compatible(version_data)?;
735
736 Ok(unsafe { self.acceleration_structure_is_compatible_unchecked(version_data) })
737 }
738
739 fn validate_acceleration_structure_is_compatible(
740 &self,
741 _version_data: &[u8; 2 * ash::vk::UUID_SIZE],
742 ) -> Result<(), Box<ValidationError>> {
743 if !self.enabled_extensions().khr_acceleration_structure {
744 return Err(Box::new(ValidationError {
745 requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::DeviceExtension(
746 "khr_acceleration_structure",
747 )])]),
748 ..Default::default()
749 }));
750 }
751
752 if !self.enabled_features().acceleration_structure {
753 return Err(Box::new(ValidationError {
754 requires_one_of: RequiresOneOf(&[
755 RequiresAllOf(&[Requires::DeviceFeature("acceleration_structure")]),
756 ]),
757 vuids: &["VUID-vkGetDeviceAccelerationStructureCompatibilityKHR-accelerationStructure-08928"],
758 ..Default::default()
759 }));
760 }
761
762 Ok(())
763 }
764
765 #[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
766 pub unsafe fn acceleration_structure_is_compatible_unchecked(
767 &self,
768 version_data: &[u8; 2 * ash::vk::UUID_SIZE],
769 ) -> bool {
770 let version_info_vk =
771 ash::vk::AccelerationStructureVersionInfoKHR::default().version_data(version_data);
772 let mut compatibility_vk = ash::vk::AccelerationStructureCompatibilityKHR::default();
773
774 let fns = self.fns();
775 unsafe {
776 (fns.khr_acceleration_structure
777 .get_device_acceleration_structure_compatibility_khr)(
778 self.handle,
779 &version_info_vk,
780 &mut compatibility_vk,
781 )
782 };
783
784 compatibility_vk == ash::vk::AccelerationStructureCompatibilityKHR::COMPATIBLE
785 }
786
787 #[inline]
801 pub fn descriptor_set_layout_support(
802 &self,
803 create_info: &DescriptorSetLayoutCreateInfo,
804 ) -> Result<Option<DescriptorSetLayoutSupport>, Box<ValidationError>> {
805 self.validate_descriptor_set_layout_support(create_info)?;
806
807 Ok(unsafe { self.descriptor_set_layout_support_unchecked(create_info) })
808 }
809
810 fn validate_descriptor_set_layout_support(
811 &self,
812 create_info: &DescriptorSetLayoutCreateInfo,
813 ) -> Result<(), Box<ValidationError>> {
814 if !(self.api_version() >= Version::V1_1 || self.enabled_extensions().khr_maintenance3) {
815 return Err(Box::new(ValidationError {
816 requires_one_of: RequiresOneOf(&[
817 RequiresAllOf(&[Requires::APIVersion(Version::V1_1)]),
818 RequiresAllOf(&[Requires::DeviceExtension("khr_maintenance3")]),
819 ]),
820 ..Default::default()
821 }));
822 }
823
824 create_info
826 .validate(self)
827 .map_err(|err| err.add_context("create_info"))?;
828
829 Ok(())
830 }
831
832 #[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
833 pub unsafe fn descriptor_set_layout_support_unchecked(
834 &self,
835 create_info: &DescriptorSetLayoutCreateInfo,
836 ) -> Option<DescriptorSetLayoutSupport> {
837 let create_info_fields2_vk = create_info.to_vk_fields2();
838 let create_info_fields1_vk = create_info.to_vk_fields1(&create_info_fields2_vk);
839 let mut create_info_extensions_vk = create_info.to_vk_extensions(&create_info_fields2_vk);
840 let create_info_vk =
841 create_info.to_vk(&create_info_fields1_vk, &mut create_info_extensions_vk);
842
843 let mut support_extensions_vk = DescriptorSetLayoutSupport::to_mut_vk_extensions(self);
844 let mut support_vk = DescriptorSetLayoutSupport::to_mut_vk(&mut support_extensions_vk);
845
846 let fns = self.fns();
847
848 if self.api_version() >= Version::V1_1 {
849 unsafe {
850 (fns.v1_1.get_descriptor_set_layout_support)(
851 self.handle(),
852 &create_info_vk,
853 &mut support_vk,
854 )
855 }
856 } else {
857 unsafe {
858 (fns.khr_maintenance3.get_descriptor_set_layout_support_khr)(
859 self.handle(),
860 &create_info_vk,
861 &mut support_vk,
862 )
863 }
864 }
865
866 let support_vk = ash::vk::DescriptorSetLayoutSupport {
868 _marker: PhantomData,
869 ..support_vk
870 };
871
872 DescriptorSetLayoutSupport::from_vk(&support_vk, &support_extensions_vk)
873 }
874
875 #[inline]
883 pub fn buffer_memory_requirements(
884 &self,
885 create_info: BufferCreateInfo,
886 ) -> Result<MemoryRequirements, Box<ValidationError>> {
887 self.validate_buffer_memory_requirements(&create_info)?;
888
889 Ok(unsafe { self.buffer_memory_requirements_unchecked(create_info) })
890 }
891
892 fn validate_buffer_memory_requirements(
893 &self,
894 create_info: &BufferCreateInfo,
895 ) -> Result<(), Box<ValidationError>> {
896 if !(self.api_version() >= Version::V1_3 || self.enabled_extensions().khr_maintenance4) {
897 return Err(Box::new(ValidationError {
898 requires_one_of: RequiresOneOf(&[
899 RequiresAllOf(&[Requires::APIVersion(Version::V1_3)]),
900 RequiresAllOf(&[Requires::DeviceExtension("khr_maintenance")]),
901 ]),
902 ..Default::default()
903 }));
904 }
905
906 create_info
907 .validate(self)
908 .map_err(|err| err.add_context("create_info"))?;
909
910 Ok(())
911 }
912
913 #[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
914 pub unsafe fn buffer_memory_requirements_unchecked(
915 &self,
916 create_info: BufferCreateInfo,
917 ) -> MemoryRequirements {
918 let mut extensions_vk = create_info.to_vk_extensions();
919 let create_info_vk = create_info.to_vk(&mut extensions_vk);
920
921 let info_vk =
922 ash::vk::DeviceBufferMemoryRequirements::default().create_info(&create_info_vk);
923
924 let mut memory_requirements2_extensions_vk =
925 MemoryRequirements::to_mut_vk2_extensions(self);
926 let mut memory_requirements2_vk =
927 MemoryRequirements::to_mut_vk2(&mut memory_requirements2_extensions_vk);
928
929 let fns = self.fns();
930
931 if self.api_version() >= Version::V1_3 {
932 unsafe {
933 (fns.v1_3.get_device_buffer_memory_requirements)(
934 self.handle(),
935 &info_vk,
936 &mut memory_requirements2_vk,
937 )
938 };
939 } else {
940 debug_assert!(self.enabled_extensions().khr_maintenance4);
941 unsafe {
942 (fns.khr_maintenance4
943 .get_device_buffer_memory_requirements_khr)(
944 self.handle(),
945 &info_vk,
946 &mut memory_requirements2_vk,
947 )
948 };
949 }
950
951 let memory_requirements2_vk = ash::vk::MemoryRequirements2 {
953 _marker: PhantomData,
954 ..memory_requirements2_vk
955 };
956
957 MemoryRequirements::from_vk2(
958 &memory_requirements2_vk,
959 &memory_requirements2_extensions_vk,
960 )
961 }
962
963 #[inline]
975 pub fn image_memory_requirements(
976 &self,
977 create_info: ImageCreateInfo,
978 plane: Option<usize>,
979 ) -> Result<MemoryRequirements, Box<ValidationError>> {
980 self.validate_image_memory_requirements(&create_info, plane)?;
981
982 Ok(unsafe { self.image_memory_requirements_unchecked(create_info, plane) })
983 }
984
985 fn validate_image_memory_requirements(
986 &self,
987 create_info: &ImageCreateInfo,
988 plane: Option<usize>,
989 ) -> Result<(), Box<ValidationError>> {
990 if !(self.api_version() >= Version::V1_3 || self.enabled_extensions().khr_maintenance4) {
991 return Err(Box::new(ValidationError {
992 requires_one_of: RequiresOneOf(&[
993 RequiresAllOf(&[Requires::APIVersion(Version::V1_3)]),
994 RequiresAllOf(&[Requires::DeviceExtension("khr_maintenance")]),
995 ]),
996 ..Default::default()
997 }));
998 }
999
1000 create_info
1001 .validate(self)
1002 .map_err(|err| err.add_context("create_info"))?;
1003
1004 let &ImageCreateInfo {
1005 flags,
1006 image_type: _,
1007 format,
1008 view_formats: _,
1009 extent: _,
1010 array_layers: _,
1011 mip_levels: _,
1012 samples: _,
1013 tiling,
1014 usage: _,
1015 stencil_usage: _,
1016 sharing: _,
1017 initial_layout: _,
1018 ref drm_format_modifiers,
1019 drm_format_modifier_plane_layouts: _,
1020 external_memory_handle_types: _,
1021 _ne: _,
1022 } = create_info;
1023
1024 if flags.intersects(ImageCreateFlags::DISJOINT) {
1025 let Some(plane) = plane else {
1026 return Err(Box::new(ValidationError {
1027 problem: "`create_info.flags` contains `ImageCreateFlags::DISJOINT`, but \
1028 `plane` is `None`"
1029 .into(),
1030 vuids: &[
1031 "VUID-VkDeviceImageMemoryRequirements-pCreateInfo-06419",
1032 "VUID-VkDeviceImageMemoryRequirements-pCreateInfo-06420",
1033 ],
1034 ..Default::default()
1035 }));
1036 };
1037
1038 match tiling {
1039 ImageTiling::Linear | ImageTiling::Optimal => {
1040 if plane >= format.planes().len() {
1041 return Err(Box::new(ValidationError {
1042 problem:
1043 "`create_info.tiling` is not `ImageTiling::DrmFormatModifier`, \
1044 but `plane` is not less than the number of planes in \
1045 `create_info.format`"
1046 .into(),
1047 vuids: &["VUID-VkDeviceImageMemoryRequirements-pCreateInfo-06419"],
1048 ..Default::default()
1049 }));
1050 }
1051 }
1052 ImageTiling::DrmFormatModifier => {
1053 if let &[drm_format_modifier] = drm_format_modifiers.as_slice() {
1057 let format_properties =
1058 unsafe { self.physical_device.format_properties_unchecked(format) };
1059 let drm_format_modifier_properties = format_properties
1060 .drm_format_modifier_properties
1061 .iter()
1062 .find(|properties| {
1063 properties.drm_format_modifier == drm_format_modifier
1064 })
1065 .unwrap();
1066
1067 if plane
1068 >= drm_format_modifier_properties.drm_format_modifier_plane_count
1069 as usize
1070 {
1071 return Err(Box::new(ValidationError {
1072 problem: "`create_info.drm_format_modifiers` has a length of 1, \
1073 but `plane` is not less than `DrmFormatModifierProperties::\
1074 drm_format_modifier_plane_count` for \
1075 `drm_format_modifiers[0]`, as returned by \
1076 `PhysicalDevice::format_properties` for `format`"
1077 .into(),
1078 vuids: &["VUID-VkDeviceImageMemoryRequirements-pCreateInfo-06420"],
1079 ..Default::default()
1080 }));
1081 }
1082 }
1083 }
1084 }
1085 } else if plane.is_some() {
1086 return Err(Box::new(ValidationError {
1087 problem: "`create_info.flags` does not contain `ImageCreateFlags::DISJOINT`, but \
1088 `plane` is `Some`"
1089 .into(),
1090 ..Default::default()
1091 }));
1092 }
1093
1094 Ok(())
1095 }
1096
1097 #[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
1098 pub unsafe fn image_memory_requirements_unchecked(
1099 &self,
1100 create_info: ImageCreateInfo,
1101 plane: Option<usize>,
1102 ) -> MemoryRequirements {
1103 let create_info_fields1_vk = create_info.to_vk_fields1();
1104 let mut create_info_extensions_vk = ImageCreateInfoExtensionsVk {
1105 drm_format_modifier_explicit_vk: None,
1106 ..create_info.to_vk_extensions(&create_info_fields1_vk)
1107 };
1108 let create_info_vk = create_info.to_vk(&mut create_info_extensions_vk);
1109
1110 let default_aspect = if create_info.tiling == ImageTiling::DrmFormatModifier {
1116 ash::vk::ImageAspectFlags::MEMORY_PLANE_0_EXT
1118 } else {
1119 ash::vk::ImageAspectFlags::NONE
1120 };
1121 let plane_aspect = plane.map_or(default_aspect, |plane| match create_info.tiling {
1122 ImageTiling::Optimal | ImageTiling::Linear => match plane {
1123 0 => ash::vk::ImageAspectFlags::PLANE_0,
1124 1 => ash::vk::ImageAspectFlags::PLANE_1,
1125 2 => ash::vk::ImageAspectFlags::PLANE_2,
1126 _ => unreachable!(),
1127 },
1128 ImageTiling::DrmFormatModifier => match plane {
1129 0 => ash::vk::ImageAspectFlags::MEMORY_PLANE_0_EXT,
1130 1 => ash::vk::ImageAspectFlags::MEMORY_PLANE_1_EXT,
1131 2 => ash::vk::ImageAspectFlags::MEMORY_PLANE_2_EXT,
1132 3 => ash::vk::ImageAspectFlags::MEMORY_PLANE_3_EXT,
1133 _ => unreachable!(),
1134 },
1135 });
1136
1137 let info_vk = ash::vk::DeviceImageMemoryRequirements::default()
1138 .create_info(&create_info_vk)
1139 .plane_aspect(plane_aspect);
1140
1141 let mut memory_requirements2_extensions_vk =
1142 MemoryRequirements::to_mut_vk2_extensions(self);
1143 let mut memory_requirements2_vk =
1144 MemoryRequirements::to_mut_vk2(&mut memory_requirements2_extensions_vk);
1145
1146 let fns = self.fns();
1147
1148 if self.api_version() >= Version::V1_3 {
1149 unsafe {
1150 (fns.v1_3.get_device_image_memory_requirements)(
1151 self.handle(),
1152 &info_vk,
1153 &mut memory_requirements2_vk,
1154 )
1155 };
1156 } else {
1157 debug_assert!(self.enabled_extensions().khr_maintenance4);
1158 unsafe {
1159 (fns.khr_maintenance4
1160 .get_device_image_memory_requirements_khr)(
1161 self.handle(),
1162 &info_vk,
1163 &mut memory_requirements2_vk,
1164 )
1165 };
1166 }
1167
1168 let memory_requirements2_vk = ash::vk::MemoryRequirements2 {
1170 _marker: PhantomData,
1171 ..memory_requirements2_vk
1172 };
1173
1174 MemoryRequirements::from_vk2(
1175 &memory_requirements2_vk,
1176 &memory_requirements2_extensions_vk,
1177 )
1178 }
1179
1180 #[inline]
1193 pub unsafe fn memory_fd_properties(
1194 &self,
1195 handle_type: ExternalMemoryHandleType,
1196 file: File,
1197 ) -> Result<MemoryFdProperties, Validated<VulkanError>> {
1198 self.validate_memory_fd_properties(handle_type, &file)?;
1199
1200 Ok(unsafe { self.memory_fd_properties_unchecked(handle_type, file) }?)
1201 }
1202
1203 fn validate_memory_fd_properties(
1204 &self,
1205 handle_type: ExternalMemoryHandleType,
1206 _file: &File,
1207 ) -> Result<(), Box<ValidationError>> {
1208 if !self.enabled_extensions().khr_external_memory_fd {
1209 return Err(Box::new(ValidationError {
1210 requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::DeviceExtension(
1211 "khr_external_memory_fd",
1212 )])]),
1213 ..Default::default()
1214 }));
1215 }
1216
1217 handle_type.validate_device(self).map_err(|err| {
1218 err.add_context("handle_type")
1219 .set_vuids(&["VUID-vkGetMemoryFdPropertiesKHR-handleType-parameter"])
1220 })?;
1221
1222 if handle_type == ExternalMemoryHandleType::OpaqueFd {
1223 return Err(Box::new(ValidationError {
1224 context: "handle_type".into(),
1225 problem: "is `ExternalMemoryHandleType::OpaqueFd`".into(),
1226 vuids: &["VUID-vkGetMemoryFdPropertiesKHR-handleType-00674"],
1227 ..Default::default()
1228 }));
1229 }
1230
1231 Ok(())
1232 }
1233
1234 #[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
1235 pub unsafe fn memory_fd_properties_unchecked(
1236 &self,
1237 handle_type: ExternalMemoryHandleType,
1238 file: File,
1239 ) -> Result<MemoryFdProperties, VulkanError> {
1240 let mut memory_fd_properties = MemoryFdProperties::to_mut_vk();
1241
1242 #[cfg(unix)]
1243 let fd = {
1244 use std::os::fd::IntoRawFd;
1245 file.into_raw_fd()
1246 };
1247
1248 #[cfg(not(unix))]
1249 let fd = {
1250 let _ = file;
1251 -1
1252 };
1253
1254 let fns = self.fns();
1255 unsafe {
1256 (fns.khr_external_memory_fd.get_memory_fd_properties_khr)(
1257 self.handle,
1258 handle_type.into(),
1259 fd,
1260 &mut memory_fd_properties,
1261 )
1262 }
1263 .result()
1264 .map_err(VulkanError::from)?;
1265
1266 Ok(MemoryFdProperties::from_vk(&memory_fd_properties))
1267 }
1268
1269 pub fn set_debug_utils_object_name<T: VulkanObject + DeviceOwned>(
1276 &self,
1277 object: &T,
1278 object_name: Option<&str>,
1279 ) -> Result<(), VulkanError> {
1280 assert_eq!(object.device().handle(), self.handle());
1281
1282 let object_name_vk = object_name.map(|object_name| CString::new(object_name).unwrap());
1283 let mut info_vk =
1284 ash::vk::DebugUtilsObjectNameInfoEXT::default().object_handle(object.handle());
1285
1286 if let Some(object_name_vk) = &object_name_vk {
1287 info_vk = info_vk.object_name(object_name_vk);
1288 }
1289
1290 let fns = self.fns();
1291 unsafe { (fns.ext_debug_utils.set_debug_utils_object_name_ext)(self.handle, &info_vk) }
1292 .result()
1293 .map_err(VulkanError::from)?;
1294
1295 Ok(())
1296 }
1297
1298 #[inline]
1309 pub unsafe fn wait_idle(&self) -> Result<(), VulkanError> {
1310 let fns = self.fns();
1311 unsafe { (fns.v1_0.device_wait_idle)(self.handle) }
1312 .result()
1313 .map_err(VulkanError::from)?;
1314
1315 Ok(())
1316 }
1317}
1318
1319impl Debug for Device {
1320 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
1321 let Self {
1322 handle,
1323 physical_device,
1324 id,
1325
1326 enabled_extensions,
1327 enabled_features,
1328 physical_devices,
1329
1330 api_version,
1331 fns,
1332 active_queue_family_indices,
1333
1334 allocation_count,
1335 fence_pool: _,
1336 semaphore_pool: _,
1337 event_pool: _,
1338 } = self;
1339
1340 f.debug_struct("Device")
1341 .field("handle", handle)
1342 .field("physical_device", physical_device)
1343 .field("id", id)
1344 .field("enabled_extensions", enabled_extensions)
1345 .field("enabled_features", enabled_features)
1346 .field("physical_devices", physical_devices)
1347 .field("api_version", api_version)
1348 .field("fns", fns)
1349 .field("active_queue_family_indices", active_queue_family_indices)
1350 .field("allocation_count", allocation_count)
1351 .finish_non_exhaustive()
1352 }
1353}
1354
1355impl Drop for Device {
1356 #[inline]
1357 fn drop(&mut self) {
1358 let fns = self.fns();
1359
1360 for &raw_fence in self.fence_pool.lock().iter() {
1361 unsafe { (fns.v1_0.destroy_fence)(self.handle, raw_fence, ptr::null()) };
1362 }
1363
1364 for &raw_sem in self.semaphore_pool.lock().iter() {
1365 unsafe { (fns.v1_0.destroy_semaphore)(self.handle, raw_sem, ptr::null()) };
1366 }
1367
1368 for &raw_event in self.event_pool.lock().iter() {
1369 unsafe { (fns.v1_0.destroy_event)(self.handle, raw_event, ptr::null()) };
1370 }
1371
1372 unsafe { (fns.v1_0.destroy_device)(self.handle, ptr::null()) };
1373 }
1374}
1375
1376unsafe impl VulkanObject for Device {
1377 type Handle = ash::vk::Device;
1378
1379 #[inline]
1380 fn handle(&self) -> Self::Handle {
1381 self.handle
1382 }
1383}
1384
1385unsafe impl InstanceOwned for Device {
1386 #[inline]
1387 fn instance(&self) -> &Arc<Instance> {
1388 self.physical_device().instance()
1389 }
1390}
1391
1392impl_id_counter!(Device);
1393
1394#[derive(Clone, Debug)]
1396pub struct DeviceCreateInfo {
1397 pub queue_create_infos: Vec<QueueCreateInfo>,
1401
1402 pub enabled_extensions: DeviceExtensions,
1416
1417 pub enabled_features: DeviceFeatures,
1424
1425 pub physical_devices: SmallVec<[Arc<PhysicalDevice>; 2]>,
1450
1451 pub private_data_slot_request_count: u32,
1464
1465 pub _ne: crate::NonExhaustive,
1466}
1467
1468impl Default for DeviceCreateInfo {
1469 #[inline]
1470 fn default() -> Self {
1471 Self {
1472 queue_create_infos: Vec::new(),
1473 enabled_extensions: DeviceExtensions::empty(),
1474 enabled_features: DeviceFeatures::empty(),
1475 physical_devices: SmallVec::new(),
1476 private_data_slot_request_count: 0,
1477 _ne: crate::NonExhaustive(()),
1478 }
1479 }
1480}
1481
1482impl DeviceCreateInfo {
1483 pub(crate) fn validate(
1484 &self,
1485 physical_device: &PhysicalDevice,
1486 ) -> Result<(), Box<ValidationError>> {
1487 let &Self {
1488 ref queue_create_infos,
1489 ref enabled_extensions,
1490 ref enabled_features,
1491 ref physical_devices,
1492 private_data_slot_request_count,
1493 _ne: _,
1494 } = self;
1495
1496 if queue_create_infos.is_empty() {
1497 return Err(Box::new(ValidationError {
1498 context: "queue_create_infos".into(),
1499 problem: "is empty".into(),
1500 vuids: &["VUID-VkDeviceCreateInfo-queueCreateInfoCount-arraylength"],
1501 ..Default::default()
1502 }));
1503 }
1504
1505 for (index, queue_create_info) in queue_create_infos.iter().enumerate() {
1506 queue_create_info
1507 .validate(physical_device, enabled_extensions, enabled_features)
1508 .map_err(|err| err.add_context(format!("queue_create_infos[{}]", index)))?;
1509
1510 let &QueueCreateInfo {
1511 flags: _,
1512 queue_family_index,
1513 queues: _,
1514 _ne: _,
1515 } = queue_create_info;
1516
1517 if queue_create_infos
1518 .iter()
1519 .filter(|qc2| qc2.queue_family_index == queue_family_index)
1520 .count()
1521 != 1
1522 {
1523 return Err(Box::new(ValidationError {
1524 problem: format!(
1525 "`queue_create_infos[{}].queue_family_index` occurs more than once in \
1526 `queue_create_infos`",
1527 index
1528 )
1529 .into(),
1530 vuids: &["VUID-VkDeviceCreateInfo-queueFamilyIndex-02802"],
1531 ..Default::default()
1532 }));
1533 }
1534 }
1535
1536 enabled_extensions
1537 .check_requirements(
1538 physical_device.supported_extensions(),
1539 physical_device.api_version(),
1540 physical_device.instance().enabled_extensions(),
1541 )
1542 .map_err(|err| {
1543 Box::new(ValidationError {
1544 context: "enabled_extensions".into(),
1545 vuids: &["VUID-vkCreateDevice-ppEnabledExtensionNames-01387"],
1546 ..ValidationError::from_error(err)
1547 })
1548 })?;
1549
1550 enabled_features
1551 .check_requirements(physical_device.supported_features())
1552 .map_err(|err| {
1553 Box::new(ValidationError {
1554 context: "enabled_features".into(),
1555 ..ValidationError::from_error(err)
1556 })
1557 })?;
1558
1559 let mut dependency_extensions = *enabled_extensions;
1560 dependency_extensions.enable_dependencies(
1561 physical_device.api_version(),
1562 physical_device.supported_extensions(),
1563 );
1564
1565 if enabled_extensions.ext_buffer_device_address {
1570 if enabled_extensions.khr_buffer_device_address {
1571 return Err(Box::new(ValidationError {
1572 context: "enabled_extensions".into(),
1573 problem: "contains `khr_buffer_device_address`, \
1574 but also contains `ext_buffer_device_address`"
1575 .into(),
1576 vuids: &["VUID-VkDeviceCreateInfo-ppEnabledExtensionNames-03328"],
1577 ..Default::default()
1578 }));
1579 } else if dependency_extensions.khr_buffer_device_address {
1580 return Err(Box::new(ValidationError {
1581 context: "enabled_extensions".into(),
1582 problem: "contains an extension that requires `khr_buffer_device_address`, \
1583 but also contains `ext_buffer_device_address`"
1584 .into(),
1585 vuids: &["VUID-VkDeviceCreateInfo-ppEnabledExtensionNames-03328"],
1586 ..Default::default()
1587 }));
1588 }
1589
1590 if physical_device.api_version() >= Version::V1_2
1591 && enabled_features.buffer_device_address
1592 {
1593 return Err(Box::new(ValidationError {
1594 problem: "the physical device API version is at least 1.2, \
1595 `enabled_features` contains `buffer_device_address`, and \
1596 `enabled_extensions` contains `ext_buffer_device_address`"
1597 .into(),
1598 vuids: &["VUID-VkDeviceCreateInfo-pNext-04748"],
1599 ..Default::default()
1600 }));
1601 }
1602 }
1603
1604 if enabled_features.shading_rate_image {
1605 if enabled_features.pipeline_fragment_shading_rate {
1606 return Err(Box::new(ValidationError {
1607 context: "enabled_features".into(),
1608 problem: "contains both `shading_rate_image` and \
1609 `pipeline_fragment_shading_rate`"
1610 .into(),
1611 vuids: &["VUID-VkDeviceCreateInfo-shadingRateImage-04478"],
1612 ..Default::default()
1613 }));
1614 }
1615
1616 if enabled_features.primitive_fragment_shading_rate {
1617 return Err(Box::new(ValidationError {
1618 context: "enabled_features".into(),
1619 problem: "contains both `shading_rate_image` and \
1620 `primitive_fragment_shading_rate`"
1621 .into(),
1622 vuids: &["VUID-VkDeviceCreateInfo-shadingRateImage-04479"],
1623 ..Default::default()
1624 }));
1625 }
1626
1627 if enabled_features.attachment_fragment_shading_rate {
1628 return Err(Box::new(ValidationError {
1629 context: "enabled_features".into(),
1630 problem: "contains both `shading_rate_image` and \
1631 `attachment_fragment_shading_rate`"
1632 .into(),
1633 vuids: &["VUID-VkDeviceCreateInfo-shadingRateImage-04480"],
1634 ..Default::default()
1635 }));
1636 }
1637 }
1638
1639 if enabled_features.fragment_density_map {
1640 if enabled_features.pipeline_fragment_shading_rate {
1641 return Err(Box::new(ValidationError {
1642 context: "enabled_features".into(),
1643 problem: "contains both `fragment_density_map` and \
1644 `pipeline_fragment_shading_rate`"
1645 .into(),
1646 vuids: &["VUID-VkDeviceCreateInfo-shadingRateImage-04481"],
1647 ..Default::default()
1648 }));
1649 }
1650
1651 if enabled_features.primitive_fragment_shading_rate {
1652 return Err(Box::new(ValidationError {
1653 context: "enabled_features".into(),
1654 problem: "contains both `fragment_density_map` and \
1655 `primitive_fragment_shading_rate`"
1656 .into(),
1657 vuids: &["VUID-VkDeviceCreateInfo-shadingRateImage-04482"],
1658 ..Default::default()
1659 }));
1660 }
1661
1662 if enabled_features.attachment_fragment_shading_rate {
1663 return Err(Box::new(ValidationError {
1664 context: "enabled_features".into(),
1665 problem: "contains both `fragment_density_map` and \
1666 `attachment_fragment_shading_rate`"
1667 .into(),
1668 vuids: &["VUID-VkDeviceCreateInfo-shadingRateImage-04483"],
1669 ..Default::default()
1670 }));
1671 }
1672 }
1673
1674 if enabled_features.sparse_image_int64_atomics
1675 && !enabled_features.shader_image_int64_atomics
1676 {
1677 return Err(Box::new(ValidationError {
1678 context: "enabled_features".into(),
1679 problem: "contains `sparse_image_int64_atomics`, but does not contain \
1680 `shader_image_int64_atomics`"
1681 .into(),
1682 vuids: &["VUID-VkDeviceCreateInfo-None-04896"],
1683 ..Default::default()
1684 }));
1685 }
1686
1687 if enabled_features.sparse_image_float32_atomics
1688 && !enabled_features.shader_image_float32_atomics
1689 {
1690 return Err(Box::new(ValidationError {
1691 context: "enabled_features".into(),
1692 problem: "contains `sparse_image_float32_atomics`, but does not contain \
1693 `shader_image_float32_atomics`"
1694 .into(),
1695 vuids: &["VUID-VkDeviceCreateInfo-None-04897"],
1696 ..Default::default()
1697 }));
1698 }
1699
1700 if enabled_features.sparse_image_float32_atomic_add
1701 && !enabled_features.shader_image_float32_atomic_add
1702 {
1703 return Err(Box::new(ValidationError {
1704 context: "enabled_features".into(),
1705 problem: "contains `sparse_image_float32_atomic_add`, but does not contain \
1706 `shader_image_float32_atomic_add`"
1707 .into(),
1708 vuids: &["VUID-VkDeviceCreateInfo-None-04898"],
1709 ..Default::default()
1710 }));
1711 }
1712
1713 if enabled_features.sparse_image_float32_atomic_min_max
1714 && !enabled_features.shader_image_float32_atomic_min_max
1715 {
1716 return Err(Box::new(ValidationError {
1717 context: "enabled_features".into(),
1718 problem: "contains `sparse_image_float32_atomic_min_max`, but does not contain \
1719 `shader_image_float32_atomic_min_max`"
1720 .into(),
1721 vuids: &["VUID-VkDeviceCreateInfo-sparseImageFloat32AtomicMinMax-04975"],
1722 ..Default::default()
1723 }));
1724 }
1725
1726 if enabled_features.descriptor_buffer && enabled_extensions.amd_shader_fragment_mask {
1727 return Err(Box::new(ValidationError {
1728 problem: "`enabled_features` contains `descriptor_buffer`, and \
1729 `enabled_extensions` contains `amd_shader_fragment_mask`"
1730 .into(),
1731 vuids: &["VUID-VkDeviceCreateInfo-None-08095"],
1732 ..Default::default()
1733 }));
1734 }
1735
1736 if physical_devices.len() > 1 {
1737 for (index, group_physical_device) in physical_devices.iter().enumerate() {
1738 if physical_devices[..index].contains(group_physical_device) {
1739 return Err(Box::new(ValidationError {
1740 context: "physical_devices".into(),
1741 problem: format!(
1742 "the physical device at index {} is contained in the list more than \
1743 once",
1744 index,
1745 )
1746 .into(),
1747 vuids: &["VUID-VkDeviceGroupDeviceCreateInfo-pPhysicalDevices-00375"],
1748 ..Default::default()
1749 }));
1750 }
1751 }
1752
1753 if !(physical_device.instance().api_version() >= Version::V1_1
1754 || physical_device
1755 .instance()
1756 .enabled_extensions()
1757 .khr_device_group_creation)
1758 {
1759 return Err(Box::new(ValidationError {
1760 context: "physical_devices".into(),
1761 problem: "the length is greater than 1".into(),
1762 requires_one_of: RequiresOneOf(&[
1763 RequiresAllOf(&[Requires::APIVersion(Version::V1_1)]),
1764 RequiresAllOf(&[Requires::InstanceExtension("khr_device_group_creation")]),
1765 ]),
1766 ..Default::default()
1767 }));
1768 }
1769
1770 if !physical_device
1771 .instance()
1772 .is_same_device_group(physical_devices.iter().map(AsRef::as_ref))
1773 {
1774 return Err(Box::new(ValidationError {
1775 context: "physical_devices".into(),
1776 problem: "the physical devices do not all belong to the same device group"
1777 .into(),
1778 vuids: &["VUID-VkDeviceGroupDeviceCreateInfo-pPhysicalDevices-00376"],
1779 ..Default::default()
1780 }));
1781 }
1782 }
1783
1784 if private_data_slot_request_count != 0
1785 && !(physical_device.api_version() >= Version::V1_3
1786 || enabled_extensions.ext_private_data)
1787 {
1788 return Err(Box::new(ValidationError {
1789 context: "private_data_slot_request_count".into(),
1790 problem: "is not zero".into(),
1791 requires_one_of: RequiresOneOf(&[
1792 RequiresAllOf(&[Requires::APIVersion(Version::V1_3)]),
1793 RequiresAllOf(&[Requires::DeviceExtension("ext_private_data")]),
1794 ]),
1795 ..Default::default()
1796 }));
1797 }
1798
1799 Ok(())
1800 }
1801
1802 pub(crate) fn to_vk<'a>(
1803 &self,
1804 fields1_vk: &'a DeviceCreateInfoFields1Vk<'_>,
1805 extensions_vk: &'a mut DeviceCreateInfoExtensionsVk<'_, '_>,
1806 ) -> ash::vk::DeviceCreateInfo<'a> {
1807 let DeviceCreateInfoFields1Vk {
1808 queue_create_infos_vk,
1809 enabled_extension_names_vk,
1810 features_vk,
1811 device_group_physical_devices_vk: _,
1812 } = fields1_vk;
1813
1814 let mut val_vk = ash::vk::DeviceCreateInfo::default()
1815 .flags(ash::vk::DeviceCreateFlags::empty())
1816 .queue_create_infos(queue_create_infos_vk)
1817 .enabled_extension_names(enabled_extension_names_vk);
1818
1819 if let Some(features_vk) = features_vk {
1820 val_vk = val_vk.enabled_features(features_vk);
1821 }
1822
1823 let DeviceCreateInfoExtensionsVk {
1824 device_group_vk,
1825 features2_vk,
1826 private_data_vk,
1827 } = extensions_vk;
1828
1829 if let Some(next) = device_group_vk {
1830 val_vk = val_vk.push_next(next);
1831 }
1832
1833 if let Some(next) = features2_vk {
1834 val_vk = val_vk.push_next(*next);
1835 }
1836
1837 if let Some(next) = private_data_vk {
1838 val_vk = val_vk.push_next(next);
1839 }
1840
1841 val_vk
1842 }
1843
1844 pub(crate) fn to_vk_extensions<'a, 'b>(
1845 &self,
1846 fields1_vk: &'a DeviceCreateInfoFields1Vk<'_>,
1847 features2_vk: Option<&'a mut ash::vk::PhysicalDeviceFeatures2<'b>>,
1848 ) -> DeviceCreateInfoExtensionsVk<'a, 'b> {
1849 let DeviceCreateInfoFields1Vk {
1850 queue_create_infos_vk: _,
1851 enabled_extension_names_vk: _,
1852 features_vk: _,
1853 device_group_physical_devices_vk,
1854 } = fields1_vk;
1855
1856 let device_group_vk = (device_group_physical_devices_vk.len() > 1).then(|| {
1863 ash::vk::DeviceGroupDeviceCreateInfo::default()
1864 .physical_devices(device_group_physical_devices_vk)
1865 });
1866
1867 let private_data_vk = (self.private_data_slot_request_count != 0).then(|| {
1868 ash::vk::DevicePrivateDataCreateInfo::default()
1869 .private_data_slot_request_count(self.private_data_slot_request_count)
1870 });
1871
1872 DeviceCreateInfoExtensionsVk {
1873 device_group_vk,
1874 features2_vk,
1875 private_data_vk,
1876 }
1877 }
1878
1879 pub(crate) fn to_vk_fields1<'a>(
1880 &'a self,
1881 fields2_vk: &'a DeviceCreateInfoFields2Vk,
1882 features_vk: Option<&'a ash::vk::PhysicalDeviceFeatures>,
1883 ) -> DeviceCreateInfoFields1Vk<'a> {
1884 let DeviceCreateInfoFields2Vk {
1885 enabled_extensions_vk,
1886 } = fields2_vk;
1887
1888 let queue_create_infos_vk = self
1889 .queue_create_infos
1890 .iter()
1891 .map(QueueCreateInfo::to_vk)
1892 .collect();
1893 let enabled_extension_names_vk = enabled_extensions_vk
1894 .iter()
1895 .map(|extension| extension.as_ptr())
1896 .collect();
1897 let device_group_physical_devices_vk = self
1898 .physical_devices
1899 .iter()
1900 .map(VulkanObject::handle)
1901 .collect();
1902
1903 DeviceCreateInfoFields1Vk {
1904 queue_create_infos_vk,
1905 enabled_extension_names_vk,
1906 features_vk,
1907 device_group_physical_devices_vk,
1908 }
1909 }
1910
1911 pub(crate) fn to_vk_fields2(&self) -> DeviceCreateInfoFields2Vk {
1912 let enabled_extensions_vk = Vec::<CString>::from(&self.enabled_extensions);
1913
1914 DeviceCreateInfoFields2Vk {
1915 enabled_extensions_vk,
1916 }
1917 }
1918}
1919
1920pub(crate) struct DeviceCreateInfoExtensionsVk<'a, 'b> {
1921 pub(crate) device_group_vk: Option<ash::vk::DeviceGroupDeviceCreateInfo<'a>>,
1922 pub(crate) features2_vk: Option<&'a mut ash::vk::PhysicalDeviceFeatures2<'b>>,
1923 pub(crate) private_data_vk: Option<ash::vk::DevicePrivateDataCreateInfo<'static>>,
1924}
1925
1926pub(crate) struct DeviceCreateInfoFields1Vk<'a> {
1927 pub(crate) queue_create_infos_vk: SmallVec<[ash::vk::DeviceQueueCreateInfo<'a>; 2]>,
1928 pub(crate) enabled_extension_names_vk: SmallVec<[*const c_char; 16]>,
1929 pub(crate) features_vk: Option<&'a ash::vk::PhysicalDeviceFeatures>,
1930 pub(crate) device_group_physical_devices_vk: SmallVec<[ash::vk::PhysicalDevice; 2]>,
1931}
1932
1933pub(crate) struct DeviceCreateInfoFields2Vk {
1934 pub(crate) enabled_extensions_vk: Vec<CString>,
1935}
1936
1937#[derive(Clone, Debug)]
1939pub struct QueueCreateInfo {
1940 pub flags: QueueCreateFlags,
1944
1945 pub queue_family_index: u32,
1949
1950 pub queues: Vec<f32>,
1959
1960 pub _ne: crate::NonExhaustive,
1961}
1962
1963impl Default for QueueCreateInfo {
1964 #[inline]
1965 fn default() -> Self {
1966 Self {
1967 flags: QueueCreateFlags::empty(),
1968 queue_family_index: 0,
1969 queues: vec![0.5],
1970 _ne: crate::NonExhaustive(()),
1971 }
1972 }
1973}
1974
1975impl QueueCreateInfo {
1976 pub(crate) fn validate(
1977 &self,
1978 physical_device: &PhysicalDevice,
1979 device_extensions: &DeviceExtensions,
1980 device_features: &DeviceFeatures,
1981 ) -> Result<(), Box<ValidationError>> {
1982 let &Self {
1983 flags,
1984 queue_family_index,
1985 ref queues,
1986 _ne: _,
1987 } = self;
1988
1989 flags
1990 .validate_device_raw(
1991 physical_device.api_version(),
1992 device_features,
1993 device_extensions,
1994 physical_device.instance().enabled_extensions(),
1995 )
1996 .map_err(|err| {
1997 err.add_context("flags")
1998 .set_vuids(&["VUID-VkDeviceQueueCreateInfo-flags-parameter"])
1999 })?;
2000
2001 let queue_family_properties = physical_device
2002 .queue_family_properties()
2003 .get(queue_family_index as usize)
2004 .ok_or_else(|| {
2005 Box::new(ValidationError {
2006 context: "queue_family_index".into(),
2007 problem: "is not less than the number of queue families in the physical device"
2008 .into(),
2009 vuids: &["VUID-VkDeviceQueueCreateInfo-queueFamilyIndex-00381"],
2010 ..Default::default()
2011 })
2012 })?;
2013
2014 if queues.is_empty() {
2015 return Err(Box::new(ValidationError {
2016 context: "queues".into(),
2017 problem: "is empty".into(),
2018 vuids: &["VUID-VkDeviceQueueCreateInfo-queueCount-arraylength"],
2019 ..Default::default()
2020 }));
2021 }
2022
2023 if queues.len() > queue_family_properties.queue_count as usize {
2024 return Err(Box::new(ValidationError {
2025 problem: "the length of `queues` is greater than the number of queues in the
2026 queue family indicated by `queue_family_index`"
2027 .into(),
2028 vuids: &["VUID-VkDeviceQueueCreateInfo-queueCount-00382"],
2029 ..Default::default()
2030 }));
2031 }
2032
2033 for (index, &priority) in queues.iter().enumerate() {
2034 if !(0.0..=1.0).contains(&priority) {
2035 return Err(Box::new(ValidationError {
2036 context: format!("queues[{}]", index).into(),
2037 problem: "is not between 0.0 and 1.0 inclusive".into(),
2038 vuids: &["VUID-VkDeviceQueueCreateInfo-pQueuePriorities-00383"],
2039 ..Default::default()
2040 }));
2041 }
2042 }
2043
2044 Ok(())
2045 }
2046
2047 pub(crate) fn to_vk(&self) -> ash::vk::DeviceQueueCreateInfo<'_> {
2048 let &Self {
2049 flags,
2050 queue_family_index,
2051 ref queues,
2052 _ne: _,
2053 } = self;
2054
2055 ash::vk::DeviceQueueCreateInfo::default()
2056 .flags(flags.into())
2057 .queue_family_index(queue_family_index)
2058 .queue_priorities(queues)
2059 }
2060}
2061
2062vulkan_bitflags! {
2063 #[non_exhaustive]
2064
2065 QueueCreateFlags = DeviceQueueCreateFlags(u32);
2067
2068 PROTECTED = PROTECTED
2069 RequiresOneOf([
2070 RequiresAllOf([APIVersion(V1_1)]),
2071 ]),
2072}
2073
2074pub unsafe trait DeviceOwned {
2080 fn device(&self) -> &Arc<Device>;
2082}
2083
2084unsafe impl<T> DeviceOwned for T
2085where
2086 T: Deref,
2087 T::Target: DeviceOwned,
2088{
2089 fn device(&self) -> &Arc<Device> {
2090 (**self).device()
2091 }
2092}
2093
2094pub unsafe trait DeviceOwnedVulkanObject {
2096 fn set_debug_utils_object_name(&self, object_name: Option<&str>) -> Result<(), VulkanError>;
2100}
2101
2102unsafe impl<T> DeviceOwnedVulkanObject for T
2103where
2104 T: DeviceOwned + VulkanObject,
2105{
2106 fn set_debug_utils_object_name(&self, object_name: Option<&str>) -> Result<(), VulkanError> {
2107 self.device().set_debug_utils_object_name(self, object_name)
2108 }
2109}
2110
2111#[derive(Clone, PartialEq, Eq, Hash)]
2115#[repr(transparent)]
2116pub(crate) struct DeviceOwnedDebugWrapper<T>(pub(crate) T);
2117
2118impl<T> DeviceOwnedDebugWrapper<T> {
2119 pub fn cast_slice_inner(slice: &[Self]) -> &[T] {
2120 unsafe { slice::from_raw_parts(<*const _>::cast(slice), slice.len()) }
2122 }
2123}
2124
2125impl<T> Debug for DeviceOwnedDebugWrapper<T>
2126where
2127 T: VulkanObject + DeviceOwned,
2128{
2129 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
2130 write!(
2131 f,
2132 "0x{:x} (device: 0x{:x})",
2133 self.0.handle().as_raw(),
2134 self.0.device().handle().as_raw(),
2135 )
2136 }
2137}
2138
2139impl<T> Deref for DeviceOwnedDebugWrapper<T> {
2140 type Target = T;
2141
2142 fn deref(&self) -> &Self::Target {
2143 &self.0
2144 }
2145}
2146
2147#[cfg(test)]
2148mod tests {
2149 use crate::device::{
2150 Device, DeviceCreateInfo, DeviceExtensions, DeviceFeatures, QueueCreateInfo,
2151 };
2152 use std::{ffi::CString, sync::Arc};
2153
2154 #[test]
2155 fn empty_extensions() {
2156 let d: Vec<CString> = (&DeviceExtensions::empty()).into();
2157 assert!(d.is_empty());
2158 }
2159
2160 #[test]
2161 fn extensions_into_iter() {
2162 let extensions = DeviceExtensions {
2163 khr_swapchain: true,
2164 ..DeviceExtensions::empty()
2165 };
2166 for (name, enabled) in extensions {
2167 if name == "VK_KHR_swapchain" {
2168 assert!(enabled);
2169 } else {
2170 assert!(!enabled);
2171 }
2172 }
2173 }
2174
2175 #[test]
2176 fn features_into_iter() {
2177 let features = DeviceFeatures {
2178 tessellation_shader: true,
2179 ..DeviceFeatures::empty()
2180 };
2181 for (name, enabled) in features {
2182 if name == "tessellationShader" {
2183 assert!(enabled);
2184 } else {
2185 assert!(!enabled);
2186 }
2187 }
2188 }
2189
2190 #[test]
2191 fn one_ref() {
2192 let (mut device, _) = gfx_dev_and_queue!();
2193 assert!(Arc::get_mut(&mut device).is_some());
2194 }
2195
2196 #[test]
2197 fn too_many_queues() {
2198 let instance = instance!();
2199 let physical_device = match instance.enumerate_physical_devices().unwrap().next() {
2200 Some(p) => p,
2201 None => return,
2202 };
2203
2204 let queue_family_index = 0;
2205 let queue_family_properties =
2206 &physical_device.queue_family_properties()[queue_family_index as usize];
2207 let queues = (0..queue_family_properties.queue_count + 1)
2208 .map(|_| 0.5)
2209 .collect();
2210
2211 if Device::new(
2212 physical_device,
2213 DeviceCreateInfo {
2214 queue_create_infos: vec![QueueCreateInfo {
2215 queue_family_index,
2216 queues,
2217 ..Default::default()
2218 }],
2219 ..Default::default()
2220 },
2221 )
2222 .is_ok()
2223 {
2224 panic!()
2225 }
2226 }
2227
2228 #[test]
2229 fn unsupported_features() {
2230 let instance = instance!();
2231 let physical_device = match instance.enumerate_physical_devices().unwrap().next() {
2232 Some(p) => p,
2233 None => return,
2234 };
2235
2236 let features = DeviceFeatures::all();
2237 if physical_device.supported_features().contains(&features) {
2239 return;
2240 }
2241
2242 if Device::new(
2243 physical_device,
2244 DeviceCreateInfo {
2245 queue_create_infos: vec![QueueCreateInfo {
2246 queue_family_index: 0,
2247 ..Default::default()
2248 }],
2249 enabled_features: features,
2250 ..Default::default()
2251 },
2252 )
2253 .is_ok()
2254 {
2255 panic!()
2256 }
2257 }
2258
2259 #[test]
2260 fn priority_out_of_range() {
2261 let instance = instance!();
2262 let physical_device = match instance.enumerate_physical_devices().unwrap().next() {
2263 Some(p) => p,
2264 None => return,
2265 };
2266
2267 if Device::new(
2268 physical_device.clone(),
2269 DeviceCreateInfo {
2270 queue_create_infos: vec![QueueCreateInfo {
2271 queue_family_index: 0,
2272 queues: vec![1.4],
2273 ..Default::default()
2274 }],
2275 ..Default::default()
2276 },
2277 )
2278 .is_ok()
2279 {
2280 panic!();
2281 }
2282
2283 if Device::new(
2284 physical_device,
2285 DeviceCreateInfo {
2286 queue_create_infos: vec![QueueCreateInfo {
2287 queue_family_index: 0,
2288 queues: vec![-0.2],
2289 ..Default::default()
2290 }],
2291 ..Default::default()
2292 },
2293 )
2294 .is_ok()
2295 {
2296 panic!();
2297 }
2298 }
2299}