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...
This commit is contained in:
Rua 2023-10-25 11:09:18 +02:00 committed by GitHub
parent 94f0f8cc80
commit fa5d1272b2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 379 additions and 386 deletions

View File

@ -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<MemoryFdProperties, VulkanError> {
#[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.

View File

@ -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()
};
Some(ash::vk::ImportMemoryFdInfoKHR {
handle_type: handle_type.into(),
fd: file.into_raw_fd(),
..Default::default()
})
#[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()
});
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()
},
);
next.p_next = allocate_info_vk.p_next;
allocate_info_vk.p_next = next as *const _ as *const _;
}
}
_ => None,
};
#[cfg(unix)]
if let Some(info) = import_fd_info.as_mut() {
allocate_info = allocate_info.push_next(info);
}
#[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,
..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);
let next = flags_info_vk.insert(ash::vk::MemoryAllocateFlagsInfo {
flags: flags.into(),
..Default::default()
});
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<File, VulkanError> {
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<ValidationError>> {
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
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-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-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
}
// 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
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-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()
}));
}
// 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
}
// VUID-VkMemoryAllocateInfo-memoryTypeIndex-00645
// Can't validate, must be ensured by user
}
}

View File

@ -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<Arc<Device>>,
id: NonZeroU64,
must_put_in_pool: bool,
flags: FenceCreateFlags,
export_handle_types: ExternalFenceHandleTypes,
must_put_in_pool: bool,
state: Mutex<FenceState>,
}
@ -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<bool, VulkanError> {
@ -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<File, VulkanError> {
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]

View File

@ -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<Arc<Device>>,
id: NonZeroU64,
must_put_in_pool: bool,
export_handle_types: ExternalSemaphoreHandleTypes,
must_put_in_pool: bool,
state: Mutex<SemaphoreState>,
}
@ -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<File, VulkanError> {
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<ash::vk::zx_handle_t, VulkanError> {
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<SignalType>,
pending_wait: Option<Weak<Queue>>,
reference_exported: bool,
exported_handle_types: ExternalSemaphoreHandleTypes,
current_import: Option<ImportType>,
permanent_import: Option<ExternalSemaphoreHandleType>,
}
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<bool> {
// 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<Queue>) {
self.pending_signal = Some(SignalType::Queue(Arc::downgrade(queue)));
}
#[inline]
pub(crate) unsafe fn add_queue_wait(&mut self, queue: &Arc<Queue>) {
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<Queue>),
SwapchainAcquire,
}
#[derive(Clone, Copy, Debug)]
enum ImportType {
SwapchainAcquire,
ExternalSemaphore(ExternalSemaphoreHandleType),
}
impl From<ExternalSemaphoreHandleType> 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<SignalType>,
pending_wait: Option<Weak<Queue>>,
reference_exported: bool,
exported_handle_types: ExternalSemaphoreHandleTypes,
current_import: Option<ImportType>,
permanent_import: Option<ExternalSemaphoreHandleType>,
}
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<bool> {
// 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<Queue>) {
self.pending_signal = Some(SignalType::Queue(Arc::downgrade(queue)));
}
#[inline]
pub(crate) unsafe fn add_queue_wait(&mut self, queue: &Arc<Queue>) {
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<Queue>),
SwapchainAcquire,
}
#[derive(Clone, Copy, Debug)]
enum ImportType {
SwapchainAcquire,
ExternalSemaphore(ExternalSemaphoreHandleType),
}
impl From<ExternalSemaphoreHandleType> 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,