#[cfg(all(target_os = "macos", feature = "metal"))]
pub mod metal_shaders;
pub trait Backend: Send + Sync {
fn name(&self) -> &str;
fn is_available(&self) -> bool;
fn device_count(&self) -> usize;
}
#[derive(Debug, Default)]
pub struct CudaBackend;
impl Backend for CudaBackend {
fn name(&self) -> &str {
"CUDA"
}
fn is_available(&self) -> bool {
crate::driver::cuda_available()
}
#[cfg(feature = "cuda")]
fn device_count(&self) -> usize {
if self.is_available() {
crate::driver::device_count().unwrap_or(0)
} else {
0
}
}
#[cfg(not(feature = "cuda"))]
fn device_count(&self) -> usize {
if self.is_available() {
crate::driver::device_count()
} else {
0
}
}
}
#[derive(Debug, Default)]
pub struct MetalBackend;
impl Backend for MetalBackend {
fn name(&self) -> &str {
"Metal"
}
#[cfg(all(target_os = "macos", feature = "metal"))]
fn is_available(&self) -> bool {
manzana::metal::is_available()
}
#[cfg(not(all(target_os = "macos", feature = "metal")))]
fn is_available(&self) -> bool {
false
}
#[cfg(all(target_os = "macos", feature = "metal"))]
fn device_count(&self) -> usize {
manzana::metal::MetalCompute::devices().len()
}
#[cfg(not(all(target_os = "macos", feature = "metal")))]
fn device_count(&self) -> usize {
0
}
}
#[cfg(all(target_os = "macos", feature = "metal"))]
pub use manzana::metal::{CompiledShader as MetalShader, MetalBuffer, MetalCompute, MetalDevice};
#[derive(Debug, Default)]
pub struct VulkanBackend;
impl Backend for VulkanBackend {
fn name(&self) -> &str {
"Vulkan"
}
fn is_available(&self) -> bool {
false }
fn device_count(&self) -> usize {
0
}
}
#[derive(Debug, Default)]
pub struct WgpuBackend;
impl Backend for WgpuBackend {
fn name(&self) -> &str {
"WGPU"
}
fn is_available(&self) -> bool {
cfg!(feature = "wgpu")
}
fn device_count(&self) -> usize {
usize::from(self.is_available())
}
}
#[must_use]
pub fn detect_backend() -> Box<dyn Backend> {
let cuda = CudaBackend;
if cuda.is_available() {
return Box::new(cuda);
}
let wgpu = WgpuBackend;
if wgpu.is_available() {
return Box::new(wgpu);
}
let metal = MetalBackend;
if metal.is_available() {
return Box::new(metal);
}
let vulkan = VulkanBackend;
if vulkan.is_available() {
return Box::new(vulkan);
}
Box::new(CudaBackend)
}
#[cfg(test)]
mod tests;