1
use std::collections::HashMap;
2

            
3
use log::info;
4
use serde::{Deserialize, Serialize};
5

            
6
use crate::app::TweakSettings;
7

            
8
#[derive(Debug, Deserialize, Serialize)]
9
pub struct System {
10
    pub gpu_driver: GpuDriver,
11
}
12

            
13
#[derive(Debug, Deserialize, Serialize)]
14
pub struct GpuDriver {
15
    pub amd: Option<SystemTweaks>,
16
    pub nvidia: Option<SystemTweaks>,
17
}
18

            
19
#[derive(PartialEq, Debug, Deserialize, Serialize)]
20
pub struct SystemTweaks {
21
    pub tricks: Vec<String>,
22
    pub env: HashMap<String, String>,
23
    pub args: Vec<String>,
24
    pub settings: TweakSettings,
25
}
26

            
27
#[derive(PartialEq, Debug)]
28
pub enum GPU {
29
    AMD,
30
    NVIDIA,
31
    UNKNOWN,
32
}
33

            
34
impl GPU {
35
    pub fn as_str(&self) -> &'static str {
36
        match self {
37
            GPU::AMD => "amd",
38
            GPU::NVIDIA => "nvidia",
39
            GPU::UNKNOWN => "unknown",
40
        }
41
    }
42
}
43

            
44
pub struct SystemInfo {
45
    pub driver: String,
46
    pub driver_type: GPU,
47
}
48

            
49
3
pub async fn get_system_info() -> Option<SystemInfo> {
50
3
    let instance = wgpu::Instance::default();
51

            
52
3
    let adapter = instance
53
3
        .request_adapter(&wgpu::RequestAdapterOptions::default())
54
3
        .await?;
55

            
56
    Some(SystemInfo {
57
        driver: adapter.get_info().driver,
58
        driver_type: match adapter.get_info().driver.as_ref() {
59
            "NVIDIA" => GPU::NVIDIA,
60
            // TODO: Need someone with an AMD GPU to verify this is correct
61
            "AMD" => GPU::AMD,
62
            _ => GPU::UNKNOWN,
63
        },
64
    })
65
3
}
66

            
67
impl GpuDriver {
68
3
    async fn get_gpu_info(&self) -> GPU {
69
3
        if let Some(system_info) = get_system_info().await {
70
            system_info.driver_type
71
        } else {
72
3
            GPU::UNKNOWN
73
        }
74
3
    }
75

            
76
3
    pub async fn get_tweaks(&self) -> &Option<SystemTweaks> {
77
3
        match self.get_gpu_info().await {
78
3
            GPU::UNKNOWN => &None,
79
            gpu => {
80
                info!("Detected gpu as '{}'", gpu.as_str());
81
                self.get_tweaks_for_gpu(gpu)
82
            }
83
        }
84
3
    }
85

            
86
6
    pub fn get_tweaks_for_gpu(&self, gpu: GPU) -> &Option<SystemTweaks> {
87
6
        match gpu {
88
3
            GPU::AMD => &self.amd,
89
3
            GPU::NVIDIA => &self.nvidia,
90
            GPU::UNKNOWN => &None,
91
        }
92
6
    }
93
}
94

            
95
#[cfg(test)]
96
mod tests {
97
    use super::*;
98

            
99
    #[tokio::test]
100
3
    async fn get_tweaks() {
101
3
        let driver = GpuDriver {
102
3
            amd: None,
103
3
            nvidia: Some(SystemTweaks {
104
3
                env: HashMap::new(),
105
3
                tricks: vec![],
106
3
                args: vec![],
107
3
                settings: TweakSettings {
108
3
                    gamemode: None,
109
3
                    mangohud: None,
110
3
                },
111
3
            }),
112
3
        };
113

            
114
3
        assert_eq!(driver.get_tweaks_for_gpu(GPU::AMD), &None);
115
3
        assert_eq!(driver.get_tweaks_for_gpu(GPU::NVIDIA), &driver.nvidia);
116
3
    }
117
}