diff options
Diffstat (limited to 'src/lib.rs')
-rw-r--r-- | src/lib.rs | 243 |
1 files changed, 243 insertions, 0 deletions
diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..8c8e7b2 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,243 @@ +// Copyright (c) 2016 The vulkano developers +// Licensed under the Apache License, Version 2.0 +// <LICENSE-APACHE or +// https://www.apache.org/licenses/LICENSE-2.0> or the MIT +// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, +// at your option. All files in the project carrying such +// notice may not be copied, modified, or distributed except +// according to those terms. + +#![doc(html_logo_url = "https://raw.githubusercontent.com/vulkano-rs/vulkano/master/logo.png")] +//! Safe and rich Rust wrapper around the Vulkan API. +//! +//! # Brief summary of Vulkan +//! +//! - The [`Instance`](instance/struct.Instance.html) object is the API entry point. It is the +//! first object you must create before starting to use Vulkan. +//! +//! - The [`PhysicalDevice`](instance/struct.PhysicalDevice.html) object represents an +//! implementation of Vulkan available on the system (eg. a graphics card, a software +//! implementation, etc.). Physical devices can be enumerated from an instance with +//! [`PhysicalDevice::enumerate()`](instance/struct.PhysicalDevice.html#method.enumerate). +//! +//! - Once you have chosen a physical device to use, you can create a +//! [`Device`](device/index.html) object from it. The `Device` is the most important +//! object of Vulkan, as it represents an open channel of communication with a physical device. +//! You always need to have one before you can do interesting things with Vulkan. +//! +//! - [*Buffers*](buffer/index.html) and [*images*](image/index.html) can be used to store data on +//! memory accessible by the GPU (or more generally by the Vulkan implementation). Buffers are +//! usually used to store information about vertices, lights, etc. or arbitrary data, while +//! images are used to store textures or multi-dimensional data. +//! +//! - In order to show something on the screen, you need a [`Swapchain`](swapchain/index.html). +//! A `Swapchain` contains special `Image`s that correspond to the content of the window or the +//! monitor. When you *present* a swapchain, the content of one of these special images is shown +//! on the screen. +//! +//! - In order to ask the GPU to do something, you must create a +//! [*command buffer*](command_buffer/index.html). A command buffer contains a list of commands +//! that the GPU must perform. This can include copies between buffers and images, compute +//! operations, or graphics operations. For the work to start, the command buffer must then be +//! submitted to a [`Queue`](device/struct.Queue.html), which is obtained when you create the +//! `Device`. +//! +//! - In order to be able to add a compute operation or a graphics operation to a command buffer, +//! you need to have created a [`ComputePipeline` or a `GraphicsPipeline` +//! object](pipeline/index.html) that describes the operation you want. These objects are usually +//! created during your program's initialization. `Shader`s are programs that the GPU will +//! execute as part of a pipeline. [*Descriptors*](descriptor/index.html) can be used to access +//! the content of buffers or images from within shaders. +//! +//! - For graphical operations, [`RenderPass`es and `Framebuffer`s](framebuffer/index.html) +//! describe on which images the implementation must draw upon. +//! +//! - Once you have built a *command buffer* that contains a list of commands, submitting it to the +//! GPU will return an object that implements [the `GpuFuture` trait](sync/index.html). +//! `GpuFuture`s allow you to chain multiple submissions together and are essential to performing +//! multiple operations on multiple different GPU queues. +//! + +//#![warn(missing_docs)] // TODO: activate +#![allow(dead_code)] // TODO: remove +#![allow(unused_variables)] // TODO: remove + +pub use ash::vk::Handle; +pub use half; +use std::error; +use std::fmt; +use std::ops::Deref; +use std::sync::Arc; +use std::sync::MutexGuard; +pub use version::Version; + +#[macro_use] +mod tests; +#[macro_use] +mod extensions; +pub mod buffer; +pub mod command_buffer; +pub mod descriptor_set; +pub mod device; +pub mod format; +mod version; +#[macro_use] +pub mod render_pass; +mod fns; +pub mod image; +pub mod instance; +pub mod memory; +pub mod pipeline; +pub mod query; +pub mod sampler; +pub mod swapchain; +pub mod sync; + +mod autogen { + // Generated by build.rs + include!(concat!(env!("OUT_DIR"), "/autogen.rs")); +} + +/// Represents memory size and offset values on a Vulkan device. +/// Analogous to the Rust `usize` type on the host. +pub use ash::vk::DeviceSize; + +/// Alternative to the `Deref` trait. Contrary to `Deref`, must always return the same object. +pub unsafe trait SafeDeref: Deref {} +unsafe impl<'a, T: ?Sized> SafeDeref for &'a T {} +unsafe impl<T: ?Sized> SafeDeref for Arc<T> {} +unsafe impl<T: ?Sized> SafeDeref for Box<T> {} + +/// Gives access to the internal identifier of an object. +pub unsafe trait VulkanObject { + /// The type of the object. + type Object: ash::vk::Handle; + + /// Returns a reference to the object. + fn internal_object(&self) -> Self::Object; +} + +/// Gives access to the internal identifier of an object. +// TODO: remove ; crappy design +pub unsafe trait SynchronizedVulkanObject { + /// The type of the object. + type Object: ash::vk::Handle; + + /// Returns a reference to the object. + fn internal_object_guard(&self) -> MutexGuard<Self::Object>; +} + +/// Error type returned by most Vulkan functions. +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub enum OomError { + /// There is no memory available on the host (ie. the CPU, RAM, etc.). + OutOfHostMemory, + /// There is no memory available on the device (ie. video memory). + OutOfDeviceMemory, +} + +impl error::Error for OomError {} + +impl fmt::Display for OomError { + #[inline] + fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { + write!( + fmt, + "{}", + match *self { + OomError::OutOfHostMemory => "no memory available on the host", + OomError::OutOfDeviceMemory => "no memory available on the graphical device", + } + ) + } +} + +impl From<Error> for OomError { + #[inline] + fn from(err: Error) -> OomError { + match err { + Error::OutOfHostMemory => OomError::OutOfHostMemory, + Error::OutOfDeviceMemory => OomError::OutOfDeviceMemory, + _ => panic!("unexpected error: {:?}", err), + } + } +} + +/// All possible success codes returned by any Vulkan function. +#[derive(Debug, Copy, Clone)] +#[repr(i32)] +enum Success { + Success = ash::vk::Result::SUCCESS.as_raw(), + NotReady = ash::vk::Result::NOT_READY.as_raw(), + Timeout = ash::vk::Result::TIMEOUT.as_raw(), + EventSet = ash::vk::Result::EVENT_SET.as_raw(), + EventReset = ash::vk::Result::EVENT_RESET.as_raw(), + Incomplete = ash::vk::Result::INCOMPLETE.as_raw(), + Suboptimal = ash::vk::Result::SUBOPTIMAL_KHR.as_raw(), +} + +/// All possible errors returned by any Vulkan function. +/// +/// This type is not public. Instead all public error types should implement `From<Error>` and +/// panic for error code that aren't supposed to happen. +#[derive(Debug, Copy, Clone)] +#[repr(i32)] +// TODO: being pub is necessary because of the weird visibility rules in rustc +pub(crate) enum Error { + OutOfHostMemory = ash::vk::Result::ERROR_OUT_OF_HOST_MEMORY.as_raw(), + OutOfDeviceMemory = ash::vk::Result::ERROR_OUT_OF_DEVICE_MEMORY.as_raw(), + InitializationFailed = ash::vk::Result::ERROR_INITIALIZATION_FAILED.as_raw(), + DeviceLost = ash::vk::Result::ERROR_DEVICE_LOST.as_raw(), + MemoryMapFailed = ash::vk::Result::ERROR_MEMORY_MAP_FAILED.as_raw(), + LayerNotPresent = ash::vk::Result::ERROR_LAYER_NOT_PRESENT.as_raw(), + ExtensionNotPresent = ash::vk::Result::ERROR_EXTENSION_NOT_PRESENT.as_raw(), + FeatureNotPresent = ash::vk::Result::ERROR_FEATURE_NOT_PRESENT.as_raw(), + IncompatibleDriver = ash::vk::Result::ERROR_INCOMPATIBLE_DRIVER.as_raw(), + TooManyObjects = ash::vk::Result::ERROR_TOO_MANY_OBJECTS.as_raw(), + FormatNotSupported = ash::vk::Result::ERROR_FORMAT_NOT_SUPPORTED.as_raw(), + SurfaceLost = ash::vk::Result::ERROR_SURFACE_LOST_KHR.as_raw(), + NativeWindowInUse = ash::vk::Result::ERROR_NATIVE_WINDOW_IN_USE_KHR.as_raw(), + OutOfDate = ash::vk::Result::ERROR_OUT_OF_DATE_KHR.as_raw(), + IncompatibleDisplay = ash::vk::Result::ERROR_INCOMPATIBLE_DISPLAY_KHR.as_raw(), + ValidationFailed = ash::vk::Result::ERROR_VALIDATION_FAILED_EXT.as_raw(), + OutOfPoolMemory = ash::vk::Result::ERROR_OUT_OF_POOL_MEMORY_KHR.as_raw(), + FullscreenExclusiveLost = ash::vk::Result::ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT.as_raw(), +} + +/// Checks whether the result returned correctly. +fn check_errors(result: ash::vk::Result) -> Result<Success, Error> { + match result { + ash::vk::Result::SUCCESS => Ok(Success::Success), + ash::vk::Result::NOT_READY => Ok(Success::NotReady), + ash::vk::Result::TIMEOUT => Ok(Success::Timeout), + ash::vk::Result::EVENT_SET => Ok(Success::EventSet), + ash::vk::Result::EVENT_RESET => Ok(Success::EventReset), + ash::vk::Result::INCOMPLETE => Ok(Success::Incomplete), + ash::vk::Result::ERROR_OUT_OF_HOST_MEMORY => Err(Error::OutOfHostMemory), + ash::vk::Result::ERROR_OUT_OF_DEVICE_MEMORY => Err(Error::OutOfDeviceMemory), + ash::vk::Result::ERROR_INITIALIZATION_FAILED => Err(Error::InitializationFailed), + ash::vk::Result::ERROR_DEVICE_LOST => Err(Error::DeviceLost), + ash::vk::Result::ERROR_MEMORY_MAP_FAILED => Err(Error::MemoryMapFailed), + ash::vk::Result::ERROR_LAYER_NOT_PRESENT => Err(Error::LayerNotPresent), + ash::vk::Result::ERROR_EXTENSION_NOT_PRESENT => Err(Error::ExtensionNotPresent), + ash::vk::Result::ERROR_FEATURE_NOT_PRESENT => Err(Error::FeatureNotPresent), + ash::vk::Result::ERROR_INCOMPATIBLE_DRIVER => Err(Error::IncompatibleDriver), + ash::vk::Result::ERROR_TOO_MANY_OBJECTS => Err(Error::TooManyObjects), + ash::vk::Result::ERROR_FORMAT_NOT_SUPPORTED => Err(Error::FormatNotSupported), + ash::vk::Result::ERROR_SURFACE_LOST_KHR => Err(Error::SurfaceLost), + ash::vk::Result::ERROR_NATIVE_WINDOW_IN_USE_KHR => Err(Error::NativeWindowInUse), + ash::vk::Result::SUBOPTIMAL_KHR => Ok(Success::Suboptimal), + ash::vk::Result::ERROR_OUT_OF_DATE_KHR => Err(Error::OutOfDate), + ash::vk::Result::ERROR_INCOMPATIBLE_DISPLAY_KHR => Err(Error::IncompatibleDisplay), + ash::vk::Result::ERROR_VALIDATION_FAILED_EXT => Err(Error::ValidationFailed), + ash::vk::Result::ERROR_OUT_OF_POOL_MEMORY_KHR => Err(Error::OutOfPoolMemory), + ash::vk::Result::ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT => { + Err(Error::FullscreenExclusiveLost) + } + ash::vk::Result::ERROR_INVALID_SHADER_NV => panic!( + "Vulkan function returned \ + VK_ERROR_INVALID_SHADER_NV" + ), + c => unreachable!("Unexpected error code returned by Vulkan: {}", c), + } +} |