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