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