Skip to content

Commit b0f260d

Browse files
committed
extensions: Use Rust IO-safety types for fd/handle arguments/returns
Use Rust's IO-safety types like `OwnedFd`/`BorrowedFd` (and their Windows `*Handle` equivalent) to communicate ownership transfer (or lack thereof) to the user and provide automatic cleanup when an owned handle is transferred to the caller. For Windows however the returned handle is only owned when it is a "handle type defined as NT handle" [1], being unclear what classifies as an NT handle (anything built/used after 1993??). We already contemplated this before, and the change puts `cfg(windows)` and `cfg(unix)` guards in place for the corresponding OS-specific extension wrappers, as these safety types are likewise only available on the aforementioned platforms. Unfortunately the import APIs pass file descriptors and handles via structs which have non-trivial ownership transfer into Vulkan functions: we could switch them to move semantics but there's no guarantee that these structs are only used with these functions. And it's even more complicated for external memory import: there the handle / file descriptor is passed in an `Info` struct chained in `pNext` for calls to `vkAllocateMemory()`, making it even more complicated (if at all possible) for us to intercept and "consume" the owned handle in a wrapper layer to prevent Rust from closing it. Furthermore note that all import APIs only transfer ownership _on Unix_; on Windows the caller remains responsible for calling `CloseHandle()` after (not sooner) the import is no longer used in Vulkan. This bumps MSRV to 1.63, and we could switch from `std::os::unix::io` to `std::os::fd` in MSRV 1.66. [1]: https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/vkGetMemoryWin32HandleKHR.html#_description
1 parent 0652aee commit b0f260d

12 files changed

+86
-31
lines changed

.github/workflows/ci.yml

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,22 +5,31 @@ name: CI
55
jobs:
66
check:
77
name: Check
8-
runs-on: ubuntu-latest
8+
strategy:
9+
matrix:
10+
os: [windows-latest, ubuntu-latest]
11+
runs-on: ${{ matrix.os }}
912
steps:
1013
- uses: actions/checkout@v1
1114
- run: cargo check --workspace --all-targets --all-features
1215

1316
check_msrv:
14-
name: Check ash MSRV (1.60.0)
15-
runs-on: ubuntu-latest
17+
name: Check ash MSRV (1.63.0)
18+
strategy:
19+
matrix:
20+
os: [windows-latest, ubuntu-latest]
21+
runs-on: ${{ matrix.os }}
1622
steps:
1723
- uses: actions/checkout@v1
18-
- uses: dtolnay/rust-toolchain@1.60.0
24+
- uses: dtolnay/rust-toolchain@1.63.0
1925
- run: cargo check -p ash -p ash-rewrite --all-features
2026

2127
check_ash_window_msrv:
2228
name: Check ash-window MSRV (1.64.0)
23-
runs-on: ubuntu-latest
29+
strategy:
30+
matrix:
31+
os: [windows-latest, ubuntu-latest]
32+
runs-on: ${{ matrix.os }}
2433
steps:
2534
- uses: actions/checkout@v1
2635
- uses: dtolnay/[email protected]

Changelog.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
4242
- Define `Display` as `c_void` instead of `*mut c_void` to match Xlib (#751)
4343
- `VK_KHR_device_group_creation`: Take borrow of `Entry` in `fn new()` (#753)
4444
- `VK_KHR_device_group_creation`: Rename `vk::Instance`-returning function from `device()` to `instance()` (#759)
45+
- Use Rust IO-safety types (`OwnedFd`, `BorrowedFd`, `OwnedHandle`, `BorrowedHandle`) in functions to signify ownership transfer (#791)
4546

4647
### Removed
4748

ash/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ readme = "../README.md"
1313
keywords = ["vulkan", "graphic"]
1414
documentation = "https://docs.rs/ash"
1515
edition = "2021"
16-
rust-version = "1.60.0"
16+
rust-version = "1.63.0"
1717

1818
[dependencies]
1919
libloading = { version = "0.7", optional = true }

ash/src/extensions/ext/acquire_drm_display.rs

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
1+
#![cfg(unix)]
2+
13
use crate::prelude::*;
24
use crate::vk;
35
use crate::{Entry, Instance};
46
use std::ffi::CStr;
57
use std::mem;
8+
use std::os::unix::io::{AsRawFd, BorrowedFd};
69

710
/// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/VK_EXT_acquire_drm_display.html>
811
#[derive(Clone)]
@@ -24,23 +27,28 @@ impl AcquireDrmDisplay {
2427
pub unsafe fn acquire_drm_display(
2528
&self,
2629
physical_device: vk::PhysicalDevice,
27-
drm_fd: i32,
30+
drm_fd: BorrowedFd<'_>,
2831
display: vk::DisplayKHR,
2932
) -> VkResult<()> {
30-
(self.fp.acquire_drm_display_ext)(physical_device, drm_fd, display).result()
33+
(self.fp.acquire_drm_display_ext)(physical_device, drm_fd.as_raw_fd(), display).result()
3134
}
3235

3336
/// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkGetDrmDisplayEXT.html>
3437
#[inline]
3538
pub unsafe fn get_drm_display(
3639
&self,
3740
physical_device: vk::PhysicalDevice,
38-
drm_fd: i32,
41+
drm_fd: BorrowedFd<'_>,
3942
connector_id: u32,
4043
) -> VkResult<vk::DisplayKHR> {
4144
let mut display = mem::MaybeUninit::uninit();
42-
(self.fp.get_drm_display_ext)(physical_device, drm_fd, connector_id, display.as_mut_ptr())
43-
.assume_init_on_success(display)
45+
(self.fp.get_drm_display_ext)(
46+
physical_device,
47+
drm_fd.as_raw_fd(),
48+
connector_id,
49+
display.as_mut_ptr(),
50+
)
51+
.assume_init_on_success(display)
4452
}
4553

4654
pub const NAME: &'static CStr = vk::ExtAcquireDrmDisplayFn::NAME;

ash/src/extensions/ext/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
#[cfg(unix)]
12
pub use self::acquire_drm_display::AcquireDrmDisplay;
23
pub use self::buffer_device_address::BufferDeviceAddress;
34
pub use self::calibrated_timestamps::CalibratedTimestamps;

ash/src/extensions/khr/external_fence_fd.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
1+
#![cfg(unix)]
2+
13
use crate::prelude::*;
24
use crate::vk;
35
use crate::{Device, Instance};
46
use std::ffi::CStr;
57
use std::mem;
8+
// use std::os::fd::OwnedFd;
9+
use std::os::unix::io::{FromRawFd, OwnedFd};
610

711
#[derive(Clone)]
812
pub struct ExternalFenceFd {
@@ -27,9 +31,10 @@ impl ExternalFenceFd {
2731

2832
/// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkGetFenceFdKHR.html>
2933
#[inline]
30-
pub unsafe fn get_fence_fd(&self, get_info: &vk::FenceGetFdInfoKHR) -> VkResult<i32> {
34+
pub unsafe fn get_fence_fd(&self, get_info: &vk::FenceGetFdInfoKHR) -> VkResult<OwnedFd> {
3135
let mut fd = -1;
32-
(self.fp.get_fence_fd_khr)(self.handle, get_info, &mut fd).result_with_success(fd)
36+
(self.fp.get_fence_fd_khr)(self.handle, get_info, &mut fd).result()?;
37+
Ok(OwnedFd::from_raw_fd(fd))
3338
}
3439

3540
pub const NAME: &'static CStr = vk::KhrExternalFenceFdFn::NAME;

ash/src/extensions/khr/external_fence_win32.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
1+
#![cfg(windows)]
2+
13
use crate::prelude::*;
24
use crate::vk;
35
use crate::{Device, Instance};
46
use std::ffi::CStr;
57
use std::mem;
8+
use std::os::windows::io::{FromRawHandle, OwnedHandle};
69
use std::ptr;
710

811
/// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/VK_KHR_external_fence_win32.html>
@@ -35,10 +38,10 @@ impl ExternalFenceWin32 {
3538
pub unsafe fn get_fence_win32_handle(
3639
&self,
3740
get_info: &vk::FenceGetWin32HandleInfoKHR,
38-
) -> VkResult<vk::HANDLE> {
41+
) -> VkResult<OwnedHandle> {
3942
let mut handle = ptr::null_mut();
40-
(self.fp.get_fence_win32_handle_khr)(self.handle, get_info, &mut handle)
41-
.result_with_success(handle)
43+
(self.fp.get_fence_win32_handle_khr)(self.handle, get_info, &mut handle).result()?;
44+
Ok(OwnedHandle::from_raw_handle(handle))
4245
}
4346

4447
pub const NAME: &'static CStr = vk::KhrExternalFenceWin32Fn::NAME;

ash/src/extensions/khr/external_memory_fd.rs

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
1+
#![cfg(unix)]
2+
13
use crate::prelude::*;
24
use crate::vk;
35
use crate::{Device, Instance};
46
use std::ffi::CStr;
57
use std::mem;
8+
use std::os::unix::io::{AsRawFd, BorrowedFd, FromRawFd, OwnedFd};
69

710
/// <https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VK_KHR_external_memory_fd.html>
811
#[derive(Clone)]
@@ -22,21 +25,27 @@ impl ExternalMemoryFd {
2225

2326
/// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkGetMemoryFdKHR.html>
2427
#[inline]
25-
pub unsafe fn get_memory_fd(&self, get_fd_info: &vk::MemoryGetFdInfoKHR) -> VkResult<i32> {
28+
pub unsafe fn get_memory_fd(&self, get_fd_info: &vk::MemoryGetFdInfoKHR) -> VkResult<OwnedFd> {
2629
let mut fd = -1;
27-
(self.fp.get_memory_fd_khr)(self.handle, get_fd_info, &mut fd).result_with_success(fd)
30+
(self.fp.get_memory_fd_khr)(self.handle, get_fd_info, &mut fd).result()?;
31+
Ok(OwnedFd::from_raw_fd(fd))
2832
}
2933

3034
/// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkGetMemoryFdPropertiesKHR.html>
3135
#[inline]
3236
pub unsafe fn get_memory_fd_properties(
3337
&self,
3438
handle_type: vk::ExternalMemoryHandleTypeFlags,
35-
fd: i32,
39+
fd: BorrowedFd<'_>,
3640
memory_fd_properties: &mut vk::MemoryFdPropertiesKHR,
3741
) -> VkResult<()> {
38-
(self.fp.get_memory_fd_properties_khr)(self.handle, handle_type, fd, memory_fd_properties)
39-
.result()
42+
(self.fp.get_memory_fd_properties_khr)(
43+
self.handle,
44+
handle_type,
45+
fd.as_raw_fd(),
46+
memory_fd_properties,
47+
)
48+
.result()
4049
}
4150

4251
pub const NAME: &'static CStr = vk::KhrExternalMemoryFdFn::NAME;

ash/src/extensions/khr/external_memory_win32.rs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
1+
#![cfg(windows)]
2+
13
use crate::prelude::*;
24
use crate::vk;
35
use crate::{Device, Instance};
46
use std::ffi::CStr;
57
use std::mem;
8+
use std::os::windows::io::{AsRawHandle, BorrowedHandle, FromRawHandle, OwnedHandle};
69
use std::ptr;
710

811
/// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/VK_KHR_external_memory_win32.html>
@@ -26,24 +29,24 @@ impl ExternalMemoryWin32 {
2629
pub unsafe fn get_memory_win32_handle(
2730
&self,
2831
create_info: &vk::MemoryGetWin32HandleInfoKHR,
29-
) -> VkResult<vk::HANDLE> {
32+
) -> VkResult<OwnedHandle> {
3033
let mut handle = ptr::null_mut();
31-
(self.fp.get_memory_win32_handle_khr)(self.handle, create_info, &mut handle)
32-
.result_with_success(handle)
34+
(self.fp.get_memory_win32_handle_khr)(self.handle, create_info, &mut handle).result()?;
35+
Ok(OwnedHandle::from_raw_handle(handle))
3336
}
3437

3538
/// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkGetMemoryWin32HandlePropertiesKHR.html>
3639
#[inline]
3740
pub unsafe fn get_memory_win32_handle_properties(
3841
&self,
3942
handle_type: vk::ExternalMemoryHandleTypeFlags,
40-
handle: vk::HANDLE,
43+
handle: BorrowedHandle<'_>,
4144
memory_win32_handle_properties: &mut vk::MemoryWin32HandlePropertiesKHR,
4245
) -> VkResult<()> {
4346
(self.fp.get_memory_win32_handle_properties_khr)(
4447
self.handle,
4548
handle_type,
46-
handle,
49+
handle.as_raw_handle(),
4750
memory_win32_handle_properties,
4851
)
4952
.result()

ash/src/extensions/khr/external_semaphore_fd.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
1+
#![cfg(unix)]
2+
13
use crate::prelude::*;
24
use crate::vk;
35
use crate::{Device, Instance};
46
use std::ffi::CStr;
57
use std::mem;
8+
use std::os::unix::io::{FromRawFd, OwnedFd};
69

710
#[derive(Clone)]
811
pub struct ExternalSemaphoreFd {
@@ -30,9 +33,13 @@ impl ExternalSemaphoreFd {
3033

3134
/// <https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkGetSemaphoreFdKHR.html>
3235
#[inline]
33-
pub unsafe fn get_semaphore_fd(&self, get_info: &vk::SemaphoreGetFdInfoKHR) -> VkResult<i32> {
36+
pub unsafe fn get_semaphore_fd(
37+
&self,
38+
get_info: &vk::SemaphoreGetFdInfoKHR,
39+
) -> VkResult<OwnedFd> {
3440
let mut fd = -1;
35-
(self.fp.get_semaphore_fd_khr)(self.handle, get_info, &mut fd).result_with_success(fd)
41+
(self.fp.get_semaphore_fd_khr)(self.handle, get_info, &mut fd).result()?;
42+
Ok(OwnedFd::from_raw_fd(fd))
3643
}
3744

3845
pub const NAME: &'static CStr = vk::KhrExternalSemaphoreFdFn::NAME;

0 commit comments

Comments
 (0)