1#![allow(dead_code)]
2
3use anyhow::Result;
4use ash::vk;
5use lazy_static::lazy_static;
6use std::marker::PhantomData;
7use std::sync::{Arc, Mutex};
8use log;
9
10pub struct AshVulkanContext {
11 pub entry: ash::Entry,
12 pub instance: ash::Instance,
13 pub device: ash::Device,
14 pub queue: ash::vk::Queue,
15 pub queue_family_index: u32,
16}
17
18impl AshVulkanContext {
19 pub fn new() -> Result<Self> {
20 env_logger::init();
21
22 let entry = unsafe { ash::Entry::load()? };
23
24 let app_name = std::ffi::CString::new("mumu-gpu")?;
25 let app_info = vk::ApplicationInfo {
26 s_type: vk::StructureType::APPLICATION_INFO,
27 p_next: std::ptr::null(),
28 p_application_name: app_name.as_ptr(),
29 application_version: 0,
30 p_engine_name: app_name.as_ptr(),
31 engine_version: 0,
32 api_version: vk::make_api_version(0, 1, 2, 0),
33 _marker: PhantomData,
34 };
35
36 let create_info = vk::InstanceCreateInfo {
37 s_type: vk::StructureType::INSTANCE_CREATE_INFO,
38 p_next: std::ptr::null(),
39 flags: vk::InstanceCreateFlags::empty(),
40 p_application_info: &app_info,
41 enabled_layer_count: 0,
42 pp_enabled_layer_names: std::ptr::null(),
43 enabled_extension_count: 0,
44 pp_enabled_extension_names: std::ptr::null(),
45 _marker: PhantomData,
46 };
47
48 let instance = unsafe { entry.create_instance(&create_info, None)? };
49
50 let pdevices = unsafe { instance.enumerate_physical_devices()? };
51 if pdevices.is_empty() {
52 return Err(anyhow::anyhow!("No Vulkan physical devices found"));
53 }
54 let physical_device = pdevices[0];
55
56 let queue_props = unsafe {
57 instance.get_physical_device_queue_family_properties(physical_device)
58 };
59 let mut compute_qfam = None;
60 for (i, props) in queue_props.iter().enumerate() {
61 if props.queue_flags.contains(vk::QueueFlags::COMPUTE) {
62 compute_qfam = Some(i as u32);
63 break;
64 }
65 }
66 let queue_family_index = compute_qfam.ok_or_else(|| {
67 anyhow::anyhow!("No queue family supports COMPUTE")
68 })?;
69
70 let queue_priority = 1.0f32;
71 let queue_info = vk::DeviceQueueCreateInfo {
72 s_type: vk::StructureType::DEVICE_QUEUE_CREATE_INFO,
73 p_next: std::ptr::null(),
74 flags: vk::DeviceQueueCreateFlags::empty(),
75 queue_family_index,
76 queue_count: 1,
77 p_queue_priorities: &queue_priority,
78 _marker: PhantomData,
79 };
80
81 #[allow(deprecated)]
82 let dev_create_info = vk::DeviceCreateInfo {
83 s_type: vk::StructureType::DEVICE_CREATE_INFO,
84 p_next: std::ptr::null(),
85 flags: vk::DeviceCreateFlags::empty(),
86 queue_create_info_count: 1,
87 p_queue_create_infos: &queue_info,
88 enabled_layer_count: 0,
89 pp_enabled_layer_names: std::ptr::null(),
90 enabled_extension_count: 0,
91 pp_enabled_extension_names: std::ptr::null(),
92 p_enabled_features: std::ptr::null(),
93 _marker: PhantomData,
94 };
95
96 let device = unsafe {
97 instance.create_device(physical_device, &dev_create_info, None)?
98 };
99 let queue = unsafe { device.get_device_queue(queue_family_index, 0) };
100
101 log::info!("AshVulkanContext => created successfully");
102 Ok(Self {
103 entry,
104 instance,
105 device,
106 queue,
107 queue_family_index,
108 })
109 }
110}
111
112impl Drop for AshVulkanContext {
113 fn drop(&mut self) {
114 unsafe {
115 self.device.destroy_device(None);
116 self.instance.destroy_instance(None);
117 }
118 log::info!("AshVulkanContext => destroyed");
119 }
120}
121
122lazy_static! {
123 pub static ref VULKAN_CONTEXT: Arc<Mutex<Option<AshVulkanContext>>> =
124 Arc::new(Mutex::new(None));
125}