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}