wgpu_types/
instance.rs

1//! Types for dealing with Instances.
2
3use crate::{link_to_wgpu_docs, Backends};
4
5#[cfg(doc)]
6use crate::{Backend, DownlevelFlags};
7
8/// A [`raw_window_handle::HasDisplayHandle`] that can be shared across threads and has no borrows.
9///
10/// This blanket trait is automatically implemented for all objects that qualify.
11pub trait WgpuHasDisplayHandle:
12    raw_window_handle::HasDisplayHandle + core::fmt::Debug + Send + Sync + 'static
13{
14}
15impl<T: raw_window_handle::HasDisplayHandle + core::fmt::Debug + Send + Sync + 'static>
16    WgpuHasDisplayHandle for T
17{
18}
19
20/// Options for creating an instance.
21///
22/// If you want to allow control of instance settings via environment variables, call any of the
23/// `*from_env()` functions or [`InstanceDescriptor::with_env()`]. Each type within this descriptor
24/// has its own equivalent methods, so you can select which options you want to expose to influence
25/// from the environment.
26#[derive(Debug)]
27pub struct InstanceDescriptor {
28    /// Which [`Backends`] to enable.
29    ///
30    /// [`Backends::BROWSER_WEBGPU`] has an additional effect:
31    /// If it is set and a [`navigator.gpu`](https://developer.mozilla.org/en-US/docs/Web/API/Navigator/gpu)
32    /// object is present, this instance will *only* be able to create WebGPU adapters.
33    ///
34    /// ⚠️ On some browsers this check is insufficient to determine whether WebGPU is supported,
35    /// as the browser may define the `navigator.gpu` object, but be unable to create any WebGPU adapters.
36    /// For targeting _both_ WebGPU & WebGL, it is recommended to use [`crate::util::new_instance_with_webgpu_detection`](../wgpu/util/fn.new_instance_with_webgpu_detection.html).
37    ///
38    /// If you instead want to force use of WebGL, either disable the `webgpu` compile-time feature
39    /// or don't include the [`Backends::BROWSER_WEBGPU`] flag in this field.
40    /// If it is set and WebGPU support is *not* detected, the instance will use `wgpu-core`
41    /// to create adapters, meaning that if the `webgl` feature is enabled, it is able to create
42    /// a WebGL adapter.
43    pub backends: Backends,
44    /// Flags to tune the behavior of the instance.
45    pub flags: InstanceFlags,
46    /// Memory budget thresholds used by some backends.
47    pub memory_budget_thresholds: MemoryBudgetThresholds,
48    /// Options for configuring the behavior of specific backends.
49    pub backend_options: crate::BackendOptions,
50    /// System platform or compositor connection to connect this `Instance` to.
51    ///
52    /// If not [`None`], it is invalid to pass a different [`raw_window_handle::HasDisplayHandle`] to `create_surface()`.
53    ///
54    /// - On GLES, this is required when intending to present on the platform, especially for Wayland.
55    /// - On Vulkan, Metal and Dx12, this is currently unused.
56    ///
57    /// When used with `winit`, callers are expected to pass its [`OwnedDisplayHandle`] (created from
58    /// the `EventLoop`) here.
59    ///
60    /// [`OwnedDisplayHandle`]: https://docs.rs/winit/latest/winit/event_loop/struct.OwnedDisplayHandle.html
61    pub display: Option<alloc::boxed::Box<dyn WgpuHasDisplayHandle>>,
62}
63
64impl InstanceDescriptor {
65    /// The default instance options, without display handle.
66    #[must_use]
67    pub fn new_without_display_handle() -> Self {
68        Self {
69            backends: Default::default(),
70            flags: Default::default(),
71            memory_budget_thresholds: Default::default(),
72            backend_options: Default::default(),
73            display: None,
74        }
75    }
76
77    /// The default instance options, with display handle.
78    #[must_use]
79    pub fn new_with_display_handle(display: alloc::boxed::Box<dyn WgpuHasDisplayHandle>) -> Self {
80        Self::new_without_display_handle().with_display_handle(display)
81    }
82
83    /// Choose instance options entirely from environment variables.
84    ///
85    /// This is equivalent to calling `from_env` on every field.
86    #[must_use]
87    pub fn new_without_display_handle_from_env() -> Self {
88        Self::new_without_display_handle().with_env()
89    }
90
91    /// Choose instance options entirely from environment variables, while including a display handle.
92    ///
93    /// This is equivalent to calling `from_env` on every field.
94    #[must_use]
95    pub fn new_with_display_handle_from_env(
96        display: alloc::boxed::Box<dyn WgpuHasDisplayHandle>,
97    ) -> Self {
98        // Self::new_without_display_handle_from_env().with_display_handle(display)
99        Self::new_with_display_handle(display).with_env()
100    }
101
102    /// Takes the given options, modifies them based on the environment variables, and returns the result.
103    ///
104    /// This is equivalent to calling `with_env` on every field.
105    #[must_use]
106    pub fn with_env(self) -> Self {
107        let backends = self.backends.with_env();
108        let flags = self.flags.with_env();
109        let backend_options = self.backend_options.with_env();
110        Self {
111            backends,
112            flags,
113            memory_budget_thresholds: MemoryBudgetThresholds::default(),
114            backend_options,
115            display: self.display,
116        }
117    }
118
119    /// Appends the given `display` object to the descriptor.
120    #[must_use]
121    pub fn with_display_handle(self, display: alloc::boxed::Box<dyn WgpuHasDisplayHandle>) -> Self {
122        Self {
123            display: Some(display),
124            ..self
125        }
126    }
127}
128
129bitflags::bitflags! {
130    /// Instance debugging flags.
131    ///
132    /// These are not part of the WebGPU standard.
133    ///
134    /// Defaults to enabling debugging-related flags if the build configuration has `debug_assertions`.
135    #[repr(transparent)]
136    #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
137    pub struct InstanceFlags: u32 {
138        /// Generate debug information in shaders and objects.
139        ///
140        /// When `Self::from_env()` is used takes value from `WGPU_DEBUG` environment variable.
141        const DEBUG = 1 << 0;
142        /// Enable validation in the backend API, if possible:
143        ///
144        /// - On the Direct3D `dx12` backend, this calls [`ID3D12Debug::EnableDebugLayer`][dx12].
145        ///
146        /// - On the Vulkan backend, this enables the [Vulkan Validation Layer][vvl].
147        ///
148        /// - On the `gles` backend driving Windows OpenGL, this enables [debug
149        ///   output][gl:do], effectively calling `glEnable(GL_DEBUG_OUTPUT)`.
150        ///
151        /// - On non-Windows `gles` backends, this calls
152        ///   [`eglDebugMessageControlKHR`][gl:dm] to enable all debugging messages.
153        ///   If the GLES implementation is ANGLE running on Vulkan, this also
154        ///   enables the Vulkan validation layers by setting
155        ///   [`EGL_PLATFORM_ANGLE_DEBUG_LAYERS_ENABLED`][gl:av].
156        ///
157        /// When `Self::from_env()` is used, this bit is set if the `WGPU_VALIDATION`
158        /// environment variable has any value but "0".
159        ///
160        /// [dx12]: https://learn.microsoft.com/en-us/windows/win32/api/d3d12sdklayers/nf-d3d12sdklayers-id3d12debug-enabledebuglayer
161        /// [vvl]: https://github.com/KhronosGroup/Vulkan-ValidationLayers
162        /// [gl:dm]: https://registry.khronos.org/EGL/extensions/KHR/EGL_KHR_debug.txt
163        /// [gl:do]: https://www.khronos.org/opengl/wiki/Debug_Output
164        /// [gl:av]: https://chromium.googlesource.com/angle/angle/+/HEAD/extensions/EGL_ANGLE_platform_angle.txt
165        const VALIDATION = 1 << 1;
166        /// Don't pass labels to wgpu-hal.
167        ///
168        /// When `Self::from_env()` is used takes value from `WGPU_DISCARD_HAL_LABELS` environment variable.
169        const DISCARD_HAL_LABELS = 1 << 2;
170        /// Whether wgpu should expose adapters that run on top of non-compliant adapters.
171        ///
172        /// Turning this on might mean that some of the functionality provided by the wgpu
173        /// adapter/device is not working or is broken. It could be that all the functionality
174        /// wgpu currently exposes works but we can't tell for sure since we have no additional
175        /// transparency into what is working and what is not on the underlying adapter.
176        ///
177        /// This mainly applies to a Vulkan driver's compliance version. If the major compliance version
178        /// is `0`, then the driver is ignored. This flag allows that driver to be enabled for testing.
179        ///
180        /// This flag controls whether adapters that don't meet the *native*
181        /// API's own compliance requirements are returned, while
182        /// [`Self::STRICT_WEBGPU_COMPLIANCE`] controls whether adapters that
183        /// can't fully satisfy the *WebGPU v1* spec are excluded.
184        ///
185        /// When `Self::from_env()` is used takes value from `WGPU_ALLOW_UNDERLYING_NONCOMPLIANT_ADAPTER` environment variable.
186        const ALLOW_UNDERLYING_NONCOMPLIANT_ADAPTER = 1 << 3;
187        /// Enable GPU-based validation. Implies [`Self::VALIDATION`]. Currently, this only changes
188        /// behavior on the DX12 and Vulkan backends.
189        ///
190        /// Supported platforms:
191        ///
192        /// - D3D12; called ["GPU-based validation", or
193        ///   "GBV"](https://web.archive.org/web/20230206120404/https://learn.microsoft.com/en-us/windows/win32/direct3d12/using-d3d12-debug-layer-gpu-based-validation)
194        /// - Vulkan, via the `VK_LAYER_KHRONOS_validation` layer; called ["GPU-Assisted
195        ///   Validation"](https://github.com/KhronosGroup/Vulkan-ValidationLayers/blob/e45aeb85079e0835694cb8f03e6681fd18ae72c9/docs/gpu_validation.md#gpu-assisted-validation)
196        ///
197        /// When `Self::from_env()` is used takes value from `WGPU_GPU_BASED_VALIDATION` environment variable.
198        const GPU_BASED_VALIDATION = 1 << 4;
199
200        /// Validate indirect buffer content prior to issuing indirect draws/dispatches.
201        ///
202        /// This validation will transform indirect calls into no-ops if they are not valid:
203        ///
204        /// - When calling `dispatch_workgroups_indirect`, all 3 indirect arguments encoded in the buffer
205        /// must be less than the `max_compute_workgroups_per_dimension` device limit.
206        /// - When calling `draw_indirect`/`draw_indexed_indirect`/`multi_draw_indirect`/`multi_draw_indexed_indirect`:
207        ///   - If `Features::INDIRECT_FIRST_INSTANCE` is not enabled on the device, the `first_instance` indirect argument must be 0.
208        ///   - The `first_instance` & `instance_count` indirect arguments must form a range that fits within all bound vertex buffers with `step_mode` set to `Instance`.
209        /// - When calling `draw_indirect`/`multi_draw_indirect`:
210        ///   - The `first_vertex` & `vertex_count` indirect arguments must form a range that fits within all bound vertex buffers with `step_mode` set to `Vertex`.
211        /// - When calling `draw_indexed_indirect`/`multi_draw_indexed_indirect`:
212        ///   - The `first_index` & `index_count` indirect arguments must form a range that fits within the bound index buffer.
213        ///
214        /// __Behavior is undefined if this validation is disabled and the rules above are not satisfied.__
215        ///
216        /// Disabling this will also cause the following built-ins to not report the right values on the D3D12 backend:
217        ///
218        /// - the 3 components of `@builtin(num_workgroups)` will be 0
219        /// - the value of `@builtin(vertex_index)` will not take into account the value of the `first_vertex`/`base_vertex` argument present in the indirect buffer
220        /// - the value of `@builtin(instance_index)` will not take into account the value of the `first_instance` argument present in the indirect buffer
221        ///
222        /// When `Self::from_env()` is used takes value from `WGPU_VALIDATION_INDIRECT_CALL` environment variable.
223        const VALIDATION_INDIRECT_CALL = 1 << 5;
224
225        /// Enable automatic timestamp normalization. This means that in [`CommandEncoder::resolve_query_set`][rqs],
226        /// the timestamps will automatically be normalized to be in nanoseconds instead of the raw timestamp values.
227        ///
228        /// This is disabled by default because it introduces a compute shader into the resolution of query sets.
229        ///
230        /// This can be useful for users that need to read timestamps on the gpu, as the normalization
231        /// can be a hassle to do manually. When this is enabled, the timestamp period returned by the queue
232        /// will always be `1.0`.
233        ///
234        #[doc = link_to_wgpu_docs!(["rqs"]: "struct.CommandEncoder.html#method.resolve_query_set")]
235        const AUTOMATIC_TIMESTAMP_NORMALIZATION = 1 << 6;
236
237        /// Restrict the available feature set to the one defined by the WebGPU specification.
238        ///
239        /// When `Self::from_env()` is used takes value from `WGPU_STRICT_WEBGPU_COMPLIANCE` environment variable.
240        const STRICT_WEBGPU_COMPLIANCE = 1 << 7;
241    }
242}
243
244impl Default for InstanceFlags {
245    fn default() -> Self {
246        Self::from_build_config()
247    }
248}
249
250impl InstanceFlags {
251    /// Enable recommended debugging and validation flags.
252    #[must_use]
253    pub fn debugging() -> Self {
254        InstanceFlags::DEBUG | InstanceFlags::VALIDATION | InstanceFlags::VALIDATION_INDIRECT_CALL
255    }
256
257    /// Enable advanced debugging and validation flags (potentially very slow).
258    #[must_use]
259    pub fn advanced_debugging() -> Self {
260        Self::debugging() | InstanceFlags::GPU_BASED_VALIDATION
261    }
262
263    /// Infer decent defaults from the build type.
264    ///
265    /// If `cfg!(debug_assertions)` is true, then this returns [`Self::debugging()`].
266    /// Otherwise, it returns [`Self::empty()`].
267    #[must_use]
268    pub fn from_build_config() -> Self {
269        if cfg!(debug_assertions) {
270            return InstanceFlags::debugging();
271        }
272
273        InstanceFlags::VALIDATION_INDIRECT_CALL
274    }
275
276    /// Derive defaults from environment variables. See [`Self::with_env()`] for more information.
277    #[must_use]
278    pub fn from_env_or_default() -> Self {
279        Self::default().with_env()
280    }
281
282    /// Takes the given flags, modifies them based on the environment variables, and returns the result.
283    ///
284    /// - If an environment variable is set to anything but "0", the corresponding flag is set.
285    /// - If the value is "0", the flag is unset.
286    /// - If the environment variable is not present, then the flag retains its initial value.
287    ///
288    /// For example `let flags = InstanceFlags::debugging().with_env();` with `WGPU_VALIDATION=0`
289    /// does not contain [`InstanceFlags::VALIDATION`].
290    ///
291    /// The environment variables are named after the flags prefixed with "WGPU_". For example:
292    /// - `WGPU_DEBUG`
293    /// - `WGPU_VALIDATION`
294    /// - `WGPU_DISCARD_HAL_LABELS`
295    /// - `WGPU_ALLOW_UNDERLYING_NONCOMPLIANT_ADAPTER`
296    /// - `WGPU_GPU_BASED_VALIDATION`
297    /// - `WGPU_VALIDATION_INDIRECT_CALL`
298    /// - `WGPU_STRICT_WEBGPU_COMPLIANCE`
299    #[must_use]
300    pub fn with_env(mut self) -> Self {
301        fn env(key: &str) -> Option<bool> {
302            crate::env::var(key).map(|s| match s.as_str() {
303                "0" => false,
304                _ => true,
305            })
306        }
307
308        if let Some(bit) = env("WGPU_VALIDATION") {
309            self.set(Self::VALIDATION, bit);
310        }
311
312        if let Some(bit) = env("WGPU_DEBUG") {
313            self.set(Self::DEBUG, bit);
314        }
315        if let Some(bit) = env("WGPU_DISCARD_HAL_LABELS") {
316            self.set(Self::DISCARD_HAL_LABELS, bit);
317        }
318        if let Some(bit) = env("WGPU_ALLOW_UNDERLYING_NONCOMPLIANT_ADAPTER") {
319            self.set(Self::ALLOW_UNDERLYING_NONCOMPLIANT_ADAPTER, bit);
320        }
321        if let Some(bit) = env("WGPU_GPU_BASED_VALIDATION") {
322            self.set(Self::GPU_BASED_VALIDATION, bit);
323        }
324        if let Some(bit) = env("WGPU_VALIDATION_INDIRECT_CALL") {
325            self.set(Self::VALIDATION_INDIRECT_CALL, bit);
326        }
327        if let Some(bit) = env("WGPU_STRICT_WEBGPU_COMPLIANCE") {
328            self.set(Self::STRICT_WEBGPU_COMPLIANCE, bit);
329        }
330
331        self
332    }
333}
334
335/// Memory budget thresholds used by backends to try to avoid high memory pressure situations.
336///
337/// Currently only the D3D12 and (optionally) Vulkan backends support these options.
338#[derive(Default, Clone, Debug, Copy)]
339pub struct MemoryBudgetThresholds {
340    /// Threshold at which texture, buffer, query set and acceleration structure creation will start to return OOM errors.
341    /// This is a percent of the memory budget reported by native APIs.
342    ///
343    /// If not specified, resource creation might still return OOM errors.
344    pub for_resource_creation: Option<u8>,
345
346    /// Threshold at which devices will become lost due to memory pressure.
347    /// This is a percent of the memory budget reported by native APIs.
348    ///
349    /// If not specified, devices might still become lost due to memory pressure.
350    pub for_device_loss: Option<u8>,
351}