From fa5d1272b27db6d743ce5cc68f9deae6b0d63a9a Mon Sep 17 00:00:00 2001 From: Rua Date: Wed, 25 Oct 2023 11:09:18 +0200 Subject: [PATCH] Minimise amount of code behind conditional compilation (#2362) * Minimise amount of code behind conditional compilation * An additional case * Copy paste derp * Fix unreachable warnings * Typo * Let's hope this works... --- vulkano/src/device/mod.rs | 42 ++-- vulkano/src/memory/device_memory.rs | 297 +++++++++++------------ vulkano/src/sync/fence.rs | 69 +++--- vulkano/src/sync/semaphore.rs | 363 ++++++++++++++-------------- 4 files changed, 382 insertions(+), 389 deletions(-) diff --git a/vulkano/src/device/mod.rs b/vulkano/src/device/mod.rs index 66c24c75d5..af1a2146a7 100644 --- a/vulkano/src/device/mod.rs +++ b/vulkano/src/device/mod.rs @@ -965,7 +965,6 @@ impl Device { /// # Safety /// /// - `file` must be a handle to external memory that was created outside the Vulkan API. - #[cfg_attr(not(unix), allow(unused_variables))] #[inline] pub unsafe fn memory_fd_properties( &self, @@ -1009,35 +1008,38 @@ impl Device { } #[cfg_attr(not(feature = "document_unchecked"), doc(hidden))] - #[cfg_attr(not(unix), allow(unused_variables))] pub unsafe fn memory_fd_properties_unchecked( &self, handle_type: ExternalMemoryHandleType, file: File, ) -> Result { - #[cfg(not(unix))] - unreachable!("`khr_external_memory_fd` was somehow enabled on a non-Unix system"); + let mut memory_fd_properties = ash::vk::MemoryFdPropertiesKHR::default(); #[cfg(unix)] - { - use std::os::unix::io::IntoRawFd; + let fd = { + use std::os::fd::IntoRawFd; + file.into_raw_fd() + }; - let mut memory_fd_properties = ash::vk::MemoryFdPropertiesKHR::default(); + #[cfg(not(unix))] + let fd = { + let _ = file; + -1 + }; - let fns = self.fns(); - (fns.khr_external_memory_fd.get_memory_fd_properties_khr)( - self.handle, - handle_type.into(), - file.into_raw_fd(), - &mut memory_fd_properties, - ) - .result() - .map_err(VulkanError::from)?; + let fns = self.fns(); + (fns.khr_external_memory_fd.get_memory_fd_properties_khr)( + self.handle, + handle_type.into(), + fd, + &mut memory_fd_properties, + ) + .result() + .map_err(VulkanError::from)?; - Ok(MemoryFdProperties { - memory_type_bits: memory_fd_properties.memory_type_bits, - }) - } + Ok(MemoryFdProperties { + memory_type_bits: memory_fd_properties.memory_type_bits, + }) } /// Assigns a human-readable name to `object` for debugging purposes. diff --git a/vulkano/src/memory/device_memory.rs b/vulkano/src/memory/device_memory.rs index e1d416e158..404948f50f 100644 --- a/vulkano/src/memory/device_memory.rs +++ b/vulkano/src/memory/device_memory.rs @@ -169,13 +169,21 @@ impl DeviceMemory { _ne: _, } = allocate_info; - let mut allocate_info = ash::vk::MemoryAllocateInfo::builder() - .allocation_size(allocation_size) - .memory_type_index(memory_type_index); + let mut allocate_info_vk = ash::vk::MemoryAllocateInfo { + allocation_size, + memory_type_index, + ..Default::default() + }; + + let mut dedicated_allocate_info_vk = None; + let mut export_allocate_info_vk = None; + let mut import_fd_info_vk = None; + let mut import_win32_handle_info_vk = None; + let mut flags_info_vk = None; // VUID-VkMemoryDedicatedAllocateInfo-image-01432 - let mut dedicated_allocate_info = - dedicated_allocation.map(|dedicated_allocation| match dedicated_allocation { + if let Some(dedicated_allocation) = dedicated_allocation { + let next = dedicated_allocate_info_vk.insert(match dedicated_allocation { DedicatedAllocation::Buffer(buffer) => ash::vk::MemoryDedicatedAllocateInfo { buffer: buffer.handle(), ..Default::default() @@ -186,21 +194,18 @@ impl DeviceMemory { }, }); - if let Some(info) = dedicated_allocate_info.as_mut() { - allocate_info = allocate_info.push_next(info); + next.p_next = allocate_info_vk.p_next; + allocate_info_vk.p_next = next as *const _ as *const _; } - let mut export_allocate_info = if !export_handle_types.is_empty() { - Some(ash::vk::ExportMemoryAllocateInfo { + if !export_handle_types.is_empty() { + let next = export_allocate_info_vk.insert(ash::vk::ExportMemoryAllocateInfo { handle_types: export_handle_types.into(), ..Default::default() - }) - } else { - None - }; + }); - if let Some(info) = export_allocate_info.as_mut() { - allocate_info = allocate_info.push_next(info); + next.p_next = allocate_info_vk.p_next; + allocate_info_vk.p_next = next as *const _ as *const _; } let imported_handle_type = import_info.as_ref().map(|import_info| match import_info { @@ -208,50 +213,56 @@ impl DeviceMemory { MemoryImportInfo::Win32 { handle_type, .. } => *handle_type, }); - #[cfg(unix)] - let mut import_fd_info = match import_info { - Some(MemoryImportInfo::Fd { handle_type, file }) => { - use std::os::unix::io::IntoRawFd; + if let Some(import_info) = import_info { + match import_info { + MemoryImportInfo::Fd { handle_type, file } => { + #[cfg(unix)] + let fd = { + use std::os::fd::IntoRawFd; + file.into_raw_fd() + }; + + #[cfg(not(unix))] + let fd = { + let _ = file; + -1 + }; + + let next = import_fd_info_vk.insert(ash::vk::ImportMemoryFdInfoKHR { + handle_type: handle_type.into(), + fd, + ..Default::default() + }); - Some(ash::vk::ImportMemoryFdInfoKHR { - handle_type: handle_type.into(), - fd: file.into_raw_fd(), - ..Default::default() - }) - } - _ => None, - }; + next.p_next = allocate_info_vk.p_next; + allocate_info_vk.p_next = next as *const _ as *const _; + } + MemoryImportInfo::Win32 { + handle_type, + handle, + } => { + let next = import_win32_handle_info_vk.insert( + ash::vk::ImportMemoryWin32HandleInfoKHR { + handle_type: handle_type.into(), + handle, + ..Default::default() + }, + ); - #[cfg(unix)] - if let Some(info) = import_fd_info.as_mut() { - allocate_info = allocate_info.push_next(info); + next.p_next = allocate_info_vk.p_next; + allocate_info_vk.p_next = next as *const _ as *const _; + } + } } - #[cfg(windows)] - let mut import_win32_handle_info = match import_info { - Some(MemoryImportInfo::Win32 { - handle_type, - handle, - }) => Some(ash::vk::ImportMemoryWin32HandleInfoKHR { - handle_type: handle_type.into(), - handle, + if !flags.is_empty() { + let next = flags_info_vk.insert(ash::vk::MemoryAllocateFlagsInfo { + flags: flags.into(), ..Default::default() - }), - _ => None, - }; - - #[cfg(windows)] - if let Some(info) = import_win32_handle_info.as_mut() { - allocate_info = allocate_info.push_next(info); - } - - let mut flags_info = ash::vk::MemoryAllocateFlagsInfo { - flags: flags.into(), - ..Default::default() - }; + }); - if !flags.is_empty() { - allocate_info = allocate_info.push_next(&mut flags_info); + next.p_next = allocate_info_vk.p_next; + allocate_info_vk.p_next = next as *const _ as *const _; } // VUID-vkAllocateMemory-maxMemoryAllocationCount-04101 @@ -271,7 +282,7 @@ impl DeviceMemory { let mut output = MaybeUninit::uninit(); (fns.v1_0.allocate_memory)( device.handle(), - &allocate_info.build(), + &allocate_info_vk, ptr::null(), output.as_mut_ptr(), ) @@ -806,37 +817,32 @@ impl DeviceMemory { &self, handle_type: ExternalMemoryHandleType, ) -> Result { - debug_assert!(self.device().enabled_extensions().khr_external_memory_fd); + let info_vk = ash::vk::MemoryGetFdInfoKHR { + memory: self.handle, + handle_type: handle_type.into(), + ..Default::default() + }; - #[cfg(not(unix))] - unreachable!("`khr_external_memory_fd` was somehow enabled on a non-Unix system"); + let fns = self.device.fns(); + let mut output = MaybeUninit::uninit(); + (fns.khr_external_memory_fd.get_memory_fd_khr)( + self.device.handle(), + &info_vk, + output.as_mut_ptr(), + ) + .result() + .map_err(VulkanError::from)?; #[cfg(unix)] { use std::os::unix::io::FromRawFd; + Ok(File::from_raw_fd(output.assume_init())) + } - let fd = unsafe { - let fns = self.device.fns(); - let info = ash::vk::MemoryGetFdInfoKHR { - memory: self.handle, - handle_type: handle_type.into(), - ..Default::default() - }; - - let mut output = MaybeUninit::uninit(); - (fns.khr_external_memory_fd.get_memory_fd_khr)( - self.device.handle(), - &info, - output.as_mut_ptr(), - ) - .result() - .map_err(VulkanError::from)?; - output.assume_init() - }; - - let file = unsafe { std::fs::File::from_raw_fd(fd) }; - - Ok(file) + #[cfg(not(unix))] + { + let _ = output; + unreachable!("`khr_external_memory_fd` was somehow enabled on a non-Unix system"); } } } @@ -1174,10 +1180,7 @@ impl MemoryImportInfo { pub(crate) fn validate(&self, device: &Device) -> Result<(), Box> { match self { MemoryImportInfo::Fd { - #[cfg(unix)] handle_type, - #[cfg(not(unix))] - handle_type: _, file: _, } => { if !device.enabled_extensions().khr_external_memory_fd { @@ -1190,49 +1193,40 @@ impl MemoryImportInfo { })); } - #[cfg(not(unix))] - unreachable!("`khr_external_memory_fd` was somehow enabled on a non-Unix system"); + handle_type.validate_device(device).map_err(|err| { + err.add_context("handle_type") + .set_vuids(&["VUID-VkImportMemoryFdInfoKHR-handleType-parameter"]) + })?; - #[cfg(unix)] - { - handle_type.validate_device(device).map_err(|err| { - err.add_context("handle_type") - .set_vuids(&["VUID-VkImportMemoryFdInfoKHR-handleType-parameter"]) - })?; - - match handle_type { - ExternalMemoryHandleType::OpaqueFd => { - // VUID-VkMemoryAllocateInfo-allocationSize-01742 - // Can't validate, must be ensured by user - - // VUID-VkMemoryDedicatedAllocateInfo-buffer-01879 - // Can't validate, must be ensured by user - - // VUID-VkMemoryDedicatedAllocateInfo-image-01878 - // Can't validate, must be ensured by user - } - ExternalMemoryHandleType::DmaBuf => {} - _ => { - return Err(Box::new(ValidationError { - context: "handle_type".into(), - problem: "is not `ExternalMemoryHandleType::OpaqueFd` or \ - `ExternalMemoryHandleType::DmaBuf`" - .into(), - vuids: &["VUID-VkImportMemoryFdInfoKHR-handleType-00669"], - ..Default::default() - })); - } - } + match handle_type { + ExternalMemoryHandleType::OpaqueFd => { + // VUID-VkMemoryAllocateInfo-allocationSize-01742 + // Can't validate, must be ensured by user - // VUID-VkMemoryAllocateInfo-memoryTypeIndex-00648 - // Can't validate, must be ensured by user + // VUID-VkMemoryDedicatedAllocateInfo-buffer-01879 + // Can't validate, must be ensured by user + + // VUID-VkMemoryDedicatedAllocateInfo-image-01878 + // Can't validate, must be ensured by user + } + ExternalMemoryHandleType::DmaBuf => {} + _ => { + return Err(Box::new(ValidationError { + context: "handle_type".into(), + problem: "is not `ExternalMemoryHandleType::OpaqueFd` or \ + `ExternalMemoryHandleType::DmaBuf`" + .into(), + vuids: &["VUID-VkImportMemoryFdInfoKHR-handleType-00669"], + ..Default::default() + })); + } } + + // VUID-VkMemoryAllocateInfo-memoryTypeIndex-00648 + // Can't validate, must be ensured by user } MemoryImportInfo::Win32 { - #[cfg(windows)] handle_type, - #[cfg(not(windows))] - handle_type: _, handle: _, } => { if !device.enabled_extensions().khr_external_memory_win32 { @@ -1245,46 +1239,37 @@ impl MemoryImportInfo { })); } - #[cfg(not(windows))] - unreachable!( - "`khr_external_memory_win32` was somehow enabled on a non-Windows system" - ); + handle_type.validate_device(device).map_err(|err| { + err.add_context("handle_type") + .set_vuids(&["VUID-VkImportMemoryWin32HandleInfoKHR-handleType-parameter"]) + })?; - #[cfg(windows)] - { - handle_type.validate_device(device).map_err(|err| { - err.add_context("handle_type").set_vuids(&[ - "VUID-VkImportMemoryWin32HandleInfoKHR-handleType-parameter", - ]) - })?; - - match handle_type { - ExternalMemoryHandleType::OpaqueWin32 - | ExternalMemoryHandleType::OpaqueWin32Kmt => { - // VUID-VkMemoryAllocateInfo-allocationSize-01742 - // Can't validate, must be ensured by user - - // VUID-VkMemoryDedicatedAllocateInfo-buffer-01879 - // Can't validate, must be ensured by user - - // VUID-VkMemoryDedicatedAllocateInfo-image-01878 - // Can't validate, must be ensured by user - } - _ => { - return Err(Box::new(ValidationError { - context: "handle_type".into(), - problem: "is not `ExternalMemoryHandleType::OpaqueWin32` or \ - `ExternalMemoryHandleType::OpaqueWin32Kmt`" - .into(), - vuids: &["VUID-VkImportMemoryWin32HandleInfoKHR-handleType-00660"], - ..Default::default() - })); - } - } + match handle_type { + ExternalMemoryHandleType::OpaqueWin32 + | ExternalMemoryHandleType::OpaqueWin32Kmt => { + // VUID-VkMemoryAllocateInfo-allocationSize-01742 + // Can't validate, must be ensured by user + + // VUID-VkMemoryDedicatedAllocateInfo-buffer-01879 + // Can't validate, must be ensured by user - // VUID-VkMemoryAllocateInfo-memoryTypeIndex-00645 - // Can't validate, must be ensured by user + // VUID-VkMemoryDedicatedAllocateInfo-image-01878 + // Can't validate, must be ensured by user + } + _ => { + return Err(Box::new(ValidationError { + context: "handle_type".into(), + problem: "is not `ExternalMemoryHandleType::OpaqueWin32` or \ + `ExternalMemoryHandleType::OpaqueWin32Kmt`" + .into(), + vuids: &["VUID-VkImportMemoryWin32HandleInfoKHR-handleType-00660"], + ..Default::default() + })); + } } + + // VUID-VkMemoryAllocateInfo-memoryTypeIndex-00645 + // Can't validate, must be ensured by user } } diff --git a/vulkano/src/sync/fence.rs b/vulkano/src/sync/fence.rs index b40f210cc4..b8c629b1fe 100644 --- a/vulkano/src/sync/fence.rs +++ b/vulkano/src/sync/fence.rs @@ -19,7 +19,6 @@ use crate::{ }; use parking_lot::{Mutex, MutexGuard}; use smallvec::SmallVec; -#[cfg(unix)] use std::fs::File; use std::{ future::Future, @@ -58,11 +57,11 @@ pub struct Fence { handle: ash::vk::Fence, device: InstanceOwnedDebugWrapper>, id: NonZeroU64, - must_put_in_pool: bool, flags: FenceCreateFlags, export_handle_types: ExternalFenceHandleTypes, + must_put_in_pool: bool, state: Mutex, } @@ -137,11 +136,11 @@ impl Fence { handle, device: InstanceOwnedDebugWrapper(device), id: Self::next_id(), - must_put_in_pool: false, flags, export_handle_types, + must_put_in_pool: false, state: Mutex::new(FenceState { is_signaled: flags.intersects(FenceCreateFlags::SIGNALED), ..Default::default() @@ -172,11 +171,11 @@ impl Fence { handle, device: InstanceOwnedDebugWrapper(device), id: Self::next_id(), - must_put_in_pool: true, flags: FenceCreateFlags::empty(), export_handle_types: ExternalFenceHandleTypes::empty(), + must_put_in_pool: true, state: Mutex::new(Default::default()), } } @@ -214,11 +213,11 @@ impl Fence { handle, device: InstanceOwnedDebugWrapper(device), id: Self::next_id(), - must_put_in_pool: false, flags, export_handle_types, + must_put_in_pool: false, state: Mutex::new(FenceState { is_signaled: flags.intersects(FenceCreateFlags::SIGNALED), ..Default::default() @@ -232,6 +231,12 @@ impl Fence { self.flags } + /// Returns the handle types that can be exported from the fence. + #[inline] + pub fn export_handle_types(&self) -> ExternalFenceHandleTypes { + self.export_handle_types + } + /// Returns true if the fence is signaled. #[inline] pub fn is_signaled(&self) -> Result { @@ -547,7 +552,6 @@ impl Fence { /// /// The [`khr_external_fence_fd`](crate::device::DeviceExtensions::khr_external_fence_fd) /// extension must be enabled on the device. - #[cfg(unix)] #[inline] pub fn export_fd( &self, @@ -559,7 +563,6 @@ impl Fence { unsafe { Ok(self.export_fd_unchecked_locked(handle_type, &mut state)?) } } - #[cfg(unix)] fn validate_export_fd( &self, handle_type: ExternalFenceHandleType, @@ -654,7 +657,6 @@ impl Fence { Ok(()) } - #[cfg(unix)] #[cfg_attr(not(feature = "document_unchecked"), doc(hidden))] #[inline] pub unsafe fn export_fd_unchecked( @@ -665,14 +667,11 @@ impl Fence { self.export_fd_unchecked_locked(handle_type, &mut state) } - #[cfg(unix)] unsafe fn export_fd_unchecked_locked( &self, handle_type: ExternalFenceHandleType, state: &mut FenceState, ) -> Result { - use std::os::unix::io::FromRawFd; - let info_vk = ash::vk::FenceGetFdInfoKHR { fence: self.handle, handle_type: handle_type.into(), @@ -691,14 +690,23 @@ impl Fence { state.export(handle_type); - Ok(File::from_raw_fd(output.assume_init())) + #[cfg(unix)] + { + use std::os::unix::io::FromRawFd; + Ok(File::from_raw_fd(output.assume_init())) + } + + #[cfg(not(unix))] + { + let _ = output; + unreachable!("`khr_external_fence_fd` was somehow enabled on a non-Unix system"); + } } /// Exports the fence into a Win32 handle. /// /// The [`khr_external_fence_win32`](crate::device::DeviceExtensions::khr_external_fence_win32) /// extension must be enabled on the device. - #[cfg(windows)] #[inline] pub fn export_win32_handle( &self, @@ -710,7 +718,6 @@ impl Fence { unsafe { Ok(self.export_win32_handle_unchecked_locked(handle_type, &mut state)?) } } - #[cfg(windows)] fn validate_export_win32_handle( &self, handle_type: ExternalFenceHandleType, @@ -817,7 +824,6 @@ impl Fence { Ok(()) } - #[cfg(windows)] #[cfg_attr(not(feature = "document_unchecked"), doc(hidden))] #[inline] pub unsafe fn export_win32_handle_unchecked( @@ -828,7 +834,6 @@ impl Fence { self.export_win32_handle_unchecked_locked(handle_type, &mut state) } - #[cfg(windows)] unsafe fn export_win32_handle_unchecked_locked( &self, handle_type: ExternalFenceHandleType, @@ -865,7 +870,6 @@ impl Fence { /// - If in `import_fence_fd_info`, `handle_type` is `ExternalHandleType::OpaqueFd`, /// then `file` must represent a fence that was exported from Vulkan or a compatible API, /// with a driver and device UUID equal to those of the device that owns `self`. - #[cfg(unix)] #[inline] pub unsafe fn import_fd( &self, @@ -877,7 +881,6 @@ impl Fence { Ok(self.import_fd_unchecked_locked(import_fence_fd_info, &mut state)?) } - #[cfg(unix)] fn validate_import_fd( &self, import_fence_fd_info: &ImportFenceFdInfo, @@ -907,7 +910,6 @@ impl Fence { Ok(()) } - #[cfg(unix)] #[cfg_attr(not(feature = "document_unchecked"), doc(hidden))] #[inline] pub unsafe fn import_fd_unchecked( @@ -918,14 +920,11 @@ impl Fence { self.import_fd_unchecked_locked(import_fence_fd_info, &mut state) } - #[cfg(unix)] unsafe fn import_fd_unchecked_locked( &self, import_fence_fd_info: ImportFenceFdInfo, state: &mut FenceState, ) -> Result<(), VulkanError> { - use std::os::unix::io::IntoRawFd; - let ImportFenceFdInfo { flags, handle_type, @@ -933,11 +932,23 @@ impl Fence { _ne: _, } = import_fence_fd_info; + #[cfg(unix)] + let fd = { + use std::os::fd::IntoRawFd; + file.map_or(-1, |file| file.into_raw_fd()) + }; + + #[cfg(not(unix))] + let fd = { + let _ = file; + -1 + }; + let info_vk = ash::vk::ImportFenceFdInfoKHR { fence: self.handle, flags: flags.into(), handle_type: handle_type.into(), - fd: file.map_or(-1, |file| file.into_raw_fd()), + fd, ..Default::default() }; @@ -961,7 +972,6 @@ impl Fence { /// - In `import_fence_win32_handle_info`, `handle` must represent a fence that was exported /// from Vulkan or a compatible API, with a driver and device UUID equal to those of the /// device that owns `self`. - #[cfg(windows)] #[inline] pub unsafe fn import_win32_handle( &self, @@ -973,7 +983,6 @@ impl Fence { Ok(self.import_win32_handle_unchecked_locked(import_fence_win32_handle_info, &mut state)?) } - #[cfg(windows)] fn validate_import_win32_handle( &self, import_fence_win32_handle_info: &ImportFenceWin32HandleInfo, @@ -996,10 +1005,13 @@ impl Fence { })); } + import_fence_win32_handle_info + .validate(&self.device) + .map_err(|err| err.add_context("import_fence_win32_handle_info"))?; + Ok(()) } - #[cfg(windows)] #[cfg_attr(not(feature = "document_unchecked"), doc(hidden))] #[inline] pub unsafe fn import_win32_handle_unchecked( @@ -1010,7 +1022,6 @@ impl Fence { self.import_win32_handle_unchecked_locked(import_fence_win32_handle_info, &mut state) } - #[cfg(windows)] unsafe fn import_win32_handle_unchecked_locked( &self, import_fence_win32_handle_info: ImportFenceWin32HandleInfo, @@ -1283,7 +1294,6 @@ vulkan_bitflags! { TEMPORARY = TEMPORARY, } -#[cfg(unix)] #[derive(Debug)] pub struct ImportFenceFdInfo { /// Additional parameters for the import operation. @@ -1311,7 +1321,6 @@ pub struct ImportFenceFdInfo { pub _ne: crate::NonExhaustive, } -#[cfg(unix)] impl ImportFenceFdInfo { /// Returns an `ImportFenceFdInfo` with the specified `handle_type`. #[inline] @@ -1373,7 +1382,6 @@ impl ImportFenceFdInfo { } } -#[cfg(windows)] #[derive(Debug)] pub struct ImportFenceWin32HandleInfo { /// Additional parameters for the import operation. @@ -1396,7 +1404,6 @@ pub struct ImportFenceWin32HandleInfo { pub _ne: crate::NonExhaustive, } -#[cfg(windows)] impl ImportFenceWin32HandleInfo { /// Returns an `ImportFenceWin32HandleInfo` with the specified `handle_type`. #[inline] diff --git a/vulkano/src/sync/semaphore.rs b/vulkano/src/sync/semaphore.rs index d19c48b865..ab145014c8 100644 --- a/vulkano/src/sync/semaphore.rs +++ b/vulkano/src/sync/semaphore.rs @@ -18,9 +18,8 @@ use crate::{ VulkanObject, }; use parking_lot::{Mutex, MutexGuard}; -#[cfg(unix)] -use std::fs::File; use std::{ + fs::File, mem::MaybeUninit, num::NonZeroU64, ptr, @@ -36,10 +35,10 @@ pub struct Semaphore { handle: ash::vk::Semaphore, device: InstanceOwnedDebugWrapper>, id: NonZeroU64, - must_put_in_pool: bool, export_handle_types: ExternalSemaphoreHandleTypes, + must_put_in_pool: bool, state: Mutex, } @@ -125,8 +124,10 @@ impl Semaphore { handle, device: InstanceOwnedDebugWrapper(device), id: Self::next_id(), - must_put_in_pool: true, + export_handle_types: ExternalSemaphoreHandleTypes::empty(), + + must_put_in_pool: true, state: Mutex::new(Default::default()), }, None => { @@ -162,14 +163,21 @@ impl Semaphore { handle, device: InstanceOwnedDebugWrapper(device), id: Self::next_id(), - must_put_in_pool: false, + export_handle_types, + + must_put_in_pool: false, state: Mutex::new(Default::default()), } } + /// Returns the handle types that can be exported from the semaphore. + #[inline] + pub fn export_handle_types(&self) -> ExternalSemaphoreHandleTypes { + self.export_handle_types + } + /// Exports the semaphore into a POSIX file descriptor. The caller owns the returned `File`. - #[cfg(unix)] #[inline] pub fn export_fd( &self, @@ -181,7 +189,6 @@ impl Semaphore { unsafe { Ok(self.export_fd_unchecked_locked(handle_type, &mut state)?) } } - #[cfg(unix)] fn validate_export_fd( &self, handle_type: ExternalSemaphoreHandleType, @@ -289,7 +296,6 @@ impl Semaphore { Ok(()) } - #[cfg(unix)] #[cfg_attr(not(feature = "document_unchecked"), doc(hidden))] #[inline] pub unsafe fn export_fd_unchecked( @@ -300,15 +306,12 @@ impl Semaphore { self.export_fd_unchecked_locked(handle_type, &mut state) } - #[cfg(unix)] unsafe fn export_fd_unchecked_locked( &self, handle_type: ExternalSemaphoreHandleType, state: &mut SemaphoreState, ) -> Result { - use std::os::unix::io::FromRawFd; - - let info = ash::vk::SemaphoreGetFdInfoKHR { + let info_vk = ash::vk::SemaphoreGetFdInfoKHR { semaphore: self.handle, handle_type: handle_type.into(), ..Default::default() @@ -318,7 +321,7 @@ impl Semaphore { let fns = self.device.fns(); (fns.khr_external_semaphore_fd.get_semaphore_fd_khr)( self.device.handle(), - &info, + &info_vk, output.as_mut_ptr(), ) .result() @@ -326,14 +329,23 @@ impl Semaphore { state.export(handle_type); - Ok(File::from_raw_fd(output.assume_init())) + #[cfg(unix)] + { + use std::os::unix::io::FromRawFd; + Ok(File::from_raw_fd(output.assume_init())) + } + + #[cfg(not(unix))] + { + let _ = output; + unreachable!("`khr_external_semaphore_fd` was somehow enabled on a non-Unix system"); + } } /// Exports the semaphore into a Win32 handle. /// /// The [`khr_external_semaphore_win32`](crate::device::DeviceExtensions::khr_external_semaphore_win32) /// extension must be enabled on the device. - #[cfg(windows)] #[inline] pub fn export_win32_handle( &self, @@ -345,7 +357,6 @@ impl Semaphore { unsafe { Ok(self.export_win32_handle_unchecked_locked(handle_type, &mut state)?) } } - #[cfg(windows)] fn validate_export_win32_handle( &self, handle_type: ExternalSemaphoreHandleType, @@ -472,7 +483,6 @@ impl Semaphore { Ok(()) } - #[cfg(windows)] #[cfg_attr(not(feature = "document_unchecked"), doc(hidden))] #[inline] pub unsafe fn export_win32_handle_unchecked( @@ -483,7 +493,6 @@ impl Semaphore { self.export_win32_handle_unchecked_locked(handle_type, &mut state) } - #[cfg(windows)] unsafe fn export_win32_handle_unchecked_locked( &self, handle_type: ExternalSemaphoreHandleType, @@ -510,7 +519,6 @@ impl Semaphore { } /// Exports the semaphore into a Zircon event handle. - #[cfg(target_os = "fuchsia")] #[inline] pub fn export_zircon_handle( &self, @@ -522,7 +530,6 @@ impl Semaphore { unsafe { Ok(self.export_zircon_handle_unchecked_locked(handle_type, &mut state)?) } } - #[cfg(target_os = "fuchsia")] fn validate_export_zircon_handle( &self, handle_type: ExternalSemaphoreHandleType, @@ -551,7 +558,7 @@ impl Semaphore { })); } - if !self.export_handle_types.intersects(&handle_type.into()) { + if !self.export_handle_types.intersects(handle_type.into()) { return Err(Box::new(ValidationError { problem: "`self.export_handle_types()` does not contain `handle_type`".into(), vuids: &["VUID-VkSemaphoreGetZirconHandleInfoFUCHSIA-handleType-04758"], @@ -581,7 +588,7 @@ impl Semaphore { if !external_semaphore_properties .export_from_imported_handle_types - .intersects(&imported_handle_type.into()) + .intersects(imported_handle_type.into()) { return Err(Box::new(ValidationError { problem: "the semaphore currently has an imported payload, whose type \ @@ -622,7 +629,6 @@ impl Semaphore { Ok(()) } - #[cfg(target_os = "fuchsia")] #[cfg_attr(not(feature = "document_unchecked"), doc(hidden))] #[inline] pub unsafe fn export_zircon_handle_unchecked( @@ -633,13 +639,12 @@ impl Semaphore { self.export_zircon_handle_unchecked_locked(handle_type, &mut state) } - #[cfg(target_os = "fuchsia")] unsafe fn export_zircon_handle_unchecked_locked( &self, handle_type: ExternalSemaphoreHandleType, state: &mut SemaphoreState, ) -> Result { - let info = ash::vk::SemaphoreGetZirconHandleInfoFUCHSIA { + let info_vk = ash::vk::SemaphoreGetZirconHandleInfoFUCHSIA { semaphore: self.handle, handle_type: handle_type.into(), ..Default::default() @@ -649,7 +654,9 @@ impl Semaphore { let fns = self.device.fns(); (fns.fuchsia_external_semaphore .get_semaphore_zircon_handle_fuchsia)( - self.device.handle(), &info, output.as_mut_ptr() + self.device.handle(), + &info_vk, + output.as_mut_ptr(), ) .result() .map_err(VulkanError::from)?; @@ -670,7 +677,6 @@ impl Semaphore { /// then `file` must represent a binary semaphore that was exported from Vulkan or a /// compatible API, with a driver and device UUID equal to those of the device that owns /// `self`. - #[cfg(unix)] #[inline] pub unsafe fn import_fd( &self, @@ -682,7 +688,6 @@ impl Semaphore { Ok(self.import_fd_unchecked_locked(import_semaphore_fd_info, &mut state)?) } - #[cfg(unix)] fn validate_import_fd( &self, import_semaphore_fd_info: &ImportSemaphoreFdInfo, @@ -712,7 +717,6 @@ impl Semaphore { Ok(()) } - #[cfg(unix)] #[cfg_attr(not(feature = "document_unchecked"), doc(hidden))] #[inline] pub unsafe fn import_fd_unchecked( @@ -723,14 +727,11 @@ impl Semaphore { self.import_fd_unchecked_locked(import_semaphore_fd_info, &mut state) } - #[cfg(unix)] unsafe fn import_fd_unchecked_locked( &self, import_semaphore_fd_info: ImportSemaphoreFdInfo, state: &mut SemaphoreState, ) -> Result<(), VulkanError> { - use std::os::unix::io::IntoRawFd; - let ImportSemaphoreFdInfo { flags, handle_type, @@ -738,11 +739,23 @@ impl Semaphore { _ne: _, } = import_semaphore_fd_info; + #[cfg(unix)] + let fd = { + use std::os::fd::IntoRawFd; + file.map_or(-1, |file| file.into_raw_fd()) + }; + + #[cfg(not(unix))] + let fd = { + let _ = file; + -1 + }; + let info_vk = ash::vk::ImportSemaphoreFdInfoKHR { semaphore: self.handle, flags: flags.into(), handle_type: handle_type.into(), - fd: file.map_or(-1, |file| file.into_raw_fd()), + fd, ..Default::default() }; @@ -769,7 +782,6 @@ impl Semaphore { /// - In `import_semaphore_win32_handle_info`, `handle` must represent a binary semaphore that /// was exported from Vulkan or a compatible API, with a driver and device UUID equal to /// those of the device that owns `self`. - #[cfg(windows)] #[inline] pub unsafe fn import_win32_handle( &self, @@ -782,7 +794,6 @@ impl Semaphore { .import_win32_handle_unchecked_locked(import_semaphore_win32_handle_info, &mut state)?) } - #[cfg(windows)] fn validate_import_win32_handle( &self, import_semaphore_win32_handle_info: &ImportSemaphoreWin32HandleInfo, @@ -816,7 +827,6 @@ impl Semaphore { Ok(()) } - #[cfg(windows)] #[cfg_attr(not(feature = "document_unchecked"), doc(hidden))] #[inline] pub unsafe fn import_win32_handle_unchecked( @@ -827,7 +837,6 @@ impl Semaphore { self.import_win32_handle_unchecked_locked(import_semaphore_win32_handle_info, &mut state) } - #[cfg(windows)] unsafe fn import_win32_handle_unchecked_locked( &self, import_semaphore_win32_handle_info: ImportSemaphoreWin32HandleInfo, @@ -872,7 +881,6 @@ impl Semaphore { /// /// - In `import_semaphore_zircon_handle_info`, `zircon_handle` must have `ZX_RIGHTS_BASIC` and /// `ZX_RIGHTS_SIGNAL`. - #[cfg(target_os = "fuchsia")] #[inline] pub unsafe fn import_zircon_handle( &self, @@ -887,7 +895,6 @@ impl Semaphore { )?) } - #[cfg(target_os = "fuchsia")] fn validate_import_zircon_handle( &self, import_semaphore_zircon_handle_info: &ImportSemaphoreZirconHandleInfo, @@ -917,7 +924,6 @@ impl Semaphore { Ok(()) } - #[cfg(target_os = "fuchsia")] #[cfg_attr(not(feature = "document_unchecked"), doc(hidden))] #[inline] pub unsafe fn import_zircon_handle_unchecked( @@ -928,7 +934,6 @@ impl Semaphore { self.import_zircon_handle_unchecked_locked(import_semaphore_zircon_handle_info, &mut state) } - #[cfg(target_os = "fuchsia")] unsafe fn import_zircon_handle_unchecked_locked( &self, import_semaphore_zircon_handle_info: ImportSemaphoreZirconHandleInfo, @@ -1001,136 +1006,6 @@ unsafe impl DeviceOwned for Semaphore { impl_id_counter!(Semaphore); -#[derive(Debug, Default)] -pub(crate) struct SemaphoreState { - is_signaled: bool, - pending_signal: Option, - pending_wait: Option>, - - reference_exported: bool, - exported_handle_types: ExternalSemaphoreHandleTypes, - current_import: Option, - permanent_import: Option, -} - -impl SemaphoreState { - /// If the semaphore does not have a pending operation and has no external references, - /// returns the current status. - #[inline] - fn is_signaled(&self) -> Option { - // If any of these is true, we can't be certain of the status. - if self.pending_signal.is_some() - || self.pending_wait.is_some() - || self.has_external_reference() - { - None - } else { - Some(self.is_signaled) - } - } - - #[inline] - fn is_signal_pending(&self) -> bool { - self.pending_signal.is_some() - } - - #[inline] - fn is_wait_pending(&self) -> bool { - self.pending_wait.is_some() - } - - #[inline] - fn is_in_queue(&self) -> bool { - matches!(self.pending_signal, Some(SignalType::Queue(_))) || self.pending_wait.is_some() - } - - /// Returns whether there are any potential external references to the semaphore payload. - /// That is, the semaphore has been exported by reference transference, or imported. - #[inline] - fn has_external_reference(&self) -> bool { - self.reference_exported || self.current_import.is_some() - } - - #[allow(dead_code)] - #[inline] - fn is_exported(&self, handle_type: ExternalSemaphoreHandleType) -> bool { - self.exported_handle_types.intersects(handle_type.into()) - } - - #[inline] - pub(crate) unsafe fn add_queue_signal(&mut self, queue: &Arc) { - self.pending_signal = Some(SignalType::Queue(Arc::downgrade(queue))); - } - - #[inline] - pub(crate) unsafe fn add_queue_wait(&mut self, queue: &Arc) { - self.pending_wait = Some(Arc::downgrade(queue)); - } - - /// Called when a queue is unlocking resources. - #[inline] - pub(crate) unsafe fn set_signal_finished(&mut self) { - self.pending_signal = None; - self.is_signaled = true; - } - - /// Called when a queue is unlocking resources. - #[inline] - pub(crate) unsafe fn set_wait_finished(&mut self) { - self.pending_wait = None; - self.current_import = self.permanent_import.map(Into::into); - self.is_signaled = false; - } - - #[allow(dead_code)] - #[inline] - unsafe fn export(&mut self, handle_type: ExternalSemaphoreHandleType) { - self.exported_handle_types |= handle_type.into(); - - if handle_type.has_copy_transference() { - self.current_import = self.permanent_import.map(Into::into); - self.is_signaled = false; - } else { - self.reference_exported = true; - } - } - - #[allow(dead_code)] - #[inline] - unsafe fn import(&mut self, handle_type: ExternalSemaphoreHandleType, temporary: bool) { - self.current_import = Some(handle_type.into()); - - if !temporary { - self.permanent_import = Some(handle_type); - } - } - - #[inline] - pub(crate) unsafe fn swapchain_acquire(&mut self) { - self.pending_signal = Some(SignalType::SwapchainAcquire); - self.current_import = Some(ImportType::SwapchainAcquire); - } -} - -#[derive(Clone, Debug)] -enum SignalType { - Queue(Weak), - SwapchainAcquire, -} - -#[derive(Clone, Copy, Debug)] -enum ImportType { - SwapchainAcquire, - ExternalSemaphore(ExternalSemaphoreHandleType), -} - -impl From for ImportType { - #[inline] - fn from(handle_type: ExternalSemaphoreHandleType) -> Self { - Self::ExternalSemaphore(handle_type) - } -} - /// Parameters to create a new `Semaphore`. #[derive(Clone, Debug)] pub struct SemaphoreCreateInfo { @@ -1302,7 +1177,6 @@ vulkan_bitflags! { TEMPORARY = TEMPORARY, } -#[cfg(unix)] #[derive(Debug)] pub struct ImportSemaphoreFdInfo { /// Additional parameters for the import operation. @@ -1330,7 +1204,6 @@ pub struct ImportSemaphoreFdInfo { pub _ne: crate::NonExhaustive, } -#[cfg(unix)] impl ImportSemaphoreFdInfo { /// Returns an `ImportSemaphoreFdInfo` with the specified `handle_type`. #[inline] @@ -1394,7 +1267,6 @@ impl ImportSemaphoreFdInfo { } } -#[cfg(windows)] #[derive(Debug)] pub struct ImportSemaphoreWin32HandleInfo { /// Additional parameters for the import operation. @@ -1417,7 +1289,6 @@ pub struct ImportSemaphoreWin32HandleInfo { pub _ne: crate::NonExhaustive, } -#[cfg(windows)] impl ImportSemaphoreWin32HandleInfo { /// Returns an `ImportSemaphoreWin32HandleInfo` with the specified `handle_type`. #[inline] @@ -1483,7 +1354,6 @@ impl ImportSemaphoreWin32HandleInfo { } } -#[cfg(target_os = "fuchsia")] #[derive(Debug)] pub struct ImportSemaphoreZirconHandleInfo { /// Additional parameters for the import operation. @@ -1506,7 +1376,6 @@ pub struct ImportSemaphoreZirconHandleInfo { pub _ne: crate::NonExhaustive, } -#[cfg(target_os = "fuchsia")] impl ImportSemaphoreZirconHandleInfo { /// Returns an `ImportSemaphoreZirconHandleInfo` with the specified `handle_type`. #[inline] @@ -1570,6 +1439,8 @@ impl ImportSemaphoreZirconHandleInfo { #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct ExternalSemaphoreInfo { /// The external handle type that will be used with the semaphore. + /// + /// There is no default value. pub handle_type: ExternalSemaphoreHandleType, pub _ne: crate::NonExhaustive, @@ -1627,18 +1498,147 @@ pub struct ExternalSemaphoreProperties { pub compatible_handle_types: ExternalSemaphoreHandleTypes, } +#[derive(Debug, Default)] +pub(crate) struct SemaphoreState { + is_signaled: bool, + pending_signal: Option, + pending_wait: Option>, + + reference_exported: bool, + exported_handle_types: ExternalSemaphoreHandleTypes, + current_import: Option, + permanent_import: Option, +} + +impl SemaphoreState { + /// If the semaphore does not have a pending operation and has no external references, + /// returns the current status. + #[inline] + fn is_signaled(&self) -> Option { + // If any of these is true, we can't be certain of the status. + if self.pending_signal.is_some() + || self.pending_wait.is_some() + || self.has_external_reference() + { + None + } else { + Some(self.is_signaled) + } + } + + #[inline] + fn is_signal_pending(&self) -> bool { + self.pending_signal.is_some() + } + + #[inline] + fn is_wait_pending(&self) -> bool { + self.pending_wait.is_some() + } + + #[inline] + fn is_in_queue(&self) -> bool { + matches!(self.pending_signal, Some(SignalType::Queue(_))) || self.pending_wait.is_some() + } + + /// Returns whether there are any potential external references to the semaphore payload. + /// That is, the semaphore has been exported by reference transference, or imported. + #[inline] + fn has_external_reference(&self) -> bool { + self.reference_exported || self.current_import.is_some() + } + + #[allow(dead_code)] + #[inline] + fn is_exported(&self, handle_type: ExternalSemaphoreHandleType) -> bool { + self.exported_handle_types.intersects(handle_type.into()) + } + + #[inline] + pub(crate) unsafe fn add_queue_signal(&mut self, queue: &Arc) { + self.pending_signal = Some(SignalType::Queue(Arc::downgrade(queue))); + } + + #[inline] + pub(crate) unsafe fn add_queue_wait(&mut self, queue: &Arc) { + self.pending_wait = Some(Arc::downgrade(queue)); + } + + /// Called when a queue is unlocking resources. + #[inline] + pub(crate) unsafe fn set_signal_finished(&mut self) { + self.pending_signal = None; + self.is_signaled = true; + } + + /// Called when a queue is unlocking resources. + #[inline] + pub(crate) unsafe fn set_wait_finished(&mut self) { + self.pending_wait = None; + self.current_import = self.permanent_import.map(Into::into); + self.is_signaled = false; + } + + #[allow(dead_code)] + #[inline] + unsafe fn export(&mut self, handle_type: ExternalSemaphoreHandleType) { + self.exported_handle_types |= handle_type.into(); + + if handle_type.has_copy_transference() { + self.current_import = self.permanent_import.map(Into::into); + self.is_signaled = false; + } else { + self.reference_exported = true; + } + } + + #[allow(dead_code)] + #[inline] + unsafe fn import(&mut self, handle_type: ExternalSemaphoreHandleType, temporary: bool) { + self.current_import = Some(handle_type.into()); + + if !temporary { + self.permanent_import = Some(handle_type); + } + } + + #[inline] + pub(crate) unsafe fn swapchain_acquire(&mut self) { + self.pending_signal = Some(SignalType::SwapchainAcquire); + self.current_import = Some(ImportType::SwapchainAcquire); + } +} + +#[derive(Clone, Debug)] +enum SignalType { + Queue(Weak), + SwapchainAcquire, +} + +#[derive(Clone, Copy, Debug)] +enum ImportType { + SwapchainAcquire, + ExternalSemaphore(ExternalSemaphoreHandleType), +} + +impl From for ImportType { + #[inline] + fn from(handle_type: ExternalSemaphoreHandleType) -> Self { + Self::ExternalSemaphore(handle_type) + } +} + #[cfg(test)] mod tests { - #[cfg(unix)] use crate::{ device::{Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo}, instance::{Instance, InstanceCreateInfo, InstanceExtensions}, sync::semaphore::{ - ExternalSemaphoreHandleType, ExternalSemaphoreHandleTypes, SemaphoreCreateInfo, + ExternalSemaphoreHandleType, ExternalSemaphoreHandleTypes, Semaphore, + SemaphoreCreateInfo, }, - VulkanLibrary, + VulkanLibrary, VulkanObject, }; - use crate::{sync::semaphore::Semaphore, VulkanObject}; #[test] fn semaphore_create() { @@ -1664,7 +1664,6 @@ mod tests { } #[test] - #[cfg(unix)] fn semaphore_export_fd() { let library = match VulkanLibrary::new() { Ok(x) => x,