From a5b5f89f952d4d2d1102dd621a7ef410735f695b Mon Sep 17 00:00:00 2001 From: Pierre Krieger Date: Sun, 18 Sep 2016 14:00:02 +0200 Subject: [PATCH] Add documentation and minor changes to instance --- vulkano/src/instance/debug.rs | 14 ++++- vulkano/src/instance/instance.rs | 27 ++++++++- vulkano/src/instance/mod.rs | 99 ++++++++++++++++++++++++++------ 3 files changed, 115 insertions(+), 25 deletions(-) diff --git a/vulkano/src/instance/debug.rs b/vulkano/src/instance/debug.rs index fc65197b..3830bc4c 100644 --- a/vulkano/src/instance/debug.rs +++ b/vulkano/src/instance/debug.rs @@ -8,15 +8,16 @@ // according to those terms. //! Debug callback called by validation layers. -//! +//! //! When working on an application, it is recommended to register a debug callback. This callback //! will be called by validation layers whenever necessary to warn you about invalid API usages //! or performance problems. //! //! Note that the vulkano library can also emit messages to warn you about performance issues. -//! +//! TODO: ^ that's not the case yet, need to choose whether we keep this idea +//! //! # Example -//! +//! //! ```no_run //! # use vulkano::instance::Instance; //! # use std::sync::Arc; @@ -27,6 +28,11 @@ //! println!("Debug callback: {:?}", msg.description); //! }).ok(); //! ``` +//! +//! Note that you must keep the `_callback` object alive for as long as you want your callback to +//! be callable. If you don't store the return value of `DebugCallback`'s constructor in a +//! variable, it will be immediately destroyed and your callback will not work. +//! use std::error; use std::ffi::CStr; @@ -48,6 +54,8 @@ use vk; /// Registration of a callback called by validation layers. /// /// The callback can be called as long as this object is alive. +#[must_use = "The DebugCallback object must be kept alive for as long as you want your callback \ + to be called"] pub struct DebugCallback { instance: Arc, debug_report_callback: vk::DebugReportCallbackEXT, diff --git a/vulkano/src/instance/instance.rs b/vulkano/src/instance/instance.rs index 4982b113..1a26f08f 100644 --- a/vulkano/src/instance/instance.rs +++ b/vulkano/src/instance/instance.rs @@ -326,6 +326,7 @@ pub enum InstanceCreationError { /// One of the requested extensions is missing. ExtensionNotPresent, /// The version requested is not supported by the implementation. + // TODO: more info about this once the question of the version has been resolved IncompatibleDriver, } @@ -397,6 +398,9 @@ struct PhysicalDeviceInfos { } /// Represents one of the available devices on this machine. +/// +/// This struct simply contains a pointer to an instance and a number representing the physical +/// device. You are therefore encouraged to pass this around by value instead of by reference. #[derive(Debug, Copy, Clone)] pub struct PhysicalDevice<'a> { instance: &'a Arc, @@ -414,6 +418,8 @@ impl<'a> PhysicalDevice<'a> { } /// Returns a physical device from its index. Returns `None` if out of range. + /// + /// Indices range from 0 to the number of devices. #[inline] pub fn from_index(instance: &'a Arc, index: usize) -> Option> { if instance.physical_devices.len() > index { @@ -556,6 +562,9 @@ impl<'a> PhysicalDevice<'a> { } /// Returns an opaque number representing the version of the driver of this device. + /// + /// The meaning of this number is implementation-specific. It can be used in bug reports, for + /// example. #[inline] pub fn driver_version(&self) -> u32 { self.infos().properties.driverVersion @@ -574,12 +583,15 @@ impl<'a> PhysicalDevice<'a> { } /// Returns a unique identifier for the device. + /// + /// Can be stored in a configuration file, so that you can retrieve the device again the next + /// time the program is run. #[inline] pub fn uuid(&self) -> &[u8; 16] { // must be equal to vk::UUID_SIZE &self.infos().properties.pipelineCacheUUID } - /// Internal function to make it easier to get the infos of this device. + // Internal function to make it easier to get the infos of this device. #[inline] fn infos(&self) -> &'a PhysicalDeviceInfos { &self.instance.physical_devices[self.device] @@ -619,6 +631,15 @@ impl<'a> Iterator for PhysicalDevicesIter<'a> { self.current_id += 1; Some(dev) } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + let len = self.instance.physical_devices.len() - self.current_id; + (len, Some(len)) + } +} + +impl<'a> ExactSizeIterator for PhysicalDevicesIter<'a> { } /// Type of a physical device. @@ -914,6 +935,8 @@ impl<'a> Iterator for MemoryHeapsIter<'a> { } } +impl<'a> ExactSizeIterator for MemoryHeapsIter<'a> {} + /// Limits of a physical device. pub struct Limits<'a> { device: PhysicalDevice<'a>, @@ -1041,8 +1064,6 @@ limits_impl!{ non_coherent_atom_size: u64 => nonCoherentAtomSize, } -impl<'a> ExactSizeIterator for MemoryHeapsIter<'a> {} - #[cfg(test)] mod tests { use instance; diff --git a/vulkano/src/instance/mod.rs b/vulkano/src/instance/mod.rs index f16743c0..2038010d 100644 --- a/vulkano/src/instance/mod.rs +++ b/vulkano/src/instance/mod.rs @@ -11,37 +11,98 @@ //! //! The first thing to do before you start using Vulkan is to create an `Instance` object. //! -//! Creating an instance initializes everything and allows you to: -//! -//! - Enumerate physical devices, ie. all the Vulkan implementations that are available on -//! the system. -//! - Enumerate monitors. -//! - Create surfaces (fullscreen or windowed) which will later be drawn upon. +//! For example: //! -//! Enumerating monitors and creating surfaces can only be done if the proper extensions are -//! available and have been enabled. It is possible for a machine to support Vulkan without -//! support for rendering on a screen. +//! ```no_run +//! use vulkano::instance::Instance; +//! use vulkano::instance::InstanceExtensions; +//! +//! let _instance = match Instance::new(None, &InstanceExtensions::none(), None) { +//! Ok(i) => i, +//! Err(err) => panic!("Couldn't build instance: {:?}", err) +//! }; +//! ``` +//! +//! Creating an instance initializes everything and allows you to enumerate physical devices, +//! ie. all the Vulkan implementations that are available on the system. +//! +//! ```no_run +//! # use vulkano::instance::Instance; +//! # use vulkano::instance::InstanceExtensions; +//! use vulkano::instance::PhysicalDevice; +//! +//! # let instance = Instance::new(None, &InstanceExtensions::none(), None).unwrap(); +//! for physical_device in PhysicalDevice::enumerate(&instance) { +//! println!("Available device: {}", physical_device.name()) +//! } +//! ``` +//! +//! # Extensions +//! +//! Notice the second parameter of `Instance::new()`. It is an `InstanceExtensions` struct that +//! contains a list of extensions that must be enabled on the newly-created instance. Trying to +//! enable an extension that is not supported by the system will result in an error. +//! +//! Contrary to OpenGL, it is not possible to use the features of an extension if it was not +//! explicitly enabled. +//! +//! Extensions are especially important to take into account if you want to render images on the +//! screen, as the only way to do so is to use the `VK_KHR_surface` extension. More information +//! about this in the `swapchain` module. +//! +//! For example, here is how we create an instance with the `VK_KHR_surface` and +//! `VK_KHR_android_surface` extensions enabled, which will allow us to render images to an +//! Android screen. You can compile and run this code on any system, but it is highly unlikely to +//! succeed on anything else than an Android-running device. +//! +//! ```no_run +//! use vulkano::instance::Instance; +//! use vulkano::instance::InstanceExtensions; +//! +//! let extensions = InstanceExtensions { +//! khr_surface: true, +//! khr_android_surface: true, +//! .. InstanceExtensions::none() +//! }; +//! +//! let _instance = match Instance::new(None, &extensions, None) { +//! Ok(i) => i, +//! Err(err) => panic!("Couldn't build instance: {:?}", err) +//! }; +//! ``` //! //! # Application info -//! -//! When you create an instance, you have the possibility to pass an `ApplicationInfo` struct. This -//! struct contains various information about your application, most notably its name and engine. -//! +//! +//! When you create an instance, you have the possibility to pass an `ApplicationInfo` struct as +//! the first parameter. This struct contains various information about your application, most +//! notably its name and engine. +//! //! Passing such a structure allows for example the driver to let the user configure the driver's //! behavior for your application alone through a control panel. //! -//! # Enumerating physical devices +//! ```no_run +//! use vulkano::instance::ApplicationInfo; +//! use vulkano::instance::Instance; +//! use vulkano::instance::InstanceExtensions; //! -//! After you have created an instance, the next step is to enumerate the physical devices that -//! are available on the system with `PhysicalDevice::enumerate()`. +//! // Builds an `ApplicationInfo` by looking at the content of the `Cargo.toml` file at +//! // compile-time. +//! let app_infos = ApplicationInfo::from_cargo_toml(); +//! +//! let _instance = Instance::new(Some(&app_infos), &InstanceExtensions::none(), None).unwrap(); +//! ``` +//! +//! # Enumerating physical devices and creating a device +//! +//! After you have created an instance, the next step is usually to enumerate the physical devices +//! that are available on the system with `PhysicalDevice::enumerate()` (see above). //! //! When choosing which physical device to use, keep in mind that physical devices may or may not //! be able to draw to a certain surface (ie. to a window or a monitor), or may even not be able //! to draw at all. See the `swapchain` module for more information about surfaces. //! -//! A physical device can designate a video card, an integrated chip, but also multiple video -//! cards working together or a software implementation. Once you have chosen a physical device, -//! you can create a `Device` object from it. See the `device` module for more info. +//! Once you have chosen a physical device, you can create a `Device` object from it. See the +//! `device` module for more info. //! pub use features::Features; pub use self::extensions::DeviceExtensions;