mirror of
https://github.com/vulkano-rs/vulkano.git
synced 2024-11-25 08:14:20 +00:00
Export features and device extensions from the device module instead of the instance module (#1015)
This commit is contained in:
parent
d779829cbd
commit
50920f868b
@ -13,6 +13,10 @@
|
|||||||
|
|
||||||
# Version 0.10.0 (2018-08-10)
|
# Version 0.10.0 (2018-08-10)
|
||||||
|
|
||||||
|
- Export features and device extensions from the device module instead of the instance module
|
||||||
|
+ `instance::Features` -> `device::Features`
|
||||||
|
+ `instance::DeviceExtensions` -> `device::DeviceExtensions`
|
||||||
|
+ `instance::RawDeviceExtensions` -> `device::RawDeviceExtensions`
|
||||||
- Use dynamically loaded `libvulkan` like on other platforms instead of linking to MoltenVK on macOS
|
- Use dynamically loaded `libvulkan` like on other platforms instead of linking to MoltenVK on macOS
|
||||||
- Updated winit to version 0.17.
|
- Updated winit to version 0.17.
|
||||||
- Allow custom implementations of `RenderPassDesc` to specify `VK_SUBPASS_EXTERNAL` as a dependency source or destination
|
- Allow custom implementations of `RenderPassDesc` to specify `VK_SUBPASS_EXTERNAL` as a dependency source or destination
|
||||||
|
@ -86,7 +86,6 @@ use vulkano::framebuffer::Subpass;
|
|||||||
use vulkano::image::AttachmentImage;
|
use vulkano::image::AttachmentImage;
|
||||||
use vulkano::image::Dimensions;
|
use vulkano::image::Dimensions;
|
||||||
use vulkano::image::StorageImage;
|
use vulkano::image::StorageImage;
|
||||||
use vulkano::instance::Features;
|
|
||||||
use vulkano::instance::Instance;
|
use vulkano::instance::Instance;
|
||||||
use vulkano::instance::InstanceExtensions;
|
use vulkano::instance::InstanceExtensions;
|
||||||
use vulkano::instance::PhysicalDevice;
|
use vulkano::instance::PhysicalDevice;
|
||||||
@ -103,7 +102,7 @@ fn main() {
|
|||||||
.find(|&q| q.supports_graphics())
|
.find(|&q| q.supports_graphics())
|
||||||
.expect("couldn't find a graphical queue family");
|
.expect("couldn't find a graphical queue family");
|
||||||
let (device, mut queues) = {
|
let (device, mut queues) = {
|
||||||
Device::new(physical, &Features::none(), &DeviceExtensions::none(),
|
Device::new(physical, physical.supported_features(), &DeviceExtensions::none(),
|
||||||
[(queue_family, 0.5)].iter().cloned()).expect("failed to create device")
|
[(queue_family, 0.5)].iter().cloned()).expect("failed to create device")
|
||||||
};
|
};
|
||||||
let queue = queues.next().unwrap();
|
let queue = queues.next().unwrap();
|
||||||
|
130
vulkano/src/device/extensions.rs
Normal file
130
vulkano/src/device/extensions.rs
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
// Copyright (c) 2016 The vulkano developers
|
||||||
|
// Licensed under the Apache License, Version 2.0
|
||||||
|
// <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT
|
||||||
|
// license <LICENSE-MIT or http://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.
|
||||||
|
|
||||||
|
use std::collections::HashSet;
|
||||||
|
use std::ffi::{CStr, CString};
|
||||||
|
use std::fmt;
|
||||||
|
use std::iter::FromIterator;
|
||||||
|
use std::ptr;
|
||||||
|
use std::str;
|
||||||
|
|
||||||
|
use VulkanObject;
|
||||||
|
use check_errors;
|
||||||
|
use instance::PhysicalDevice;
|
||||||
|
use extensions::SupportedExtensionsError;
|
||||||
|
use vk;
|
||||||
|
|
||||||
|
macro_rules! device_extensions {
|
||||||
|
($sname:ident, $rawname:ident, $($ext:ident => $s:expr,)*) => (
|
||||||
|
extensions! {
|
||||||
|
$sname, $rawname,
|
||||||
|
$( $ext => $s,)*
|
||||||
|
}
|
||||||
|
|
||||||
|
impl $rawname {
|
||||||
|
/// See the docs of supported_by_device().
|
||||||
|
pub fn supported_by_device_raw(physical_device: PhysicalDevice) -> Result<Self, SupportedExtensionsError> {
|
||||||
|
let vk = physical_device.instance().pointers();
|
||||||
|
|
||||||
|
let properties: Vec<vk::ExtensionProperties> = unsafe {
|
||||||
|
let mut num = 0;
|
||||||
|
try!(check_errors(vk.EnumerateDeviceExtensionProperties(
|
||||||
|
physical_device.internal_object(), ptr::null(), &mut num, ptr::null_mut())));
|
||||||
|
|
||||||
|
let mut properties = Vec::with_capacity(num as usize);
|
||||||
|
try!(check_errors(vk.EnumerateDeviceExtensionProperties(
|
||||||
|
physical_device.internal_object(), ptr::null(), &mut num, properties.as_mut_ptr())));
|
||||||
|
properties.set_len(num as usize);
|
||||||
|
properties
|
||||||
|
};
|
||||||
|
Ok($rawname(properties.iter().map(|x| unsafe { CStr::from_ptr(x.extensionName.as_ptr()) }.to_owned()).collect()))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns an `Extensions` object with extensions supported by the `PhysicalDevice`.
|
||||||
|
pub fn supported_by_device(physical_device: PhysicalDevice) -> Self {
|
||||||
|
match $rawname::supported_by_device_raw(physical_device) {
|
||||||
|
Ok(l) => l,
|
||||||
|
Err(SupportedExtensionsError::LoadingError(_)) => unreachable!(),
|
||||||
|
Err(SupportedExtensionsError::OomError(e)) => panic!("{:?}", e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl $sname {
|
||||||
|
/// See the docs of supported_by_device().
|
||||||
|
pub fn supported_by_device_raw(physical_device: PhysicalDevice) -> Result<Self, SupportedExtensionsError> {
|
||||||
|
let vk = physical_device.instance().pointers();
|
||||||
|
|
||||||
|
let properties: Vec<vk::ExtensionProperties> = unsafe {
|
||||||
|
let mut num = 0;
|
||||||
|
try!(check_errors(vk.EnumerateDeviceExtensionProperties(
|
||||||
|
physical_device.internal_object(), ptr::null(), &mut num, ptr::null_mut())));
|
||||||
|
|
||||||
|
let mut properties = Vec::with_capacity(num as usize);
|
||||||
|
try!(check_errors(vk.EnumerateDeviceExtensionProperties(
|
||||||
|
physical_device.internal_object(), ptr::null(), &mut num, properties.as_mut_ptr())));
|
||||||
|
properties.set_len(num as usize);
|
||||||
|
properties
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut extensions = $sname::none();
|
||||||
|
for property in properties {
|
||||||
|
let name = unsafe { CStr::from_ptr(property.extensionName.as_ptr()) };
|
||||||
|
$(
|
||||||
|
// TODO: Check specVersion?
|
||||||
|
if name.to_bytes() == &$s[..] {
|
||||||
|
extensions.$ext = true;
|
||||||
|
}
|
||||||
|
)*
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(extensions)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns an `Extensions` object with extensions supported by the `PhysicalDevice`.
|
||||||
|
pub fn supported_by_device(physical_device: PhysicalDevice) -> Self {
|
||||||
|
match $sname::supported_by_device_raw(physical_device) {
|
||||||
|
Ok(l) => l,
|
||||||
|
Err(SupportedExtensionsError::LoadingError(_)) => unreachable!(),
|
||||||
|
Err(SupportedExtensionsError::OomError(e)) => panic!("{:?}", e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
device_extensions! {
|
||||||
|
DeviceExtensions,
|
||||||
|
RawDeviceExtensions,
|
||||||
|
khr_swapchain => b"VK_KHR_swapchain",
|
||||||
|
khr_display_swapchain => b"VK_KHR_display_swapchain",
|
||||||
|
khr_sampler_mirror_clamp_to_edge => b"VK_KHR_sampler_mirror_clamp_to_edge",
|
||||||
|
khr_maintenance1 => b"VK_KHR_maintenance1",
|
||||||
|
khr_get_memory_requirements2 => b"VK_KHR_get_memory_requirements2",
|
||||||
|
khr_dedicated_allocation => b"VK_KHR_dedicated_allocation",
|
||||||
|
khr_incremental_present => b"VK_KHR_incremental_present",
|
||||||
|
ext_debug_marker => b"VK_EXT_debug_marker",
|
||||||
|
}
|
||||||
|
|
||||||
|
/// This helper type can only be instantiated inside this module.
|
||||||
|
/// See `*Extensions::_unbuildable`.
|
||||||
|
#[doc(hidden)]
|
||||||
|
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||||
|
pub struct Unbuildable(());
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use device::{DeviceExtensions, RawDeviceExtensions};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn empty_extensions() {
|
||||||
|
let d: RawDeviceExtensions = (&DeviceExtensions::none()).into();
|
||||||
|
assert!(d.iter().next().is_none());
|
||||||
|
}
|
||||||
|
}
|
@ -16,8 +16,8 @@
|
|||||||
//!
|
//!
|
||||||
//! ```no_run
|
//! ```no_run
|
||||||
//! use vulkano::device::Device;
|
//! use vulkano::device::Device;
|
||||||
//! use vulkano::instance::DeviceExtensions;
|
//! use vulkano::device::DeviceExtensions;
|
||||||
//! use vulkano::instance::Features;
|
//! use vulkano::device::Features;
|
||||||
//! use vulkano::instance::Instance;
|
//! use vulkano::instance::Instance;
|
||||||
//! use vulkano::instance::InstanceExtensions;
|
//! use vulkano::instance::InstanceExtensions;
|
||||||
//! use vulkano::instance::PhysicalDevice;
|
//! use vulkano::instance::PhysicalDevice;
|
||||||
@ -107,7 +107,6 @@ use std::ffi::CStr;
|
|||||||
|
|
||||||
use command_buffer::pool::StandardCommandPool;
|
use command_buffer::pool::StandardCommandPool;
|
||||||
use descriptor::descriptor_set::StdDescriptorPool;
|
use descriptor::descriptor_set::StdDescriptorPool;
|
||||||
use instance::Features;
|
|
||||||
use instance::Instance;
|
use instance::Instance;
|
||||||
use instance::PhysicalDevice;
|
use instance::PhysicalDevice;
|
||||||
use instance::QueueFamily;
|
use instance::QueueFamily;
|
||||||
@ -121,7 +120,10 @@ use VulkanHandle;
|
|||||||
use check_errors;
|
use check_errors;
|
||||||
use vk;
|
use vk;
|
||||||
|
|
||||||
pub use instance::{DeviceExtensions, RawDeviceExtensions};
|
pub use self::extensions::DeviceExtensions;
|
||||||
|
pub use self::extensions::RawDeviceExtensions;
|
||||||
|
pub use ::features::Features;
|
||||||
|
mod extensions;
|
||||||
|
|
||||||
/// Represents a Vulkan context.
|
/// Represents a Vulkan context.
|
||||||
pub struct Device {
|
pub struct Device {
|
227
vulkano/src/extensions.rs
Normal file
227
vulkano/src/extensions.rs
Normal file
@ -0,0 +1,227 @@
|
|||||||
|
// Copyright (c) 2016 The vulkano developers
|
||||||
|
// Licensed under the Apache License, Version 2.0
|
||||||
|
// <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT
|
||||||
|
// license <LICENSE-MIT or http://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.
|
||||||
|
|
||||||
|
use std::error;
|
||||||
|
use std::fmt;
|
||||||
|
use std::str;
|
||||||
|
|
||||||
|
use Error;
|
||||||
|
use OomError;
|
||||||
|
use instance::loader::LoadingError;
|
||||||
|
|
||||||
|
macro_rules! extensions {
|
||||||
|
($sname:ident, $rawname:ident, $($ext:ident => $s:expr,)*) => (
|
||||||
|
/// List of extensions that are enabled or available.
|
||||||
|
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||||
|
#[allow(missing_docs)]
|
||||||
|
pub struct $sname {
|
||||||
|
$(
|
||||||
|
pub $ext: bool,
|
||||||
|
)*
|
||||||
|
|
||||||
|
/// This field ensures that an instance of this `Extensions` struct
|
||||||
|
/// can only be created through Vulkano functions and the update
|
||||||
|
/// syntax. This way, extensions can be added to Vulkano without
|
||||||
|
/// breaking existing code.
|
||||||
|
pub _unbuildable: Unbuildable,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl $sname {
|
||||||
|
/// Returns an `Extensions` object with all members set to `false`.
|
||||||
|
#[inline]
|
||||||
|
pub fn none() -> $sname {
|
||||||
|
$sname {
|
||||||
|
$($ext: false,)*
|
||||||
|
_unbuildable: Unbuildable(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the intersection of this list and another list.
|
||||||
|
#[inline]
|
||||||
|
pub fn intersection(&self, other: &$sname) -> $sname {
|
||||||
|
$sname {
|
||||||
|
$(
|
||||||
|
$ext: self.$ext && other.$ext,
|
||||||
|
)*
|
||||||
|
_unbuildable: Unbuildable(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the difference of another list from this list.
|
||||||
|
#[inline]
|
||||||
|
pub fn difference(&self, other: &$sname) -> $sname {
|
||||||
|
$sname {
|
||||||
|
$(
|
||||||
|
$ext: self.$ext && !other.$ext,
|
||||||
|
)*
|
||||||
|
_unbuildable: Unbuildable(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Debug for $sname {
|
||||||
|
#[allow(unused_assignments)]
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
try!(write!(f, "["));
|
||||||
|
|
||||||
|
let mut first = true;
|
||||||
|
|
||||||
|
$(
|
||||||
|
if self.$ext {
|
||||||
|
if !first { try!(write!(f, ", ")); }
|
||||||
|
else { first = false; }
|
||||||
|
try!(f.write_str(str::from_utf8($s).unwrap()));
|
||||||
|
}
|
||||||
|
)*
|
||||||
|
|
||||||
|
write!(f, "]")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set of extensions, not restricted to those vulkano knows about.
|
||||||
|
///
|
||||||
|
/// This is useful when interacting with external code that has statically-unknown extension
|
||||||
|
/// requirements.
|
||||||
|
#[derive(Clone, Eq, PartialEq)]
|
||||||
|
pub struct $rawname(HashSet<CString>);
|
||||||
|
|
||||||
|
impl $rawname {
|
||||||
|
/// Constructs an extension set containing the supplied extensions.
|
||||||
|
pub fn new<I>(extensions: I) -> Self
|
||||||
|
where I: IntoIterator<Item=CString>
|
||||||
|
{
|
||||||
|
$rawname(extensions.into_iter().collect())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Constructs an empty extension set.
|
||||||
|
pub fn none() -> Self { $rawname(HashSet::new()) }
|
||||||
|
|
||||||
|
/// Adds an extension to the set if it is not already present.
|
||||||
|
pub fn insert(&mut self, extension: CString) {
|
||||||
|
self.0.insert(extension);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the intersection of this set and another.
|
||||||
|
pub fn intersection(&self, other: &Self) -> Self {
|
||||||
|
$rawname(self.0.intersection(&other.0).cloned().collect())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the difference of another set from this one.
|
||||||
|
pub fn difference(&self, other: &Self) -> Self {
|
||||||
|
$rawname(self.0.difference(&other.0).cloned().collect())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the union of both extension sets
|
||||||
|
pub fn union(&self, other: &Self) -> Self {
|
||||||
|
$rawname(self.0.union(&other.0).cloned().collect())
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: impl Iterator
|
||||||
|
pub fn iter(&self) -> ::std::collections::hash_set::Iter<CString> { self.0.iter() }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Debug for $rawname {
|
||||||
|
#[allow(unused_assignments)]
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
self.0.fmt(f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromIterator<CString> for $rawname {
|
||||||
|
fn from_iter<T>(iter: T) -> Self
|
||||||
|
where T: IntoIterator<Item = CString>
|
||||||
|
{
|
||||||
|
$rawname(iter.into_iter().collect())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> From<&'a $sname> for $rawname {
|
||||||
|
fn from(x: &'a $sname) -> Self {
|
||||||
|
let mut data = HashSet::new();
|
||||||
|
$(if x.$ext { data.insert(CString::new(&$s[..]).unwrap()); })*
|
||||||
|
$rawname(data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> From<&'a $rawname> for $sname {
|
||||||
|
fn from(x: &'a $rawname) -> Self {
|
||||||
|
let mut extensions = $sname::none();
|
||||||
|
$(
|
||||||
|
if x.0.iter().any(|x| x.as_bytes() == &$s[..]) {
|
||||||
|
extensions.$ext = true;
|
||||||
|
}
|
||||||
|
)*
|
||||||
|
extensions
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Error that can happen when loading the list of layers.
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub enum SupportedExtensionsError {
|
||||||
|
/// Failed to load the Vulkan shared library.
|
||||||
|
LoadingError(LoadingError),
|
||||||
|
/// Not enough memory.
|
||||||
|
OomError(OomError),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl error::Error for SupportedExtensionsError {
|
||||||
|
#[inline]
|
||||||
|
fn description(&self) -> &str {
|
||||||
|
match *self {
|
||||||
|
SupportedExtensionsError::LoadingError(_) => "failed to load the Vulkan shared library",
|
||||||
|
SupportedExtensionsError::OomError(_) => "not enough memory available",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn cause(&self) -> Option<&error::Error> {
|
||||||
|
match *self {
|
||||||
|
SupportedExtensionsError::LoadingError(ref err) => Some(err),
|
||||||
|
SupportedExtensionsError::OomError(ref err) => Some(err),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for SupportedExtensionsError {
|
||||||
|
#[inline]
|
||||||
|
fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
||||||
|
write!(fmt, "{}", error::Error::description(self))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<OomError> for SupportedExtensionsError {
|
||||||
|
#[inline]
|
||||||
|
fn from(err: OomError) -> SupportedExtensionsError {
|
||||||
|
SupportedExtensionsError::OomError(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<LoadingError> for SupportedExtensionsError {
|
||||||
|
#[inline]
|
||||||
|
fn from(err: LoadingError) -> SupportedExtensionsError {
|
||||||
|
SupportedExtensionsError::LoadingError(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Error> for SupportedExtensionsError {
|
||||||
|
#[inline]
|
||||||
|
fn from(err: Error) -> SupportedExtensionsError {
|
||||||
|
match err {
|
||||||
|
err @ Error::OutOfHostMemory => {
|
||||||
|
SupportedExtensionsError::OomError(OomError::from(err))
|
||||||
|
},
|
||||||
|
err @ Error::OutOfDeviceMemory => {
|
||||||
|
SupportedExtensionsError::OomError(OomError::from(err))
|
||||||
|
},
|
||||||
|
_ => panic!("unexpected error: {:?}", err),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -20,16 +20,17 @@ macro_rules! features {
|
|||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
|
/// use vulkano::device::Features;
|
||||||
/// # let physical_device: vulkano::instance::PhysicalDevice = return;
|
/// # let physical_device: vulkano::instance::PhysicalDevice = return;
|
||||||
/// let minimal_features = vulkano::instance::Features {
|
/// let minimal_features = Features {
|
||||||
/// geometry_shader: true,
|
/// geometry_shader: true,
|
||||||
/// .. vulkano::instance::Features::none()
|
/// .. Features::none()
|
||||||
/// };
|
/// };
|
||||||
///
|
///
|
||||||
/// let optimal_features = vulkano::instance::Features {
|
/// let optimal_features = vulkano::device::Features {
|
||||||
/// geometry_shader: true,
|
/// geometry_shader: true,
|
||||||
/// tessellation_shader: true,
|
/// tessellation_shader: true,
|
||||||
/// .. vulkano::instance::Features::none()
|
/// .. Features::none()
|
||||||
/// };
|
/// };
|
||||||
///
|
///
|
||||||
/// if !physical_device.supported_features().superset_of(&minimal_features) {
|
/// if !physical_device.supported_features().superset_of(&minimal_features) {
|
||||||
|
@ -8,170 +8,18 @@
|
|||||||
// according to those terms.
|
// according to those terms.
|
||||||
|
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
use std::error;
|
|
||||||
use std::ffi::{CStr, CString};
|
use std::ffi::{CStr, CString};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::iter::FromIterator;
|
use std::iter::FromIterator;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
use std::str;
|
use std::str;
|
||||||
|
|
||||||
use Error;
|
|
||||||
use OomError;
|
|
||||||
use VulkanObject;
|
|
||||||
use check_errors;
|
use check_errors;
|
||||||
use instance::PhysicalDevice;
|
|
||||||
use instance::loader;
|
use instance::loader;
|
||||||
use instance::loader::LoadingError;
|
use instance::loader::LoadingError;
|
||||||
|
use extensions::SupportedExtensionsError;
|
||||||
use vk;
|
use vk;
|
||||||
|
|
||||||
macro_rules! extensions {
|
|
||||||
($sname:ident, $rawname:ident, $($ext:ident => $s:expr,)*) => (
|
|
||||||
/// List of extensions that are enabled or available.
|
|
||||||
#[derive(Copy, Clone, PartialEq, Eq)]
|
|
||||||
#[allow(missing_docs)]
|
|
||||||
pub struct $sname {
|
|
||||||
$(
|
|
||||||
pub $ext: bool,
|
|
||||||
)*
|
|
||||||
|
|
||||||
/// This field ensures that an instance of this `Extensions` struct
|
|
||||||
/// can only be created through Vulkano functions and the update
|
|
||||||
/// syntax. This way, extensions can be added to Vulkano without
|
|
||||||
/// breaking existing code.
|
|
||||||
pub _unbuildable: Unbuildable,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl $sname {
|
|
||||||
/// Returns an `Extensions` object with all members set to `false`.
|
|
||||||
#[inline]
|
|
||||||
pub fn none() -> $sname {
|
|
||||||
$sname {
|
|
||||||
$($ext: false,)*
|
|
||||||
_unbuildable: Unbuildable(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the intersection of this list and another list.
|
|
||||||
#[inline]
|
|
||||||
pub fn intersection(&self, other: &$sname) -> $sname {
|
|
||||||
$sname {
|
|
||||||
$(
|
|
||||||
$ext: self.$ext && other.$ext,
|
|
||||||
)*
|
|
||||||
_unbuildable: Unbuildable(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the difference of another list from this list.
|
|
||||||
#[inline]
|
|
||||||
pub fn difference(&self, other: &$sname) -> $sname {
|
|
||||||
$sname {
|
|
||||||
$(
|
|
||||||
$ext: self.$ext && !other.$ext,
|
|
||||||
)*
|
|
||||||
_unbuildable: Unbuildable(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Debug for $sname {
|
|
||||||
#[allow(unused_assignments)]
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
try!(write!(f, "["));
|
|
||||||
|
|
||||||
let mut first = true;
|
|
||||||
|
|
||||||
$(
|
|
||||||
if self.$ext {
|
|
||||||
if !first { try!(write!(f, ", ")); }
|
|
||||||
else { first = false; }
|
|
||||||
try!(f.write_str(str::from_utf8($s).unwrap()));
|
|
||||||
}
|
|
||||||
)*
|
|
||||||
|
|
||||||
write!(f, "]")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Set of extensions, not restricted to those vulkano knows about.
|
|
||||||
///
|
|
||||||
/// This is useful when interacting with external code that has statically-unknown extension
|
|
||||||
/// requirements.
|
|
||||||
#[derive(Clone, Eq, PartialEq)]
|
|
||||||
pub struct $rawname(HashSet<CString>);
|
|
||||||
|
|
||||||
impl $rawname {
|
|
||||||
/// Constructs an extension set containing the supplied extensions.
|
|
||||||
pub fn new<I>(extensions: I) -> Self
|
|
||||||
where I: IntoIterator<Item=CString>
|
|
||||||
{
|
|
||||||
$rawname(extensions.into_iter().collect())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Constructs an empty extension set.
|
|
||||||
pub fn none() -> Self { $rawname(HashSet::new()) }
|
|
||||||
|
|
||||||
/// Adds an extension to the set if it is not already present.
|
|
||||||
pub fn insert(&mut self, extension: CString) {
|
|
||||||
self.0.insert(extension);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the intersection of this set and another.
|
|
||||||
pub fn intersection(&self, other: &Self) -> Self {
|
|
||||||
$rawname(self.0.intersection(&other.0).cloned().collect())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the difference of another set from this one.
|
|
||||||
pub fn difference(&self, other: &Self) -> Self {
|
|
||||||
$rawname(self.0.difference(&other.0).cloned().collect())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the union of both extension sets
|
|
||||||
pub fn union(&self, other: &Self) -> Self {
|
|
||||||
$rawname(self.0.union(&other.0).cloned().collect())
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: impl Iterator
|
|
||||||
pub fn iter(&self) -> ::std::collections::hash_set::Iter<CString> { self.0.iter() }
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Debug for $rawname {
|
|
||||||
#[allow(unused_assignments)]
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
self.0.fmt(f)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FromIterator<CString> for $rawname {
|
|
||||||
fn from_iter<T>(iter: T) -> Self
|
|
||||||
where T: IntoIterator<Item = CString>
|
|
||||||
{
|
|
||||||
$rawname(iter.into_iter().collect())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> From<&'a $sname> for $rawname {
|
|
||||||
fn from(x: &'a $sname) -> Self {
|
|
||||||
let mut data = HashSet::new();
|
|
||||||
$(if x.$ext { data.insert(CString::new(&$s[..]).unwrap()); })*
|
|
||||||
$rawname(data)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> From<&'a $rawname> for $sname {
|
|
||||||
fn from(x: &'a $rawname) -> Self {
|
|
||||||
let mut extensions = $sname::none();
|
|
||||||
$(
|
|
||||||
if x.0.iter().any(|x| x.as_bytes() == &$s[..]) {
|
|
||||||
extensions.$ext = true;
|
|
||||||
}
|
|
||||||
)*
|
|
||||||
extensions
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! instance_extensions {
|
macro_rules! instance_extensions {
|
||||||
($sname:ident, $rawname:ident, $($ext:ident => $s:expr,)*) => (
|
($sname:ident, $rawname:ident, $($ext:ident => $s:expr,)*) => (
|
||||||
extensions! {
|
extensions! {
|
||||||
@ -290,85 +138,6 @@ macro_rules! instance_extensions {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! device_extensions {
|
|
||||||
($sname:ident, $rawname:ident, $($ext:ident => $s:expr,)*) => (
|
|
||||||
extensions! {
|
|
||||||
$sname, $rawname,
|
|
||||||
$( $ext => $s,)*
|
|
||||||
}
|
|
||||||
|
|
||||||
impl $rawname {
|
|
||||||
/// See the docs of supported_by_device().
|
|
||||||
pub fn supported_by_device_raw(physical_device: PhysicalDevice) -> Result<Self, SupportedExtensionsError> {
|
|
||||||
let vk = physical_device.instance().pointers();
|
|
||||||
|
|
||||||
let properties: Vec<vk::ExtensionProperties> = unsafe {
|
|
||||||
let mut num = 0;
|
|
||||||
try!(check_errors(vk.EnumerateDeviceExtensionProperties(
|
|
||||||
physical_device.internal_object(), ptr::null(), &mut num, ptr::null_mut())));
|
|
||||||
|
|
||||||
let mut properties = Vec::with_capacity(num as usize);
|
|
||||||
try!(check_errors(vk.EnumerateDeviceExtensionProperties(
|
|
||||||
physical_device.internal_object(), ptr::null(), &mut num, properties.as_mut_ptr())));
|
|
||||||
properties.set_len(num as usize);
|
|
||||||
properties
|
|
||||||
};
|
|
||||||
Ok($rawname(properties.iter().map(|x| unsafe { CStr::from_ptr(x.extensionName.as_ptr()) }.to_owned()).collect()))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns an `Extensions` object with extensions supported by the `PhysicalDevice`.
|
|
||||||
pub fn supported_by_device(physical_device: PhysicalDevice) -> Self {
|
|
||||||
match $rawname::supported_by_device_raw(physical_device) {
|
|
||||||
Ok(l) => l,
|
|
||||||
Err(SupportedExtensionsError::LoadingError(_)) => unreachable!(),
|
|
||||||
Err(SupportedExtensionsError::OomError(e)) => panic!("{:?}", e),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl $sname {
|
|
||||||
/// See the docs of supported_by_device().
|
|
||||||
pub fn supported_by_device_raw(physical_device: PhysicalDevice) -> Result<Self, SupportedExtensionsError> {
|
|
||||||
let vk = physical_device.instance().pointers();
|
|
||||||
|
|
||||||
let properties: Vec<vk::ExtensionProperties> = unsafe {
|
|
||||||
let mut num = 0;
|
|
||||||
try!(check_errors(vk.EnumerateDeviceExtensionProperties(
|
|
||||||
physical_device.internal_object(), ptr::null(), &mut num, ptr::null_mut())));
|
|
||||||
|
|
||||||
let mut properties = Vec::with_capacity(num as usize);
|
|
||||||
try!(check_errors(vk.EnumerateDeviceExtensionProperties(
|
|
||||||
physical_device.internal_object(), ptr::null(), &mut num, properties.as_mut_ptr())));
|
|
||||||
properties.set_len(num as usize);
|
|
||||||
properties
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut extensions = $sname::none();
|
|
||||||
for property in properties {
|
|
||||||
let name = unsafe { CStr::from_ptr(property.extensionName.as_ptr()) };
|
|
||||||
$(
|
|
||||||
// TODO: Check specVersion?
|
|
||||||
if name.to_bytes() == &$s[..] {
|
|
||||||
extensions.$ext = true;
|
|
||||||
}
|
|
||||||
)*
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(extensions)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns an `Extensions` object with extensions supported by the `PhysicalDevice`.
|
|
||||||
pub fn supported_by_device(physical_device: PhysicalDevice) -> Self {
|
|
||||||
match $sname::supported_by_device_raw(physical_device) {
|
|
||||||
Ok(l) => l,
|
|
||||||
Err(SupportedExtensionsError::LoadingError(_)) => unreachable!(),
|
|
||||||
Err(SupportedExtensionsError::OomError(e)) => panic!("{:?}", e),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
instance_extensions! {
|
instance_extensions! {
|
||||||
InstanceExtensions,
|
InstanceExtensions,
|
||||||
RawInstanceExtensions,
|
RawInstanceExtensions,
|
||||||
@ -388,82 +157,6 @@ instance_extensions! {
|
|||||||
khr_get_physical_device_properties2 => b"VK_KHR_get_physical_device_properties2",
|
khr_get_physical_device_properties2 => b"VK_KHR_get_physical_device_properties2",
|
||||||
}
|
}
|
||||||
|
|
||||||
device_extensions! {
|
|
||||||
DeviceExtensions,
|
|
||||||
RawDeviceExtensions,
|
|
||||||
khr_swapchain => b"VK_KHR_swapchain",
|
|
||||||
khr_display_swapchain => b"VK_KHR_display_swapchain",
|
|
||||||
khr_sampler_mirror_clamp_to_edge => b"VK_KHR_sampler_mirror_clamp_to_edge",
|
|
||||||
khr_maintenance1 => b"VK_KHR_maintenance1",
|
|
||||||
khr_get_memory_requirements2 => b"VK_KHR_get_memory_requirements2",
|
|
||||||
khr_dedicated_allocation => b"VK_KHR_dedicated_allocation",
|
|
||||||
khr_incremental_present => b"VK_KHR_incremental_present",
|
|
||||||
ext_debug_marker => b"VK_EXT_debug_marker",
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Error that can happen when loading the list of layers.
|
|
||||||
#[derive(Clone, Debug)]
|
|
||||||
pub enum SupportedExtensionsError {
|
|
||||||
/// Failed to load the Vulkan shared library.
|
|
||||||
LoadingError(LoadingError),
|
|
||||||
/// Not enough memory.
|
|
||||||
OomError(OomError),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl error::Error for SupportedExtensionsError {
|
|
||||||
#[inline]
|
|
||||||
fn description(&self) -> &str {
|
|
||||||
match *self {
|
|
||||||
SupportedExtensionsError::LoadingError(_) => "failed to load the Vulkan shared library",
|
|
||||||
SupportedExtensionsError::OomError(_) => "not enough memory available",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn cause(&self) -> Option<&error::Error> {
|
|
||||||
match *self {
|
|
||||||
SupportedExtensionsError::LoadingError(ref err) => Some(err),
|
|
||||||
SupportedExtensionsError::OomError(ref err) => Some(err),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Display for SupportedExtensionsError {
|
|
||||||
#[inline]
|
|
||||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
|
||||||
write!(fmt, "{}", error::Error::description(self))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<OomError> for SupportedExtensionsError {
|
|
||||||
#[inline]
|
|
||||||
fn from(err: OomError) -> SupportedExtensionsError {
|
|
||||||
SupportedExtensionsError::OomError(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<LoadingError> for SupportedExtensionsError {
|
|
||||||
#[inline]
|
|
||||||
fn from(err: LoadingError) -> SupportedExtensionsError {
|
|
||||||
SupportedExtensionsError::LoadingError(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<Error> for SupportedExtensionsError {
|
|
||||||
#[inline]
|
|
||||||
fn from(err: Error) -> SupportedExtensionsError {
|
|
||||||
match err {
|
|
||||||
err @ Error::OutOfHostMemory => {
|
|
||||||
SupportedExtensionsError::OomError(OomError::from(err))
|
|
||||||
},
|
|
||||||
err @ Error::OutOfDeviceMemory => {
|
|
||||||
SupportedExtensionsError::OomError(OomError::from(err))
|
|
||||||
},
|
|
||||||
_ => panic!("unexpected error: {:?}", err),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// This helper type can only be instantiated inside this module.
|
/// This helper type can only be instantiated inside this module.
|
||||||
/// See `*Extensions::_unbuildable`.
|
/// See `*Extensions::_unbuildable`.
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
@ -472,15 +165,11 @@ pub struct Unbuildable(());
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use instance::{DeviceExtensions, RawDeviceExtensions};
|
|
||||||
use instance::{InstanceExtensions, RawInstanceExtensions};
|
use instance::{InstanceExtensions, RawInstanceExtensions};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn empty_extensions() {
|
fn empty_extensions() {
|
||||||
let i: RawInstanceExtensions = (&InstanceExtensions::none()).into();
|
let i: RawInstanceExtensions = (&InstanceExtensions::none()).into();
|
||||||
assert!(i.iter().next().is_none());
|
assert!(i.iter().next().is_none());
|
||||||
|
|
||||||
let d: RawDeviceExtensions = (&DeviceExtensions::none()).into();
|
|
||||||
assert!(d.iter().next().is_none());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,9 +30,9 @@ use instance::loader::Loader;
|
|||||||
use instance::loader::LoadingError;
|
use instance::loader::LoadingError;
|
||||||
use vk;
|
use vk;
|
||||||
|
|
||||||
use features::Features;
|
|
||||||
use instance::{InstanceExtensions, RawInstanceExtensions};
|
use instance::{InstanceExtensions, RawInstanceExtensions};
|
||||||
use version::Version;
|
use version::Version;
|
||||||
|
use features::Features;
|
||||||
|
|
||||||
/// An instance of a Vulkan context. This is the main object that should be created by an
|
/// An instance of a Vulkan context. This is the main object that should be created by an
|
||||||
/// application before everything else.
|
/// application before everything else.
|
||||||
|
@ -106,9 +106,7 @@
|
|||||||
//! `device` module for more info.
|
//! `device` module for more info.
|
||||||
//!
|
//!
|
||||||
|
|
||||||
pub use self::extensions::DeviceExtensions;
|
|
||||||
pub use self::extensions::InstanceExtensions;
|
pub use self::extensions::InstanceExtensions;
|
||||||
pub use self::extensions::RawDeviceExtensions;
|
|
||||||
pub use self::extensions::RawInstanceExtensions;
|
pub use self::extensions::RawInstanceExtensions;
|
||||||
pub use self::instance::ApplicationInfo;
|
pub use self::instance::ApplicationInfo;
|
||||||
pub use self::instance::Instance;
|
pub use self::instance::Instance;
|
||||||
@ -128,7 +126,6 @@ pub use self::layers::LayersListError;
|
|||||||
pub use self::layers::layers_list;
|
pub use self::layers::layers_list;
|
||||||
pub use self::limits::Limits;
|
pub use self::limits::Limits;
|
||||||
pub use self::loader::LoadingError;
|
pub use self::loader::LoadingError;
|
||||||
pub use features::Features;
|
|
||||||
pub use version::Version;
|
pub use version::Version;
|
||||||
|
|
||||||
pub mod debug;
|
pub mod debug;
|
||||||
|
@ -73,6 +73,8 @@ pub extern crate half;
|
|||||||
#[macro_use]
|
#[macro_use]
|
||||||
mod tests;
|
mod tests;
|
||||||
|
|
||||||
|
#[macro_use]
|
||||||
|
mod extensions;
|
||||||
mod features;
|
mod features;
|
||||||
mod version;
|
mod version;
|
||||||
|
|
||||||
|
@ -120,7 +120,7 @@
|
|||||||
//! on the device (and not on the instance like `VK_KHR_surface`):
|
//! on the device (and not on the instance like `VK_KHR_surface`):
|
||||||
//!
|
//!
|
||||||
//! ```no_run
|
//! ```no_run
|
||||||
//! # use vulkano::instance::DeviceExtensions;
|
//! # use vulkano::device::DeviceExtensions;
|
||||||
//! let ext = DeviceExtensions {
|
//! let ext = DeviceExtensions {
|
||||||
//! khr_swapchain: true,
|
//! khr_swapchain: true,
|
||||||
//! .. DeviceExtensions::none()
|
//! .. DeviceExtensions::none()
|
||||||
|
Loading…
Reference in New Issue
Block a user