• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #![doc(html_logo_url = "https://raw.githubusercontent.com/vulkano-rs/vulkano/master/logo.png")]
11 //! Safe and rich Rust wrapper around the Vulkan API.
12 //!
13 //! # Brief summary of Vulkan
14 //!
15 //! - The [`Instance`](instance/struct.Instance.html) object is the API entry point. It is the
16 //!   first object you must create before starting to use Vulkan.
17 //!
18 //! - The [`PhysicalDevice`](instance/struct.PhysicalDevice.html) object represents an
19 //!   implementation of Vulkan available on the system (eg. a graphics card, a software
20 //!   implementation, etc.). Physical devices can be enumerated from an instance with
21 //!   [`PhysicalDevice::enumerate()`](instance/struct.PhysicalDevice.html#method.enumerate).
22 //!
23 //! - Once you have chosen a physical device to use, you can create a
24 //!   [`Device`](device/index.html) object from it. The `Device` is the most important
25 //!   object of Vulkan, as it represents an open channel of communication with a physical device.
26 //!   You always need to have one before you can do interesting things with Vulkan.
27 //!
28 //! - [*Buffers*](buffer/index.html) and [*images*](image/index.html) can be used to store data on
29 //!   memory accessible by the GPU (or more generally by the Vulkan implementation). Buffers are
30 //!   usually used to store information about vertices, lights, etc. or arbitrary data, while
31 //!   images are used to store textures or multi-dimensional data.
32 //!
33 //! - In order to show something on the screen, you need a [`Swapchain`](swapchain/index.html).
34 //!   A `Swapchain` contains special `Image`s that correspond to the content of the window or the
35 //!   monitor. When you *present* a swapchain, the content of one of these special images is shown
36 //!   on the screen.
37 //!
38 //! - In order to ask the GPU to do something, you must create a
39 //!   [*command buffer*](command_buffer/index.html). A command buffer contains a list of commands
40 //!   that the GPU must perform. This can include copies between buffers and images, compute
41 //!   operations, or graphics operations. For the work to start, the command buffer must then be
42 //!   submitted to a [`Queue`](device/struct.Queue.html), which is obtained when you create the
43 //!   `Device`.
44 //!
45 //! - In order to be able to add a compute operation or a graphics operation to a command buffer,
46 //!   you need to have created a [`ComputePipeline` or a `GraphicsPipeline`
47 //!   object](pipeline/index.html) that describes the operation you want. These objects are usually
48 //!   created during your program's initialization. `Shader`s are programs that the GPU will
49 //!   execute as part of a pipeline. [*Descriptors*](descriptor/index.html) can be used to access
50 //!   the content of buffers or images from within shaders.
51 //!
52 //! - For graphical operations, [`RenderPass`es and `Framebuffer`s](framebuffer/index.html)
53 //!   describe on which images the implementation must draw upon.
54 //!
55 //! - Once you have built a *command buffer* that contains a list of commands, submitting it to the
56 //!   GPU will return an object that implements [the `GpuFuture` trait](sync/index.html).
57 //!   `GpuFuture`s allow you to chain multiple submissions together and are essential to performing
58 //!   multiple operations on multiple different GPU queues.
59 //!
60 
61 //#![warn(missing_docs)]        // TODO: activate
62 #![allow(dead_code)] // TODO: remove
63 #![allow(unused_variables)] // TODO: remove
64 
65 pub use ash::vk::Handle;
66 pub use half;
67 use std::error;
68 use std::fmt;
69 use std::ops::Deref;
70 use std::sync::Arc;
71 use std::sync::MutexGuard;
72 pub use version::Version;
73 
74 #[macro_use]
75 mod tests;
76 #[macro_use]
77 mod extensions;
78 pub mod buffer;
79 pub mod command_buffer;
80 pub mod descriptor_set;
81 pub mod device;
82 pub mod format;
83 mod version;
84 #[macro_use]
85 pub mod render_pass;
86 mod fns;
87 pub mod image;
88 pub mod instance;
89 pub mod memory;
90 pub mod pipeline;
91 pub mod query;
92 pub mod sampler;
93 pub mod swapchain;
94 pub mod sync;
95 
96 mod autogen {
97     // Generated by build.rs
98     include!(concat!(env!("OUT_DIR"), "/autogen.rs"));
99 }
100 
101 /// Represents memory size and offset values on a Vulkan device.
102 /// Analogous to the Rust `usize` type on the host.
103 pub use ash::vk::DeviceSize;
104 
105 /// Alternative to the `Deref` trait. Contrary to `Deref`, must always return the same object.
106 pub unsafe trait SafeDeref: Deref {}
107 unsafe impl<'a, T: ?Sized> SafeDeref for &'a T {}
108 unsafe impl<T: ?Sized> SafeDeref for Arc<T> {}
109 unsafe impl<T: ?Sized> SafeDeref for Box<T> {}
110 
111 /// Gives access to the internal identifier of an object.
112 pub unsafe trait VulkanObject {
113     /// The type of the object.
114     type Object: ash::vk::Handle;
115 
116     /// Returns a reference to the object.
internal_object(&self) -> Self::Object117     fn internal_object(&self) -> Self::Object;
118 }
119 
120 /// Gives access to the internal identifier of an object.
121 // TODO: remove ; crappy design
122 pub unsafe trait SynchronizedVulkanObject {
123     /// The type of the object.
124     type Object: ash::vk::Handle;
125 
126     /// Returns a reference to the object.
internal_object_guard(&self) -> MutexGuard<Self::Object>127     fn internal_object_guard(&self) -> MutexGuard<Self::Object>;
128 }
129 
130 /// Error type returned by most Vulkan functions.
131 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
132 pub enum OomError {
133     /// There is no memory available on the host (ie. the CPU, RAM, etc.).
134     OutOfHostMemory,
135     /// There is no memory available on the device (ie. video memory).
136     OutOfDeviceMemory,
137 }
138 
139 impl error::Error for OomError {}
140 
141 impl fmt::Display for OomError {
142     #[inline]
fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error>143     fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
144         write!(
145             fmt,
146             "{}",
147             match *self {
148                 OomError::OutOfHostMemory => "no memory available on the host",
149                 OomError::OutOfDeviceMemory => "no memory available on the graphical device",
150             }
151         )
152     }
153 }
154 
155 impl From<Error> for OomError {
156     #[inline]
from(err: Error) -> OomError157     fn from(err: Error) -> OomError {
158         match err {
159             Error::OutOfHostMemory => OomError::OutOfHostMemory,
160             Error::OutOfDeviceMemory => OomError::OutOfDeviceMemory,
161             _ => panic!("unexpected error: {:?}", err),
162         }
163     }
164 }
165 
166 /// All possible success codes returned by any Vulkan function.
167 #[derive(Debug, Copy, Clone)]
168 #[repr(i32)]
169 enum Success {
170     Success = ash::vk::Result::SUCCESS.as_raw(),
171     NotReady = ash::vk::Result::NOT_READY.as_raw(),
172     Timeout = ash::vk::Result::TIMEOUT.as_raw(),
173     EventSet = ash::vk::Result::EVENT_SET.as_raw(),
174     EventReset = ash::vk::Result::EVENT_RESET.as_raw(),
175     Incomplete = ash::vk::Result::INCOMPLETE.as_raw(),
176     Suboptimal = ash::vk::Result::SUBOPTIMAL_KHR.as_raw(),
177 }
178 
179 /// All possible errors returned by any Vulkan function.
180 ///
181 /// This type is not public. Instead all public error types should implement `From<Error>` and
182 /// panic for error code that aren't supposed to happen.
183 #[derive(Debug, Copy, Clone)]
184 #[repr(i32)]
185 // TODO: being pub is necessary because of the weird visibility rules in rustc
186 pub(crate) enum Error {
187     OutOfHostMemory = ash::vk::Result::ERROR_OUT_OF_HOST_MEMORY.as_raw(),
188     OutOfDeviceMemory = ash::vk::Result::ERROR_OUT_OF_DEVICE_MEMORY.as_raw(),
189     InitializationFailed = ash::vk::Result::ERROR_INITIALIZATION_FAILED.as_raw(),
190     DeviceLost = ash::vk::Result::ERROR_DEVICE_LOST.as_raw(),
191     MemoryMapFailed = ash::vk::Result::ERROR_MEMORY_MAP_FAILED.as_raw(),
192     LayerNotPresent = ash::vk::Result::ERROR_LAYER_NOT_PRESENT.as_raw(),
193     ExtensionNotPresent = ash::vk::Result::ERROR_EXTENSION_NOT_PRESENT.as_raw(),
194     FeatureNotPresent = ash::vk::Result::ERROR_FEATURE_NOT_PRESENT.as_raw(),
195     IncompatibleDriver = ash::vk::Result::ERROR_INCOMPATIBLE_DRIVER.as_raw(),
196     TooManyObjects = ash::vk::Result::ERROR_TOO_MANY_OBJECTS.as_raw(),
197     FormatNotSupported = ash::vk::Result::ERROR_FORMAT_NOT_SUPPORTED.as_raw(),
198     SurfaceLost = ash::vk::Result::ERROR_SURFACE_LOST_KHR.as_raw(),
199     NativeWindowInUse = ash::vk::Result::ERROR_NATIVE_WINDOW_IN_USE_KHR.as_raw(),
200     OutOfDate = ash::vk::Result::ERROR_OUT_OF_DATE_KHR.as_raw(),
201     IncompatibleDisplay = ash::vk::Result::ERROR_INCOMPATIBLE_DISPLAY_KHR.as_raw(),
202     ValidationFailed = ash::vk::Result::ERROR_VALIDATION_FAILED_EXT.as_raw(),
203     OutOfPoolMemory = ash::vk::Result::ERROR_OUT_OF_POOL_MEMORY_KHR.as_raw(),
204     FullscreenExclusiveLost = ash::vk::Result::ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT.as_raw(),
205 }
206 
207 /// Checks whether the result returned correctly.
check_errors(result: ash::vk::Result) -> Result<Success, Error>208 fn check_errors(result: ash::vk::Result) -> Result<Success, Error> {
209     match result {
210         ash::vk::Result::SUCCESS => Ok(Success::Success),
211         ash::vk::Result::NOT_READY => Ok(Success::NotReady),
212         ash::vk::Result::TIMEOUT => Ok(Success::Timeout),
213         ash::vk::Result::EVENT_SET => Ok(Success::EventSet),
214         ash::vk::Result::EVENT_RESET => Ok(Success::EventReset),
215         ash::vk::Result::INCOMPLETE => Ok(Success::Incomplete),
216         ash::vk::Result::ERROR_OUT_OF_HOST_MEMORY => Err(Error::OutOfHostMemory),
217         ash::vk::Result::ERROR_OUT_OF_DEVICE_MEMORY => Err(Error::OutOfDeviceMemory),
218         ash::vk::Result::ERROR_INITIALIZATION_FAILED => Err(Error::InitializationFailed),
219         ash::vk::Result::ERROR_DEVICE_LOST => Err(Error::DeviceLost),
220         ash::vk::Result::ERROR_MEMORY_MAP_FAILED => Err(Error::MemoryMapFailed),
221         ash::vk::Result::ERROR_LAYER_NOT_PRESENT => Err(Error::LayerNotPresent),
222         ash::vk::Result::ERROR_EXTENSION_NOT_PRESENT => Err(Error::ExtensionNotPresent),
223         ash::vk::Result::ERROR_FEATURE_NOT_PRESENT => Err(Error::FeatureNotPresent),
224         ash::vk::Result::ERROR_INCOMPATIBLE_DRIVER => Err(Error::IncompatibleDriver),
225         ash::vk::Result::ERROR_TOO_MANY_OBJECTS => Err(Error::TooManyObjects),
226         ash::vk::Result::ERROR_FORMAT_NOT_SUPPORTED => Err(Error::FormatNotSupported),
227         ash::vk::Result::ERROR_SURFACE_LOST_KHR => Err(Error::SurfaceLost),
228         ash::vk::Result::ERROR_NATIVE_WINDOW_IN_USE_KHR => Err(Error::NativeWindowInUse),
229         ash::vk::Result::SUBOPTIMAL_KHR => Ok(Success::Suboptimal),
230         ash::vk::Result::ERROR_OUT_OF_DATE_KHR => Err(Error::OutOfDate),
231         ash::vk::Result::ERROR_INCOMPATIBLE_DISPLAY_KHR => Err(Error::IncompatibleDisplay),
232         ash::vk::Result::ERROR_VALIDATION_FAILED_EXT => Err(Error::ValidationFailed),
233         ash::vk::Result::ERROR_OUT_OF_POOL_MEMORY_KHR => Err(Error::OutOfPoolMemory),
234         ash::vk::Result::ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT => {
235             Err(Error::FullscreenExclusiveLost)
236         }
237         ash::vk::Result::ERROR_INVALID_SHADER_NV => panic!(
238             "Vulkan function returned \
239                                                VK_ERROR_INVALID_SHADER_NV"
240         ),
241         c => unreachable!("Unexpected error code returned by Vulkan: {}", c),
242     }
243 }
244