cvkg_render_gpu/subsystems/
gpu_capabilities.rs1use std::fmt;
8
9#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
13pub enum GpuVendor {
14 Nvidia,
15 Amd,
16 Intel,
17 Apple,
18 Qualcomm,
19 Arm,
20 ImgTec,
21 Microsoft,
22 Mesa,
23 Broadcom,
24 Unknown,
25}
26
27impl fmt::Display for GpuVendor {
28 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
29 let s = match self {
30 GpuVendor::Nvidia => "NVIDIA",
31 GpuVendor::Amd => "AMD",
32 GpuVendor::Intel => "Intel",
33 GpuVendor::Apple => "Apple",
34 GpuVendor::Qualcomm => "Qualcomm",
35 GpuVendor::Arm => "ARM",
36 GpuVendor::ImgTec => "Imagination",
37 GpuVendor::Microsoft => "Microsoft",
38 GpuVendor::Mesa => "Mesa",
39 GpuVendor::Broadcom => "Broadcom",
40 GpuVendor::Unknown => "Unknown",
41 };
42 f.write_str(s)
43 }
44}
45
46pub fn detect_gpu_vendor(adapter_name: &str) -> GpuVendor {
54 let name = adapter_name.to_lowercase();
55 if name.contains("nvidia")
56 || name.contains("geforce")
57 || name.contains("quadro")
58 || name.contains("tesla")
59 {
60 GpuVendor::Nvidia
61 } else if name.contains("amd")
62 || name.contains("radeon")
63 || name.contains("rx ")
64 || name.contains("firepro")
65 {
66 GpuVendor::Amd
67 } else if name.contains("intel")
68 || name.contains("uhd")
69 || name.contains("iris")
70 || name.contains("hd graphics")
71 {
72 GpuVendor::Intel
73 } else if name.contains("apple")
74 || name.contains("m1")
75 || name.contains("m2")
76 || name.contains("m3")
77 {
78 GpuVendor::Apple
79 } else if name.contains("qualcomm") || name.contains("adreno") {
80 GpuVendor::Qualcomm
81 } else if name.contains("arm") || name.contains("mali") {
82 GpuVendor::Arm
83 } else if name.contains("imgtec") || name.contains("powervr") {
84 GpuVendor::ImgTec
85 } else if name.contains("microsoft") || name.contains("direct3d12") {
86 GpuVendor::Microsoft
87 } else if name.contains("mesa") || name.contains("llvmpipe") || name.contains("swiftshader") {
88 GpuVendor::Mesa
89 } else if name.contains("broadcom") || name.contains("videocore") {
90 GpuVendor::Broadcom
91 } else {
92 GpuVendor::Unknown
93 }
94}
95
96#[derive(Debug, Clone)]
100pub struct GpuCapabilities {
101 pub vendor: GpuVendor,
103 pub adapter_name: String,
105 pub backend: String,
107}
108
109impl GpuCapabilities {
110 pub fn detect(adapter_name: &str, backend: impl Into<String>) -> Self {
112 Self {
113 vendor: detect_gpu_vendor(adapter_name),
114 adapter_name: adapter_name.to_string(),
115 backend: backend.into(),
116 }
117 }
118}
119
120impl fmt::Display for GpuCapabilities {
121 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
122 write!(
123 f,
124 "{} GPU '{}' on {} backend",
125 self.vendor, self.adapter_name, self.backend
126 )
127 }
128}
129
130#[cfg(test)]
131mod tests {
132 use super::*;
133
134 #[test]
135 fn detects_nvidia() {
136 assert_eq!(
137 detect_gpu_vendor("NVIDIA GeForce RTX 3080"),
138 GpuVendor::Nvidia
139 );
140 assert_eq!(detect_gpu_vendor("Quadro P4000"), GpuVendor::Nvidia);
141 }
142
143 #[test]
144 fn detects_amd() {
145 assert_eq!(detect_gpu_vendor("AMD Radeon RX 6800 XT"), GpuVendor::Amd);
146 assert_eq!(detect_gpu_vendor("Radeon Pro 5500M"), GpuVendor::Amd);
147 }
148
149 #[test]
150 fn detects_intel() {
151 assert_eq!(
152 detect_gpu_vendor("Intel UHD Graphics 630"),
153 GpuVendor::Intel
154 );
155 assert_eq!(detect_gpu_vendor("Intel Iris Xe"), GpuVendor::Intel);
156 }
157
158 #[test]
159 fn detects_apple() {
160 assert_eq!(detect_gpu_vendor("Apple M1 Pro"), GpuVendor::Apple);
161 assert_eq!(detect_gpu_vendor("Apple M2 GPU"), GpuVendor::Apple);
162 }
163
164 #[test]
165 fn detects_qualcomm() {
166 assert_eq!(
167 detect_gpu_vendor("Qualcomm Adreno 660"),
168 GpuVendor::Qualcomm
169 );
170 }
171
172 #[test]
173 fn detects_arm_mali() {
174 assert_eq!(detect_gpu_vendor("ARM Mali-G78"), GpuVendor::Arm);
175 }
176
177 #[test]
178 fn detects_mesa_software() {
179 assert_eq!(detect_gpu_vendor("Mesa llvmpipe"), GpuVendor::Mesa);
180 assert_eq!(detect_gpu_vendor("Google SwiftShader"), GpuVendor::Mesa);
181 }
182
183 #[test]
184 fn unknown_for_garbage() {
185 assert_eq!(detect_gpu_vendor("Custom XYZ GPU 9000"), GpuVendor::Unknown);
186 }
187
188 #[test]
189 fn case_insensitive() {
190 assert_eq!(
191 detect_gpu_vendor("nvidia geforce gtx 1080"),
192 GpuVendor::Nvidia
193 );
194 assert_eq!(detect_gpu_vendor("AMD RADEON VII"), GpuVendor::Amd);
195 }
196
197 #[test]
198 fn capabilities_display() {
199 let caps = GpuCapabilities::detect("NVIDIA GeForce RTX 3080", "Vulkan");
200 let s = format!("{}", caps);
201 assert!(s.contains("NVIDIA"));
202 assert!(s.contains("GeForce"));
203 assert!(s.contains("Vulkan"));
204 }
205}