use crate::WgpuBackend;
pub use wgpu::Backend;
pub trait GraphicsApi: Send + Sync + core::fmt::Debug + Default + Clone + 'static {
fn backend() -> Backend;
fn backend_for(_device: &crate::WgpuDevice) -> WgpuBackend {
match Self::backend() {
Backend::Vulkan => WgpuBackend::Vulkan,
Backend::Metal => WgpuBackend::Metal,
Backend::Dx12 => WgpuBackend::Dx12,
Backend::Gl => WgpuBackend::Gl,
Backend::BrowserWebGpu => WgpuBackend::WebGpu,
Backend::Noop => panic!("The noop backend has no WgpuBackend selection"),
}
}
}
#[derive(Default, Debug, Clone)]
pub struct Vulkan;
#[derive(Default, Debug, Clone)]
pub struct Metal;
#[derive(Default, Debug, Clone)]
pub struct OpenGl;
#[derive(Default, Debug, Clone)]
pub struct Dx12;
#[derive(Default, Debug, Clone)]
pub struct WebGpu;
#[derive(Default, Debug, Clone)]
pub struct AutoGraphicsApi;
impl GraphicsApi for Vulkan {
fn backend() -> Backend {
Backend::Vulkan
}
}
impl GraphicsApi for Metal {
fn backend() -> Backend {
Backend::Metal
}
}
impl GraphicsApi for OpenGl {
fn backend() -> Backend {
Backend::Gl
}
}
impl GraphicsApi for Dx12 {
fn backend() -> Backend {
Backend::Dx12
}
}
impl GraphicsApi for WebGpu {
fn backend() -> Backend {
Backend::BrowserWebGpu
}
}
impl AutoGraphicsApi {
pub fn chain() -> alloc::vec::Vec<Backend> {
#[cfg(all(feature = "std", test))]
if let Ok(backend) = std::env::var("AUTO_GRAPHICS_BACKEND") {
let backend = match backend.to_lowercase().as_str() {
"metal" => Backend::Metal,
"vulkan" => Backend::Vulkan,
"dx12" => Backend::Dx12,
"opengl" => Backend::Gl,
"webgpu" => Backend::BrowserWebGpu,
_ => {
eprintln!(
"Invalid graphics backend specified in AUTO_GRAPHICS_BACKEND environment \
variable"
);
std::process::exit(1);
}
};
return alloc::vec![backend];
}
cfg_if::cfg_if! {
if #[cfg(target_family = "wasm")] {
alloc::vec![Backend::BrowserWebGpu]
} else if #[cfg(target_os = "macos")] {
alloc::vec![Backend::Metal]
} else {
alloc::vec![Backend::Vulkan, Backend::Dx12, Backend::Gl]
}
}
}
}
impl GraphicsApi for AutoGraphicsApi {
fn backend() -> Backend {
crate::runtime::resolve_backend(crate::WgpuBackend::Auto)
}
fn backend_for(device: &crate::WgpuDevice) -> WgpuBackend {
device.backend
}
}
#[cfg(test)]
mod selection_tests {
use super::*;
#[test]
fn named_apis_preserve_their_backend() {
fn check<G: GraphicsApi>(expected: WgpuBackend) {
let selected = G::backend_for(&crate::WgpuDevice::default());
assert_eq!(selected, expected);
}
check::<Vulkan>(WgpuBackend::Vulkan);
check::<Metal>(WgpuBackend::Metal);
check::<Dx12>(WgpuBackend::Dx12);
check::<OpenGl>(WgpuBackend::Gl);
check::<WebGpu>(WgpuBackend::WebGpu);
}
#[test]
fn automatic_api_preserves_auto_and_pinned_selections() {
for backend in [
WgpuBackend::Auto,
WgpuBackend::Vulkan,
WgpuBackend::Metal,
WgpuBackend::Dx12,
WgpuBackend::Gl,
WgpuBackend::WebGpu,
] {
let device = crate::WgpuDevice::default().on(backend);
assert_eq!(AutoGraphicsApi::backend_for(&device), backend);
}
}
}