1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
//! Ergonomic wrappers for `VK_KHR_external_memory_{win32,fd}`.
//!
//! These extensions let you export an allocation's platform-native handle
//! (a Windows `HANDLE` or a POSIX file descriptor) so it can be imported
//! by a *different* API on the same device — the typical use cases are:
//!
//! - CUDA / HIP interop (`cudaExternalMemory`, `hipExternalMemory`).
//! - DirectX 12 interop (`ID3D12Resource` sharing on Windows).
//! - cross-process or cross-engine buffer sharing (DMA-BUF on Linux).
//!
//! ## Creating an exportable allocation
//!
//! The export capability is configured at *creation time*. You must:
//!
//! 1. Enable `VK_KHR_external_memory` plus the platform-specific
//! sub-extension (`_win32` or `_fd`) on the [`Device`](super::Device).
//! 2. Attach `VkExternalMemoryBufferCreateInfo` /
//! `VkExternalMemoryImageCreateInfo` to the buffer / image create
//! info via [`Buffer::new_with_pnext`](super::Buffer::new_with_pnext)
//! or [`Image::new_2d_with_pnext`](super::Image::new_2d_with_pnext).
//! 3. Attach `VkExportMemoryAllocateInfo` to the memory allocate info
//! via [`DeviceMemory::allocate_with`](super::DeviceMemory::allocate_with).
//! 4. After binding, call [`DeviceMemory::get_win32_handle`] or
//! [`DeviceMemory::get_fd`] to extract the native handle.
//!
//! ```ignore
//! use vulkane::raw::bindings::*;
//! use vulkane::raw::PNextChainable;
//! use vulkane::safe::{
//! Buffer, BufferCreateInfo, BufferUsage, DeviceMemory, MemoryAllocateInfo, PNextChain,
//! };
//!
//! # let (device, physical) = todo!();
//! // 1. Buffer marked as exportable.
//! let mut buf_chain = PNextChain::new();
//! let mut buf_ext = VkExternalMemoryBufferCreateInfo::new_pnext();
//! buf_ext.handleTypes = EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT;
//! buf_chain.push(buf_ext);
//! let buffer = Buffer::new_with_pnext(
//! &device,
//! BufferCreateInfo { size: 4096, usage: BufferUsage::STORAGE_BUFFER },
//! Some(&buf_chain),
//! )?;
//!
//! // 2. Memory marked as exportable.
//! let req = buffer.memory_requirements();
//! let mt = physical.find_memory_type(req.memory_type_bits, /*…*/).unwrap();
//! let mut mem_chain = PNextChain::new();
//! let mut mem_ext = VkExportMemoryAllocateInfo::new_pnext();
//! mem_ext.handleTypes = EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT;
//! mem_chain.push(mem_ext);
//! let memory = DeviceMemory::allocate_with(&device, &MemoryAllocateInfo {
//! size: req.size,
//! memory_type_index: mt,
//! pnext: Some(&mem_chain),
//! })?;
//! buffer.bind_memory(&memory, 0)?;
//!
//! // 3. Extract the Win32 HANDLE to hand to CUDA / D3D12.
//! let handle = memory.get_win32_handle(EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT)?;
//! # Ok::<(), vulkane::safe::Error>(())
//! ```
use ;
use crate*;
/// A Windows `HANDLE` returned from a Vulkan external-memory or
/// external-semaphore export.
///
/// The handle is *not* closed on drop. The Vulkan spec makes the caller
/// responsible for handle ownership: for NT handle types
/// (`OPAQUE_WIN32`, `D3D11_TEXTURE`, `D3D12_HEAP`, `D3D12_RESOURCE`) the
/// returned handle is a fresh NT handle that must be released with
/// `CloseHandle` when no longer needed. For KMT handle types
/// (`_KMT_BIT`) the handle is a shared KMT handle whose lifetime is
/// controlled separately; closing it would be incorrect.
///
/// Because the correct disposal depends on the handle type — and
/// because most callers forward the handle straight to another API
/// (CUDA, D3D12) which assumes ownership — `Win32Handle` does *not*
/// auto-close. Callers must track ownership themselves.
// HANDLE is *mut c_void which is !Send + !Sync by default. In practice
// Win32 HANDLEs are Send (they are process-global integer-like values).
// Mark explicitly so the caller can thread it to another runtime.
unsafe
unsafe