1 // Copyright (c) 2016 The vulkano developers
2 // Licensed under the Apache License, Version 2.0
3 // <LICENSE-APACHE or
4 // https://www.apache.org/licenses/LICENSE-2.0> or the MIT
5 // license <LICENSE-MIT or https://opensource.org/licenses/MIT>,
6 // at your option. All files in the project carrying such
7 // notice may not be copied, modified, or distributed except
8 // according to those terms.
9 
10 //! API entry point.
11 //!
12 //! The first thing to do after loading the Vulkan library is to create an `Instance` object.
13 //!
14 //! For example:
15 //!
16 //! ```no_run
17 //! use vulkano::{
18 //!     instance::{Instance, InstanceExtensions},
19 //!     Version, VulkanLibrary,
20 //! };
21 //!
22 //! let library = VulkanLibrary::new()
23 //!     .unwrap_or_else(|err| panic!("Couldn't load Vulkan library: {:?}", err));
24 //! let instance = Instance::new(library, Default::default())
25 //!     .unwrap_or_else(|err| panic!("Couldn't create instance: {:?}", err));
26 //! ```
27 //!
28 //! Creating an instance initializes everything and allows you to enumerate physical devices,
29 //! ie. all the Vulkan implementations that are available on the system.
30 //!
31 //! ```no_run
32 //! # use vulkano::{
33 //! #     instance::{Instance, InstanceExtensions},
34 //! #     Version, VulkanLibrary,
35 //! # };
36 //! use vulkano::device::physical::PhysicalDevice;
37 //!
38 //! # let library = VulkanLibrary::new().unwrap();
39 //! # let instance = Instance::new(library, Default::default()).unwrap();
40 //! for physical_device in instance.enumerate_physical_devices().unwrap() {
41 //!     println!("Available device: {}", physical_device.properties().device_name);
42 //! }
43 //! ```
44 //!
45 //! # Enumerating physical devices and creating a device
46 //!
47 //! After you have created an instance, the next step is usually to enumerate the physical devices
48 //! that are available on the system with `Instance::enumerate_physical_devices()` (see above).
49 //!
50 //! When choosing which physical device to use, keep in mind that physical devices may or may not
51 //! be able to draw to a certain surface (ie. to a window or a monitor), or may even not be able
52 //! to draw at all. See the `swapchain` module for more information about surfaces.
53 //!
54 //! Once you have chosen a physical device, you can create a `Device` object from it. See the
55 //! `device` module for more info.
56 //!
57 //! # Portability subset devices and the `enumerate_portability` flag
58 //!
59 //! Certain devices, currently those on MacOS and iOS systems, do not fully conform to the Vulkan
60 //! specification. They are usable as normal devices, but they do not implement everything that
61 //! is required; some mandatory parts of Vulkan are missing. These are known as
62 //! "portability subset" devices.
63 //!
64 //! A portability subset device will advertise support for the
65 //! [`khr_portability_subset`](crate::device::DeviceExtensions::khr_portability_subset) device
66 //! extension. This extension must always be enabled when it is supported, and Vulkano will
67 //! automatically enable it when creating the device. When it is enabled, some parts of Vulkan that
68 //! are available in standard Vulkan will not be available by default, but they can be used by
69 //! enabling corresponding features when creating the device, if the device supports them.
70 //!
71 //! Because these devices are non-conformant, Vulkan programs that rely on full compliance may
72 //! not work (crash or have validation errors) when run on them, if they happen to use a part of
73 //! Vulkan that is missing from the non-conformant device. Therefore, Vulkan hides them from
74 //! the user by default when calling `enumerate_physical_devices` on the instance. If there are no
75 //! conformant devices on the system, `Instance::new` will return an `IncompatibleDriver` error.
76 //!
77 //! In order to enumerate portability subset devices, you must set the
78 //! [`InstanceCreateInfo::enumerate_portability`] flag when creating the instance. However, if you
79 //! do this, your program must be prepared to handle the non-conformant aspects of these devices,
80 //! and must enable the appropriate features when creating the `Device` if you intend to use them.
81 
82 use self::debug::{
83     DebugUtilsMessengerCreateInfo, UserCallback, ValidationFeatureDisable, ValidationFeatureEnable,
84 };
85 pub use self::{extensions::InstanceExtensions, layers::LayerProperties};
86 use crate::{
87     device::physical::PhysicalDevice, instance::debug::trampoline, macros::impl_id_counter,
88     OomError, RequiresOneOf, VulkanError, VulkanLibrary, VulkanObject,
89 };
90 pub use crate::{
91     extensions::{ExtensionRestriction, ExtensionRestrictionError},
92     fns::InstanceFunctions,
93     version::Version,
94 };
95 use smallvec::SmallVec;
96 use std::{
97     error::Error,
98     ffi::{c_void, CString},
99     fmt::{Debug, Display, Error as FmtError, Formatter},
100     mem::MaybeUninit,
101     num::NonZeroU64,
102     panic::{RefUnwindSafe, UnwindSafe},
103     ptr,
104     sync::Arc,
105 };
106 
107 pub mod debug;
108 pub(crate) mod extensions;
109 mod layers;
110 
111 /// An instance of a Vulkan context. This is the main object that should be created by an
112 /// application before everything else.
113 ///
114 /// # Application and engine info
115 ///
116 /// When you create an instance, you have the possibility to set information about your application
117 /// and its engine.
118 ///
119 /// Providing this information allows for example the driver to let the user configure the driver's
120 /// behavior for your application alone through a control panel.
121 ///
122 /// ```no_run
123 /// # #[macro_use] extern crate vulkano;
124 /// # fn main() {
125 /// use vulkano::{
126 ///     instance::{Instance, InstanceCreateInfo, InstanceExtensions},
127 ///     Version, VulkanLibrary,
128 /// };
129 ///
130 /// let library = VulkanLibrary::new().unwrap();
131 /// let _instance = Instance::new(
132 ///     library,
133 ///     InstanceCreateInfo::application_from_cargo_toml(),
134 /// ).unwrap();
135 /// # }
136 /// ```
137 ///
138 /// # API versions
139 ///
140 /// Both an `Instance` and a [`Device`](crate::device::Device) have a highest version of the Vulkan
141 /// API that they support. This places a limit on what Vulkan functions and features are available
142 /// to use when used on a particular instance or device. It is possible for the instance and the
143 /// device to support different versions. The supported version for an instance can be queried
144 /// before creation with
145 /// [`VulkanLibrary::api_version`](crate::VulkanLibrary::api_version),
146 /// while for a device it can be retrieved with
147 /// [`PhysicalDevice::api_version`](crate::device::physical::PhysicalDevice::api_version).
148 ///
149 /// When creating an `Instance`, you have to specify a maximum API version that you will use.
150 /// This restricts the API version that is available for the instance and any devices created from
151 /// it. For example, if both instance and device potentially support Vulkan 1.2, but you specify
152 /// 1.1 as the maximum API version when creating the `Instance`, then you can only use Vulkan 1.1
153 /// functions, even though they could theoretically support a higher version. You can think of it
154 /// as a promise never to use any functionality from a higher version.
155 ///
156 /// The maximum API version is not a _minimum_, so it is possible to set it to a higher version than
157 /// what the instance or device inherently support. The final API version that you are able to use
158 /// on an instance or device is the lower of the supported API version and the chosen maximum API
159 /// version of the `Instance`.
160 ///
161 /// Due to a quirk in how the Vulkan 1.0 specification was written, if the instance only
162 /// supports Vulkan 1.0, then it is not possible to specify a maximum API version higher than 1.0.
163 /// Trying to create an `Instance` will return an `IncompatibleDriver` error. Consequently, it is
164 /// not possible to use a higher device API version with an instance that only supports 1.0.
165 ///
166 /// # Extensions
167 ///
168 /// When creating an `Instance`, you must provide a list of extensions that must be enabled on the
169 /// newly-created instance. Trying to enable an extension that is not supported by the system will
170 /// result in an error.
171 ///
172 /// Contrary to OpenGL, it is not possible to use the features of an extension if it was not
173 /// explicitly enabled.
174 ///
175 /// Extensions are especially important to take into account if you want to render images on the
176 /// screen, as the only way to do so is to use the `VK_KHR_surface` extension. More information
177 /// about this in the `swapchain` module.
178 ///
179 /// For example, here is how we create an instance with the `VK_KHR_surface` and
180 /// `VK_KHR_android_surface` extensions enabled, which will allow us to render images to an
181 /// Android screen. You can compile and run this code on any system, but it is highly unlikely to
182 /// succeed on anything else than an Android-running device.
183 ///
184 /// ```no_run
185 /// use vulkano::{
186 ///     instance::{Instance, InstanceCreateInfo, InstanceExtensions},
187 ///     Version, VulkanLibrary,
188 /// };
189 ///
190 /// let library = VulkanLibrary::new()
191 ///     .unwrap_or_else(|err| panic!("Couldn't load Vulkan library: {:?}", err));
192 ///
193 /// let extensions = InstanceExtensions {
194 ///     khr_surface: true,
195 ///     khr_android_surface: true,
196 ///     .. InstanceExtensions::empty()
197 /// };
198 ///
199 /// let instance = Instance::new(
200 ///     library,
201 ///     InstanceCreateInfo {
202 ///         enabled_extensions: extensions,
203 ///         ..Default::default()
204 ///     },
205 /// )
206 /// .unwrap_or_else(|err| panic!("Couldn't create instance: {:?}", err));
207 /// ```
208 ///
209 /// # Layers
210 ///
211 /// When creating an `Instance`, you have the possibility to pass a list of **layers** that will
212 /// be activated on the newly-created instance. The list of available layers can be retrieved by
213 /// calling the [`layer_properties`](crate::VulkanLibrary::layer_properties) method of
214 /// `VulkanLibrary`.
215 ///
216 /// A layer is a component that will hook and potentially modify the Vulkan function calls.
217 /// For example, activating a layer could add a frames-per-second counter on the screen, or it
218 /// could send information to a debugger that will debug your application.
219 ///
220 /// > **Note**: From an application's point of view, layers "just exist". In practice, on Windows
221 /// > and Linux, layers can be installed by third party installers or by package managers and can
222 /// > also be activated by setting the value of the `VK_INSTANCE_LAYERS` environment variable
223 /// > before starting the program. See the documentation of the official Vulkan loader for these
224 /// > platforms.
225 ///
226 /// > **Note**: In practice, the most common use of layers right now is for debugging purposes.
227 /// > To do so, you are encouraged to set the `VK_INSTANCE_LAYERS` environment variable on Windows
228 /// > or Linux instead of modifying the source code of your program. For example:
229 /// > `export VK_INSTANCE_LAYERS=VK_LAYER_LUNARG_api_dump` on Linux if you installed the Vulkan SDK
230 /// > will print the list of raw Vulkan function calls.
231 ///
232 /// ## Examples
233 ///
234 /// ```
235 /// # use std::{sync::Arc, error::Error};
236 /// # use vulkano::{
237 /// #     instance::{Instance, InstanceCreateInfo, InstanceExtensions},
238 /// #     Version, VulkanLibrary,
239 /// # };
240 /// # fn test() -> Result<Arc<Instance>, Box<dyn Error>> {
241 /// let library = VulkanLibrary::new()?;
242 ///
243 /// // For the sake of the example, we activate all the layers that
244 /// // contain the word "foo" in their description.
245 /// let layers: Vec<_> = library.layer_properties()?
246 ///     .filter(|l| l.description().contains("foo"))
247 ///     .collect();
248 ///
249 /// let instance = Instance::new(
250 ///     library,
251 ///     InstanceCreateInfo {
252 ///         enabled_layers: layers.iter().map(|l| l.name().to_owned()).collect(),
253 ///         ..Default::default()
254 ///     },
255 /// )?;
256 /// # Ok(instance)
257 /// # }
258 /// ```
259 // TODO: mention that extensions must be supported by layers as well
260 pub struct Instance {
261     handle: ash::vk::Instance,
262     fns: InstanceFunctions,
263     id: NonZeroU64,
264 
265     api_version: Version,
266     enabled_extensions: InstanceExtensions,
267     enabled_layers: Vec<String>,
268     library: Arc<VulkanLibrary>,
269     max_api_version: Version,
270     _user_callbacks: Vec<Box<UserCallback>>,
271 }
272 
273 // TODO: fix the underlying cause instead
274 impl UnwindSafe for Instance {}
275 impl RefUnwindSafe for Instance {}
276 
277 impl Instance {
278     /// Creates a new `Instance`.
279     ///
280     /// # Panics
281     ///
282     /// - Panics if any version numbers in `create_info` contain a field too large to be converted
283     ///   into a Vulkan version number.
284     /// - Panics if `create_info.max_api_version` is not at least `V1_0`.
new( library: Arc<VulkanLibrary>, create_info: InstanceCreateInfo, ) -> Result<Arc<Instance>, InstanceCreationError>285     pub fn new(
286         library: Arc<VulkanLibrary>,
287         create_info: InstanceCreateInfo,
288     ) -> Result<Arc<Instance>, InstanceCreationError> {
289         unsafe { Self::with_debug_utils_messengers(library, create_info, []) }
290     }
291 
292     /// Creates a new `Instance` with debug messengers to use during the creation and destruction
293     /// of the instance.
294     ///
295     /// The debug messengers are not used at any other time,
296     /// [`DebugUtilsMessenger`](crate::instance::debug::DebugUtilsMessenger) should be used for
297     /// that.
298     ///
299     /// If `debug_utils_messengers` is not empty, the `ext_debug_utils` extension must be set in
300     /// `enabled_extensions`.
301     ///
302     /// # Panics
303     ///
304     /// - Panics if the `message_severity` or `message_type` members of any element of
305     ///   `debug_utils_messengers` are empty.
306     ///
307     /// # Safety
308     ///
309     /// - The `user_callback` of each element of `debug_utils_messengers` must not make any calls
310     ///   to the Vulkan API.
with_debug_utils_messengers( library: Arc<VulkanLibrary>, create_info: InstanceCreateInfo, debug_utils_messengers: impl IntoIterator<Item = DebugUtilsMessengerCreateInfo>, ) -> Result<Arc<Instance>, InstanceCreationError>311     pub unsafe fn with_debug_utils_messengers(
312         library: Arc<VulkanLibrary>,
313         create_info: InstanceCreateInfo,
314         debug_utils_messengers: impl IntoIterator<Item = DebugUtilsMessengerCreateInfo>,
315     ) -> Result<Arc<Instance>, InstanceCreationError> {
316         let InstanceCreateInfo {
317             application_name,
318             application_version,
319             mut enabled_extensions,
320             enabled_layers,
321             engine_name,
322             engine_version,
323             max_api_version,
324             enumerate_portability,
325             enabled_validation_features,
326             disabled_validation_features,
327             _ne: _,
328         } = create_info;
329 
330         let (api_version, max_api_version) = {
331             let api_version = library.api_version();
332             let max_api_version = if let Some(max_api_version) = max_api_version {
333                 max_api_version
334             } else if api_version < Version::V1_1 {
335                 api_version
336             } else {
337                 Version::HEADER_VERSION
338             };
339 
340             (std::cmp::min(max_api_version, api_version), max_api_version)
341         };
342 
343         // VUID-VkApplicationInfo-apiVersion-04010
344         assert!(max_api_version >= Version::V1_0);
345         let supported_extensions =
346             library.supported_extensions_with_layers(enabled_layers.iter().map(String::as_str))?;
347         let mut flags = ash::vk::InstanceCreateFlags::empty();
348 
349         if enumerate_portability && supported_extensions.khr_portability_enumeration {
350             enabled_extensions.khr_portability_enumeration = true;
351             flags |= ash::vk::InstanceCreateFlags::ENUMERATE_PORTABILITY_KHR;
352         }
353 
354         // Check if the extensions are correct
355         enabled_extensions.check_requirements(&supported_extensions, api_version)?;
356 
357         // FIXME: check whether each layer is supported
358         let enabled_layers_cstr: Vec<CString> = enabled_layers
359             .iter()
360             .map(|name| CString::new(name.clone()).unwrap())
361             .collect();
362         let enabled_layers_ptrs = enabled_layers_cstr
363             .iter()
364             .map(|layer| layer.as_ptr())
365             .collect::<SmallVec<[_; 2]>>();
366 
367         let enabled_extensions_cstr: Vec<CString> = (&enabled_extensions).into();
368         let enabled_extensions_ptrs = enabled_extensions_cstr
369             .iter()
370             .map(|extension| extension.as_ptr())
371             .collect::<SmallVec<[_; 2]>>();
372 
373         let application_name_cstr = application_name.map(|name| CString::new(name).unwrap());
374         let engine_name_cstr = engine_name.map(|name| CString::new(name).unwrap());
375         let application_info = ash::vk::ApplicationInfo {
376             p_application_name: application_name_cstr
377                 .as_ref()
378                 .map(|s| s.as_ptr())
379                 .unwrap_or(ptr::null()),
380             application_version: application_version
381                 .try_into()
382                 .expect("Version out of range"),
383             p_engine_name: engine_name_cstr
384                 .as_ref()
385                 .map(|s| s.as_ptr())
386                 .unwrap_or(ptr::null()),
387             engine_version: engine_version.try_into().expect("Version out of range"),
388             api_version: max_api_version.try_into().expect("Version out of range"),
389             ..Default::default()
390         };
391 
392         let enable_validation_features_vk: SmallVec<[_; 5]> = enabled_validation_features
393             .iter()
394             .copied()
395             .map(Into::into)
396             .collect();
397         let disable_validation_features_vk: SmallVec<[_; 8]> = disabled_validation_features
398             .iter()
399             .copied()
400             .map(Into::into)
401             .collect();
402 
403         let mut create_info_vk = ash::vk::InstanceCreateInfo {
404             flags,
405             p_application_info: &application_info,
406             enabled_layer_count: enabled_layers_ptrs.len() as u32,
407             pp_enabled_layer_names: enabled_layers_ptrs.as_ptr(),
408             enabled_extension_count: enabled_extensions_ptrs.len() as u32,
409             pp_enabled_extension_names: enabled_extensions_ptrs.as_ptr(),
410             ..Default::default()
411         };
412         let mut validation_features_vk = None;
413 
414         if !enabled_validation_features.is_empty() || !disabled_validation_features.is_empty() {
415             if !enabled_extensions.ext_validation_features {
416                 return Err(InstanceCreationError::RequirementNotMet {
417                     required_for: "`create_info.enabled_validation_features` or \
418                         `create_info.disabled_validation_features` are not empty",
419                     requires_one_of: RequiresOneOf {
420                         instance_extensions: &["ext_validation_features"],
421                         ..Default::default()
422                     },
423                 });
424             }
425 
426             // VUID-VkValidationFeaturesEXT-pEnabledValidationFeatures-02967
427             assert!(
428                 !enabled_validation_features
429                     .contains(&ValidationFeatureEnable::GpuAssistedReserveBindingSlot)
430                     || enabled_validation_features.contains(&ValidationFeatureEnable::GpuAssisted)
431             );
432 
433             // VUID-VkValidationFeaturesEXT-pEnabledValidationFeatures-02968
434             assert!(
435                 !(enabled_validation_features.contains(&ValidationFeatureEnable::DebugPrintf)
436                     && enabled_validation_features.contains(&ValidationFeatureEnable::GpuAssisted))
437             );
438 
439             let next = validation_features_vk.insert(ash::vk::ValidationFeaturesEXT {
440                 enabled_validation_feature_count: enable_validation_features_vk.len() as u32,
441                 p_enabled_validation_features: enable_validation_features_vk.as_ptr(),
442                 disabled_validation_feature_count: disable_validation_features_vk.len() as u32,
443                 p_disabled_validation_features: disable_validation_features_vk.as_ptr(),
444                 ..Default::default()
445             });
446 
447             next.p_next = create_info_vk.p_next;
448             create_info_vk.p_next = next as *const _ as *const _;
449         }
450 
451         // Handle debug messengers
452         let debug_utils_messengers = debug_utils_messengers.into_iter();
453         let mut debug_utils_messenger_create_infos =
454             Vec::with_capacity(debug_utils_messengers.size_hint().0);
455         let mut user_callbacks = Vec::with_capacity(debug_utils_messengers.size_hint().0);
456 
457         for create_info in debug_utils_messengers {
458             let DebugUtilsMessengerCreateInfo {
459                 message_type,
460                 message_severity,
461                 user_callback,
462                 _ne: _,
463             } = create_info;
464 
465             // VUID-VkInstanceCreateInfo-pNext-04926
466             if !enabled_extensions.ext_debug_utils {
467                 return Err(InstanceCreationError::RequirementNotMet {
468                     required_for: "`create_info.debug_utils_messengers` is not empty",
469                     requires_one_of: RequiresOneOf {
470                         instance_extensions: &["ext_debug_utils"],
471                         ..Default::default()
472                     },
473                 });
474             }
475 
476             // VUID-VkDebugUtilsMessengerCreateInfoEXT-messageSeverity-parameter
477             // TODO: message_severity.validate_instance()?;
478 
479             // VUID-VkDebugUtilsMessengerCreateInfoEXT-messageSeverity-requiredbitmask
480             assert!(!message_severity.is_empty());
481 
482             // VUID-VkDebugUtilsMessengerCreateInfoEXT-messageType-parameter
483             // TODO: message_type.validate_instance()?;
484 
485             // VUID-VkDebugUtilsMessengerCreateInfoEXT-messageType-requiredbitmask
486             assert!(!message_type.is_empty());
487 
488             // VUID-PFN_vkDebugUtilsMessengerCallbackEXT-None-04769
489             // Can't be checked, creation is unsafe.
490 
491             let user_callback = Box::new(user_callback);
492             let create_info = ash::vk::DebugUtilsMessengerCreateInfoEXT {
493                 flags: ash::vk::DebugUtilsMessengerCreateFlagsEXT::empty(),
494                 message_severity: message_severity.into(),
495                 message_type: message_type.into(),
496                 pfn_user_callback: Some(trampoline),
497                 p_user_data: &*user_callback as &Arc<_> as *const Arc<_> as *const c_void as *mut _,
498                 ..Default::default()
499             };
500 
501             debug_utils_messenger_create_infos.push(create_info);
502             user_callbacks.push(user_callback);
503         }
504 
505         for i in 1..debug_utils_messenger_create_infos.len() {
506             debug_utils_messenger_create_infos[i - 1].p_next =
507                 &debug_utils_messenger_create_infos[i] as *const _ as *const _;
508         }
509 
510         if let Some(info) = debug_utils_messenger_create_infos.first() {
511             create_info_vk.p_next = info as *const _ as *const _;
512         }
513 
514         // Creating the Vulkan instance.
515         let handle = {
516             let mut output = MaybeUninit::uninit();
517             let fns = library.fns();
518             (fns.v1_0.create_instance)(&create_info_vk, ptr::null(), output.as_mut_ptr())
519                 .result()
520                 .map_err(VulkanError::from)?;
521             output.assume_init()
522         };
523 
524         // Loading the function pointers of the newly-created instance.
525         let fns = {
526             InstanceFunctions::load(|name| {
527                 library
528                     .get_instance_proc_addr(handle, name.as_ptr())
529                     .map_or(ptr::null(), |func| func as _)
530             })
531         };
532 
533         Ok(Arc::new(Instance {
534             handle,
535             fns,
536             id: Self::next_id(),
537             api_version,
538             enabled_extensions,
539             enabled_layers,
540             library,
541             max_api_version,
542             _user_callbacks: user_callbacks,
543         }))
544     }
545 
546     /// Returns the Vulkan library used to create this instance.
547     #[inline]
library(&self) -> &Arc<VulkanLibrary>548     pub fn library(&self) -> &Arc<VulkanLibrary> {
549         &self.library
550     }
551 
552     /// Returns the Vulkan version supported by the instance.
553     ///
554     /// This is the lower of the
555     /// [driver's supported version](crate::VulkanLibrary::api_version) and
556     /// [`max_api_version`](Instance::max_api_version).
557     #[inline]
api_version(&self) -> Version558     pub fn api_version(&self) -> Version {
559         self.api_version
560     }
561 
562     /// Returns the maximum Vulkan version that was specified when creating the instance.
563     #[inline]
max_api_version(&self) -> Version564     pub fn max_api_version(&self) -> Version {
565         self.max_api_version
566     }
567 
568     /// Returns pointers to the raw Vulkan functions of the instance.
569     #[inline]
fns(&self) -> &InstanceFunctions570     pub fn fns(&self) -> &InstanceFunctions {
571         &self.fns
572     }
573 
574     /// Returns the extensions that have been enabled on the instance.
575     #[inline]
enabled_extensions(&self) -> &InstanceExtensions576     pub fn enabled_extensions(&self) -> &InstanceExtensions {
577         &self.enabled_extensions
578     }
579 
580     /// Returns the layers that have been enabled on the instance.
581     #[inline]
enabled_layers(&self) -> &[String]582     pub fn enabled_layers(&self) -> &[String] {
583         &self.enabled_layers
584     }
585 
586     /// Returns an iterator that enumerates the physical devices available.
587     ///
588     /// # Examples
589     ///
590     /// ```no_run
591     /// # use vulkano::{
592     /// #     instance::{Instance, InstanceExtensions},
593     /// #     Version, VulkanLibrary,
594     /// # };
595     ///
596     /// # let library = VulkanLibrary::new().unwrap();
597     /// # let instance = Instance::new(library, Default::default()).unwrap();
598     /// for physical_device in instance.enumerate_physical_devices().unwrap() {
599     ///     println!("Available device: {}", physical_device.properties().device_name);
600     /// }
601     /// ```
enumerate_physical_devices( self: &Arc<Self>, ) -> Result<impl ExactSizeIterator<Item = Arc<PhysicalDevice>>, VulkanError>602     pub fn enumerate_physical_devices(
603         self: &Arc<Self>,
604     ) -> Result<impl ExactSizeIterator<Item = Arc<PhysicalDevice>>, VulkanError> {
605         let fns = self.fns();
606 
607         unsafe {
608             let handles = loop {
609                 let mut count = 0;
610                 (fns.v1_0.enumerate_physical_devices)(self.handle, &mut count, ptr::null_mut())
611                     .result()
612                     .map_err(VulkanError::from)?;
613 
614                 let mut handles = Vec::with_capacity(count as usize);
615                 let result = (fns.v1_0.enumerate_physical_devices)(
616                     self.handle,
617                     &mut count,
618                     handles.as_mut_ptr(),
619                 );
620 
621                 match result {
622                     ash::vk::Result::SUCCESS => {
623                         handles.set_len(count as usize);
624                         break handles;
625                     }
626                     ash::vk::Result::INCOMPLETE => (),
627                     err => return Err(VulkanError::from(err)),
628                 }
629             };
630 
631             let physical_devices: SmallVec<[_; 4]> = handles
632                 .into_iter()
633                 .map(|handle| PhysicalDevice::from_handle(self.clone(), handle))
634                 .collect::<Result<_, _>>()?;
635 
636             Ok(physical_devices.into_iter())
637         }
638     }
639 }
640 
641 impl Drop for Instance {
642     #[inline]
drop(&mut self)643     fn drop(&mut self) {
644         let fns = self.fns();
645 
646         unsafe {
647             (fns.v1_0.destroy_instance)(self.handle, ptr::null());
648         }
649     }
650 }
651 
652 unsafe impl VulkanObject for Instance {
653     type Handle = ash::vk::Instance;
654 
655     #[inline]
handle(&self) -> Self::Handle656     fn handle(&self) -> Self::Handle {
657         self.handle
658     }
659 }
660 
661 impl_id_counter!(Instance);
662 
663 impl Debug for Instance {
fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError>664     fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
665         let Self {
666             handle,
667             fns,
668             id: _,
669             api_version,
670             enabled_extensions,
671             enabled_layers,
672             library: function_pointers,
673             max_api_version,
674             _user_callbacks: _,
675         } = self;
676 
677         f.debug_struct("Instance")
678             .field("handle", handle)
679             .field("fns", fns)
680             .field("api_version", api_version)
681             .field("enabled_extensions", enabled_extensions)
682             .field("enabled_layers", enabled_layers)
683             .field("function_pointers", function_pointers)
684             .field("max_api_version", max_api_version)
685             .finish_non_exhaustive()
686     }
687 }
688 
689 /// Parameters to create a new `Instance`.
690 #[derive(Debug)]
691 pub struct InstanceCreateInfo {
692     /// A string of your choice stating the name of your application.
693     ///
694     /// The default value is `None`.
695     pub application_name: Option<String>,
696 
697     /// A version number of your choice specifying the version of your application.
698     ///
699     /// The default value is zero.
700     pub application_version: Version,
701 
702     /// The extensions to enable on the instance.
703     ///
704     /// The default value is [`InstanceExtensions::empty()`].
705     pub enabled_extensions: InstanceExtensions,
706 
707     /// The layers to enable on the instance.
708     ///
709     /// The default value is empty.
710     pub enabled_layers: Vec<String>,
711 
712     /// A string of your choice stating the name of the engine used to power the application.
713     pub engine_name: Option<String>,
714 
715     /// A version number of your choice specifying the version of the engine used to power the
716     /// application.
717     ///
718     /// The default value is zero.
719     pub engine_version: Version,
720 
721     /// The highest Vulkan API version that the application will use with the instance.
722     ///
723     /// Usually, you will want to leave this at the default.
724     ///
725     /// The default value is [`Version::HEADER_VERSION`], but if the
726     /// supported instance version is 1.0, then it will be 1.0.
727     pub max_api_version: Option<Version>,
728 
729     /// Include [portability subset](crate::instance#portability-subset-devices-and-the-enumerate_portability-flag)
730     /// devices when enumerating physical devices.
731     ///
732     /// If you enable this flag, you must ensure that your program is prepared to handle the
733     /// non-conformant aspects of these devices.
734     ///
735     /// If this flag is not enabled, and there are no fully-conformant devices on the system, then
736     /// [`Instance::new`] will return an `IncompatibleDriver` error.
737     ///
738     /// The default value is `false`.
739     ///
740     /// # Notes
741     ///
742     /// If this flag is enabled, and the
743     /// [`khr_portability_enumeration`](crate::instance::InstanceExtensions::khr_portability_enumeration)
744     /// extension is supported, it will be enabled automatically when creating the instance.
745     /// If the extension is not supported, this flag will be ignored.
746     pub enumerate_portability: bool,
747 
748     /// Features of the validation layer to enable.
749     ///
750     /// If not empty, the
751     /// [`ext_validation_features`](crate::instance::InstanceExtensions::ext_validation_features)
752     /// extension must be enabled on the instance.
753     pub enabled_validation_features: Vec<ValidationFeatureEnable>,
754 
755     /// Features of the validation layer to disable.
756     ///
757     /// If not empty, the
758     /// [`ext_validation_features`](crate::instance::InstanceExtensions::ext_validation_features)
759     /// extension must be enabled on the instance.
760     pub disabled_validation_features: Vec<ValidationFeatureDisable>,
761 
762     pub _ne: crate::NonExhaustive,
763 }
764 
765 impl Default for InstanceCreateInfo {
766     #[inline]
default() -> Self767     fn default() -> Self {
768         Self {
769             application_name: None,
770             application_version: Version::major_minor(0, 0),
771             enabled_extensions: InstanceExtensions::empty(),
772             enabled_layers: Vec::new(),
773             engine_name: None,
774             engine_version: Version::major_minor(0, 0),
775             max_api_version: None,
776             enumerate_portability: false,
777             enabled_validation_features: Vec::new(),
778             disabled_validation_features: Vec::new(),
779             _ne: crate::NonExhaustive(()),
780         }
781     }
782 }
783 
784 impl InstanceCreateInfo {
785     /// Returns an `InstanceCreateInfo` with the `application_name` and `application_version` set
786     /// from information in your crate's Cargo.toml file.
787     ///
788     /// # Panics
789     ///
790     /// - Panics if the required environment variables are missing, which happens if the project
791     ///   wasn't built by Cargo.
792     #[inline]
application_from_cargo_toml() -> Self793     pub fn application_from_cargo_toml() -> Self {
794         Self {
795             application_name: Some(env!("CARGO_PKG_NAME").to_owned()),
796             application_version: Version {
797                 major: env!("CARGO_PKG_VERSION_MAJOR").parse().unwrap(),
798                 minor: env!("CARGO_PKG_VERSION_MINOR").parse().unwrap(),
799                 patch: env!("CARGO_PKG_VERSION_PATCH").parse().unwrap(),
800             },
801             ..Default::default()
802         }
803     }
804 }
805 
806 /// Error that can happen when creating an instance.
807 #[derive(Clone, Debug)]
808 pub enum InstanceCreationError {
809     /// Not enough memory.
810     OomError(OomError),
811 
812     /// Failed to initialize for an implementation-specific reason.
813     InitializationFailed,
814 
815     /// One of the requested layers is missing.
816     LayerNotPresent,
817 
818     /// One of the requested extensions is not supported by the implementation.
819     ExtensionNotPresent,
820 
821     /// The version requested is not supported by the implementation.
822     IncompatibleDriver,
823 
824     /// A restriction for an extension was not met.
825     ExtensionRestrictionNotMet(ExtensionRestrictionError),
826 
827     RequirementNotMet {
828         required_for: &'static str,
829         requires_one_of: RequiresOneOf,
830     },
831 }
832 
833 impl Error for InstanceCreationError {
source(&self) -> Option<&(dyn Error + 'static)>834     fn source(&self) -> Option<&(dyn Error + 'static)> {
835         match self {
836             Self::OomError(err) => Some(err),
837             _ => None,
838         }
839     }
840 }
841 
842 impl Display for InstanceCreationError {
fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError>843     fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
844         match self {
845             Self::OomError(_) => write!(f, "not enough memory available"),
846             Self::InitializationFailed => write!(f, "initialization failed"),
847             Self::LayerNotPresent => write!(f, "layer not present"),
848             Self::ExtensionNotPresent => write!(f, "extension not present"),
849             Self::IncompatibleDriver => write!(f, "incompatible driver"),
850             Self::ExtensionRestrictionNotMet(err) => Display::fmt(err, f),
851             Self::RequirementNotMet {
852                 required_for,
853                 requires_one_of,
854             } => write!(
855                 f,
856                 "a requirement was not met for: {}; requires one of: {}",
857                 required_for, requires_one_of,
858             ),
859         }
860     }
861 }
862 
863 impl From<OomError> for InstanceCreationError {
from(err: OomError) -> Self864     fn from(err: OomError) -> Self {
865         Self::OomError(err)
866     }
867 }
868 
869 impl From<ExtensionRestrictionError> for InstanceCreationError {
from(err: ExtensionRestrictionError) -> Self870     fn from(err: ExtensionRestrictionError) -> Self {
871         Self::ExtensionRestrictionNotMet(err)
872     }
873 }
874 
875 impl From<VulkanError> for InstanceCreationError {
from(err: VulkanError) -> Self876     fn from(err: VulkanError) -> Self {
877         match err {
878             err @ VulkanError::OutOfHostMemory => Self::OomError(OomError::from(err)),
879             err @ VulkanError::OutOfDeviceMemory => Self::OomError(OomError::from(err)),
880             VulkanError::InitializationFailed => Self::InitializationFailed,
881             VulkanError::LayerNotPresent => Self::LayerNotPresent,
882             VulkanError::ExtensionNotPresent => Self::ExtensionNotPresent,
883             VulkanError::IncompatibleDriver => Self::IncompatibleDriver,
884             _ => panic!("unexpected error: {:?}", err),
885         }
886     }
887 }
888 
889 #[cfg(test)]
890 mod tests {
891 
892     #[test]
create_instance()893     fn create_instance() {
894         let _ = instance!();
895     }
896 }
897