()
| 160 | } |
| 161 | |
| 162 | unsafe fn init_vulkan() -> std::result::Result<Self, String> { |
| 163 | // 1. Entry + Instance |
| 164 | let entry = ash::Entry::linked(); |
| 165 | let app_info = vk::ApplicationInfo::default() |
| 166 | .application_name(c"cake-vulkan") |
| 167 | .api_version(vk::make_api_version(0, 1, 3, 0)); |
| 168 | let instance_ci = vk::InstanceCreateInfo::default().application_info(&app_info); |
| 169 | let instance = entry |
| 170 | .create_instance(&instance_ci, None) |
| 171 | .map_err(|e| format!("vkCreateInstance: {e}"))?; |
| 172 | |
| 173 | // 2. Physical device |
| 174 | let phys_devices = instance |
| 175 | .enumerate_physical_devices() |
| 176 | .map_err(|e| format!("enumerate_physical_devices: {e}"))?; |
| 177 | if phys_devices.is_empty() { |
| 178 | return Err("no Vulkan physical devices found".into()); |
| 179 | } |
| 180 | // Prefer discrete, fall back to first |
| 181 | let physical_device = phys_devices |
| 182 | .iter() |
| 183 | .find(|&&pd| { |
| 184 | let props = instance.get_physical_device_properties(pd); |
| 185 | props.device_type == vk::PhysicalDeviceType::DISCRETE_GPU |
| 186 | }) |
| 187 | .copied() |
| 188 | .unwrap_or(phys_devices[0]); |
| 189 | |
| 190 | let props = instance.get_physical_device_properties(physical_device); |
| 191 | let dev_name = CStr::from_ptr(props.device_name.as_ptr()) |
| 192 | .to_string_lossy() |
| 193 | .to_string(); |
| 194 | log::info!("Vulkan backend (ash): {dev_name}"); |
| 195 | |
| 196 | // 3. Queue family |
| 197 | let queue_families = |
| 198 | instance.get_physical_device_queue_family_properties(physical_device); |
| 199 | let queue_family_index = queue_families |
| 200 | .iter() |
| 201 | .position(|qf| qf.queue_flags.contains(vk::QueueFlags::COMPUTE)) |
| 202 | .ok_or("no compute queue family")? as u32; |
| 203 | |
| 204 | // 4. Logical device + queue |
| 205 | let queue_priorities = [1.0f32]; |
| 206 | let queue_ci = |
| 207 | vk::DeviceQueueCreateInfo::default() |
| 208 | .queue_family_index(queue_family_index) |
| 209 | .queue_priorities(&queue_priorities); |
| 210 | let device_ci = vk::DeviceCreateInfo::default().queue_create_infos(std::slice::from_ref(&queue_ci)); |
| 211 | let vk_device = instance |
| 212 | .create_device(physical_device, &device_ci, None) |
| 213 | .map_err(|e| format!("vkCreateDevice: {e}"))?; |
| 214 | let queue = vk_device.get_device_queue(queue_family_index, 0); |
| 215 | |
| 216 | // 5. Command pool + buffer |
| 217 | let pool_ci = vk::CommandPoolCreateInfo::default() |
| 218 | .queue_family_index(queue_family_index) |
| 219 | .flags(vk::CommandPoolCreateFlags::RESET_COMMAND_BUFFER); |
nothing calls this directly
no test coverage detected