trueno_gpu/backend/
mod.rs1#[cfg(all(target_os = "macos", feature = "metal"))]
10pub mod metal_shaders;
11
12pub trait Backend: Send + Sync {
14 fn name(&self) -> &str;
16
17 fn is_available(&self) -> bool;
19
20 fn device_count(&self) -> usize;
22}
23
24#[derive(Debug, Default)]
26pub struct CudaBackend;
27
28impl Backend for CudaBackend {
29 fn name(&self) -> &str {
30 "CUDA"
31 }
32
33 fn is_available(&self) -> bool {
34 #[cfg(feature = "cuda")]
35 {
36 crate::driver::cuda_available()
37 }
38 #[cfg(not(feature = "cuda"))]
39 {
40 false
41 }
42 }
43
44 fn device_count(&self) -> usize {
45 #[cfg(feature = "cuda")]
46 {
47 if self.is_available() {
48 crate::driver::device_count().unwrap_or(0)
49 } else {
50 0
51 }
52 }
53 #[cfg(not(feature = "cuda"))]
54 {
55 0
56 }
57 }
58}
59
60#[derive(Debug, Default)]
65pub struct MetalBackend;
66
67impl Backend for MetalBackend {
68 fn name(&self) -> &str {
69 "Metal"
70 }
71
72 #[cfg(all(target_os = "macos", feature = "metal"))]
73 fn is_available(&self) -> bool {
74 manzana::metal::is_available()
75 }
76
77 #[cfg(not(all(target_os = "macos", feature = "metal")))]
78 fn is_available(&self) -> bool {
79 false
80 }
81
82 #[cfg(all(target_os = "macos", feature = "metal"))]
83 fn device_count(&self) -> usize {
84 manzana::metal::MetalCompute::devices().len()
85 }
86
87 #[cfg(not(all(target_os = "macos", feature = "metal")))]
88 fn device_count(&self) -> usize {
89 0
90 }
91}
92
93#[cfg(all(target_os = "macos", feature = "metal"))]
95pub use manzana::metal::{CompiledShader as MetalShader, MetalBuffer, MetalCompute, MetalDevice};
96
97#[derive(Debug, Default)]
99pub struct VulkanBackend;
100
101impl Backend for VulkanBackend {
102 fn name(&self) -> &str {
103 "Vulkan"
104 }
105
106 fn is_available(&self) -> bool {
107 false }
109
110 fn device_count(&self) -> usize {
111 0
112 }
113}
114
115#[derive(Debug, Default)]
123pub struct WgpuBackend;
124
125impl Backend for WgpuBackend {
126 fn name(&self) -> &str {
127 "WGPU"
128 }
129
130 fn is_available(&self) -> bool {
131 cfg!(feature = "wgpu")
133 }
134
135 fn device_count(&self) -> usize {
136 usize::from(self.is_available())
138 }
139}
140
141#[must_use]
149pub fn detect_backend() -> Box<dyn Backend> {
150 let cuda = CudaBackend;
151 if cuda.is_available() {
152 return Box::new(cuda);
153 }
154
155 let wgpu = WgpuBackend;
156 if wgpu.is_available() {
157 return Box::new(wgpu);
158 }
159
160 let metal = MetalBackend;
161 if metal.is_available() {
162 return Box::new(metal);
163 }
164
165 let vulkan = VulkanBackend;
166 if vulkan.is_available() {
167 return Box::new(vulkan);
168 }
169
170 Box::new(CudaBackend)
172}
173
174#[cfg(test)]
175mod tests;