vulkano/device/
mod.rs

1//! Communication channel with a physical device.
2//!
3//! The `Device` is one of the most important objects of Vulkan. Creating a `Device` is required
4//! before you can create buffers, textures, shaders, etc.
5//!
6//! Basic example:
7//!
8//! ```no_run
9//! use vulkano::{
10//!     device::{
11//!         physical::PhysicalDevice, Device, DeviceCreateInfo, DeviceExtensions, DeviceFeatures,
12//!         QueueCreateInfo,
13//!     },
14//!     instance::{Instance, InstanceExtensions},
15//!     Version, VulkanLibrary,
16//! };
17//!
18//! // Creating the instance. See the documentation of the `instance` module.
19//! let library = VulkanLibrary::new()
20//!     .unwrap_or_else(|err| panic!("Couldn't load Vulkan library: {:?}", err));
21//! let instance = Instance::new(library, Default::default())
22//!     .unwrap_or_else(|err| panic!("Couldn't create instance: {:?}", err));
23//!
24//! // We just choose the first physical device. In a real application you would choose depending
25//! // on the capabilities of the physical device and the user's preferences.
26//! let physical_device = instance
27//!     .enumerate_physical_devices()
28//!     .unwrap_or_else(|err| panic!("Couldn't enumerate physical devices: {:?}", err))
29//!     .next()
30//!     .expect("No physical device");
31//!
32//! // Here is the device-creating code.
33//! let device = {
34//!     let features = DeviceFeatures::empty();
35//!     let extensions = DeviceExtensions::empty();
36//!
37//!     match Device::new(
38//!         physical_device,
39//!         DeviceCreateInfo {
40//!             queue_create_infos: vec![QueueCreateInfo {
41//!                 queue_family_index: 0,
42//!                 ..Default::default()
43//!             }],
44//!             enabled_extensions: extensions,
45//!             enabled_features: features,
46//!             ..Default::default()
47//!         },
48//!     ) {
49//!         Ok(d) => d,
50//!         Err(err) => panic!("Couldn't build device: {:?}", err),
51//!     }
52//! };
53//! ```
54//!
55//! # Features and extensions
56//!
57//! Two of the parameters that you pass to `Device::new` are the list of the features and the list
58//! of extensions to enable on the newly-created device.
59//!
60//! > **Note**: Device extensions are the same as instance extensions, except for the device.
61//! > Features are similar to extensions, except that they are part of the core Vulkan
62//! > specifications instead of being separate documents.
63//!
64//! Some Vulkan capabilities, such as swapchains (that allow you to render on the screen) or
65//! geometry shaders for example, require that you enable a certain feature or extension when you
66//! create the device. Contrary to OpenGL, you can't use the functions provided by a feature or an
67//! extension if you didn't explicitly enable it when creating the device.
68//!
69//! Not all physical devices support all possible features and extensions. For example mobile
70//! devices tend to not support geometry shaders, because their hardware is not capable of it. You
71//! can query what is supported with respectively `PhysicalDevice::supported_features` and
72//! `DeviceExtensions::supported_by_device`.
73//!
74//! > **Note**: The fact that you need to manually enable features at initialization also means
75//! > that you don't need to worry about a capability not being supported later on in your code.
76//!
77//! # Queues
78//!
79//! Each physical device proposes one or more *queues* that are divided in *queue families*. A
80//! queue is a thread of execution to which you can submit commands that the GPU will execute.
81//!
82//! > **Note**: You can think of a queue like a CPU thread. Each queue executes its commands one
83//! > after the other, and queues run concurrently. A GPU behaves similarly to the hyper-threading
84//! > technology, in the sense that queues will only run partially in parallel.
85//!
86//! The Vulkan API requires that you specify the list of queues that you are going to use at the
87//! same time as when you create the device. This is done in vulkano by passing an iterator where
88//! each element is a tuple containing a queue family and a number between 0.0 and 1.0 indicating
89//! the priority of execution of the queue relative to the others.
90//!
91//! TODO: write better doc here
92//!
93//! The `Device::new` function returns the newly-created device, but also the list of queues.
94//!
95//! # Extended example
96//!
97//! TODO: write
98
99pub(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
143// Generated by build.rs
144include!(concat!(env!("OUT_DIR"), "/device_extensions.rs"));
145include!(concat!(env!("OUT_DIR"), "/features.rs"));
146
147/// Represents a Vulkan context.
148pub struct Device {
149    handle: ash::vk::Device,
150    // NOTE: `physical_devices` always contains this.
151    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    // The highest version that is supported for this device.
159    // This is the minimum of Instance::max_api_version and PhysicalDevice::api_version.
160    api_version: Version,
161    fns: DeviceFunctions,
162    active_queue_family_indices: SmallVec<[u32; 2]>,
163
164    // This is required for validation in `memory::device_memory`, the count must only be modified
165    // in that module.
166    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    /// Creates a new `Device`.
174    #[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        // VUID-vkCreateDevice-ppEnabledExtensionNames-01387
225        create_info.enabled_extensions.enable_dependencies(
226            physical_device.api_version(),
227            physical_device.supported_extensions(),
228        );
229
230        // VUID-VkDeviceCreateInfo-pProperties-04451
231        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            // VUID-VkDeviceCreateInfo-ppEnabledExtensionNames-04476
259            enable_extension_required_features!(khr_shader_draw_parameters, shader_draw_parameters);
260        }
261
262        if physical_device.api_version() >= Version::V1_2 {
263            // VUID-VkDeviceCreateInfo-ppEnabledExtensionNames-02831
264            enable_extension_required_features!(khr_draw_indirect_count, draw_indirect_count);
265
266            // VUID-VkDeviceCreateInfo-ppEnabledExtensionNames-02832
267            enable_extension_required_features!(
268                khr_sampler_mirror_clamp_to_edge,
269                sampler_mirror_clamp_to_edge,
270            );
271
272            // VUID-VkDeviceCreateInfo-ppEnabledExtensionNames-02833
273            enable_extension_required_features!(ext_descriptor_indexing, descriptor_indexing);
274
275            // VUID-VkDeviceCreateInfo-ppEnabledExtensionNames-02834
276            enable_extension_required_features!(ext_sampler_filter_minmax, sampler_filter_minmax);
277
278            // VUID-VkDeviceCreateInfo-ppEnabledExtensionNames-02835
279            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        // VUID-VkPhysicalDeviceVariablePointersFeatures-variablePointers-01431
309        enable_feature_required_features!(variable_pointers, variable_pointers_storage_buffer);
310
311        // VUID-VkPhysicalDeviceMultiviewFeatures-multiviewGeometryShader-00580
312        enable_feature_required_features!(multiview_geometry_shader, multiview);
313
314        // VUID-VkPhysicalDeviceMultiviewFeatures-multiviewTessellationShader-00581
315        enable_feature_required_features!(multiview_tessellation_shader, multiview);
316
317        // VUID-VkPhysicalDeviceMeshShaderFeaturesEXT-multiviewMeshShader-07032
318        enable_feature_required_features!(multiview_mesh_shader, multiview);
319
320        // VUID-VkPhysicalDeviceMeshShaderFeaturesEXT-primitiveFragmentShadingRateMeshShader-07033
321        enable_feature_required_features!(
322            primitive_fragment_shading_rate_mesh_shader,
323            primitive_fragment_shading_rate,
324        );
325
326        // VUID-VkPhysicalDeviceRayTracingPipelineFeaturesKHR-rayTracingPipelineShaderGroupHandleCaptureReplayMixed-03575
327        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        // VUID-VkPhysicalDeviceRobustness2FeaturesEXT-robustBufferAccess2-04000
333        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            // VUID-VkDeviceCreateInfo-pNext-00373
352            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    /// Creates a new `Device` from a raw object handle.
386    ///
387    /// # Safety
388    ///
389    /// - `handle` must be a valid Vulkan object handle created from `physical_device`.
390    /// - `create_info` must match the info used to create the object.
391    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    /// Returns the Vulkan version supported by the device.
478    ///
479    /// This is the lower of the
480    /// [physical device's supported version](PhysicalDevice::api_version)
481    /// and the instance's [`max_api_version`](Instance::max_api_version).
482    #[inline]
483    pub fn api_version(&self) -> Version {
484        self.api_version
485    }
486
487    /// Returns pointers to the raw Vulkan functions of the device.
488    #[inline]
489    pub fn fns(&self) -> &DeviceFunctions {
490        &self.fns
491    }
492
493    /// Returns the physical device that was used to create this device.
494    #[inline]
495    pub fn physical_device(&self) -> &Arc<PhysicalDevice> {
496        &self.physical_device
497    }
498
499    /// Returns the list of physical devices that was used to create this device. The index of
500    /// each physical device in this list is its *device index*.
501    ///
502    /// This always contains the physical device returned by [`physical_device`].
503    ///
504    /// [`physical_device`]: Self::physical_device
505    #[inline]
506    pub fn physical_devices(&self) -> &[Arc<PhysicalDevice>] {
507        InstanceOwnedDebugWrapper::cast_slice_inner(&self.physical_devices)
508    }
509
510    /// Returns a device mask containing all physical devices in this device. In other words:
511    /// every bit that corresponds to a physical device in this device is set to 1.
512    #[inline]
513    pub fn device_mask(&self) -> u32 {
514        (1 << self.physical_devices.len() as u32) - 1
515    }
516
517    /// Returns the instance used to create this device.
518    #[inline]
519    pub fn instance(&self) -> &Arc<Instance> {
520        self.physical_device.instance()
521    }
522
523    /// Returns the queue family indices that this device uses.
524    #[inline]
525    pub fn active_queue_family_indices(&self) -> &[u32] {
526        &self.active_queue_family_indices
527    }
528
529    /// Returns the extensions that have been enabled on the device.
530    ///
531    /// This includes both the extensions specified in [`DeviceCreateInfo::enabled_extensions`],
532    /// and any extensions that are required by those extensions.
533    #[inline]
534    pub fn enabled_extensions(&self) -> &DeviceExtensions {
535        &self.enabled_extensions
536    }
537
538    /// Returns the features that have been enabled on the device.
539    ///
540    /// This includes both the features specified in [`DeviceCreateInfo::enabled_features`],
541    /// and any features that are required by the enabled extensions.
542    #[inline]
543    pub fn enabled_features(&self) -> &DeviceFeatures {
544        &self.enabled_features
545    }
546
547    /// Returns the current number of active [`DeviceMemory`] allocations the device has.
548    ///
549    /// [`DeviceMemory`]: crate::memory::DeviceMemory
550    #[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    /// For the given acceleration structure build info and primitive counts, returns the
568    /// minimum size required to build the acceleration structure, and the minimum size of the
569    /// scratch buffer used during the build operation.
570    #[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        // VUID-vkGetAccelerationStructureBuildSizesKHR-pBuildInfo-parameter
625        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    /// Returns whether a serialized acceleration structure with the specified version data
728    /// is compatible with this device.
729    #[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    /// Returns whether a descriptor set layout with the given `create_info` could be created
788    /// on the device, and additional supported properties where relevant. `Some` is returned if
789    /// the descriptor set layout is supported, `None` if it is not.
790    ///
791    /// This is primarily useful for checking whether the device supports a descriptor set layout
792    /// that goes beyond the [`max_per_set_descriptors`] limit. A layout that does not exceed
793    /// that limit is guaranteed to be supported, otherwise this function can be called.
794    ///
795    /// The device API version must be at least 1.1, or the [`khr_maintenance3`] extension must
796    /// be enabled on the device.
797    ///
798    /// [`max_per_set_descriptors`]: crate::device::DeviceProperties::max_per_set_descriptors
799    /// [`khr_maintenance3`]: crate::device::DeviceExtensions::khr_maintenance3
800    #[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        // VUID-vkGetDescriptorSetLayoutSupport-pCreateInfo-parameter
825        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        // Unborrow
867        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    /// Returns the memory requirements that would apply for a buffer created with the specified
876    /// `create_info`.
877    ///
878    /// The device API version must be at least 1.3, or the [`khr_maintenance4`] extension must
879    /// be enabled on the device.
880    ///
881    /// [`khr_maintenance4`]: DeviceExtensions::khr_maintenance4
882    #[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        // Unborrow
952        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    /// Returns the memory requirements that would apply for an image created with the specified
964    /// `create_info`.
965    ///
966    /// If `create_info.flags` contains [`ImageCreateFlags::DISJOINT`], then `plane` must specify
967    /// the plane number of the format or memory plane (depending on tiling) that memory
968    /// requirements will be returned for. Otherwise, `plane` must be `None`.
969    ///
970    /// The device API version must be at least 1.3, or the [`khr_maintenance4`] extension must
971    /// be enabled on the device.
972    ///
973    /// [`khr_maintenance4`]: DeviceExtensions::khr_maintenance4
974    #[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                    // TODO: handle the case where `drm_format_modifiers` contains multiple
1054                    // elements. See: https://github.com/KhronosGroup/Vulkan-Docs/issues/2309
1055
1056                    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        // This is currently necessary because of an issue with the spec. The plane aspect should
1111        // only be needed if the image is disjoint, but the spec currently demands a valid aspect
1112        // even for non-disjoint DRM format modifier images.
1113        // See: https://github.com/KhronosGroup/Vulkan-Docs/issues/2309
1114        // Replace this variable with ash::vk::ImageAspectFlags::NONE when resolved.
1115        let default_aspect = if create_info.tiling == ImageTiling::DrmFormatModifier {
1116            // Hopefully valid for any DrmFormatModifier image?
1117            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        // Unborrow
1169        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    // TODO: image_sparse_memory_requirements
1181
1182    /// Retrieves the properties of an external file descriptor when imported as a given external
1183    /// handle type.
1184    ///
1185    /// An error will be returned if the
1186    /// [`khr_external_memory_fd`](DeviceExtensions::khr_external_memory_fd) extension was not
1187    /// enabled on the device, or if `handle_type` is [`ExternalMemoryHandleType::OpaqueFd`].
1188    ///
1189    /// # Safety
1190    ///
1191    /// - `file` must be a handle to external memory that was created outside the Vulkan API.
1192    #[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    /// Assigns a human-readable name to `object` for debugging purposes.
1270    ///
1271    /// If `object_name` is `None`, a previously set object name is removed.
1272    ///
1273    /// # Panics
1274    /// - If `object` is not owned by this device.
1275    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    /// Waits until all work on this device has finished. You should never need to call
1299    /// this function, but it can be useful for debugging or benchmarking purposes.
1300    ///
1301    /// > **Note**: This is the Vulkan equivalent of OpenGL's `glFinish`.
1302    ///
1303    /// # Safety
1304    ///
1305    /// This function is not thread-safe. You must not submit anything to any of the queue
1306    /// of the device (either explicitly or implicitly, for example with a future's destructor)
1307    /// while this function is waiting.
1308    #[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/// Parameters to create a new `Device`.
1395#[derive(Clone, Debug)]
1396pub struct DeviceCreateInfo {
1397    /// The queues to create for the device.
1398    ///
1399    /// The default value is empty, which must be overridden.
1400    pub queue_create_infos: Vec<QueueCreateInfo>,
1401
1402    /// The extensions to enable on the device.
1403    ///
1404    /// You only need to enable the extensions that you need. If the extensions you specified
1405    /// require additional extensions to be enabled, they will be automatically enabled as well.
1406    ///
1407    /// If the [`khr_portability_subset`](DeviceExtensions::khr_portability_subset) extension is
1408    /// available, it will be enabled automatically, so you do not have to do this yourself.
1409    /// You are responsible for ensuring that your program can work correctly on such devices.
1410    /// See [the documentation of the `instance`
1411    /// module](crate::instance#portability-subset-devices-and-the-enumerate_portability-flag)
1412    /// for more information.
1413    ///
1414    /// The default value is [`DeviceExtensions::empty()`].
1415    pub enabled_extensions: DeviceExtensions,
1416
1417    /// The features to enable on the device.
1418    ///
1419    /// You only need to enable the features that you need. If the extensions you specified
1420    /// require certain features to be enabled, they will be automatically enabled as well.
1421    ///
1422    /// The default value is [`DeviceFeatures::empty()`].
1423    pub enabled_features: DeviceFeatures,
1424
1425    /// A list of physical devices to create this device from, to act together as a single
1426    /// logical device. The physical devices must all belong to the same device group, as returned
1427    /// by [`Instance::enumerate_physical_device_groups`], and a physical device must not appear
1428    /// in the list more than once.
1429    ///
1430    /// The index of each physical device in this list becomes that physical
1431    /// device's *device index*, which can be used in other Vulkan functions to specify
1432    /// a particular physical device within the group.
1433    /// If the list is left empty, then it behaves as if it contained the physical device,
1434    /// that was passed to the `physical_device` parameter of [`Device::new`], as its only element.
1435    /// Otherwise, that physical device must always be part of the list, but it does not need to
1436    /// be the first element.
1437    ///
1438    /// If the list contains more than one physical device, the instance API version must be at
1439    /// least 1.1, or the [`khr_device_group_creation`] extension must be enabled on the instance.
1440    /// In order to use any device-level functionality for dealing with device groups,
1441    /// the physical device API version should also be at least 1.1,
1442    /// or `enabled_extensions` should contain [`khr_device_group`].
1443    ///
1444    /// The default value is empty.
1445    ///
1446    /// [`Instance::enumerate_physical_device_groups`]: Instance::enumerate_physical_device_groups
1447    /// [`khr_device_group_creation`]: crate::instance::InstanceExtensions::khr_device_group_creation
1448    /// [`khr_device_group`]: crate::device::DeviceExtensions::khr_device_group
1449    pub physical_devices: SmallVec<[Arc<PhysicalDevice>; 2]>,
1450
1451    /// The number of [private data slots] to reserve when creating the device.
1452    ///
1453    /// This is purely an optimization, and it is not necessary to do this in order to use private
1454    /// data slots, but it may improve performance.
1455    ///
1456    /// If not zero, the physical device API version must be at least 1.3, or `enabled_extensions`
1457    /// must contain [`ext_private_data`].
1458    ///
1459    /// The default value is `0`.
1460    ///
1461    /// [private data slots]: private_data
1462    /// [`ext_private_data`]: DeviceExtensions::ext_private_data
1463    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        // VUID-VkDeviceCreateInfo-ppEnabledExtensionNames-01840
1566        // VUID-VkDeviceCreateInfo-ppEnabledExtensionNames-00374
1567        // Ensured because `DeviceExtensions` doesn't contain obsoleted extensions.
1568
1569        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        // Length of zero and length of one are completely equivalent,
1857        // so only do anything special here if more than one physical device was given.
1858        // Spec:
1859        // A logical device created without using VkDeviceGroupDeviceCreateInfo,
1860        // or with physicalDeviceCount equal to zero, is equivalent to a physicalDeviceCount of one
1861        // and pPhysicalDevices pointing to the physicalDevice parameter to vkCreateDevice.
1862        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/// Parameters to create queues in a new `Device`.
1938#[derive(Clone, Debug)]
1939pub struct QueueCreateInfo {
1940    /// Additional properties of the queue.
1941    ///
1942    /// The default value is empty.
1943    pub flags: QueueCreateFlags,
1944
1945    /// The index of the queue family to create queues for.
1946    ///
1947    /// The default value is `0`.
1948    pub queue_family_index: u32,
1949
1950    /// The queues to create for the given queue family, each with a relative priority.
1951    ///
1952    /// The relative priority value is an arbitrary number between 0.0 and 1.0. Giving a queue a
1953    /// higher priority is a hint to the driver that the queue should be given more processing
1954    /// time. As this is only a hint, different drivers may handle this value differently and
1955    /// there are no guarantees about its behavior.
1956    ///
1957    /// The default value is a single queue with a priority of 0.5.
1958    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    /// Flags specifying additional properties of a queue.
2066    QueueCreateFlags = DeviceQueueCreateFlags(u32);
2067
2068    PROTECTED = PROTECTED
2069    RequiresOneOf([
2070        RequiresAllOf([APIVersion(V1_1)]),
2071    ]),
2072}
2073
2074/// Implemented on objects that belong to a Vulkan device.
2075///
2076/// # Safety
2077///
2078/// - `device()` must return the correct device.
2079pub unsafe trait DeviceOwned {
2080    /// Returns the device that owns `self`.
2081    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
2094/// Implemented on objects that implement both `DeviceOwned` and `VulkanObject`.
2095pub unsafe trait DeviceOwnedVulkanObject {
2096    /// Assigns a human-readable name to the object for debugging purposes.
2097    ///
2098    /// If `object_name` is `None`, a previously set object name is removed.
2099    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/// Same as [`DebugWrapper`], but also prints the device handle for disambiguation.
2112///
2113/// [`DebugWrapper`]: crate:: DebugWrapper
2114#[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        // SAFETY: `DeviceOwnedDebugWrapper<T>` and `T` have the same layout.
2121        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        // In the unlikely situation where the device supports everything, we ignore the test.
2238        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}