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