cubecl_wgpu/graphics.rs
1pub use wgpu::Backend;
2/// The basic trait to specify which graphics API to use as Backend.
3///
4/// Options are:
5/// - [Vulkan](Vulkan)
6/// - [Metal](Metal)
7/// - [OpenGL](OpenGl)
8/// - [DirectX 12](Dx12)
9/// - [WebGpu](WebGpu)
10pub trait GraphicsApi: Send + Sync + core::fmt::Debug + Default + Clone + 'static {
11 /// The wgpu backend.
12 fn backend() -> Backend;
13
14 /// The wgpu backend `device` comes up on when set up through this API.
15 ///
16 /// A named API is itself, whatever the device. [`AutoGraphicsApi`] is the
17 /// one that defers, to the API the device pins where it pins one.
18 fn backend_for(device: &crate::WgpuDevice) -> Backend {
19 let _ = device;
20 Self::backend()
21 }
22}
23
24/// Vulkan graphics API.
25#[derive(Default, Debug, Clone)]
26pub struct Vulkan;
27
28/// Metal graphics API.
29#[derive(Default, Debug, Clone)]
30pub struct Metal;
31
32/// OpenGL graphics API.
33#[derive(Default, Debug, Clone)]
34pub struct OpenGl;
35
36/// DirectX 12 graphics API.
37#[derive(Default, Debug, Clone)]
38pub struct Dx12;
39
40/// `WebGpu` graphics API.
41#[derive(Default, Debug, Clone)]
42pub struct WebGpu;
43
44/// Automatic graphics API based on OS.
45#[derive(Default, Debug, Clone)]
46pub struct AutoGraphicsApi;
47
48impl GraphicsApi for Vulkan {
49 fn backend() -> Backend {
50 Backend::Vulkan
51 }
52}
53
54impl GraphicsApi for Metal {
55 fn backend() -> Backend {
56 Backend::Metal
57 }
58}
59
60impl GraphicsApi for OpenGl {
61 fn backend() -> Backend {
62 Backend::Gl
63 }
64}
65
66impl GraphicsApi for Dx12 {
67 fn backend() -> Backend {
68 Backend::Dx12
69 }
70}
71
72impl GraphicsApi for WebGpu {
73 fn backend() -> Backend {
74 Backend::BrowserWebGpu
75 }
76}
77
78impl AutoGraphicsApi {
79 /// The graphics APIs to try on this machine, best first.
80 ///
81 /// Vulkan leads wherever it reaches a GPU: it is the one that compiles to
82 /// `SPIR-V`, and the rest are what a machine without it still offers. An
83 /// API with only a software rasterizer is passed over for a later one
84 /// with a GPU, and taken only when none has one. Backends this machine has
85 /// no driver for enumerate nothing, so a list costs only the asking.
86 ///
87 /// This crate's own tests can narrow it to one with `AUTO_GRAPHICS_BACKEND`,
88 /// which then holds for every `Auto` device, not only those set up through
89 /// [`GraphicsApi::backend`].
90 pub fn chain() -> alloc::vec::Vec<Backend> {
91 #[cfg(all(feature = "std", test))]
92 if let Ok(backend) = std::env::var("AUTO_GRAPHICS_BACKEND") {
93 let backend = match backend.to_lowercase().as_str() {
94 "metal" => Backend::Metal,
95 "vulkan" => Backend::Vulkan,
96 "dx12" => Backend::Dx12,
97 "opengl" => Backend::Gl,
98 "webgpu" => Backend::BrowserWebGpu,
99 _ => {
100 eprintln!(
101 "Invalid graphics backend specified in AUTO_GRAPHICS_BACKEND environment \
102 variable"
103 );
104 std::process::exit(1);
105 }
106 };
107
108 return alloc::vec![backend];
109 }
110
111 cfg_if::cfg_if! {
112 if #[cfg(target_family = "wasm")] {
113 alloc::vec![Backend::BrowserWebGpu]
114 } else if #[cfg(target_os = "macos")] {
115 alloc::vec![Backend::Metal]
116 } else {
117 alloc::vec![Backend::Vulkan, Backend::Dx12, Backend::Gl]
118 }
119 }
120 }
121}
122
123impl GraphicsApi for AutoGraphicsApi {
124 /// The first of the [chain](Self::chain) this machine has an adapter for —
125 /// the API a [`WgpuBackend::Auto`](crate::WgpuBackend::Auto) device comes
126 /// up on, so a setup made through this lands where a client made on first
127 /// use would.
128 fn backend() -> Backend {
129 crate::runtime::resolve_backend(crate::WgpuBackend::Auto)
130 }
131
132 /// The API `device` pins, or where it pins none, [`backend`](Self::backend).
133 fn backend_for(device: &crate::WgpuDevice) -> Backend {
134 crate::runtime::resolve_backend(device.backend)
135 }
136}