kronos_compute/implementation/sync.rs
1//! Synchronization primitives implementation
2//!
3//! Implements fences, semaphores, and events for GPU synchronization
4
5use crate::sys::*;
6use crate::core::*;
7use crate::ffi::*;
8
9/// Create a fence
10// SAFETY: This function is called from C code. Caller must ensure:
11// 1. device is a valid VkDevice
12// 2. pCreateInfo points to a valid VkFenceCreateInfo structure
13// 3. pAllocator is either null or points to valid allocation callbacks
14// 4. pFence points to valid memory for writing the fence handle
15// 5. Fences are thread-safe and can be used across multiple threads
16#[no_mangle]
17pub unsafe extern "C" fn vkCreateFence(
18 device: VkDevice,
19 pCreateInfo: *const VkFenceCreateInfo,
20 pAllocator: *const VkAllocationCallbacks,
21 pFence: *mut VkFence,
22) -> VkResult {
23 if device.is_null() || pCreateInfo.is_null() || pFence.is_null() {
24 return VkResult::ErrorInitializationFailed;
25 }
26
27 // Forward to real ICD
28 if let Some(icd) = super::forward::get_icd_if_enabled() {
29 if let Some(create_fence) = icd.create_fence {
30 return create_fence(device, pCreateInfo, pAllocator, pFence);
31 }
32 }
33
34 // No ICD available
35 VkResult::ErrorInitializationFailed
36}
37
38/// Destroy a fence
39// SAFETY: This function is called from C code. Caller must ensure:
40// 1. device is a valid VkDevice
41// 2. fence is a valid VkFence created by vkCreateFence, or VK_NULL_HANDLE
42// 3. pAllocator matches the allocator used in vkCreateFence (or both are null)
43// 4. The fence is not currently being waited on by any thread
44// 5. No queue operations are pending on this fence
45#[no_mangle]
46pub unsafe extern "C" fn vkDestroyFence(
47 device: VkDevice,
48 fence: VkFence,
49 pAllocator: *const VkAllocationCallbacks,
50) {
51 if device.is_null() || fence.is_null() {
52 return;
53 }
54
55 // Forward to real ICD
56 if let Some(icd) = super::forward::get_icd_if_enabled() {
57 if let Some(destroy_fence) = icd.destroy_fence {
58 destroy_fence(device, fence, pAllocator);
59 }
60 }
61}
62
63/// Reset fences
64// SAFETY: This function is called from C code. Caller must ensure:
65// 1. device is a valid VkDevice
66// 2. fenceCount is > 0 and matches the number of fences in pFences array
67// 3. pFences points to an array of fenceCount valid VkFence handles
68// 4. All fences are in the signaled state (cannot reset unsignaled fences)
69// 5. No threads are currently waiting on these fences
70#[no_mangle]
71pub unsafe extern "C" fn vkResetFences(
72 device: VkDevice,
73 fenceCount: u32,
74 pFences: *const VkFence,
75) -> VkResult {
76 if device.is_null() || fenceCount == 0 || pFences.is_null() {
77 return VkResult::ErrorInitializationFailed;
78 }
79
80 // Forward to real ICD
81 if let Some(icd) = super::forward::get_icd_if_enabled() {
82 if let Some(reset_fences) = icd.reset_fences {
83 return reset_fences(device, fenceCount, pFences);
84 }
85 }
86
87 // No ICD available
88 VkResult::ErrorInitializationFailed
89}
90
91/// Get fence status
92// SAFETY: This function is called from C code. Caller must ensure:
93// 1. device is a valid VkDevice
94// 2. fence is a valid VkFence created by vkCreateFence
95// 3. This function is thread-safe and can be called concurrently
96// 4. The fence has not been destroyed
97#[no_mangle]
98pub unsafe extern "C" fn vkGetFenceStatus(
99 device: VkDevice,
100 fence: VkFence,
101) -> VkResult {
102 if device.is_null() || fence.is_null() {
103 return VkResult::ErrorDeviceLost;
104 }
105
106 // Forward to real ICD
107 if let Some(icd) = super::forward::get_icd_if_enabled() {
108 if let Some(get_fence_status) = icd.get_fence_status {
109 return get_fence_status(device, fence);
110 }
111 }
112
113 // No ICD available
114 VkResult::ErrorInitializationFailed
115}
116
117/// Wait for fences
118// SAFETY: This function is called from C code. Caller must ensure:
119// 1. device is a valid VkDevice
120// 2. fenceCount is > 0 and matches the number of fences in pFences array
121// 3. pFences points to an array of fenceCount valid VkFence handles
122// 4. waitAll is either VK_TRUE or VK_FALSE
123// 5. timeout value is valid (can be UINT64_MAX for infinite wait)
124// 6. This function may block the calling thread until timeout or fence signaling
125#[no_mangle]
126pub unsafe extern "C" fn vkWaitForFences(
127 device: VkDevice,
128 fenceCount: u32,
129 pFences: *const VkFence,
130 waitAll: VkBool32,
131 timeout: u64,
132) -> VkResult {
133 if device.is_null() || fenceCount == 0 || pFences.is_null() {
134 return VkResult::ErrorInitializationFailed;
135 }
136
137 // Forward to real ICD
138 if let Some(icd) = super::forward::get_icd_if_enabled() {
139 if let Some(wait_for_fences) = icd.wait_for_fences {
140 return wait_for_fences(device, fenceCount, pFences, waitAll, timeout);
141 }
142 }
143
144 // No ICD available
145 VkResult::ErrorInitializationFailed
146}
147
148/// Create a semaphore
149// SAFETY: This function is called from C code. Caller must ensure:
150// 1. device is a valid VkDevice
151// 2. pCreateInfo points to a valid VkSemaphoreCreateInfo structure
152// 3. pAllocator is either null or points to valid allocation callbacks
153// 4. pSemaphore points to valid memory for writing the semaphore handle
154// 5. Semaphores are used for GPU-GPU synchronization and queue ordering
155#[no_mangle]
156pub unsafe extern "C" fn vkCreateSemaphore(
157 device: VkDevice,
158 pCreateInfo: *const VkSemaphoreCreateInfo,
159 pAllocator: *const VkAllocationCallbacks,
160 pSemaphore: *mut VkSemaphore,
161) -> VkResult {
162 if device.is_null() || pCreateInfo.is_null() || pSemaphore.is_null() {
163 return VkResult::ErrorInitializationFailed;
164 }
165
166 // Forward to real ICD
167 if let Some(icd) = super::forward::get_icd_if_enabled() {
168 if let Some(create_semaphore) = icd.create_semaphore {
169 return create_semaphore(device, pCreateInfo, pAllocator, pSemaphore);
170 }
171 }
172
173 // No ICD available
174 VkResult::ErrorInitializationFailed
175}
176
177/// Destroy a semaphore
178// SAFETY: This function is called from C code. Caller must ensure:
179// 1. device is a valid VkDevice
180// 2. semaphore is a valid VkSemaphore created by vkCreateSemaphore, or VK_NULL_HANDLE
181// 3. pAllocator matches the allocator used in vkCreateSemaphore (or both are null)
182// 4. The semaphore is not pending in any queue operation
183// 5. No command buffers reference this semaphore in wait or signal operations
184#[no_mangle]
185pub unsafe extern "C" fn vkDestroySemaphore(
186 device: VkDevice,
187 semaphore: VkSemaphore,
188 pAllocator: *const VkAllocationCallbacks,
189) {
190 if device.is_null() || semaphore.is_null() {
191 return;
192 }
193
194 // Forward to real ICD
195 if let Some(icd) = super::forward::get_icd_if_enabled() {
196 if let Some(destroy_semaphore) = icd.destroy_semaphore {
197 destroy_semaphore(device, semaphore, pAllocator);
198 }
199 }
200}
201
202/// Create an event
203// SAFETY: This function is called from C code. Caller must ensure:
204// 1. device is a valid VkDevice
205// 2. pCreateInfo points to a valid VkEventCreateInfo structure
206// 3. pAllocator is either null or points to valid allocation callbacks
207// 4. pEvent points to valid memory for writing the event handle
208// 5. Events provide fine-grained synchronization within command buffers
209#[no_mangle]
210pub unsafe extern "C" fn vkCreateEvent(
211 device: VkDevice,
212 pCreateInfo: *const VkEventCreateInfo,
213 pAllocator: *const VkAllocationCallbacks,
214 pEvent: *mut VkEvent,
215) -> VkResult {
216 if device.is_null() || pCreateInfo.is_null() || pEvent.is_null() {
217 return VkResult::ErrorInitializationFailed;
218 }
219
220 // Forward to real ICD
221 if let Some(icd) = super::forward::get_icd_if_enabled() {
222 if let Some(create_event) = icd.create_event {
223 return create_event(device, pCreateInfo, pAllocator, pEvent);
224 }
225 }
226
227 // No ICD available
228 VkResult::ErrorInitializationFailed
229}
230
231/// Destroy an event
232// SAFETY: This function is called from C code. Caller must ensure:
233// 1. device is a valid VkDevice
234// 2. event is a valid VkEvent created by vkCreateEvent, or VK_NULL_HANDLE
235// 3. pAllocator matches the allocator used in vkCreateEvent (or both are null)
236// 4. No command buffers are currently waiting on or setting this event
237// 5. All command buffers that reference this event have completed execution
238#[no_mangle]
239pub unsafe extern "C" fn vkDestroyEvent(
240 device: VkDevice,
241 event: VkEvent,
242 pAllocator: *const VkAllocationCallbacks,
243) {
244 if device.is_null() || event.is_null() {
245 return;
246 }
247
248 // Forward to real ICD
249 if let Some(icd) = super::forward::get_icd_if_enabled() {
250 if let Some(destroy_event) = icd.destroy_event {
251 destroy_event(device, event, pAllocator);
252 }
253 }
254}
255
256/// Get event status
257// SAFETY: This function is called from C code. Caller must ensure:
258// 1. device is a valid VkDevice
259// 2. event is a valid VkEvent created by vkCreateEvent
260// 3. This function can be called from the host to check event signaling state
261// 4. The event has not been destroyed
262#[no_mangle]
263pub unsafe extern "C" fn vkGetEventStatus(
264 device: VkDevice,
265 event: VkEvent,
266) -> VkResult {
267 if device.is_null() || event.is_null() {
268 return VkResult::ErrorDeviceLost;
269 }
270
271 // Forward to real ICD
272 if let Some(icd) = super::forward::get_icd_if_enabled() {
273 if let Some(get_event_status) = icd.get_event_status {
274 return get_event_status(device, event);
275 }
276 }
277
278 // No ICD available
279 VkResult::ErrorInitializationFailed
280}
281
282/// Set event
283// SAFETY: This function is called from C code. Caller must ensure:
284// 1. device is a valid VkDevice
285// 2. event is a valid VkEvent created by vkCreateEvent
286// 3. Setting an event from the host signals all command buffers waiting on it
287// 4. The event has not been destroyed
288// 5. This can cause command buffers to proceed past vkCmdWaitEvents
289#[no_mangle]
290pub unsafe extern "C" fn vkSetEvent(
291 device: VkDevice,
292 event: VkEvent,
293) -> VkResult {
294 if device.is_null() || event.is_null() {
295 return VkResult::ErrorDeviceLost;
296 }
297
298 // Forward to real ICD
299 if let Some(icd) = super::forward::get_icd_if_enabled() {
300 if let Some(set_event) = icd.set_event {
301 return set_event(device, event);
302 }
303 }
304
305 // No ICD available
306 VkResult::ErrorInitializationFailed
307}
308
309/// Reset event
310// SAFETY: This function is called from C code. Caller must ensure:
311// 1. device is a valid VkDevice
312// 2. event is a valid VkEvent created by vkCreateEvent
313// 3. Resetting an event puts it back into the unsignaled state
314// 4. The event has not been destroyed
315// 5. No command buffers should be waiting on this event when reset
316#[no_mangle]
317pub unsafe extern "C" fn vkResetEvent(
318 device: VkDevice,
319 event: VkEvent,
320) -> VkResult {
321 if device.is_null() || event.is_null() {
322 return VkResult::ErrorDeviceLost;
323 }
324
325 // Forward to real ICD
326 if let Some(icd) = super::forward::get_icd_if_enabled() {
327 if let Some(reset_event) = icd.reset_event {
328 return reset_event(device, event);
329 }
330 }
331
332 // No ICD available
333 VkResult::ErrorInitializationFailed
334}