1use crate::WgpuBackend;
2pub use wgpu::Backend;
3pub trait GraphicsApi: Send + Sync + core::fmt::Debug + Default + Clone + 'static {
12 fn backend() -> Backend;
14
15 fn backend_for(_device: &crate::WgpuDevice) -> WgpuBackend {
24 match Self::backend() {
25 Backend::Vulkan => WgpuBackend::Vulkan,
26 Backend::Metal => WgpuBackend::Metal,
27 Backend::Dx12 => WgpuBackend::Dx12,
28 Backend::Gl => WgpuBackend::Gl,
29 Backend::BrowserWebGpu => WgpuBackend::WebGpu,
30 Backend::Noop => panic!("The noop backend has no WgpuBackend selection"),
31 }
32 }
33}
34
35#[derive(Default, Debug, Clone)]
37pub struct Vulkan;
38
39#[derive(Default, Debug, Clone)]
41pub struct Metal;
42
43#[derive(Default, Debug, Clone)]
45pub struct OpenGl;
46
47#[derive(Default, Debug, Clone)]
49pub struct Dx12;
50
51#[derive(Default, Debug, Clone)]
53pub struct WebGpu;
54
55#[derive(Default, Debug, Clone)]
57pub struct AutoGraphicsApi;
58
59impl GraphicsApi for Vulkan {
60 fn backend() -> Backend {
61 Backend::Vulkan
62 }
63}
64
65impl GraphicsApi for Metal {
66 fn backend() -> Backend {
67 Backend::Metal
68 }
69}
70
71impl GraphicsApi for OpenGl {
72 fn backend() -> Backend {
73 Backend::Gl
74 }
75}
76
77impl GraphicsApi for Dx12 {
78 fn backend() -> Backend {
79 Backend::Dx12
80 }
81}
82
83impl GraphicsApi for WebGpu {
84 fn backend() -> Backend {
85 Backend::BrowserWebGpu
86 }
87}
88
89impl AutoGraphicsApi {
90 pub fn chain() -> alloc::vec::Vec<Backend> {
102 #[cfg(all(feature = "std", test))]
103 if let Ok(backend) = std::env::var("AUTO_GRAPHICS_BACKEND") {
104 let backend = match backend.to_lowercase().as_str() {
105 "metal" => Backend::Metal,
106 "vulkan" => Backend::Vulkan,
107 "dx12" => Backend::Dx12,
108 "opengl" => Backend::Gl,
109 "webgpu" => Backend::BrowserWebGpu,
110 _ => {
111 eprintln!(
112 "Invalid graphics backend specified in AUTO_GRAPHICS_BACKEND environment \
113 variable"
114 );
115 std::process::exit(1);
116 }
117 };
118
119 return alloc::vec![backend];
120 }
121
122 cfg_if::cfg_if! {
123 if #[cfg(target_family = "wasm")] {
124 alloc::vec![Backend::BrowserWebGpu]
125 } else if #[cfg(target_os = "macos")] {
126 alloc::vec![Backend::Metal]
127 } else {
128 alloc::vec![Backend::Vulkan, Backend::Dx12, Backend::Gl]
129 }
130 }
131 }
132}
133
134impl GraphicsApi for AutoGraphicsApi {
135 fn backend() -> Backend {
140 crate::runtime::resolve_backend(crate::WgpuBackend::Auto)
141 }
142
143 fn backend_for(device: &crate::WgpuDevice) -> WgpuBackend {
145 device.backend
146 }
147}
148
149#[cfg(test)]
150mod selection_tests {
151 use super::*;
152
153 #[test]
154 fn named_apis_preserve_their_backend() {
155 fn check<G: GraphicsApi>(expected: WgpuBackend) {
156 let selected = G::backend_for(&crate::WgpuDevice::default());
157 assert_eq!(selected, expected);
158 }
159
160 check::<Vulkan>(WgpuBackend::Vulkan);
161 check::<Metal>(WgpuBackend::Metal);
162 check::<Dx12>(WgpuBackend::Dx12);
163 check::<OpenGl>(WgpuBackend::Gl);
164 check::<WebGpu>(WgpuBackend::WebGpu);
165 }
166
167 #[test]
168 fn automatic_api_preserves_auto_and_pinned_selections() {
169 for backend in [
170 WgpuBackend::Auto,
171 WgpuBackend::Vulkan,
172 WgpuBackend::Metal,
173 WgpuBackend::Dx12,
174 WgpuBackend::Gl,
175 WgpuBackend::WebGpu,
176 ] {
177 let device = crate::WgpuDevice::default().on(backend);
178 assert_eq!(AutoGraphicsApi::backend_for(&device), backend);
179 }
180 }
181}