mumugpu/
vulkan.rs

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}