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") || name.contains("geforce") || name.contains("quadro") || name.contains("tesla") {
56 GpuVendor::Nvidia
57 } else if name.contains("amd") || name.contains("radeon") || name.contains("rx ") || name.contains("firepro") {
58 GpuVendor::Amd
59 } else if name.contains("intel") || name.contains("uhd") || name.contains("iris") || name.contains("hd graphics") {
60 GpuVendor::Intel
61 } else if name.contains("apple") || name.contains("m1") || name.contains("m2") || name.contains("m3") {
62 GpuVendor::Apple
63 } else if name.contains("qualcomm") || name.contains("adreno") {
64 GpuVendor::Qualcomm
65 } else if name.contains("arm") || name.contains("mali") {
66 GpuVendor::Arm
67 } else if name.contains("imgtec") || name.contains("powervr") {
68 GpuVendor::ImgTec
69 } else if name.contains("microsoft") || name.contains("direct3d12") {
70 GpuVendor::Microsoft
71 } else if name.contains("mesa") || name.contains("llvmpipe") || name.contains("swiftshader") {
72 GpuVendor::Mesa
73 } else if name.contains("broadcom") || name.contains("videocore") {
74 GpuVendor::Broadcom
75 } else {
76 GpuVendor::Unknown
77 }
78}
79
80#[derive(Debug, Clone)]
84pub struct GpuCapabilities {
85 pub vendor: GpuVendor,
87 pub adapter_name: String,
89 pub backend: String,
91}
92
93impl GpuCapabilities {
94 pub fn detect(adapter_name: &str, backend: impl Into<String>) -> Self {
96 Self {
97 vendor: detect_gpu_vendor(adapter_name),
98 adapter_name: adapter_name.to_string(),
99 backend: backend.into(),
100 }
101 }
102}
103
104impl fmt::Display for GpuCapabilities {
105 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
106 write!(
107 f,
108 "{} GPU '{}' on {} backend",
109 self.vendor, self.adapter_name, self.backend
110 )
111 }
112}
113
114#[cfg(test)]
115mod tests {
116 use super::*;
117
118 #[test]
119 fn detects_nvidia() {
120 assert_eq!(detect_gpu_vendor("NVIDIA GeForce RTX 3080"), GpuVendor::Nvidia);
121 assert_eq!(detect_gpu_vendor("Quadro P4000"), GpuVendor::Nvidia);
122 }
123
124 #[test]
125 fn detects_amd() {
126 assert_eq!(detect_gpu_vendor("AMD Radeon RX 6800 XT"), GpuVendor::Amd);
127 assert_eq!(detect_gpu_vendor("Radeon Pro 5500M"), GpuVendor::Amd);
128 }
129
130 #[test]
131 fn detects_intel() {
132 assert_eq!(detect_gpu_vendor("Intel UHD Graphics 630"), GpuVendor::Intel);
133 assert_eq!(detect_gpu_vendor("Intel Iris Xe"), GpuVendor::Intel);
134 }
135
136 #[test]
137 fn detects_apple() {
138 assert_eq!(detect_gpu_vendor("Apple M1 Pro"), GpuVendor::Apple);
139 assert_eq!(detect_gpu_vendor("Apple M2 GPU"), GpuVendor::Apple);
140 }
141
142 #[test]
143 fn detects_qualcomm() {
144 assert_eq!(detect_gpu_vendor("Qualcomm Adreno 660"), GpuVendor::Qualcomm);
145 }
146
147 #[test]
148 fn detects_arm_mali() {
149 assert_eq!(detect_gpu_vendor("ARM Mali-G78"), GpuVendor::Arm);
150 }
151
152 #[test]
153 fn detects_mesa_software() {
154 assert_eq!(detect_gpu_vendor("Mesa llvmpipe"), GpuVendor::Mesa);
155 assert_eq!(detect_gpu_vendor("Google SwiftShader"), GpuVendor::Mesa);
156 }
157
158 #[test]
159 fn unknown_for_garbage() {
160 assert_eq!(detect_gpu_vendor("Custom XYZ GPU 9000"), GpuVendor::Unknown);
161 }
162
163 #[test]
164 fn case_insensitive() {
165 assert_eq!(detect_gpu_vendor("nvidia geforce gtx 1080"), GpuVendor::Nvidia);
166 assert_eq!(detect_gpu_vendor("AMD RADEON VII"), GpuVendor::Amd);
167 }
168
169 #[test]
170 fn capabilities_display() {
171 let caps = GpuCapabilities::detect("NVIDIA GeForce RTX 3080", "Vulkan");
172 let s = format!("{}", caps);
173 assert!(s.contains("NVIDIA"));
174 assert!(s.contains("GeForce"));
175 assert!(s.contains("Vulkan"));
176 }
177}