use FromNativeObject;
use TryDestroyError;
use TryDestroyErrorKind;
use VulkanObject;
use core::allocator_helper::AllocatorHelper;
use core::{self, Device, Instance};
use khr_display;
use khr_get_physical_device_properties2;
use khr_surface;
use mir_types;
use nv_external_memory_capabilities;
use std::cmp::Ordering;
use std::ffi::CStr;
use std::hash::{Hash, Hasher};
use std::iter::FromIterator;
use std::mem;
use std::ptr;
use utils;
use vks;
use wayland_types;
use xcb_types;
use xlib_types;
#[derive(Debug, Clone)]
pub struct PhysicalDevice {
pub(crate) handle: vks::core::VkPhysicalDevice,
pub(crate) instance: Instance,
}
unsafe impl Send for PhysicalDevice { }
unsafe impl Sync for PhysicalDevice { }
impl PartialEq for PhysicalDevice {
#[inline]
fn eq(&self, other: &Self) -> bool {
self.handle == other.handle
}
}
impl Eq for PhysicalDevice { }
impl PartialOrd for PhysicalDevice {
#[inline]
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
self.handle.partial_cmp(&other.handle)
}
}
impl Ord for PhysicalDevice {
#[inline]
fn cmp(&self, other: &Self) -> Ordering {
self.handle.cmp(&other.handle)
}
}
impl Hash for PhysicalDevice {
#[inline]
fn hash<H: Hasher>(&self, state: &mut H) {
self.handle.hash(state);
}
}
impl VulkanObject for PhysicalDevice {
type NativeVulkanObject = vks::core::VkPhysicalDevice;
#[inline]
fn id(&self) -> u64 {
self.as_native_vulkan_object() as u64
}
#[inline]
fn as_native_vulkan_object(&self) -> Self::NativeVulkanObject {
self.handle
}
fn try_destroy(self) -> Result<(), TryDestroyError<Self>> {
Err(TryDestroyError::new(self, TryDestroyErrorKind::Unsupported))
}
}
impl FromNativeObject for PhysicalDevice {
type Parameters = Instance;
unsafe fn from_native_object(object: Self::NativeVulkanObject, params: Self::Parameters) -> Self {
PhysicalDevice::new(object, params)
}
}
impl PhysicalDevice {
pub(crate) fn new(handle: vks::core::VkPhysicalDevice, instance: Instance) -> Self {
PhysicalDevice {
handle: handle,
instance: instance,
}
}
#[inline]
pub(crate) fn loader(&self) -> &vks::InstanceProcAddrLoader {
self.instance.loader()
}
pub fn get_properties(&self) -> core::PhysicalDeviceProperties {
unsafe {
let mut properties = mem::uninitialized();
self.loader().core.vkGetPhysicalDeviceProperties(self.handle, &mut properties);
(&properties).into()
}
}
pub fn get_features(&self) -> core::PhysicalDeviceFeatures {
unsafe {
let mut features = mem::uninitialized();
self.loader().core.vkGetPhysicalDeviceFeatures(self.handle, &mut features);
(&features).into()
}
}
pub fn enumerate_device_layer_properties<B>(&self) -> Result<B, core::Error>
where B: FromIterator<core::LayerProperties>
{
unsafe {
let mut num_layer_properties = 0;
let res = self.loader().core.vkEnumerateDeviceLayerProperties(self.handle, &mut num_layer_properties, ptr::null_mut());
if res != vks::core::VK_SUCCESS {
return Err(res.into());
}
let mut layer_properties = Vec::with_capacity(num_layer_properties as usize);
let res = self.loader().core.vkEnumerateDeviceLayerProperties(self.handle, &mut num_layer_properties, layer_properties.as_mut_ptr());
layer_properties.set_len(num_layer_properties as usize);
if res != vks::core::VK_SUCCESS {
return Err(res.into());
}
Ok(layer_properties.iter().map(From::from).collect())
}
}
pub fn get_device_extension_properties(&self, layer_name: Option<&str>) -> Result<core::DeviceExtensionsProperties, core::Error> {
unsafe {
let layer_name_cstr = utils::cstr_from_str(layer_name);
let mut num_extension_properties = 0;
let res = self.loader().core.vkEnumerateDeviceExtensionProperties(self.handle, layer_name_cstr.1, &mut num_extension_properties, ptr::null_mut());
if res != vks::core::VK_SUCCESS {
return Err(res.into());
}
let mut extension_properties = Vec::with_capacity(num_extension_properties as usize);
extension_properties.set_len(num_extension_properties as usize);
let res = self.loader().core.vkEnumerateDeviceExtensionProperties(self.handle, layer_name_cstr.1, &mut num_extension_properties, extension_properties.as_mut_ptr());
if res != vks::core::VK_SUCCESS {
return Err(res.into());
}
let mut res = core::DeviceExtensionsProperties::new();
for extension in extension_properties {
let name = CStr::from_ptr(extension.extensionName.as_ptr()).to_str().unwrap();
res.add(name, extension.specVersion);
}
Ok(res)
}
}
pub fn get_format_properties(&self, format: core::Format) -> core::FormatProperties {
let mut properties = unsafe { mem::uninitialized() };
unsafe {
self.loader().core.vkGetPhysicalDeviceFormatProperties(self.handle, format.into(), &mut properties);
}
(&properties).into()
}
pub fn get_image_format_properties(&self, format: core::Format, image_type: core::ImageType, tiling: core::ImageTiling, usage: core::ImageUsageFlags, flags: core::ImageCreateFlags) -> Result<core::ImageFormatProperties, core::Error> {
let mut properties = unsafe { mem::uninitialized() };
let res = unsafe {
self.loader().core.vkGetPhysicalDeviceImageFormatProperties(self.handle, format.into(), image_type.into(), tiling.into(), usage.bits(), flags.bits(), &mut properties)
};
if res == vks::core::VK_SUCCESS {
Ok((&properties).into())
}
else {
Err(res.into())
}
}
pub fn get_sparse_image_format_properties<B>(&self, format: core::Format, image_type: core::ImageType, samples: core::SampleCountFlagBits, usage: core::ImageUsageFlags, tiling: core::ImageTiling) -> B
where B: FromIterator<core::SparseImageFormatProperties>
{
let mut num_properties = 0;
unsafe {
self.loader().core.vkGetPhysicalDeviceSparseImageFormatProperties(self.handle, format.into(), image_type.into(), samples.bit(), usage.bits(), tiling.into(), &mut num_properties, ptr::null_mut());
}
let mut properties = Vec::with_capacity(num_properties as usize);
unsafe {
self.loader().core.vkGetPhysicalDeviceSparseImageFormatProperties(self.handle, format.into(), image_type.into(), samples.bit(), usage.bits(), tiling.into(), &mut num_properties, properties.as_mut_ptr());
properties.set_len(num_properties as usize);
}
properties.iter().map(From::from).collect()
}
pub fn get_queue_family_properties<B>(&self) -> B
where B: FromIterator<core::QueueFamilyProperties>
{
let mut num_properties = 0;
unsafe {
self.loader().core.vkGetPhysicalDeviceQueueFamilyProperties(self.handle, &mut num_properties, ptr::null_mut());
}
let mut properties = Vec::with_capacity(num_properties as usize);
unsafe {
self.loader().core.vkGetPhysicalDeviceQueueFamilyProperties(self.handle, &mut num_properties, properties.as_mut_ptr());
properties.set_len(num_properties as usize);
}
properties.iter().map(From::from).collect()
}
pub fn get_memory_properties(&self) -> core::PhysicalDeviceMemoryProperties {
let mut properties = unsafe { mem::uninitialized() };
unsafe {
self.loader().core.vkGetPhysicalDeviceMemoryProperties(self.handle, &mut properties);
}
(&properties).into()
}
pub fn create_device(&self, create_info: &core::DeviceCreateInfo, allocator: Option<Box<core::Allocator>>) -> Result<Device, core::Error> {
let allocator_helper = allocator.map(AllocatorHelper::new);
let allocation_callbacks = allocator_helper.as_ref().map_or(ptr::null(), AllocatorHelper::callbacks);
let create_info_wrapper = core::VkDeviceCreateInfoWrapper::new(create_info, true);
let mut device = ptr::null_mut();
let res = unsafe {
self.loader().core.vkCreateDevice(self.handle, &create_info_wrapper.vks_struct, allocation_callbacks, &mut device)
};
if res == vks::core::VK_SUCCESS {
let mut loader = vks::DeviceProcAddrLoader::from_get_device_proc_addr(self.loader().core.pfn_vkGetDeviceProcAddr);
unsafe {
loader.load_core(device);
create_info.enabled_extensions.load_device(&mut loader, device);
self.instance.get_enabled_extensions().load_device(&mut loader, device);
}
Ok(Device::new(device, self.instance.clone(), allocator_helper, loader, create_info.enabled_extensions.clone()))
}
else {
Err(res.into())
}
}
pub fn get_surface_support_khr(&self, queue_family_index: u32, surface: &khr_surface::SurfaceKhr) -> Result<bool, core::Error> {
let mut supported = vks::core::VK_FALSE;
let res = unsafe {
self.loader().khr_surface.vkGetPhysicalDeviceSurfaceSupportKHR(self.handle, queue_family_index, surface.handle(), &mut supported)
};
if res == vks::core::VK_SUCCESS {
Ok(utils::from_vk_bool(supported))
}
else {
Err(res.into())
}
}
pub fn get_surface_capabilities_khr(&self, surface: &khr_surface::SurfaceKhr) -> Result<khr_surface::SurfaceCapabilitiesKhr, core::Error> {
unsafe {
let mut capabilities = mem::uninitialized();
let res = self.loader().khr_surface.vkGetPhysicalDeviceSurfaceCapabilitiesKHR(self.handle, surface.handle(), &mut capabilities);
if res == vks::core::VK_SUCCESS {
Ok((&capabilities).into())
}
else {
Err(res.into())
}
}
}
pub fn get_surface_formats_khr<B>(&self, surface: &khr_surface::SurfaceKhr) -> Result<B, core::Error>
where B: FromIterator<khr_surface::SurfaceFormatKhr>
{
let mut num_formats = 0;
let res = unsafe {
self.loader().khr_surface.vkGetPhysicalDeviceSurfaceFormatsKHR(self.handle, surface.handle(), &mut num_formats, ptr::null_mut())
};
if (res != vks::core::VK_SUCCESS) && (res != vks::core::VK_INCOMPLETE) {
return Err(res.into());
}
let mut formats = Vec::with_capacity(num_formats as usize);
let res = unsafe {
self.loader().khr_surface.vkGetPhysicalDeviceSurfaceFormatsKHR(self.handle, surface.handle(), &mut num_formats, formats.as_mut_ptr())
};
if res == vks::core::VK_SUCCESS {
unsafe {
formats.set_len(num_formats as usize);
}
Ok(formats.iter().map(From::from).collect())
}
else {
Err(res.into())
}
}
pub fn get_surface_present_modes_khr<B>(&self, surface: &khr_surface::SurfaceKhr) -> Result<B, core::Error>
where B: FromIterator<khr_surface::PresentModeKhr>
{
let mut num_modes = 0;
let res = unsafe {
self.loader().khr_surface.vkGetPhysicalDeviceSurfacePresentModesKHR(self.handle, surface.handle(), &mut num_modes, ptr::null_mut())
};
if (res != vks::core::VK_SUCCESS) && (res != vks::core::VK_INCOMPLETE) {
return Err(res.into());
}
let mut modes = Vec::with_capacity(num_modes as usize);
let res = unsafe {
self.loader().khr_surface.vkGetPhysicalDeviceSurfacePresentModesKHR(self.handle, surface.handle(), &mut num_modes, modes.as_mut_ptr())
};
if res == vks::core::VK_SUCCESS {
unsafe {
modes.set_len(num_modes as usize);
}
Ok(modes.into_iter().map(From::from).collect())
}
else {
Err(res.into())
}
}
pub fn get_display_properties_khr(&self) -> Result<Vec<khr_display::DisplayPropertiesKhr>, core::Error> {
let mut len = 0;
let res = unsafe {
self.loader().khr_display.vkGetPhysicalDeviceDisplayPropertiesKHR(self.handle, &mut len, ptr::null_mut())
};
if res != vks::core::VK_SUCCESS {
return Err(res.into());
}
let mut properties = Vec::with_capacity(len as usize);
let res = unsafe {
properties.set_len(len as usize);
self.loader().khr_display.vkGetPhysicalDeviceDisplayPropertiesKHR(self.handle, &mut len, properties.as_mut_ptr())
};
if res == vks::core::VK_SUCCESS {
unsafe {
Ok(properties.iter().map(|p| khr_display::DisplayPropertiesKhr::from_vks(p, self.clone())).collect())
}
}
else {
Err(res.into())
}
}
pub fn get_display_plane_properties_khr(&self) -> Result<Vec<khr_display::DisplayPlanePropertiesKhr>, core::Error> {
let mut len = 0;
let res = unsafe {
self.loader().khr_display.vkGetPhysicalDeviceDisplayPlanePropertiesKHR(self.handle, &mut len, ptr::null_mut())
};
if res != vks::core::VK_SUCCESS {
return Err(res.into());
}
let mut properties = Vec::with_capacity(len as usize);
let res = unsafe {
properties.set_len(len as usize);
self.loader().khr_display.vkGetPhysicalDeviceDisplayPlanePropertiesKHR(self.handle, &mut len, properties.as_mut_ptr())
};
if res == vks::core::VK_SUCCESS {
unsafe {
Ok(properties.iter().map(|p| khr_display::DisplayPlanePropertiesKhr::from_vks(p, self)).collect())
}
}
else {
Err(res.into())
}
}
pub fn get_display_plane_supported_displays_khr(&self, plane_index: u32) -> Result<Vec<khr_display::DisplayKhr>, core::Error> {
let mut len = 0;
let res = unsafe {
self.loader().khr_display.vkGetDisplayPlaneSupportedDisplaysKHR(self.handle, plane_index, &mut len, ptr::null_mut())
};
if res != vks::core::VK_SUCCESS {
return Err(res.into());
}
let mut displays = Vec::with_capacity(len as usize);
let res = unsafe {
displays.set_len(len as usize);
self.loader().khr_display.vkGetDisplayPlaneSupportedDisplaysKHR(self.handle, plane_index, &mut len, displays.as_mut_ptr())
};
if res == vks::core::VK_SUCCESS {
Ok(displays.iter().map(|d| khr_display::DisplayKhr::new(*d, self.clone())).collect())
}
else {
Err(res.into())
}
}
#[cfg_attr(feature = "cargo-clippy", allow(not_unsafe_ptr_arg_deref))]
pub fn get_xlib_presentation_support_khr(&self, queue_family_index: u32, dpy: *mut xlib_types::Display, visual_id: xlib_types::VisualID) -> bool {
let res = unsafe {
self.loader().khr_xlib_surface.vkGetPhysicalDeviceXlibPresentationSupportKHR(self.handle, queue_family_index, dpy, visual_id)
};
utils::from_vk_bool(res)
}
#[cfg_attr(feature = "cargo-clippy", allow(not_unsafe_ptr_arg_deref))]
pub fn get_wayland_presentation_support_khr(&self, queue_family_index: u32, display: *mut wayland_types::wl_display) -> bool {
let res = unsafe {
self.loader().khr_wayland_surface.vkGetPhysicalDeviceWaylandPresentationSupportKHR(self.handle, queue_family_index, display)
};
utils::from_vk_bool(res)
}
#[cfg_attr(feature = "cargo-clippy", allow(not_unsafe_ptr_arg_deref))]
pub fn get_xcb_presentation_support_khr(&self, queue_family_index: u32, connection: *mut xcb_types::xcb_connection_t, visual_id: xcb_types::xcb_visualid_t) -> bool {
let res = unsafe {
self.loader().khr_xcb_surface.vkGetPhysicalDeviceXcbPresentationSupportKHR(self.handle, queue_family_index, connection, visual_id)
};
utils::from_vk_bool(res)
}
#[cfg_attr(feature = "cargo-clippy", allow(not_unsafe_ptr_arg_deref))]
pub fn get_mir_presentation_support_khr(&self, queue_family_index: u32, connection: *mut mir_types::MirConnection) -> bool {
let res = unsafe {
self.loader().khr_mir_surface.vkGetPhysicalDeviceMirPresentationSupportKHR(self.handle, queue_family_index, connection)
};
utils::from_vk_bool(res)
}
pub fn get_win32_presentation_support_khr(&self, queue_family_index: u32) -> bool {
let res = unsafe {
self.loader().khr_win32_surface.vkGetPhysicalDeviceWin32PresentationSupportKHR(self.handle, queue_family_index)
};
utils::from_vk_bool(res)
}
pub fn get_features2_khr(&self, chain_query: Option<&khr_get_physical_device_properties2::PhysicalDeviceFeatures2ChainQueryKhr>) -> khr_get_physical_device_properties2::PhysicalDeviceFeatures2Khr {
let mut chain_query_wrapper = khr_get_physical_device_properties2::PhysicalDeviceFeatures2ChainQueryKhrWrapper::new_optional(chain_query);
unsafe {
self.loader().khr_get_physical_device_properties2.vkGetPhysicalDeviceFeatures2KHR(self.handle, &mut chain_query_wrapper.vks_struct);
khr_get_physical_device_properties2::PhysicalDeviceFeatures2Khr::from_vks(&chain_query_wrapper.vks_struct, true)
}
}
pub fn get_properties2_khr(&self, chain_query: Option<&khr_get_physical_device_properties2::PhysicalDeviceProperties2ChainQueryKhr>) -> khr_get_physical_device_properties2::PhysicalDeviceProperties2Khr {
let mut chain_query_wrapper = khr_get_physical_device_properties2::PhysicalDeviceProperties2ChainQueryKhrWrapper::new_optional(chain_query);
unsafe {
self.loader().khr_get_physical_device_properties2.vkGetPhysicalDeviceProperties2KHR(self.handle, &mut chain_query_wrapper.vks_struct);
khr_get_physical_device_properties2::PhysicalDeviceProperties2Khr::from_vks(&chain_query_wrapper.vks_struct, true)
}
}
pub fn get_format_properties2_khr(&self, format: core::Format, chain_query: Option<&khr_get_physical_device_properties2::FormatProperties2ChainQueryKhr>) -> khr_get_physical_device_properties2::FormatProperties2Khr {
let mut chain_query_wrapper = khr_get_physical_device_properties2::FormatProperties2ChainQueryKhrWrapper::new_optional(chain_query);
unsafe {
self.loader().khr_get_physical_device_properties2.vkGetPhysicalDeviceFormatProperties2KHR(self.handle, format.into(), &mut chain_query_wrapper.vks_struct);
khr_get_physical_device_properties2::FormatProperties2Khr::from_vks(&chain_query_wrapper.vks_struct, true)
}
}
pub fn get_image_format_properties2_khr(&self, image_format_info: &khr_get_physical_device_properties2::PhysicalDeviceImageFormatInfo2Khr, chain_query: Option<&khr_get_physical_device_properties2::ImageFormatProperties2ChainQueryKhr>) -> Result<khr_get_physical_device_properties2::ImageFormatProperties2Khr, core::Error> {
let image_format_info_wrapper = khr_get_physical_device_properties2::VkPhysicalDeviceImageFormatInfo2KHRWrapper::new(image_format_info, true);
let mut chain_query_wrapper = khr_get_physical_device_properties2::ImageFormatProperties2ChainQueryKhrWrapper::new_optional(chain_query);
unsafe {
let res = self.loader().khr_get_physical_device_properties2.vkGetPhysicalDeviceImageFormatProperties2KHR(self.handle, &image_format_info_wrapper.vks_struct, &mut chain_query_wrapper.vks_struct);
if res == vks::core::VK_SUCCESS {
Ok(khr_get_physical_device_properties2::ImageFormatProperties2Khr::from_vks(&chain_query_wrapper.vks_struct, true))
}
else {
Err(res.into())
}
}
}
pub fn get_queue_family_properties2_khr<B>(&self, chain_query: Option<&khr_get_physical_device_properties2::QueueFamilyProperties2ChainQueryKhr>) -> B
where B: FromIterator<khr_get_physical_device_properties2::QueueFamilyProperties2Khr>
{
unsafe {
let mut num = 0;
self.loader().khr_get_physical_device_properties2.vkGetPhysicalDeviceQueueFamilyProperties2KHR(self.handle, &mut num, ptr::null_mut());
let mut chain_query_wrappers = Vec::with_capacity(num as usize);
for _ in 0..num {
chain_query_wrappers.push(khr_get_physical_device_properties2::QueueFamilyProperties2ChainQueryKhrWrapper::new_optional(chain_query));
}
let mut vks_structs: Vec<_> = chain_query_wrappers.iter().map(|w| w.vks_struct).collect();
self.loader().khr_get_physical_device_properties2.vkGetPhysicalDeviceQueueFamilyProperties2KHR(self.handle, &mut num, vks_structs.as_mut_ptr());
vks_structs.iter().map(|p| khr_get_physical_device_properties2::QueueFamilyProperties2Khr::from_vks(p, true)).collect()
}
}
pub fn get_memory_properties2_khr(&self, chain_query: Option<&khr_get_physical_device_properties2::PhysicalDeviceMemoryProperties2ChainQueryKhr>) -> khr_get_physical_device_properties2::PhysicalDeviceMemoryProperties2Khr {
let mut chain_query_wrapper = khr_get_physical_device_properties2::PhysicalDeviceMemoryProperties2ChainQueryKhrWrapper::new_optional(chain_query);
unsafe {
self.loader().khr_get_physical_device_properties2.vkGetPhysicalDeviceMemoryProperties2KHR(self.handle, &mut chain_query_wrapper.vks_struct);
khr_get_physical_device_properties2::PhysicalDeviceMemoryProperties2Khr::from_vks(&chain_query_wrapper.vks_struct, true)
}
}
pub fn get_sparse_image_format_properties2_khr<B>(&self, format_info: &khr_get_physical_device_properties2::PhysicalDeviceSparseImageFormatInfo2Khr, chain_query: Option<&khr_get_physical_device_properties2::SparseImageFormatProperties2ChainQueryKhr>) -> B
where B: FromIterator<khr_get_physical_device_properties2::SparseImageFormatProperties2Khr>
{
let format_info_wrapper = khr_get_physical_device_properties2::VkPhysicalDeviceSparseImageFormatInfo2KHRWrapper::new(format_info, true);
unsafe {
let mut num = 0;
self.loader().khr_get_physical_device_properties2.vkGetPhysicalDeviceSparseImageFormatProperties2KHR(self.handle, &format_info_wrapper.vks_struct, &mut num, ptr::null_mut());
let mut chain_query_wrappers = Vec::with_capacity(num as usize);
for _ in 0..num {
chain_query_wrappers.push(khr_get_physical_device_properties2::SparseImageFormatProperties2ChainQueryKhrWrapper::new_optional(chain_query));
}
let mut vks_structs: Vec<_> = chain_query_wrappers.iter().map(|w| w.vks_struct).collect();
self.loader().khr_get_physical_device_properties2.vkGetPhysicalDeviceSparseImageFormatProperties2KHR(self.handle, &format_info_wrapper.vks_struct, &mut num, vks_structs.as_mut_ptr());
vks_structs.iter().map(|p| khr_get_physical_device_properties2::SparseImageFormatProperties2Khr::from_vks(p, true)).collect()
}
}
pub fn get_external_image_format_properties_nv(&self, format: core::Format, image_type: core::ImageType, tiling: core::ImageTiling, usage: core::ImageUsageFlags, flags: core::ImageCreateFlags, external_handle_type: nv_external_memory_capabilities::ExternalMemoryHandleTypeFlagsNv) -> Result<nv_external_memory_capabilities::ExternalImageFormatPropertiesNv, core::Error> {
let mut properties = unsafe { mem::uninitialized() };
let res = unsafe {
self.loader().nv_external_memory_capabilities.vkGetPhysicalDeviceExternalImageFormatPropertiesNV(self.handle, format.into(), image_type.into(), tiling.into(), usage.bits(), flags.bits(), external_handle_type.bits(), &mut properties)
};
if res == vks::core::VK_SUCCESS {
Ok((&properties).into())
}
else {
Err(res.into())
}
}
}