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