wgpu_types/
instance.rs

1//! Types for dealing with Instances
2
3use alloc::string::String;
4
5use crate::Backends;
6
7/// Options for creating an instance.
8#[derive(Clone, Debug)]
9pub struct InstanceDescriptor {
10    /// Which `Backends` to enable.
11    pub backends: Backends,
12    /// Flags to tune the behavior of the instance.
13    pub flags: InstanceFlags,
14    /// Options the control the behavior of various backends.
15    pub backend_options: BackendOptions,
16}
17
18impl Default for InstanceDescriptor {
19    fn default() -> Self {
20        Self {
21            backends: Backends::all(),
22            flags: InstanceFlags::default(),
23            backend_options: BackendOptions::default(),
24        }
25    }
26}
27
28impl InstanceDescriptor {
29    /// Choose instance options entirely from environment variables.
30    ///
31    /// This is equivalent to calling `from_env` on every field.
32    #[must_use]
33    pub fn from_env_or_default() -> Self {
34        Self::default().with_env()
35    }
36
37    /// Takes the given options, modifies them based on the environment variables, and returns the result.
38    ///
39    /// This is equivalent to calling `with_env` on every field.
40    #[must_use]
41    pub fn with_env(self) -> Self {
42        let backends = self.backends.with_env();
43        let flags = self.flags.with_env();
44        let backend_options = self.backend_options.with_env();
45        Self {
46            backends,
47            flags,
48            backend_options,
49        }
50    }
51}
52
53bitflags::bitflags! {
54    /// Instance debugging flags.
55    ///
56    /// These are not part of the webgpu standard.
57    ///
58    /// Defaults to enabling debugging-related flags if the build configuration has `debug_assertions`.
59    #[repr(transparent)]
60    #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
61    pub struct InstanceFlags: u32 {
62        /// Generate debug information in shaders and objects.
63        ///
64        /// When `Self::from_env()` is used takes value from `WGPU_DEBUG` environment variable.
65        const DEBUG = 1 << 0;
66        /// Enable validation, if possible.
67        ///
68        /// When `Self::from_env()` is used takes value from `WGPU_VALIDATION` environment variable.
69        const VALIDATION = 1 << 1;
70        /// Don't pass labels to wgpu-hal.
71        ///
72        /// When `Self::from_env()` is used takes value from `WGPU_DISCARD_HAL_LABELS` environment variable.
73        const DISCARD_HAL_LABELS = 1 << 2;
74        /// Whether wgpu should expose adapters that run on top of non-compliant adapters.
75        ///
76        /// Turning this on might mean that some of the functionality provided by the wgpu
77        /// adapter/device is not working or is broken. It could be that all the functionality
78        /// wgpu currently exposes works but we can't tell for sure since we have no additional
79        /// transparency into what is working and what is not on the underlying adapter.
80        ///
81        /// This mainly applies to a Vulkan driver's compliance version. If the major compliance version
82        /// is `0`, then the driver is ignored. This flag allows that driver to be enabled for testing.
83        ///
84        /// When `Self::from_env()` is used takes value from `WGPU_ALLOW_UNDERLYING_NONCOMPLIANT_ADAPTER` environment variable.
85        const ALLOW_UNDERLYING_NONCOMPLIANT_ADAPTER = 1 << 3;
86        /// Enable GPU-based validation. Implies [`Self::VALIDATION`]. Currently, this only changes
87        /// behavior on the DX12 and Vulkan backends.
88        ///
89        /// Supported platforms:
90        ///
91        /// - D3D12; called ["GPU-based validation", or
92        ///   "GBV"](https://web.archive.org/web/20230206120404/https://learn.microsoft.com/en-us/windows/win32/direct3d12/using-d3d12-debug-layer-gpu-based-validation)
93        /// - Vulkan, via the `VK_LAYER_KHRONOS_validation` layer; called ["GPU-Assisted
94        ///   Validation"](https://github.com/KhronosGroup/Vulkan-ValidationLayers/blob/e45aeb85079e0835694cb8f03e6681fd18ae72c9/docs/gpu_validation.md#gpu-assisted-validation)
95        ///
96        /// When `Self::from_env()` is used takes value from `WGPU_GPU_BASED_VALIDATION` environment variable.
97        const GPU_BASED_VALIDATION = 1 << 4;
98    }
99}
100
101impl Default for InstanceFlags {
102    fn default() -> Self {
103        Self::from_build_config()
104    }
105}
106
107impl InstanceFlags {
108    /// Enable recommended debugging and validation flags.
109    #[must_use]
110    pub fn debugging() -> Self {
111        InstanceFlags::DEBUG | InstanceFlags::VALIDATION
112    }
113
114    /// Enable advanced debugging and validation flags (potentially very slow).
115    #[must_use]
116    pub fn advanced_debugging() -> Self {
117        Self::debugging() | InstanceFlags::GPU_BASED_VALIDATION
118    }
119
120    /// Infer decent defaults from the build type.
121    ///
122    /// If cfg!(debug_assertions) is true, then this returns [`Self::debugging()`].
123    /// Otherwise, it returns [`Self::empty()`].
124    #[must_use]
125    pub fn from_build_config() -> Self {
126        if cfg!(debug_assertions) {
127            return InstanceFlags::debugging();
128        }
129
130        InstanceFlags::empty()
131    }
132
133    /// Derive defaults from environment variables. See [`Self::with_env()`] for more information.
134    #[must_use]
135    pub fn from_env_or_default() -> Self {
136        Self::default().with_env()
137    }
138
139    /// Takes the given flags, modifies them based on the environment variables, and returns the result.
140    ///
141    /// - If an environment variable is set to anything but "0", the corresponding flag is set.
142    /// - If the value is "0", the flag is unset.
143    /// - If the environment variable is not present, then the flag retains its initial value.
144    ///
145    /// For example `let flags = InstanceFlags::debugging().with_env();` with `WGPU_VALIDATION=0`
146    /// does not contain `InstanceFlags::VALIDATION`.
147    ///
148    /// The environment variables are named after the flags prefixed with "WGPU_". For example:
149    /// - `WGPU_DEBUG`
150    /// - `WGPU_VALIDATION`
151    /// - `WGPU_DISCARD_HAL_LABELS`
152    /// - `WGPU_ALLOW_UNDERLYING_NONCOMPLIANT_ADAPTER`
153    /// - `WGPU_GPU_BASED_VALIDATION`
154    #[must_use]
155    pub fn with_env(mut self) -> Self {
156        fn env(key: &str) -> Option<bool> {
157            crate::env::var(key).map(|s| match s.as_str() {
158                "0" => false,
159                _ => true,
160            })
161        }
162
163        if let Some(bit) = env("WGPU_VALIDATION") {
164            self.set(Self::VALIDATION, bit);
165        }
166        if let Some(bit) = env("WGPU_DEBUG") {
167            self.set(Self::DEBUG, bit);
168        }
169        if let Some(bit) = env("WGPU_DISCARD_HAL_LABELS") {
170            self.set(Self::DISCARD_HAL_LABELS, bit);
171        }
172        if let Some(bit) = env("WGPU_ALLOW_UNDERLYING_NONCOMPLIANT_ADAPTER") {
173            self.set(Self::ALLOW_UNDERLYING_NONCOMPLIANT_ADAPTER, bit);
174        }
175        if let Some(bit) = env("WGPU_GPU_BASED_VALIDATION") {
176            self.set(Self::GPU_BASED_VALIDATION, bit);
177        }
178
179        self
180    }
181}
182
183/// Options that are passed to a given backend.
184#[derive(Clone, Debug, Default)]
185pub struct BackendOptions {
186    /// Options for the OpenGL/OpenGLES backend.
187    pub gl: GlBackendOptions,
188    /// Options for the DX12 backend.
189    pub dx12: Dx12BackendOptions,
190}
191
192impl BackendOptions {
193    /// Choose backend options by calling `from_env` on every field.
194    ///
195    /// See those methods for more information.
196    #[must_use]
197    pub fn from_env_or_default() -> Self {
198        let gl = GlBackendOptions::from_env_or_default();
199        let dx12 = Dx12BackendOptions::from_env_or_default();
200        Self { gl, dx12 }
201    }
202
203    /// Takes the given options, modifies them based on the environment variables, and returns the result.
204    ///
205    /// This is equivalent to calling `with_env` on every field.
206    #[must_use]
207    pub fn with_env(self) -> Self {
208        let gl = self.gl.with_env();
209        let dx12 = self.dx12.with_env();
210        Self { gl, dx12 }
211    }
212}
213
214/// Configuration for the OpenGL/OpenGLES backend.
215#[derive(Clone, Debug, Default)]
216pub struct GlBackendOptions {
217    /// Which OpenGL ES 3 minor version to request, if using OpenGL ES.
218    pub gles_minor_version: Gles3MinorVersion,
219}
220
221impl GlBackendOptions {
222    /// Choose OpenGL backend options by calling `from_env` on every field.
223    ///
224    /// See those methods for more information.
225    #[must_use]
226    pub fn from_env_or_default() -> Self {
227        let gles_minor_version = Gles3MinorVersion::from_env().unwrap_or_default();
228        Self { gles_minor_version }
229    }
230
231    /// Takes the given options, modifies them based on the environment variables, and returns the result.
232    ///
233    /// This is equivalent to calling `with_env` on every field.
234    #[must_use]
235    pub fn with_env(self) -> Self {
236        let gles_minor_version = self.gles_minor_version.with_env();
237        Self { gles_minor_version }
238    }
239}
240
241/// Configuration for the DX12 backend.
242#[derive(Clone, Debug, Default)]
243pub struct Dx12BackendOptions {
244    /// Which DX12 shader compiler to use.
245    pub shader_compiler: Dx12Compiler,
246}
247
248impl Dx12BackendOptions {
249    /// Choose DX12 backend options by calling `from_env` on every field.
250    ///
251    /// See those methods for more information.
252    #[must_use]
253    pub fn from_env_or_default() -> Self {
254        let compiler = Dx12Compiler::from_env().unwrap_or_default();
255        Self {
256            shader_compiler: compiler,
257        }
258    }
259
260    /// Takes the given options, modifies them based on the environment variables, and returns the result.
261    ///
262    /// This is equivalent to calling `with_env` on every field.
263    #[must_use]
264    pub fn with_env(self) -> Self {
265        let shader_compiler = self.shader_compiler.with_env();
266        Self { shader_compiler }
267    }
268}
269
270/// Selects which DX12 shader compiler to use.
271///
272/// If the `DynamicDxc` option is selected, but `dxcompiler.dll` and `dxil.dll` files aren't found,
273/// then this will fall back to the Fxc compiler at runtime and log an error.
274#[derive(Clone, Debug, Default)]
275pub enum Dx12Compiler {
276    /// The Fxc compiler (default) is old, slow and unmaintained.
277    ///
278    /// However, it doesn't require any additional .dlls to be shipped with the application.
279    #[default]
280    Fxc,
281    /// The Dxc compiler is new, fast and maintained.
282    ///
283    /// However, it requires both `dxcompiler.dll` and `dxil.dll` to be shipped with the application.
284    /// These files can be downloaded from <https://github.com/microsoft/DirectXShaderCompiler/releases>.
285    ///
286    /// Minimum supported version: [v1.5.2010](https://github.com/microsoft/DirectXShaderCompiler/releases/tag/v1.5.2010)
287    ///
288    /// It also requires WDDM 2.1 (Windows 10 version 1607).
289    DynamicDxc {
290        /// Path to `dxcompiler.dll`.
291        dxc_path: String,
292        /// Path to `dxil.dll`.
293        dxil_path: String,
294    },
295    /// The statically-linked variant of Dxc.
296    ///
297    /// The `static-dxc` feature is required for this setting to be used successfully on DX12.
298    /// Not available on `windows-aarch64-pc-*` targets.
299    StaticDxc,
300}
301
302impl Dx12Compiler {
303    /// Choose which DX12 shader compiler to use from the environment variable `WGPU_DX12_COMPILER`.
304    ///
305    /// Valid values, case insensitive:
306    /// - `Fxc`
307    /// - `Dxc` or `DynamicDxc`
308    /// - `StaticDxc`
309    #[must_use]
310    pub fn from_env() -> Option<Self> {
311        let value = crate::env::var("WGPU_DX12_COMPILER")
312            .as_deref()?
313            .to_lowercase();
314        match value.as_str() {
315            "dxc" | "dynamicdxc" => Some(Self::DynamicDxc {
316                dxc_path: String::from("dxcompiler.dll"),
317                dxil_path: String::from("dxil.dll"),
318            }),
319            "staticdxc" => Some(Self::StaticDxc),
320            "fxc" => Some(Self::Fxc),
321            _ => None,
322        }
323    }
324
325    /// Takes the given compiler, modifies it based on the `WGPU_DX12_COMPILER` environment variable, and returns the result.
326    ///
327    /// See `from_env` for more information.
328    #[must_use]
329    pub fn with_env(self) -> Self {
330        if let Some(compiler) = Self::from_env() {
331            compiler
332        } else {
333            self
334        }
335    }
336}
337
338/// Selects which OpenGL ES 3 minor version to request.
339///
340/// When using ANGLE as an OpenGL ES/EGL implementation, explicitly requesting `Version1` can provide a non-conformant ES 3.1 on APIs like D3D11.
341#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Hash)]
342pub enum Gles3MinorVersion {
343    /// No explicit minor version is requested, the driver automatically picks the highest available.
344    #[default]
345    Automatic,
346
347    /// Request an ES 3.0 context.
348    Version0,
349
350    /// Request an ES 3.1 context.
351    Version1,
352
353    /// Request an ES 3.2 context.
354    Version2,
355}
356
357impl Gles3MinorVersion {
358    /// Choose which minor OpenGL ES version to use from the environment variable `WGPU_GLES_MINOR_VERSION`.
359    ///
360    /// Possible values are `0`, `1`, `2` or `automatic`. Case insensitive.
361    ///
362    /// Use with `unwrap_or_default()` to get the default value if the environment variable is not set.
363    #[must_use]
364    pub fn from_env() -> Option<Self> {
365        let value = crate::env::var("WGPU_GLES_MINOR_VERSION")
366            .as_deref()?
367            .to_lowercase();
368        match value.as_str() {
369            "automatic" => Some(Self::Automatic),
370            "0" => Some(Self::Version0),
371            "1" => Some(Self::Version1),
372            "2" => Some(Self::Version2),
373            _ => None,
374        }
375    }
376
377    /// Takes the given compiler, modifies it based on the `WGPU_GLES_MINOR_VERSION` environment variable, and returns the result.
378    ///
379    /// See `from_env` for more information.
380    #[must_use]
381    pub fn with_env(self) -> Self {
382        if let Some(compiler) = Self::from_env() {
383            compiler
384        } else {
385            self
386        }
387    }
388}