kronos_compute/implementation/
device.rs

1//! Device creation and queue management
2
3use crate::sys::*;
4use crate::core::*;
5use crate::ffi::*;
6use crate::implementation::icd_loader;
7
8/// Create a logical device
9// SAFETY: This function is called from C code. Caller must ensure:
10// 1. physicalDevice is a valid VkPhysicalDevice from vkEnumeratePhysicalDevices
11// 2. pCreateInfo points to a valid VkDeviceCreateInfo structure
12// 3. pAllocator is either null or points to valid allocation callbacks
13// 4. pDevice points to valid memory for writing the device handle
14#[no_mangle]
15pub unsafe extern "C" fn vkCreateDevice(
16    physicalDevice: VkPhysicalDevice,
17    pCreateInfo: *const VkDeviceCreateInfo,
18    pAllocator: *const VkAllocationCallbacks,
19    pDevice: *mut VkDevice,
20) -> VkResult {
21    if physicalDevice.is_null() || pCreateInfo.is_null() || pDevice.is_null() {
22        return VkResult::ErrorInitializationFailed;
23    }
24
25    // Aggregated-aware: prefer ICD owning the physical device
26    if let Some(icd_arc) = icd_loader::icd_for_physical_device(physicalDevice) {
27        if let Some(create_device_fn) = icd_arc.create_device {
28            let result = create_device_fn(physicalDevice, pCreateInfo, pAllocator, pDevice);
29            if result == VkResult::Success {
30                // Load device-level functions into a cloned ICD and register device → ICD mapping
31                let mut cloned = (*icd_arc).clone();
32                let _ = icd_loader::load_device_functions_inner(&mut cloned, *pDevice);
33                let updated = std::sync::Arc::new(cloned);
34                icd_loader::register_device_icd(*pDevice, &updated);
35            }
36            return result;
37        }
38    }
39
40    // Fallback to single-ICD driver
41    if let Some(icd) = super::forward::get_icd_if_enabled() {
42        if let Some(create_device_fn) = icd.create_device {
43            let result = create_device_fn(physicalDevice, pCreateInfo, pAllocator, pDevice);
44            if result == VkResult::Success {
45                let _ = super::icd_loader::update_device_functions(*pDevice);
46            }
47            return result;
48        }
49    }
50
51    VkResult::ErrorInitializationFailed
52}
53
54/// Destroy a logical device
55// SAFETY: This function is called from C code. Caller must ensure:
56// 1. device is a valid VkDevice created by vkCreateDevice
57// 2. pAllocator matches the allocator used in vkCreateDevice (or both are null)
58// 3. All objects created from this device have been destroyed
59#[no_mangle]
60pub unsafe extern "C" fn vkDestroyDevice(
61    device: VkDevice,
62    pAllocator: *const VkAllocationCallbacks,
63) {
64    if device.is_null() {
65        return;
66    }
67    
68    // Forward to real ICD
69    if let Some(icd) = super::forward::get_icd_if_enabled() {
70        if let Some(destroy_device) = icd.destroy_device {
71            destroy_device(device, pAllocator);
72        }
73    }
74
75    // Unregister device from provenance registry (aggregated mode)
76    crate::implementation::icd_loader::unregister_device(device);
77}
78
79/// Get a device queue
80// SAFETY: This function is called from C code. Caller must ensure:
81// 1. device is a valid VkDevice
82// 2. queueFamilyIndex and queueIndex are valid for this device
83// 3. pQueue points to valid memory for writing the queue handle
84#[no_mangle]
85pub unsafe extern "C" fn vkGetDeviceQueue(
86    device: VkDevice,
87    queueFamilyIndex: u32,
88    queueIndex: u32,
89    pQueue: *mut VkQueue,
90) {
91    if device.is_null() || pQueue.is_null() {
92        return;
93    }
94
95    // Route via owning ICD if known
96    if let Some(icd) = icd_loader::icd_for_device(device) {
97        if let Some(f) = icd.get_device_queue {
98            f(device, queueFamilyIndex, queueIndex, pQueue);
99            if let Some(queue) = pQueue.as_ref() {
100                // Register queue → ICD mapping
101                icd_loader::register_queue_icd(unsafe { *queue }, &icd);
102            }
103            return;
104        }
105    }
106    // Fallback
107    if let Some(icd) = super::forward::get_icd_if_enabled() {
108        if let Some(get_device_queue) = icd.get_device_queue {
109            get_device_queue(device, queueFamilyIndex, queueIndex, pQueue);
110        }
111    }
112}
113
114/// Submit work to a queue
115// SAFETY: This function is called from C code. Caller must ensure:
116// 1. queue is a valid VkQueue obtained from vkGetDeviceQueue
117// 2. If submitCount > 0, pSubmits points to an array of valid VkSubmitInfo structures
118// 3. fence is either VK_NULL_HANDLE or a valid VkFence
119// 4. All command buffers, semaphores, and other resources referenced are valid
120#[no_mangle]
121pub unsafe extern "C" fn vkQueueSubmit(
122    queue: VkQueue,
123    submitCount: u32,
124    pSubmits: *const VkSubmitInfo,
125    fence: VkFence,
126) -> VkResult {
127    if queue.is_null() {
128        return VkResult::ErrorDeviceLost;
129    }
130
131    // Route via queue owner if known
132    if let Some(icd) = icd_loader::icd_for_queue(queue) {
133        if let Some(f) = icd.queue_submit { return f(queue, submitCount, pSubmits, fence); }
134    }
135    // Fallback
136    if let Some(icd) = super::forward::get_icd_if_enabled() {
137        if let Some(f) = icd.queue_submit { return f(queue, submitCount, pSubmits, fence); }
138    }
139    VkResult::ErrorInitializationFailed
140}
141
142/// Wait for queue to become idle
143#[no_mangle]
144pub unsafe extern "C" fn vkQueueWaitIdle(queue: VkQueue) -> VkResult {
145    if queue.is_null() {
146        return VkResult::ErrorDeviceLost;
147    }
148
149    if let Some(icd) = icd_loader::icd_for_queue(queue) {
150        if let Some(f) = icd.queue_wait_idle { return f(queue); }
151    }
152    if let Some(icd) = super::forward::get_icd_if_enabled() {
153        if let Some(f) = icd.queue_wait_idle { return f(queue); }
154    }
155    VkResult::ErrorInitializationFailed
156}
157
158/// Wait for device to become idle
159#[no_mangle]
160pub unsafe extern "C" fn vkDeviceWaitIdle(device: VkDevice) -> VkResult {
161    if device.is_null() {
162        return VkResult::ErrorDeviceLost;
163    }
164
165    if let Some(icd) = icd_loader::icd_for_device(device) {
166        if let Some(f) = icd.device_wait_idle { return f(device); }
167    }
168    if let Some(icd) = super::forward::get_icd_if_enabled() {
169        if let Some(f) = icd.device_wait_idle { return f(device); }
170    }
171    VkResult::ErrorInitializationFailed
172}