mirror of
https://github.com/vulkano-rs/vulkano.git
synced 2024-11-25 16:25:31 +00:00
Add khr_external_fence and remaining parts of khr_external_semaphore (#1972)
This commit is contained in:
parent
00c006aafa
commit
e99ad4fce5
@ -43,8 +43,8 @@ mod linux {
|
||||
sampler::{Filter, Sampler, SamplerAddressMode, SamplerCreateInfo},
|
||||
swapchain::{AcquireError, Swapchain, SwapchainCreateInfo, SwapchainCreationError},
|
||||
sync::{
|
||||
now, ExternalSemaphoreHandleTypes, FlushError, GpuFuture, PipelineStages, Semaphore,
|
||||
SemaphoreCreateInfo,
|
||||
now, ExternalSemaphoreHandleType, ExternalSemaphoreHandleTypes, FlushError, GpuFuture,
|
||||
PipelineStages, Semaphore, SemaphoreCreateInfo,
|
||||
},
|
||||
VulkanLibrary,
|
||||
};
|
||||
@ -146,8 +146,16 @@ mod linux {
|
||||
.unwrap(),
|
||||
);
|
||||
|
||||
let acquire_fd = unsafe { acquire_sem.export_opaque_fd().unwrap() };
|
||||
let release_fd = unsafe { release_sem.export_opaque_fd().unwrap() };
|
||||
let acquire_fd = unsafe {
|
||||
acquire_sem
|
||||
.export_fd(ExternalSemaphoreHandleType::OpaqueFd)
|
||||
.unwrap()
|
||||
};
|
||||
let release_fd = unsafe {
|
||||
release_sem
|
||||
.export_fd(ExternalSemaphoreHandleType::OpaqueFd)
|
||||
.unwrap()
|
||||
};
|
||||
|
||||
let barrier_clone = barrier.clone();
|
||||
let barrier_2_clone = barrier_2.clone();
|
||||
|
@ -23,7 +23,10 @@ use crate::{
|
||||
ColorSpace, FullScreenExclusive, PresentMode, SupportedSurfaceTransforms, Surface,
|
||||
SurfaceApi, SurfaceCapabilities, SurfaceInfo,
|
||||
},
|
||||
sync::{ExternalSemaphoreInfo, ExternalSemaphoreProperties},
|
||||
sync::{
|
||||
ExternalFenceInfo, ExternalFenceProperties, ExternalSemaphoreInfo,
|
||||
ExternalSemaphoreProperties,
|
||||
},
|
||||
OomError, RequirementNotMet, RequiresOneOf, Version, VulkanError, VulkanObject,
|
||||
};
|
||||
use bytemuck::cast_slice;
|
||||
@ -499,6 +502,107 @@ impl PhysicalDevice {
|
||||
}
|
||||
}
|
||||
|
||||
/// Retrieves the external handle properties supported for fences with a given
|
||||
/// configuration.
|
||||
///
|
||||
/// The instance API version must be at least 1.1, or the
|
||||
/// [`khr_external_fence_capabilities`](crate::instance::InstanceExtensions::khr_external_fence_capabilities)
|
||||
/// extension must be enabled on the instance.
|
||||
#[inline]
|
||||
pub fn external_fence_properties(
|
||||
&self,
|
||||
info: ExternalFenceInfo,
|
||||
) -> Result<ExternalFenceProperties, ExternalFenceSemaphorePropertiesError> {
|
||||
self.validate_external_fence_properties(&info)?;
|
||||
|
||||
unsafe { Ok(self.external_fence_properties_unchecked(info)) }
|
||||
}
|
||||
|
||||
fn validate_external_fence_properties(
|
||||
&self,
|
||||
info: &ExternalFenceInfo,
|
||||
) -> Result<(), ExternalFenceSemaphorePropertiesError> {
|
||||
if !(self.instance.api_version() >= Version::V1_1
|
||||
|| self
|
||||
.instance
|
||||
.enabled_extensions()
|
||||
.khr_external_fence_capabilities)
|
||||
{
|
||||
return Err(ExternalFenceSemaphorePropertiesError::RequirementNotMet {
|
||||
required_for: "`external_fence_properties`",
|
||||
requires_one_of: RequiresOneOf {
|
||||
api_version: Some(Version::V1_1),
|
||||
instance_extensions: &["khr_external_fence_capabilities"],
|
||||
..Default::default()
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
let &ExternalFenceInfo {
|
||||
handle_type,
|
||||
_ne: _,
|
||||
} = info;
|
||||
|
||||
// VUID-VkPhysicalDeviceExternalFenceInfo-handleType-parameter
|
||||
handle_type.validate_physical_device(self)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
|
||||
pub unsafe fn external_fence_properties_unchecked(
|
||||
&self,
|
||||
info: ExternalFenceInfo,
|
||||
) -> ExternalFenceProperties {
|
||||
/* Input */
|
||||
|
||||
let ExternalFenceInfo {
|
||||
handle_type,
|
||||
_ne: _,
|
||||
} = info;
|
||||
|
||||
let external_fence_info = ash::vk::PhysicalDeviceExternalFenceInfo {
|
||||
handle_type: handle_type.into(),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
/* Output */
|
||||
|
||||
let mut external_fence_properties = ash::vk::ExternalFenceProperties::default();
|
||||
|
||||
/* Call */
|
||||
|
||||
let fns = self.instance.fns();
|
||||
|
||||
if self.instance.api_version() >= Version::V1_1 {
|
||||
(fns.v1_1.get_physical_device_external_fence_properties)(
|
||||
self.handle,
|
||||
&external_fence_info,
|
||||
&mut external_fence_properties,
|
||||
)
|
||||
} else {
|
||||
(fns.khr_external_fence_capabilities
|
||||
.get_physical_device_external_fence_properties_khr)(
|
||||
self.handle,
|
||||
&external_fence_info,
|
||||
&mut external_fence_properties,
|
||||
);
|
||||
}
|
||||
|
||||
ExternalFenceProperties {
|
||||
exportable: external_fence_properties
|
||||
.external_fence_features
|
||||
.intersects(ash::vk::ExternalFenceFeatureFlags::EXPORTABLE),
|
||||
importable: external_fence_properties
|
||||
.external_fence_features
|
||||
.intersects(ash::vk::ExternalFenceFeatureFlags::IMPORTABLE),
|
||||
export_from_imported_handle_types: external_fence_properties
|
||||
.export_from_imported_handle_types
|
||||
.into(),
|
||||
compatible_handle_types: external_fence_properties.compatible_handle_types.into(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Retrieves the external handle properties supported for semaphores with a given
|
||||
/// configuration.
|
||||
///
|
||||
@ -509,7 +613,7 @@ impl PhysicalDevice {
|
||||
pub fn external_semaphore_properties(
|
||||
&self,
|
||||
info: ExternalSemaphoreInfo,
|
||||
) -> Result<ExternalSemaphoreProperties, ExternalSemaphorePropertiesError> {
|
||||
) -> Result<ExternalSemaphoreProperties, ExternalFenceSemaphorePropertiesError> {
|
||||
self.validate_external_semaphore_properties(&info)?;
|
||||
|
||||
unsafe { Ok(self.external_semaphore_properties_unchecked(info)) }
|
||||
@ -518,14 +622,14 @@ impl PhysicalDevice {
|
||||
fn validate_external_semaphore_properties(
|
||||
&self,
|
||||
info: &ExternalSemaphoreInfo,
|
||||
) -> Result<(), ExternalSemaphorePropertiesError> {
|
||||
) -> Result<(), ExternalFenceSemaphorePropertiesError> {
|
||||
if !(self.instance.api_version() >= Version::V1_1
|
||||
|| self
|
||||
.instance
|
||||
.enabled_extensions()
|
||||
.khr_external_semaphore_capabilities)
|
||||
{
|
||||
return Err(ExternalSemaphorePropertiesError::RequirementNotMet {
|
||||
return Err(ExternalFenceSemaphorePropertiesError::RequirementNotMet {
|
||||
required_for: "`external_semaphore_properties`",
|
||||
requires_one_of: RequiresOneOf {
|
||||
api_version: Some(Version::V1_1),
|
||||
@ -1977,18 +2081,18 @@ impl From<RequirementNotMet> for ExternalBufferPropertiesError {
|
||||
}
|
||||
}
|
||||
|
||||
/// Error that can happen when retrieving properties of an external semaphore.
|
||||
/// Error that can happen when retrieving properties of an external fence or semaphore.
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum ExternalSemaphorePropertiesError {
|
||||
pub enum ExternalFenceSemaphorePropertiesError {
|
||||
RequirementNotMet {
|
||||
required_for: &'static str,
|
||||
requires_one_of: RequiresOneOf,
|
||||
},
|
||||
}
|
||||
|
||||
impl Error for ExternalSemaphorePropertiesError {}
|
||||
impl Error for ExternalFenceSemaphorePropertiesError {}
|
||||
|
||||
impl Display for ExternalSemaphorePropertiesError {
|
||||
impl Display for ExternalFenceSemaphorePropertiesError {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> {
|
||||
match self {
|
||||
@ -2004,7 +2108,7 @@ impl Display for ExternalSemaphorePropertiesError {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<RequirementNotMet> for ExternalSemaphorePropertiesError {
|
||||
impl From<RequirementNotMet> for ExternalFenceSemaphorePropertiesError {
|
||||
#[inline]
|
||||
fn from(err: RequirementNotMet) -> Self {
|
||||
Self::RequirementNotMet {
|
||||
|
@ -28,8 +28,8 @@ use crate::{
|
||||
macros::vulkan_enum,
|
||||
swapchain::{SurfaceApi, SurfaceInfo, SurfaceSwapchainLock},
|
||||
sync::{
|
||||
AccessCheckError, AccessError, AccessFlags, Fence, FlushError, GpuFuture, PipelineStages,
|
||||
Semaphore, SemaphoreCreationError, Sharing,
|
||||
AccessCheckError, AccessError, AccessFlags, Fence, FenceError, FlushError, GpuFuture,
|
||||
PipelineStages, Semaphore, SemaphoreError, Sharing,
|
||||
},
|
||||
DeviceSize, OomError, RequirementNotMet, RequiresOneOf, VulkanError, VulkanObject,
|
||||
};
|
||||
@ -1717,8 +1717,11 @@ pub enum AcquireError {
|
||||
/// surface's new properties and recreate a new swapchain if you want to continue drawing.
|
||||
OutOfDate,
|
||||
|
||||
/// Error during semaphore creation
|
||||
SemaphoreError(SemaphoreCreationError),
|
||||
/// Error during fence creation.
|
||||
FenceError(FenceError),
|
||||
|
||||
/// Error during semaphore creation.
|
||||
SemaphoreError(SemaphoreError),
|
||||
}
|
||||
|
||||
impl Error for AcquireError {
|
||||
@ -1746,14 +1749,21 @@ impl Display for AcquireError {
|
||||
AcquireError::FullScreenExclusiveModeLost => {
|
||||
"the swapchain no longer has full-screen exclusivity"
|
||||
}
|
||||
AcquireError::FenceError(_) => "error creating fence",
|
||||
AcquireError::SemaphoreError(_) => "error creating semaphore",
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<SemaphoreCreationError> for AcquireError {
|
||||
fn from(err: SemaphoreCreationError) -> Self {
|
||||
impl From<FenceError> for AcquireError {
|
||||
fn from(err: FenceError) -> Self {
|
||||
AcquireError::FenceError(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<SemaphoreError> for AcquireError {
|
||||
fn from(err: SemaphoreError) -> Self {
|
||||
AcquireError::SemaphoreError(err)
|
||||
}
|
||||
}
|
||||
|
@ -9,7 +9,8 @@
|
||||
|
||||
use crate::{
|
||||
device::{Device, DeviceOwned},
|
||||
OomError, VulkanError, VulkanObject,
|
||||
macros::{vulkan_bitflags, vulkan_enum},
|
||||
OomError, RequirementNotMet, RequiresOneOf, Version, VulkanError, VulkanObject,
|
||||
};
|
||||
use smallvec::SmallVec;
|
||||
use std::{
|
||||
@ -35,6 +36,8 @@ pub struct Fence {
|
||||
handle: ash::vk::Fence,
|
||||
device: Arc<Device>,
|
||||
|
||||
_export_handle_types: ExternalFenceHandleTypes,
|
||||
|
||||
// If true, we know that the `Fence` is signaled. If false, we don't know.
|
||||
// This variable exists so that we don't need to call `vkGetFenceStatus` or `vkWaitForFences`
|
||||
// multiple times.
|
||||
@ -47,8 +50,55 @@ pub struct Fence {
|
||||
|
||||
impl Fence {
|
||||
/// Creates a new `Fence`.
|
||||
pub fn new(device: Arc<Device>, create_info: FenceCreateInfo) -> Result<Fence, OomError> {
|
||||
let FenceCreateInfo { signaled, _ne: _ } = create_info;
|
||||
#[inline]
|
||||
pub fn new(device: Arc<Device>, create_info: FenceCreateInfo) -> Result<Fence, FenceError> {
|
||||
Self::validate_new(&device, &create_info)?;
|
||||
|
||||
unsafe { Ok(Self::new_unchecked(device, create_info)?) }
|
||||
}
|
||||
|
||||
fn validate_new(device: &Device, create_info: &FenceCreateInfo) -> Result<(), FenceError> {
|
||||
let FenceCreateInfo {
|
||||
signaled: _,
|
||||
export_handle_types,
|
||||
_ne: _,
|
||||
} = create_info;
|
||||
|
||||
if !export_handle_types.is_empty() {
|
||||
if !(device.api_version() >= Version::V1_1
|
||||
|| device.enabled_extensions().khr_external_fence)
|
||||
{
|
||||
return Err(FenceError::RequirementNotMet {
|
||||
required_for: "`create_info.export_handle_types` is not empty",
|
||||
requires_one_of: RequiresOneOf {
|
||||
api_version: Some(Version::V1_1),
|
||||
device_extensions: &["khr_external_fence"],
|
||||
..Default::default()
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// VUID-VkExportFenceCreateInfo-handleTypes-01446
|
||||
export_handle_types.validate_device(device)?;
|
||||
|
||||
// VUID-VkExportFenceCreateInfo-handleTypes-01446
|
||||
// TODO: `vkGetPhysicalDeviceExternalFenceProperties` can only be called with one
|
||||
// handle type, so which one do we give it?
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
|
||||
pub unsafe fn new_unchecked(
|
||||
device: Arc<Device>,
|
||||
create_info: FenceCreateInfo,
|
||||
) -> Result<Fence, VulkanError> {
|
||||
let FenceCreateInfo {
|
||||
signaled,
|
||||
export_handle_types,
|
||||
_ne: _,
|
||||
} = create_info;
|
||||
|
||||
let mut flags = ash::vk::FenceCreateFlags::empty();
|
||||
|
||||
@ -56,17 +106,30 @@ impl Fence {
|
||||
flags |= ash::vk::FenceCreateFlags::SIGNALED;
|
||||
}
|
||||
|
||||
let create_info = ash::vk::FenceCreateInfo {
|
||||
let mut create_info_vk = ash::vk::FenceCreateInfo {
|
||||
flags,
|
||||
..Default::default()
|
||||
};
|
||||
let mut export_fence_create_info_vk = None;
|
||||
|
||||
let handle = unsafe {
|
||||
if !export_handle_types.is_empty() {
|
||||
let _ = export_fence_create_info_vk.insert(ash::vk::ExportFenceCreateInfo {
|
||||
handle_types: export_handle_types.into(),
|
||||
..Default::default()
|
||||
});
|
||||
}
|
||||
|
||||
if let Some(info) = export_fence_create_info_vk.as_mut() {
|
||||
info.p_next = create_info_vk.p_next;
|
||||
create_info_vk.p_next = info as *const _ as *const _;
|
||||
}
|
||||
|
||||
let handle = {
|
||||
let fns = device.fns();
|
||||
let mut output = MaybeUninit::uninit();
|
||||
(fns.v1_0.create_fence)(
|
||||
device.internal_object(),
|
||||
&create_info,
|
||||
&create_info_vk,
|
||||
ptr::null(),
|
||||
output.as_mut_ptr(),
|
||||
)
|
||||
@ -78,18 +141,43 @@ impl Fence {
|
||||
Ok(Fence {
|
||||
handle,
|
||||
device,
|
||||
_export_handle_types: export_handle_types,
|
||||
is_signaled: AtomicBool::new(signaled),
|
||||
must_put_in_pool: false,
|
||||
})
|
||||
}
|
||||
|
||||
/// Creates a new `Fence` from an ash-handle
|
||||
/// # Safety
|
||||
/// The `handle` has to be a valid vulkan object handle and
|
||||
/// the `create_info` must match the info used to create said object
|
||||
pub unsafe fn from_handle(
|
||||
handle: ash::vk::Fence,
|
||||
create_info: FenceCreateInfo,
|
||||
device: Arc<Device>,
|
||||
) -> Fence {
|
||||
let FenceCreateInfo {
|
||||
signaled,
|
||||
export_handle_types,
|
||||
_ne: _,
|
||||
} = create_info;
|
||||
|
||||
Fence {
|
||||
handle,
|
||||
device,
|
||||
_export_handle_types: export_handle_types,
|
||||
is_signaled: AtomicBool::new(signaled),
|
||||
must_put_in_pool: false,
|
||||
}
|
||||
}
|
||||
|
||||
/// Takes a fence from the vulkano-provided fence pool.
|
||||
/// If the pool is empty, a new fence will be created.
|
||||
/// Upon `drop`, the fence is put back into the pool.
|
||||
///
|
||||
/// For most applications, using the fence pool should be preferred,
|
||||
/// in order to avoid creating new fences every frame.
|
||||
pub fn from_pool(device: Arc<Device>) -> Result<Fence, OomError> {
|
||||
pub fn from_pool(device: Arc<Device>) -> Result<Fence, FenceError> {
|
||||
let handle = device.fence_pool().lock().pop();
|
||||
let fence = match handle {
|
||||
Some(handle) => {
|
||||
@ -104,6 +192,7 @@ impl Fence {
|
||||
Fence {
|
||||
handle,
|
||||
device,
|
||||
_export_handle_types: ExternalFenceHandleTypes::empty(),
|
||||
is_signaled: AtomicBool::new(false),
|
||||
must_put_in_pool: true,
|
||||
}
|
||||
@ -119,25 +208,6 @@ impl Fence {
|
||||
Ok(fence)
|
||||
}
|
||||
|
||||
/// Creates a new `Fence` from an ash-handle
|
||||
/// # Safety
|
||||
/// The `handle` has to be a valid vulkan object handle and
|
||||
/// the `create_info` must match the info used to create said object
|
||||
pub unsafe fn from_handle(
|
||||
handle: ash::vk::Fence,
|
||||
create_info: FenceCreateInfo,
|
||||
device: Arc<Device>,
|
||||
) -> Fence {
|
||||
let FenceCreateInfo { signaled, _ne: _ } = create_info;
|
||||
|
||||
Fence {
|
||||
handle,
|
||||
device,
|
||||
is_signaled: AtomicBool::new(signaled),
|
||||
must_put_in_pool: false,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns true if the fence is signaled.
|
||||
#[inline]
|
||||
pub fn is_signaled(&self) -> Result<bool, OomError> {
|
||||
@ -164,7 +234,7 @@ impl Fence {
|
||||
/// Returns `Ok` if the fence is now signaled. Returns `Err` if the timeout was reached instead.
|
||||
///
|
||||
/// If you pass a duration of 0, then the function will return without blocking.
|
||||
pub fn wait(&self, timeout: Option<Duration>) -> Result<(), FenceWaitError> {
|
||||
pub fn wait(&self, timeout: Option<Duration>) -> Result<(), FenceError> {
|
||||
unsafe {
|
||||
if self.is_signaled.load(Ordering::Relaxed) {
|
||||
return Ok(());
|
||||
@ -193,7 +263,7 @@ impl Fence {
|
||||
self.is_signaled.store(true, Ordering::Relaxed);
|
||||
Ok(())
|
||||
}
|
||||
ash::vk::Result::TIMEOUT => Err(FenceWaitError::Timeout),
|
||||
ash::vk::Result::TIMEOUT => Err(FenceError::Timeout),
|
||||
err => Err(VulkanError::from(err).into()),
|
||||
}
|
||||
}
|
||||
@ -204,7 +274,7 @@ impl Fence {
|
||||
/// # Panic
|
||||
///
|
||||
/// Panics if not all fences belong to the same device.
|
||||
pub fn multi_wait<'a, I>(iter: I, timeout: Option<Duration>) -> Result<(), FenceWaitError>
|
||||
pub fn multi_wait<'a, I>(iter: I, timeout: Option<Duration>) -> Result<(), FenceError>
|
||||
where
|
||||
I: IntoIterator<Item = &'a Fence>,
|
||||
{
|
||||
@ -256,7 +326,7 @@ impl Fence {
|
||||
|
||||
match result {
|
||||
ash::vk::Result::SUCCESS => Ok(()),
|
||||
ash::vk::Result::TIMEOUT => Err(FenceWaitError::Timeout),
|
||||
ash::vk::Result::TIMEOUT => Err(FenceError::Timeout),
|
||||
err => Err(VulkanError::from(err).into()),
|
||||
}
|
||||
}
|
||||
@ -377,6 +447,8 @@ pub struct FenceCreateInfo {
|
||||
/// The default value is `false`.
|
||||
pub signaled: bool,
|
||||
|
||||
pub export_handle_types: ExternalFenceHandleTypes,
|
||||
|
||||
pub _ne: crate::NonExhaustive,
|
||||
}
|
||||
|
||||
@ -385,57 +457,189 @@ impl Default for FenceCreateInfo {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
signaled: false,
|
||||
export_handle_types: ExternalFenceHandleTypes::empty(),
|
||||
_ne: crate::NonExhaustive(()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Error that can be returned when waiting on a fence.
|
||||
vulkan_enum! {
|
||||
/// The handle type used for Vulkan external fence APIs.
|
||||
#[non_exhaustive]
|
||||
ExternalFenceHandleType = ExternalFenceHandleTypeFlags(u32);
|
||||
|
||||
// TODO: document
|
||||
OpaqueFd = OPAQUE_FD,
|
||||
|
||||
// TODO: document
|
||||
OpaqueWin32 = OPAQUE_WIN32,
|
||||
|
||||
// TODO: document
|
||||
OpaqueWin32Kmt = OPAQUE_WIN32_KMT,
|
||||
|
||||
// TODO: document
|
||||
SyncFd = SYNC_FD,
|
||||
}
|
||||
|
||||
vulkan_bitflags! {
|
||||
/// A mask of multiple external fence handle types.
|
||||
#[non_exhaustive]
|
||||
ExternalFenceHandleTypes = ExternalFenceHandleTypeFlags(u32);
|
||||
|
||||
// TODO: document
|
||||
opaque_fd = OPAQUE_FD,
|
||||
|
||||
// TODO: document
|
||||
opaque_win32 = OPAQUE_WIN32,
|
||||
|
||||
// TODO: document
|
||||
opaque_win32_kmt = OPAQUE_WIN32_KMT,
|
||||
|
||||
// TODO: document
|
||||
sync_fd = SYNC_FD,
|
||||
}
|
||||
|
||||
impl From<ExternalFenceHandleType> for ExternalFenceHandleTypes {
|
||||
#[inline]
|
||||
fn from(val: ExternalFenceHandleType) -> Self {
|
||||
let mut result = Self::empty();
|
||||
|
||||
match val {
|
||||
ExternalFenceHandleType::OpaqueFd => result.opaque_fd = true,
|
||||
ExternalFenceHandleType::OpaqueWin32 => result.opaque_win32 = true,
|
||||
ExternalFenceHandleType::OpaqueWin32Kmt => result.opaque_win32_kmt = true,
|
||||
ExternalFenceHandleType::SyncFd => result.sync_fd = true,
|
||||
}
|
||||
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
vulkan_bitflags! {
|
||||
/// Additional parameters for a fence payload import.
|
||||
#[non_exhaustive]
|
||||
FenceImportFlags = FenceImportFlags(u32);
|
||||
|
||||
/// The fence payload will be imported only temporarily, regardless of the permanence of the
|
||||
/// imported handle type.
|
||||
temporary = TEMPORARY,
|
||||
}
|
||||
|
||||
/// The fence configuration to query in
|
||||
/// [`PhysicalDevice::external_fence_properties`](crate::device::physical::PhysicalDevice::external_fence_properties).
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct ExternalFenceInfo {
|
||||
/// The external handle type that will be used with the fence.
|
||||
pub handle_type: ExternalFenceHandleType,
|
||||
|
||||
pub _ne: crate::NonExhaustive,
|
||||
}
|
||||
|
||||
impl ExternalFenceInfo {
|
||||
/// Returns an `ExternalFenceInfo` with the specified `handle_type`.
|
||||
#[inline]
|
||||
pub fn handle_type(handle_type: ExternalFenceHandleType) -> Self {
|
||||
Self {
|
||||
handle_type,
|
||||
_ne: crate::NonExhaustive(()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The properties for exporting or importing external handles, when a fence is created
|
||||
/// with a specific configuration.
|
||||
#[derive(Clone, Debug)]
|
||||
#[non_exhaustive]
|
||||
pub struct ExternalFenceProperties {
|
||||
/// Whether a handle can be exported to an external source with the queried
|
||||
/// external handle type.
|
||||
pub exportable: bool,
|
||||
|
||||
/// Whether a handle can be imported from an external source with the queried
|
||||
/// external handle type.
|
||||
pub importable: bool,
|
||||
|
||||
/// Which external handle types can be re-exported after the queried external handle type has
|
||||
/// been imported.
|
||||
pub export_from_imported_handle_types: ExternalFenceHandleTypes,
|
||||
|
||||
/// Which external handle types can be enabled along with the queried external handle type
|
||||
/// when creating the fence.
|
||||
pub compatible_handle_types: ExternalFenceHandleTypes,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
pub enum FenceWaitError {
|
||||
/// Not enough memory to complete the wait.
|
||||
pub enum FenceError {
|
||||
/// Not enough memory available.
|
||||
OomError(OomError),
|
||||
|
||||
/// The device has been lost.
|
||||
DeviceLost,
|
||||
|
||||
/// The specified timeout wasn't long enough.
|
||||
Timeout,
|
||||
|
||||
/// The device has been lost.
|
||||
DeviceLostError,
|
||||
RequirementNotMet {
|
||||
required_for: &'static str,
|
||||
requires_one_of: RequiresOneOf,
|
||||
},
|
||||
}
|
||||
|
||||
impl Error for FenceWaitError {
|
||||
impl Error for FenceError {
|
||||
#[inline]
|
||||
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||
match *self {
|
||||
FenceWaitError::OomError(ref err) => Some(err),
|
||||
Self::OomError(ref err) => Some(err),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for FenceWaitError {
|
||||
#[inline]
|
||||
impl Display for FenceError {
|
||||
fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> {
|
||||
write!(
|
||||
f,
|
||||
"{}",
|
||||
match *self {
|
||||
FenceWaitError::OomError(_) => "no memory available",
|
||||
FenceWaitError::Timeout => "the timeout has been reached",
|
||||
FenceWaitError::DeviceLostError => "the device was lost",
|
||||
}
|
||||
)
|
||||
match self {
|
||||
Self::OomError(_) => write!(f, "not enough memory available"),
|
||||
Self::DeviceLost => write!(f, "the device was lost"),
|
||||
Self::Timeout => write!(f, "the timeout has been reached"),
|
||||
|
||||
Self::RequirementNotMet {
|
||||
required_for,
|
||||
requires_one_of,
|
||||
} => write!(
|
||||
f,
|
||||
"a requirement was not met for: {}; requires one of: {}",
|
||||
required_for, requires_one_of,
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<VulkanError> for FenceWaitError {
|
||||
impl From<VulkanError> for FenceError {
|
||||
#[inline]
|
||||
fn from(err: VulkanError) -> FenceWaitError {
|
||||
fn from(err: VulkanError) -> Self {
|
||||
match err {
|
||||
VulkanError::OutOfHostMemory => FenceWaitError::OomError(From::from(err)),
|
||||
VulkanError::OutOfDeviceMemory => FenceWaitError::OomError(From::from(err)),
|
||||
VulkanError::DeviceLost => FenceWaitError::DeviceLostError,
|
||||
_ => panic!("Unexpected error value"),
|
||||
e @ VulkanError::OutOfHostMemory | e @ VulkanError::OutOfDeviceMemory => {
|
||||
Self::OomError(e.into())
|
||||
}
|
||||
VulkanError::DeviceLost => Self::DeviceLost,
|
||||
_ => panic!("unexpected error: {:?}", err),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<OomError> for FenceError {
|
||||
#[inline]
|
||||
fn from(err: OomError) -> Self {
|
||||
Self::OomError(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<RequirementNotMet> for FenceError {
|
||||
#[inline]
|
||||
fn from(err: RequirementNotMet) -> Self {
|
||||
Self::RequirementNotMet {
|
||||
required_for: err.required_for,
|
||||
requires_one_of: err.requires_one_of,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -13,7 +13,7 @@ pub use self::{
|
||||
now::{now, NowFuture},
|
||||
semaphore_signal::SemaphoreSignalFuture,
|
||||
};
|
||||
use super::{AccessFlags, FenceWaitError, PipelineStages};
|
||||
use super::{AccessFlags, FenceError, PipelineStages};
|
||||
use crate::{
|
||||
buffer::sys::UnsafeBuffer,
|
||||
command_buffer::{
|
||||
@ -578,13 +578,14 @@ impl From<SubmitBindSparseError> for FlushError {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<FenceWaitError> for FlushError {
|
||||
impl From<FenceError> for FlushError {
|
||||
#[inline]
|
||||
fn from(err: FenceWaitError) -> FlushError {
|
||||
fn from(err: FenceError) -> FlushError {
|
||||
match err {
|
||||
FenceWaitError::OomError(err) => FlushError::OomError(err),
|
||||
FenceWaitError::Timeout => FlushError::Timeout,
|
||||
FenceWaitError::DeviceLostError => FlushError::DeviceLost,
|
||||
FenceError::OomError(err) => FlushError::OomError(err),
|
||||
FenceError::Timeout => FlushError::Timeout,
|
||||
FenceError::DeviceLost => FlushError::DeviceLost,
|
||||
FenceError::RequirementNotMet { .. } => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -105,7 +105,10 @@
|
||||
|
||||
pub use self::{
|
||||
event::{Event, EventCreateInfo},
|
||||
fence::{Fence, FenceCreateInfo, FenceWaitError},
|
||||
fence::{
|
||||
ExternalFenceHandleType, ExternalFenceHandleTypes, ExternalFenceInfo,
|
||||
ExternalFenceProperties, Fence, FenceCreateInfo, FenceError, FenceImportFlags,
|
||||
},
|
||||
future::{
|
||||
now, AccessCheckError, AccessError, FenceSignalFuture, FlushError, GpuFuture, JoinFuture,
|
||||
NowFuture, SemaphoreSignalFuture,
|
||||
@ -116,7 +119,8 @@ pub use self::{
|
||||
},
|
||||
semaphore::{
|
||||
ExternalSemaphoreHandleType, ExternalSemaphoreHandleTypes, ExternalSemaphoreInfo,
|
||||
ExternalSemaphoreProperties, Semaphore, SemaphoreCreateInfo, SemaphoreCreationError,
|
||||
ExternalSemaphoreProperties, Semaphore, SemaphoreCreateInfo, SemaphoreError,
|
||||
SemaphoreImportFlags,
|
||||
},
|
||||
};
|
||||
use crate::device::Queue;
|
||||
|
@ -30,18 +30,29 @@ use std::{
|
||||
pub struct Semaphore {
|
||||
handle: ash::vk::Semaphore,
|
||||
device: Arc<Device>,
|
||||
must_put_in_pool: bool,
|
||||
|
||||
export_handle_types: ExternalSemaphoreHandleTypes,
|
||||
|
||||
must_put_in_pool: bool,
|
||||
}
|
||||
|
||||
impl Semaphore {
|
||||
/// Creates a new `Semaphore`.
|
||||
#[inline]
|
||||
pub fn new(
|
||||
device: Arc<Device>,
|
||||
create_info: SemaphoreCreateInfo,
|
||||
) -> Result<Semaphore, SemaphoreCreationError> {
|
||||
let SemaphoreCreateInfo {
|
||||
) -> Result<Semaphore, SemaphoreError> {
|
||||
Self::validate_new(&device, &create_info)?;
|
||||
|
||||
unsafe { Ok(Self::new_unchecked(device, create_info)?) }
|
||||
}
|
||||
|
||||
fn validate_new(
|
||||
device: &Device,
|
||||
create_info: &SemaphoreCreateInfo,
|
||||
) -> Result<(), SemaphoreError> {
|
||||
let &SemaphoreCreateInfo {
|
||||
export_handle_types,
|
||||
_ne: _,
|
||||
} = create_info;
|
||||
@ -50,7 +61,7 @@ impl Semaphore {
|
||||
if !(device.api_version() >= Version::V1_1
|
||||
|| device.enabled_extensions().khr_external_semaphore)
|
||||
{
|
||||
return Err(SemaphoreCreationError::RequirementNotMet {
|
||||
return Err(SemaphoreError::RequirementNotMet {
|
||||
required_for: "`create_info.export_handle_types` is not empty",
|
||||
requires_one_of: RequiresOneOf {
|
||||
api_version: Some(Version::V1_1),
|
||||
@ -61,34 +72,50 @@ impl Semaphore {
|
||||
}
|
||||
|
||||
// VUID-VkExportSemaphoreCreateInfo-handleTypes-parameter
|
||||
export_handle_types.validate_device(&device)?;
|
||||
export_handle_types.validate_device(device)?;
|
||||
|
||||
// VUID-VkExportSemaphoreCreateInfo-handleTypes-01124
|
||||
// TODO: `vkGetPhysicalDeviceExternalSemaphoreProperties` can only be called with one
|
||||
// handle type, so which one do we give it?
|
||||
}
|
||||
|
||||
let mut create_info = ash::vk::SemaphoreCreateInfo::builder();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
let mut export_semaphore_create_info = if !export_handle_types.is_empty() {
|
||||
Some(ash::vk::ExportSemaphoreCreateInfo {
|
||||
#[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
|
||||
pub unsafe fn new_unchecked(
|
||||
device: Arc<Device>,
|
||||
create_info: SemaphoreCreateInfo,
|
||||
) -> Result<Semaphore, VulkanError> {
|
||||
let SemaphoreCreateInfo {
|
||||
export_handle_types,
|
||||
_ne: _,
|
||||
} = create_info;
|
||||
|
||||
let mut create_info_vk = ash::vk::SemaphoreCreateInfo {
|
||||
flags: ash::vk::SemaphoreCreateFlags::empty(),
|
||||
..Default::default()
|
||||
};
|
||||
let mut export_semaphore_create_info_vk = None;
|
||||
|
||||
if !export_handle_types.is_empty() {
|
||||
let _ = export_semaphore_create_info_vk.insert(ash::vk::ExportSemaphoreCreateInfo {
|
||||
handle_types: export_handle_types.into(),
|
||||
..Default::default()
|
||||
})
|
||||
} else {
|
||||
None
|
||||
});
|
||||
};
|
||||
|
||||
if let Some(info) = export_semaphore_create_info.as_mut() {
|
||||
create_info = create_info.push_next(info);
|
||||
if let Some(info) = export_semaphore_create_info_vk.as_mut() {
|
||||
info.p_next = create_info_vk.p_next;
|
||||
create_info_vk.p_next = info as *const _ as *const _;
|
||||
}
|
||||
|
||||
let handle = unsafe {
|
||||
let handle = {
|
||||
let fns = device.fns();
|
||||
let mut output = MaybeUninit::uninit();
|
||||
(fns.v1_0.create_semaphore)(
|
||||
device.internal_object(),
|
||||
&create_info.build(),
|
||||
&create_info_vk,
|
||||
ptr::null(),
|
||||
output.as_mut_ptr(),
|
||||
)
|
||||
@ -100,39 +127,13 @@ impl Semaphore {
|
||||
Ok(Semaphore {
|
||||
device,
|
||||
handle,
|
||||
must_put_in_pool: false,
|
||||
|
||||
export_handle_types,
|
||||
|
||||
must_put_in_pool: false,
|
||||
})
|
||||
}
|
||||
|
||||
/// Takes a semaphore from the vulkano-provided semaphore pool.
|
||||
/// If the pool is empty, a new semaphore will be allocated.
|
||||
/// Upon `drop`, the semaphore is put back into the pool.
|
||||
///
|
||||
/// For most applications, using the pool should be preferred,
|
||||
/// in order to avoid creating new semaphores every frame.
|
||||
pub fn from_pool(device: Arc<Device>) -> Result<Semaphore, SemaphoreCreationError> {
|
||||
let handle = device.semaphore_pool().lock().pop();
|
||||
let semaphore = match handle {
|
||||
Some(handle) => Semaphore {
|
||||
device,
|
||||
handle,
|
||||
must_put_in_pool: true,
|
||||
|
||||
export_handle_types: ExternalSemaphoreHandleTypes::empty(),
|
||||
},
|
||||
None => {
|
||||
// Pool is empty, alloc new semaphore
|
||||
let mut semaphore = Semaphore::new(device, Default::default())?;
|
||||
semaphore.must_put_in_pool = true;
|
||||
semaphore
|
||||
}
|
||||
};
|
||||
|
||||
Ok(semaphore)
|
||||
}
|
||||
|
||||
/// Creates a new `Semaphore` from an ash-handle
|
||||
/// # Safety
|
||||
/// The `handle` has to be a valid vulkan object handle and
|
||||
@ -150,58 +151,138 @@ impl Semaphore {
|
||||
Semaphore {
|
||||
device,
|
||||
handle,
|
||||
must_put_in_pool: false,
|
||||
|
||||
export_handle_types,
|
||||
|
||||
must_put_in_pool: false,
|
||||
}
|
||||
}
|
||||
|
||||
/// Takes a semaphore from the vulkano-provided semaphore pool.
|
||||
/// If the pool is empty, a new semaphore will be allocated.
|
||||
/// Upon `drop`, the semaphore is put back into the pool.
|
||||
///
|
||||
/// For most applications, using the pool should be preferred,
|
||||
/// in order to avoid creating new semaphores every frame.
|
||||
pub fn from_pool(device: Arc<Device>) -> Result<Semaphore, SemaphoreError> {
|
||||
let handle = device.semaphore_pool().lock().pop();
|
||||
let semaphore = match handle {
|
||||
Some(handle) => Semaphore {
|
||||
device,
|
||||
handle,
|
||||
|
||||
export_handle_types: ExternalSemaphoreHandleTypes::empty(),
|
||||
|
||||
must_put_in_pool: true,
|
||||
},
|
||||
None => {
|
||||
// Pool is empty, alloc new semaphore
|
||||
let mut semaphore = Semaphore::new(device, Default::default())?;
|
||||
semaphore.must_put_in_pool = true;
|
||||
semaphore
|
||||
}
|
||||
};
|
||||
|
||||
Ok(semaphore)
|
||||
}
|
||||
|
||||
/// Exports the semaphore into a POSIX file descriptor. The caller owns the returned `File`.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// - The semaphore must not be used, or have been used, to acquire a swapchain image.
|
||||
pub unsafe fn export_opaque_fd(&self) -> Result<File, SemaphoreExportError> {
|
||||
let fns = self.device.fns();
|
||||
#[inline]
|
||||
pub unsafe fn export_fd(
|
||||
&self,
|
||||
handle_type: ExternalSemaphoreHandleType,
|
||||
) -> Result<File, SemaphoreError> {
|
||||
self.validate_export_fd(handle_type)?;
|
||||
|
||||
// VUID-VkSemaphoreGetFdInfoKHR-handleType-01132
|
||||
if !self.export_handle_types.opaque_fd {
|
||||
return Err(SemaphoreExportError::HandleTypeNotSupported {
|
||||
handle_type: ExternalSemaphoreHandleType::OpaqueFd,
|
||||
Ok(self.export_fd_unchecked(handle_type)?)
|
||||
}
|
||||
|
||||
fn validate_export_fd(
|
||||
&self,
|
||||
handle_type: ExternalSemaphoreHandleType,
|
||||
) -> Result<(), SemaphoreError> {
|
||||
if !self.device.enabled_extensions().khr_external_semaphore_fd {
|
||||
return Err(SemaphoreError::RequirementNotMet {
|
||||
required_for: "`export_fd`",
|
||||
requires_one_of: RequiresOneOf {
|
||||
device_extensions: &["khr_external_semaphore_fd"],
|
||||
..Default::default()
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
assert!(self.device.enabled_extensions().khr_external_semaphore);
|
||||
assert!(self.device.enabled_extensions().khr_external_semaphore_fd);
|
||||
// VUID-VkMemoryGetFdInfoKHR-handleType-parameter
|
||||
handle_type.validate_device(&self.device)?;
|
||||
|
||||
// VUID-VkSemaphoreGetFdInfoKHR-handleType-01132
|
||||
if !self.export_handle_types.intersects(&handle_type.into()) {
|
||||
return Err(SemaphoreError::HandleTypeNotSupported { handle_type });
|
||||
}
|
||||
|
||||
// VUID-VkSemaphoreGetFdInfoKHR-semaphore-01133
|
||||
// Can't validate for swapchain.
|
||||
|
||||
#[cfg(not(unix))]
|
||||
unreachable!("`khr_external_semaphore_fd` was somehow enabled on a non-Unix system");
|
||||
// VUID-VkSemaphoreGetFdInfoKHR-handleType-01134
|
||||
// TODO:
|
||||
|
||||
#[cfg(unix)]
|
||||
{
|
||||
use std::os::unix::io::FromRawFd;
|
||||
// VUID-VkSemaphoreGetFdInfoKHR-handleType-01135
|
||||
// TODO:
|
||||
|
||||
let fd = {
|
||||
let info = ash::vk::SemaphoreGetFdInfoKHR {
|
||||
semaphore: self.handle,
|
||||
handle_type: ash::vk::ExternalSemaphoreHandleTypeFlagsKHR::OPAQUE_FD,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let mut output = MaybeUninit::uninit();
|
||||
(fns.khr_external_semaphore_fd.get_semaphore_fd_khr)(
|
||||
self.device.internal_object(),
|
||||
&info,
|
||||
output.as_mut_ptr(),
|
||||
)
|
||||
.result()
|
||||
.map_err(VulkanError::from)?;
|
||||
output.assume_init()
|
||||
};
|
||||
let file = File::from_raw_fd(fd);
|
||||
Ok(file)
|
||||
// VUID-VkSemaphoreGetFdInfoKHR-handleType-01136
|
||||
if !matches!(
|
||||
handle_type,
|
||||
ExternalSemaphoreHandleType::OpaqueFd | ExternalSemaphoreHandleType::SyncFd
|
||||
) {
|
||||
return Err(SemaphoreError::HandleTypeNotSupported { handle_type });
|
||||
}
|
||||
|
||||
// VUID-VkSemaphoreGetFdInfoKHR-handleType-03253
|
||||
// TODO:
|
||||
|
||||
// VUID-VkSemaphoreGetFdInfoKHR-handleType-03254
|
||||
// TODO:
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(not(unix))]
|
||||
#[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
|
||||
pub unsafe fn export_fd_unchecked(
|
||||
&self,
|
||||
_handle_type: ExternalSemaphoreHandleType,
|
||||
) -> Result<File, VulkanError> {
|
||||
unreachable!("`khr_external_semaphore_fd` was somehow enabled on a non-Unix system");
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
#[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
|
||||
pub unsafe fn export_fd_unchecked(
|
||||
&self,
|
||||
handle_type: ExternalSemaphoreHandleType,
|
||||
) -> Result<File, VulkanError> {
|
||||
use std::os::unix::io::FromRawFd;
|
||||
|
||||
let info = ash::vk::SemaphoreGetFdInfoKHR {
|
||||
semaphore: self.handle,
|
||||
handle_type: handle_type.into(),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let mut output = MaybeUninit::uninit();
|
||||
let fns = self.device.fns();
|
||||
(fns.khr_external_semaphore_fd.get_semaphore_fd_khr)(
|
||||
self.device.internal_object(),
|
||||
&info,
|
||||
output.as_mut_ptr(),
|
||||
)
|
||||
.result()
|
||||
.map_err(VulkanError::from)?;
|
||||
|
||||
Ok(File::from_raw_fd(output.assume_init()))
|
||||
}
|
||||
}
|
||||
|
||||
@ -257,73 +338,6 @@ impl Hash for Semaphore {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
pub enum SemaphoreCreationError {
|
||||
/// Not enough memory available.
|
||||
OomError(OomError),
|
||||
|
||||
RequirementNotMet {
|
||||
required_for: &'static str,
|
||||
requires_one_of: RequiresOneOf,
|
||||
},
|
||||
}
|
||||
|
||||
impl Error for SemaphoreCreationError {
|
||||
#[inline]
|
||||
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||
match *self {
|
||||
Self::OomError(ref err) => Some(err),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for SemaphoreCreationError {
|
||||
fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> {
|
||||
match self {
|
||||
Self::OomError(_) => write!(f, "not enough memory available"),
|
||||
|
||||
Self::RequirementNotMet {
|
||||
required_for,
|
||||
requires_one_of,
|
||||
} => write!(
|
||||
f,
|
||||
"a requirement was not met for: {}; requires one of: {}",
|
||||
required_for, requires_one_of,
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<VulkanError> for SemaphoreCreationError {
|
||||
#[inline]
|
||||
fn from(err: VulkanError) -> Self {
|
||||
match err {
|
||||
e @ VulkanError::OutOfHostMemory | e @ VulkanError::OutOfDeviceMemory => {
|
||||
Self::OomError(e.into())
|
||||
}
|
||||
_ => panic!("unexpected error: {:?}", err),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<OomError> for SemaphoreCreationError {
|
||||
#[inline]
|
||||
fn from(err: OomError) -> Self {
|
||||
Self::OomError(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<RequirementNotMet> for SemaphoreCreationError {
|
||||
#[inline]
|
||||
fn from(err: RequirementNotMet) -> Self {
|
||||
Self::RequirementNotMet {
|
||||
required_for: err.required_for,
|
||||
requires_one_of: err.requires_one_of,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Parameters to create a new `Semaphore`.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct SemaphoreCreateInfo {
|
||||
@ -346,7 +360,7 @@ impl Default for SemaphoreCreateInfo {
|
||||
}
|
||||
|
||||
vulkan_enum! {
|
||||
/// Describes the handle type used for Vulkan external semaphore APIs.
|
||||
/// The handle type used for Vulkan external semaphore APIs.
|
||||
#[non_exhaustive]
|
||||
ExternalSemaphoreHandleType = ExternalSemaphoreHandleTypeFlags(u32);
|
||||
|
||||
@ -374,7 +388,7 @@ vulkan_enum! {
|
||||
}
|
||||
|
||||
vulkan_bitflags! {
|
||||
/// A mask of multiple handle types.
|
||||
/// A mask of multiple external semaphore handle types.
|
||||
#[non_exhaustive]
|
||||
ExternalSemaphoreHandleTypes = ExternalSemaphoreHandleTypeFlags(u32);
|
||||
|
||||
@ -401,6 +415,33 @@ vulkan_bitflags! {
|
||||
*/
|
||||
}
|
||||
|
||||
impl From<ExternalSemaphoreHandleType> for ExternalSemaphoreHandleTypes {
|
||||
#[inline]
|
||||
fn from(val: ExternalSemaphoreHandleType) -> Self {
|
||||
let mut result = Self::empty();
|
||||
|
||||
match val {
|
||||
ExternalSemaphoreHandleType::OpaqueFd => result.opaque_fd = true,
|
||||
ExternalSemaphoreHandleType::OpaqueWin32 => result.opaque_win32 = true,
|
||||
ExternalSemaphoreHandleType::OpaqueWin32Kmt => result.opaque_win32_kmt = true,
|
||||
ExternalSemaphoreHandleType::D3D12Fence => result.d3d12_fence = true,
|
||||
ExternalSemaphoreHandleType::SyncFd => result.sync_fd = true,
|
||||
}
|
||||
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
vulkan_bitflags! {
|
||||
/// Additional parameters for a semaphore payload import.
|
||||
#[non_exhaustive]
|
||||
SemaphoreImportFlags = SemaphoreImportFlags(u32);
|
||||
|
||||
/// The semaphore payload will be imported only temporarily, regardless of the permanence of the
|
||||
/// imported handle type.
|
||||
temporary = TEMPORARY,
|
||||
}
|
||||
|
||||
/// The semaphore configuration to query in
|
||||
/// [`PhysicalDevice::external_semaphore_properties`](crate::device::physical::PhysicalDevice::external_semaphore_properties).
|
||||
#[derive(Clone, Debug)]
|
||||
@ -440,15 +481,21 @@ pub struct ExternalSemaphoreProperties {
|
||||
pub export_from_imported_handle_types: ExternalSemaphoreHandleTypes,
|
||||
|
||||
/// Which external handle types can be enabled along with the queried external handle type
|
||||
/// when creating the buffer or image.
|
||||
/// when creating the semaphore.
|
||||
pub compatible_handle_types: ExternalSemaphoreHandleTypes,
|
||||
}
|
||||
|
||||
/// Error that can be returned from operations on a semaphore.
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
pub enum SemaphoreExportError {
|
||||
pub enum SemaphoreError {
|
||||
/// Not enough memory available.
|
||||
OomError(OomError),
|
||||
|
||||
RequirementNotMet {
|
||||
required_for: &'static str,
|
||||
requires_one_of: RequiresOneOf,
|
||||
},
|
||||
|
||||
/// The requested export handle type was not provided in `export_handle_types` when creating the
|
||||
/// semaphore.
|
||||
HandleTypeNotSupported {
|
||||
@ -456,10 +503,30 @@ pub enum SemaphoreExportError {
|
||||
},
|
||||
}
|
||||
|
||||
impl Display for SemaphoreExportError {
|
||||
fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> {
|
||||
impl Error for SemaphoreError {
|
||||
#[inline]
|
||||
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||
match *self {
|
||||
Self::OomError(ref err) => Some(err),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for SemaphoreError {
|
||||
fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> {
|
||||
match self {
|
||||
Self::OomError(_) => write!(f, "not enough memory available"),
|
||||
|
||||
Self::RequirementNotMet {
|
||||
required_for,
|
||||
requires_one_of,
|
||||
} => write!(
|
||||
f,
|
||||
"a requirement was not met for: {}; requires one of: {}",
|
||||
required_for, requires_one_of,
|
||||
),
|
||||
|
||||
Self::HandleTypeNotSupported { handle_type } => write!(
|
||||
f,
|
||||
"the requested export handle type ({:?}) was not provided in `export_handle_types` when creating the semaphore",
|
||||
@ -469,7 +536,7 @@ impl Display for SemaphoreExportError {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<VulkanError> for SemaphoreExportError {
|
||||
impl From<VulkanError> for SemaphoreError {
|
||||
#[inline]
|
||||
fn from(err: VulkanError) -> Self {
|
||||
match err {
|
||||
@ -481,25 +548,26 @@ impl From<VulkanError> for SemaphoreExportError {
|
||||
}
|
||||
}
|
||||
|
||||
impl Error for SemaphoreExportError {
|
||||
#[inline]
|
||||
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||
match *self {
|
||||
Self::OomError(ref err) => Some(err),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<OomError> for SemaphoreExportError {
|
||||
impl From<OomError> for SemaphoreError {
|
||||
#[inline]
|
||||
fn from(err: OomError) -> Self {
|
||||
Self::OomError(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<RequirementNotMet> for SemaphoreError {
|
||||
#[inline]
|
||||
fn from(err: RequirementNotMet) -> Self {
|
||||
Self::RequirementNotMet {
|
||||
required_for: err.required_for,
|
||||
requires_one_of: err.requires_one_of,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::ExternalSemaphoreHandleType;
|
||||
use crate::{
|
||||
device::{Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo},
|
||||
instance::{Instance, InstanceCreateInfo, InstanceExtensions},
|
||||
@ -587,6 +655,9 @@ mod tests {
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
let _fd = unsafe { sem.export_opaque_fd().unwrap() };
|
||||
let _fd = unsafe {
|
||||
sem.export_fd(ExternalSemaphoreHandleType::OpaqueFd)
|
||||
.unwrap()
|
||||
};
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user