wgpu_types/instance.rs
1//! Types for dealing with Instances
2
3use alloc::string::String;
4
5use crate::Backends;
6
7#[cfg(doc)]
8use crate::{Backend, DownlevelFlags};
9
10/// Options for creating an instance.
11///
12/// If you want to allow control of instance settings via environment variables, call either
13/// [`InstanceDescriptor::from_env_or_default()`] or [`InstanceDescriptor::with_env()`]. Each type
14/// within this descriptor has its own equivalent methods, so you can select which options you want
15/// to expose to influence from the environment.
16#[derive(Clone, Debug, Default)]
17pub struct InstanceDescriptor {
18 /// Which [`Backends`] to enable.
19 ///
20 /// [`Backends::BROWSER_WEBGPU`] has an additional effect:
21 /// If it is set and a [`navigator.gpu`](https://developer.mozilla.org/en-US/docs/Web/API/Navigator/gpu)
22 /// object is present, this instance will *only* be able to create WebGPU adapters.
23 ///
24 /// ⚠️ On some browsers this check is insufficient to determine whether WebGPU is supported,
25 /// as the browser may define the `navigator.gpu` object, but be unable to create any WebGPU adapters.
26 /// 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).
27 ///
28 /// If you instead want to force use of WebGL, either disable the `webgpu` compile-time feature
29 /// or don't include the [`Backends::BROWSER_WEBGPU`] flag in this field.
30 /// If it is set and WebGPU support is *not* detected, the instance will use `wgpu-core`
31 /// to create adapters, meaning that if the `webgl` feature is enabled, it is able to create
32 /// a WebGL adapter.
33 pub backends: Backends,
34 /// Flags to tune the behavior of the instance.
35 pub flags: InstanceFlags,
36 /// Memory budget thresholds used by some backends.
37 pub memory_budget_thresholds: MemoryBudgetThresholds,
38 /// Options the control the behavior of specific backends.
39 pub backend_options: BackendOptions,
40}
41
42impl InstanceDescriptor {
43 /// Choose instance options entirely from environment variables.
44 ///
45 /// This is equivalent to calling `from_env` on every field.
46 #[must_use]
47 pub fn from_env_or_default() -> Self {
48 Self::default().with_env()
49 }
50
51 /// Takes the given options, modifies them based on the environment variables, and returns the result.
52 ///
53 /// This is equivalent to calling `with_env` on every field.
54 #[must_use]
55 pub fn with_env(self) -> Self {
56 let backends = self.backends.with_env();
57 let flags = self.flags.with_env();
58 let backend_options = self.backend_options.with_env();
59 Self {
60 backends,
61 flags,
62 memory_budget_thresholds: MemoryBudgetThresholds::default(),
63 backend_options,
64 }
65 }
66}
67
68bitflags::bitflags! {
69 /// Instance debugging flags.
70 ///
71 /// These are not part of the WebGPU standard.
72 ///
73 /// Defaults to enabling debugging-related flags if the build configuration has `debug_assertions`.
74 #[repr(transparent)]
75 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
76 pub struct InstanceFlags: u32 {
77 /// Generate debug information in shaders and objects.
78 ///
79 /// When `Self::from_env()` is used takes value from `WGPU_DEBUG` environment variable.
80 const DEBUG = 1 << 0;
81 /// Enable validation in the backend API, if possible:
82 ///
83 /// - On the Direct3D `dx12` backend, this calls [`ID3D12Debug::EnableDebugLayer`][dx12].
84 ///
85 /// - On the Vulkan backend, this enables the [Vulkan Validation Layer][vvl].
86 ///
87 /// - On the `gles` backend driving Windows OpenGL, this enables [debug
88 /// output][gl:do], effectively calling `glEnable(GL_DEBUG_OUTPUT)`.
89 ///
90 /// - On non-Windows `gles` backends, this calls
91 /// [`eglDebugMessageControlKHR`][gl:dm] to enable all debugging messages.
92 /// If the GLES implementation is ANGLE running on Vulkan, this also
93 /// enables the Vulkan validation layers by setting
94 /// [`EGL_PLATFORM_ANGLE_DEBUG_LAYERS_ENABLED`][gl:av].
95 ///
96 /// When `Self::from_env()` is used, this bit is set if the `WGPU_VALIDATION`
97 /// environment variable has any value but "0".
98 ///
99 /// [dx12]: https://learn.microsoft.com/en-us/windows/win32/api/d3d12sdklayers/nf-d3d12sdklayers-id3d12debug-enabledebuglayer
100 /// [vvl]: https://github.com/KhronosGroup/Vulkan-ValidationLayers
101 /// [gl:dm]: https://registry.khronos.org/EGL/extensions/KHR/EGL_KHR_debug.txt
102 /// [gl:do]: https://www.khronos.org/opengl/wiki/Debug_Output
103 /// [gl:av]: https://chromium.googlesource.com/angle/angle/+/HEAD/extensions/EGL_ANGLE_platform_angle.txt
104 const VALIDATION = 1 << 1;
105 /// Don't pass labels to wgpu-hal.
106 ///
107 /// When `Self::from_env()` is used takes value from `WGPU_DISCARD_HAL_LABELS` environment variable.
108 const DISCARD_HAL_LABELS = 1 << 2;
109 /// Whether wgpu should expose adapters that run on top of non-compliant adapters.
110 ///
111 /// Turning this on might mean that some of the functionality provided by the wgpu
112 /// adapter/device is not working or is broken. It could be that all the functionality
113 /// wgpu currently exposes works but we can't tell for sure since we have no additional
114 /// transparency into what is working and what is not on the underlying adapter.
115 ///
116 /// This mainly applies to a Vulkan driver's compliance version. If the major compliance version
117 /// is `0`, then the driver is ignored. This flag allows that driver to be enabled for testing.
118 ///
119 /// When `Self::from_env()` is used takes value from `WGPU_ALLOW_UNDERLYING_NONCOMPLIANT_ADAPTER` environment variable.
120 const ALLOW_UNDERLYING_NONCOMPLIANT_ADAPTER = 1 << 3;
121 /// Enable GPU-based validation. Implies [`Self::VALIDATION`]. Currently, this only changes
122 /// behavior on the DX12 and Vulkan backends.
123 ///
124 /// Supported platforms:
125 ///
126 /// - D3D12; called ["GPU-based validation", or
127 /// "GBV"](https://web.archive.org/web/20230206120404/https://learn.microsoft.com/en-us/windows/win32/direct3d12/using-d3d12-debug-layer-gpu-based-validation)
128 /// - Vulkan, via the `VK_LAYER_KHRONOS_validation` layer; called ["GPU-Assisted
129 /// Validation"](https://github.com/KhronosGroup/Vulkan-ValidationLayers/blob/e45aeb85079e0835694cb8f03e6681fd18ae72c9/docs/gpu_validation.md#gpu-assisted-validation)
130 ///
131 /// When `Self::from_env()` is used takes value from `WGPU_GPU_BASED_VALIDATION` environment variable.
132 const GPU_BASED_VALIDATION = 1 << 4;
133
134 /// Validate indirect buffer content prior to issuing indirect draws/dispatches.
135 ///
136 /// This validation will transform indirect calls into no-ops if they are not valid:
137 ///
138 /// - When calling `dispatch_workgroups_indirect`, all 3 indirect arguments encoded in the buffer
139 /// must be less than the `max_compute_workgroups_per_dimension` device limit.
140 /// - When calling `draw_indirect`/`draw_indexed_indirect`/`multi_draw_indirect`/`multi_draw_indexed_indirect`:
141 /// - If `Features::INDIRECT_FIRST_INSTANCE` is not enabled on the device, the `first_instance` indirect argument must be 0.
142 /// - The `first_instance` & `instance_count` indirect arguments must form a range that fits within all bound vertex buffers with `step_mode` set to `Instance`.
143 /// - When calling `draw_indirect`/`multi_draw_indirect`:
144 /// - The `first_vertex` & `vertex_count` indirect arguments must form a range that fits within all bound vertex buffers with `step_mode` set to `Vertex`.
145 /// - When calling `draw_indexed_indirect`/`multi_draw_indexed_indirect`:
146 /// - The `first_index` & `index_count` indirect arguments must form a range that fits within the bound index buffer.
147 ///
148 /// __Behavior is undefined if this validation is disabled and the rules above are not satisfied.__
149 ///
150 /// Disabling this will also cause the following built-ins to not report the right values on the D3D12 backend:
151 ///
152 /// - the 3 components of `@builtin(num_workgroups)` will be 0
153 /// - 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
154 /// - the value of `@builtin(instance_index)` will not take into account the value of the `first_instance` argument present in the indirect buffer
155 ///
156 /// When `Self::from_env()` is used takes value from `WGPU_VALIDATION_INDIRECT_CALL` environment variable.
157 const VALIDATION_INDIRECT_CALL = 1 << 5;
158
159 /// Enable automatic timestamp normalization. This means that in [`CommandEncoder::resolve_query_set`][rqs],
160 /// the timestamps will automatically be normalized to be in nanoseconds instead of the raw timestamp values.
161 ///
162 /// This is disabled by default because it introduces a compute shader into the resolution of query sets.
163 ///
164 /// This can be useful for users that need to read timestamps on the gpu, as the normalization
165 /// can be a hassle to do manually. When this is enabled, the timestamp period returned by the queue
166 /// will always be `1.0`.
167 ///
168 /// [rqs]: ../wgpu/struct.CommandEncoder.html#method.resolve_query_set
169 const AUTOMATIC_TIMESTAMP_NORMALIZATION = 1 << 6;
170 }
171}
172
173impl Default for InstanceFlags {
174 fn default() -> Self {
175 Self::from_build_config()
176 }
177}
178
179impl InstanceFlags {
180 /// Enable recommended debugging and validation flags.
181 #[must_use]
182 pub fn debugging() -> Self {
183 InstanceFlags::DEBUG | InstanceFlags::VALIDATION | InstanceFlags::VALIDATION_INDIRECT_CALL
184 }
185
186 /// Enable advanced debugging and validation flags (potentially very slow).
187 #[must_use]
188 pub fn advanced_debugging() -> Self {
189 Self::debugging() | InstanceFlags::GPU_BASED_VALIDATION
190 }
191
192 /// Infer decent defaults from the build type.
193 ///
194 /// If `cfg!(debug_assertions)` is true, then this returns [`Self::debugging()`].
195 /// Otherwise, it returns [`Self::empty()`].
196 #[must_use]
197 pub fn from_build_config() -> Self {
198 if cfg!(debug_assertions) {
199 return InstanceFlags::debugging();
200 }
201
202 InstanceFlags::VALIDATION_INDIRECT_CALL
203 }
204
205 /// Derive defaults from environment variables. See [`Self::with_env()`] for more information.
206 #[must_use]
207 pub fn from_env_or_default() -> Self {
208 Self::default().with_env()
209 }
210
211 /// Takes the given flags, modifies them based on the environment variables, and returns the result.
212 ///
213 /// - If an environment variable is set to anything but "0", the corresponding flag is set.
214 /// - If the value is "0", the flag is unset.
215 /// - If the environment variable is not present, then the flag retains its initial value.
216 ///
217 /// For example `let flags = InstanceFlags::debugging().with_env();` with `WGPU_VALIDATION=0`
218 /// does not contain [`InstanceFlags::VALIDATION`].
219 ///
220 /// The environment variables are named after the flags prefixed with "WGPU_". For example:
221 /// - `WGPU_DEBUG`
222 /// - `WGPU_VALIDATION`
223 /// - `WGPU_DISCARD_HAL_LABELS`
224 /// - `WGPU_ALLOW_UNDERLYING_NONCOMPLIANT_ADAPTER`
225 /// - `WGPU_GPU_BASED_VALIDATION`
226 /// - `WGPU_VALIDATION_INDIRECT_CALL`
227 #[must_use]
228 pub fn with_env(mut self) -> Self {
229 fn env(key: &str) -> Option<bool> {
230 crate::env::var(key).map(|s| match s.as_str() {
231 "0" => false,
232 _ => true,
233 })
234 }
235
236 if let Some(bit) = env("WGPU_VALIDATION") {
237 self.set(Self::VALIDATION, bit);
238 }
239
240 if let Some(bit) = env("WGPU_DEBUG") {
241 self.set(Self::DEBUG, bit);
242 }
243 if let Some(bit) = env("WGPU_DISCARD_HAL_LABELS") {
244 self.set(Self::DISCARD_HAL_LABELS, bit);
245 }
246 if let Some(bit) = env("WGPU_ALLOW_UNDERLYING_NONCOMPLIANT_ADAPTER") {
247 self.set(Self::ALLOW_UNDERLYING_NONCOMPLIANT_ADAPTER, bit);
248 }
249 if let Some(bit) = env("WGPU_GPU_BASED_VALIDATION") {
250 self.set(Self::GPU_BASED_VALIDATION, bit);
251 }
252 if let Some(bit) = env("WGPU_VALIDATION_INDIRECT_CALL") {
253 self.set(Self::VALIDATION_INDIRECT_CALL, bit);
254 }
255
256 self
257 }
258}
259
260/// Memory budget thresholds used by backends to try to avoid high memory pressure situations.
261///
262/// Currently only the D3D12 and (optionally) Vulkan backends support these options.
263#[derive(Default, Clone, Debug, Copy)]
264pub struct MemoryBudgetThresholds {
265 /// Threshold at which texture, buffer, query set and acceleration structure creation will start to return OOM errors.
266 /// This is a percent of the memory budget reported by native APIs.
267 ///
268 /// If not specified, resource creation might still return OOM errors.
269 pub for_resource_creation: Option<u8>,
270
271 /// Threshold at which devices will become lost due to memory pressure.
272 /// This is a percent of the memory budget reported by native APIs.
273 ///
274 /// If not specified, devices might still become lost due to memory pressure.
275 pub for_device_loss: Option<u8>,
276}
277
278/// Options that are passed to a given backend.
279///
280/// Part of [`InstanceDescriptor`].
281#[derive(Clone, Debug, Default)]
282pub struct BackendOptions {
283 /// Options for the OpenGL/OpenGLES backend, [`Backend::Gl`].
284 pub gl: GlBackendOptions,
285 /// Options for the DX12 backend, [`Backend::Dx12`].
286 pub dx12: Dx12BackendOptions,
287 /// Options for the noop backend, [`Backend::Noop`].
288 pub noop: NoopBackendOptions,
289}
290
291impl BackendOptions {
292 /// Choose backend options by calling `from_env` on every field.
293 ///
294 /// See those methods for more information.
295 #[must_use]
296 pub fn from_env_or_default() -> Self {
297 Self {
298 gl: GlBackendOptions::from_env_or_default(),
299 dx12: Dx12BackendOptions::from_env_or_default(),
300 noop: NoopBackendOptions::from_env_or_default(),
301 }
302 }
303
304 /// Takes the given options, modifies them based on the environment variables, and returns the result.
305 ///
306 /// This is equivalent to calling `with_env` on every field.
307 #[must_use]
308 pub fn with_env(self) -> Self {
309 Self {
310 gl: self.gl.with_env(),
311 dx12: self.dx12.with_env(),
312 noop: self.noop.with_env(),
313 }
314 }
315}
316
317/// Configuration for the OpenGL/OpenGLES backend.
318///
319/// Part of [`BackendOptions`].
320#[derive(Clone, Debug, Default)]
321pub struct GlBackendOptions {
322 /// Which OpenGL ES 3 minor version to request, if using OpenGL ES.
323 pub gles_minor_version: Gles3MinorVersion,
324 /// Behavior of OpenGL fences. Affects how `on_completed_work_done` and `device.poll` behave.
325 pub fence_behavior: GlFenceBehavior,
326}
327
328impl GlBackendOptions {
329 /// Choose OpenGL backend options by calling `from_env` on every field.
330 ///
331 /// See those methods for more information.
332 #[must_use]
333 pub fn from_env_or_default() -> Self {
334 let gles_minor_version = Gles3MinorVersion::from_env().unwrap_or_default();
335 Self {
336 gles_minor_version,
337 fence_behavior: GlFenceBehavior::Normal,
338 }
339 }
340
341 /// Takes the given options, modifies them based on the environment variables, and returns the result.
342 ///
343 /// This is equivalent to calling `with_env` on every field.
344 #[must_use]
345 pub fn with_env(self) -> Self {
346 let gles_minor_version = self.gles_minor_version.with_env();
347 let short_circuit_fences = self.fence_behavior.with_env();
348 Self {
349 gles_minor_version,
350 fence_behavior: short_circuit_fences,
351 }
352 }
353}
354
355/// Configuration for the DX12 backend.
356///
357/// Part of [`BackendOptions`].
358#[derive(Clone, Debug, Default)]
359pub struct Dx12BackendOptions {
360 /// Which DX12 shader compiler to use.
361 pub shader_compiler: Dx12Compiler,
362 /// Presentation system to use.
363 pub presentation_system: Dx12SwapchainKind,
364 /// Whether to wait for the latency waitable object before acquiring the next swapchain image.
365 pub latency_waitable_object: Dx12UseFrameLatencyWaitableObject,
366}
367
368impl Dx12BackendOptions {
369 /// Choose DX12 backend options by calling `from_env` on every field.
370 ///
371 /// See those methods for more information.
372 #[must_use]
373 pub fn from_env_or_default() -> Self {
374 let compiler = Dx12Compiler::from_env().unwrap_or_default();
375 let presentation_system = Dx12SwapchainKind::from_env().unwrap_or_default();
376 let latency_waitable_object =
377 Dx12UseFrameLatencyWaitableObject::from_env().unwrap_or_default();
378 Self {
379 shader_compiler: compiler,
380 presentation_system,
381 latency_waitable_object,
382 }
383 }
384
385 /// Takes the given options, modifies them based on the environment variables, and returns the result.
386 ///
387 /// This is equivalent to calling `with_env` on every field.
388 #[must_use]
389 pub fn with_env(self) -> Self {
390 let shader_compiler = self.shader_compiler.with_env();
391 let presentation_system = self.presentation_system.with_env();
392 let latency_waitable_object = self.latency_waitable_object.with_env();
393 Self {
394 shader_compiler,
395 presentation_system,
396 latency_waitable_object,
397 }
398 }
399}
400
401/// Configuration for the noop backend.
402///
403/// Part of [`BackendOptions`].
404#[derive(Clone, Debug, Default)]
405pub struct NoopBackendOptions {
406 /// Whether to allow the noop backend to be used.
407 ///
408 /// The noop backend stubs out all operations except for buffer creation and mapping, so
409 /// it must not be used when not expected. Therefore, it will not be used unless explicitly
410 /// enabled.
411 pub enable: bool,
412}
413
414impl NoopBackendOptions {
415 /// Choose whether the noop backend is enabled from the environment.
416 ///
417 /// It will be enabled if the environment variable `WGPU_NOOP_BACKEND` has the value `1`
418 /// and not otherwise. Future versions may assign other meanings to other values.
419 #[must_use]
420 pub fn from_env_or_default() -> Self {
421 Self {
422 enable: Self::enable_from_env().unwrap_or(false),
423 }
424 }
425
426 /// Takes the given options, modifies them based on the environment variables, and returns the
427 /// result.
428 ///
429 /// See [`from_env_or_default()`](Self::from_env_or_default) for the interpretation.
430 #[must_use]
431 pub fn with_env(self) -> Self {
432 Self {
433 enable: Self::enable_from_env().unwrap_or(self.enable),
434 }
435 }
436
437 fn enable_from_env() -> Option<bool> {
438 let value = crate::env::var("WGPU_NOOP_BACKEND")?;
439 match value.as_str() {
440 "1" => Some(true),
441 "0" => Some(false),
442 _ => None,
443 }
444 }
445}
446
447#[derive(Clone, Debug, Default, Copy, PartialEq, Eq)]
448/// Selects which kind of swapchain to use on DX12.
449pub enum Dx12SwapchainKind {
450 /// Use a DXGI swapchain made directly from the window's HWND.
451 ///
452 /// This does not support transparency but has better support from developer tooling from RenderDoc.
453 #[default]
454 DxgiFromHwnd,
455 /// Use a DXGI swapchain made from a DirectComposition visual made automatically from the window's HWND.
456 ///
457 /// This creates a single [`IDCompositionVisual`] over the entire window that is used by the `Surface`.
458 /// If a user wants to manage the composition tree themselves, they should create their own device and
459 /// composition, and pass the relevant visual down via [`SurfaceTargetUnsafe::CompositionVisual`][CV].
460 ///
461 /// This supports transparent windows, but does not have support from RenderDoc.
462 ///
463 /// [`IDCompositionVisual`]: https://learn.microsoft.com/en-us/windows/win32/api/dcomp/nn-dcomp-idcompositionvisual
464 /// [CV]: ../wgpu/struct.SurfaceTargetUnsafe.html#variant.CompositionVisual
465 DxgiFromVisual,
466}
467
468impl Dx12SwapchainKind {
469 /// Choose which presentation system to use from the environment variable `WGPU_DX12_PRESENTATION_SYSTEM`.
470 ///
471 /// Valid values, case insensitive:
472 /// - `DxgiFromVisual` or `Visual`
473 /// - `DxgiFromHwnd` or `Hwnd` for [`Self::DxgiFromHwnd`]
474 #[must_use]
475 pub fn from_env() -> Option<Self> {
476 let value = crate::env::var("WGPU_DX12_PRESENTATION_SYSTEM")
477 .as_deref()?
478 .to_lowercase();
479 match value.as_str() {
480 "dxgifromvisual" | "visual" => Some(Self::DxgiFromVisual),
481 "dxgifromhwnd" | "hwnd" => Some(Self::DxgiFromHwnd),
482 _ => None,
483 }
484 }
485
486 /// Takes the given presentation system, modifies it based on the `WGPU_DX12_PRESENTATION_SYSTEM` environment variable, and returns the result.
487 ///
488 /// See [`from_env`](Self::from_env) for more information.
489 #[must_use]
490 pub fn with_env(self) -> Self {
491 if let Some(presentation_system) = Self::from_env() {
492 presentation_system
493 } else {
494 self
495 }
496 }
497}
498
499/// DXC shader model.
500#[derive(Clone, Debug)]
501#[allow(missing_docs)]
502pub enum DxcShaderModel {
503 V6_0,
504 V6_1,
505 V6_2,
506 V6_3,
507 V6_4,
508 V6_5,
509 V6_6,
510 V6_7,
511}
512
513/// Selects which DX12 shader compiler to use.
514#[derive(Clone, Debug, Default)]
515pub enum Dx12Compiler {
516 /// The Fxc compiler (default) is old, slow and unmaintained.
517 ///
518 /// However, it doesn't require any additional .dlls to be shipped with the application.
519 #[default]
520 Fxc,
521 /// The Dxc compiler is new, fast and maintained.
522 ///
523 /// However, it requires `dxcompiler.dll` to be shipped with the application.
524 /// These files can be downloaded from <https://github.com/microsoft/DirectXShaderCompiler/releases>.
525 ///
526 /// Minimum supported version: [v1.8.2502](https://github.com/microsoft/DirectXShaderCompiler/releases/tag/v1.8.2502)
527 ///
528 /// It also requires WDDM 2.1 (Windows 10 version 1607).
529 DynamicDxc {
530 /// Path to `dxcompiler.dll`.
531 dxc_path: String,
532 /// Maximum shader model the given dll supports.
533 max_shader_model: DxcShaderModel,
534 },
535 /// The statically-linked variant of Dxc.
536 ///
537 /// The `static-dxc` feature is required for this setting to be used successfully on DX12.
538 /// Not available on `windows-aarch64-pc-*` targets.
539 StaticDxc,
540}
541
542impl Dx12Compiler {
543 /// Helper function to construct a `DynamicDxc` variant with default paths.
544 ///
545 /// The dll must support at least shader model 6.8.
546 pub fn default_dynamic_dxc() -> Self {
547 Self::DynamicDxc {
548 dxc_path: String::from("dxcompiler.dll"),
549 max_shader_model: DxcShaderModel::V6_7, // should be 6.8 but the variant is missing
550 }
551 }
552
553 /// Choose which DX12 shader compiler to use from the environment variable `WGPU_DX12_COMPILER`.
554 ///
555 /// Valid values, case insensitive:
556 /// - `Fxc`
557 /// - `Dxc` or `DynamicDxc`
558 /// - `StaticDxc`
559 #[must_use]
560 pub fn from_env() -> Option<Self> {
561 let value = crate::env::var("WGPU_DX12_COMPILER")
562 .as_deref()?
563 .to_lowercase();
564 match value.as_str() {
565 "dxc" | "dynamicdxc" => Some(Self::default_dynamic_dxc()),
566 "staticdxc" => Some(Self::StaticDxc),
567 "fxc" => Some(Self::Fxc),
568 _ => None,
569 }
570 }
571
572 /// Takes the given compiler, modifies it based on the `WGPU_DX12_COMPILER` environment variable, and returns the result.
573 ///
574 /// See `from_env` for more information.
575 #[must_use]
576 pub fn with_env(self) -> Self {
577 if let Some(compiler) = Self::from_env() {
578 compiler
579 } else {
580 self
581 }
582 }
583}
584
585/// Whether and how to use a waitable handle obtained from `GetFrameLatencyWaitableObject`.
586#[derive(Clone, Debug, Default)]
587pub enum Dx12UseFrameLatencyWaitableObject {
588 /// Do not obtain a waitable handle and do not wait for it. The swapchain will
589 /// be created without the `DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT` flag.
590 None,
591 /// Obtain a waitable handle and wait for it before acquiring the next swapchain image.
592 #[default]
593 Wait,
594 /// Create the swapchain with the `DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT` flag and
595 /// obtain a waitable handle, but do not wait for it before acquiring the next swapchain image.
596 /// This is useful if the application wants to wait for the waitable object itself.
597 DontWait,
598}
599
600impl Dx12UseFrameLatencyWaitableObject {
601 /// Choose whether to use a frame latency waitable object from the environment variable `WGPU_DX12_USE_FRAME_LATENCY_WAITABLE_OBJECT`.
602 ///
603 /// Valid values, case insensitive:
604 /// - `None`
605 /// - `Wait`
606 /// - `DontWait`
607 #[must_use]
608 pub fn from_env() -> Option<Self> {
609 let value = crate::env::var("WGPU_DX12_USE_FRAME_LATENCY_WAITABLE_OBJECT")
610 .as_deref()?
611 .to_lowercase();
612 match value.as_str() {
613 "none" => Some(Self::None),
614 "wait" => Some(Self::Wait),
615 "dontwait" => Some(Self::DontWait),
616 _ => None,
617 }
618 }
619
620 /// Takes the given setting, modifies it based on the `WGPU_DX12_USE_FRAME_LATENCY_WAITABLE_OBJECT` environment variable, and returns the result.
621 ///
622 /// See `from_env` for more information.
623 #[must_use]
624 pub fn with_env(self) -> Self {
625 if let Some(compiler) = Self::from_env() {
626 compiler
627 } else {
628 self
629 }
630 }
631}
632
633/// Selects which OpenGL ES 3 minor version to request.
634///
635/// When using ANGLE as an OpenGL ES/EGL implementation, explicitly requesting `Version1` can provide a non-conformant ES 3.1 on APIs like D3D11.
636#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Hash)]
637pub enum Gles3MinorVersion {
638 /// No explicit minor version is requested, the driver automatically picks the highest available.
639 #[default]
640 Automatic,
641
642 /// Request an ES 3.0 context.
643 Version0,
644
645 /// Request an ES 3.1 context.
646 Version1,
647
648 /// Request an ES 3.2 context.
649 Version2,
650}
651
652impl Gles3MinorVersion {
653 /// Choose which minor OpenGL ES version to use from the environment variable `WGPU_GLES_MINOR_VERSION`.
654 ///
655 /// Possible values are `0`, `1`, `2` or `automatic`. Case insensitive.
656 ///
657 /// Use with `unwrap_or_default()` to get the default value if the environment variable is not set.
658 #[must_use]
659 pub fn from_env() -> Option<Self> {
660 let value = crate::env::var("WGPU_GLES_MINOR_VERSION")
661 .as_deref()?
662 .to_lowercase();
663 match value.as_str() {
664 "automatic" => Some(Self::Automatic),
665 "0" => Some(Self::Version0),
666 "1" => Some(Self::Version1),
667 "2" => Some(Self::Version2),
668 _ => None,
669 }
670 }
671
672 /// Takes the given compiler, modifies it based on the `WGPU_GLES_MINOR_VERSION` environment variable, and returns the result.
673 ///
674 /// See `from_env` for more information.
675 #[must_use]
676 pub fn with_env(self) -> Self {
677 if let Some(compiler) = Self::from_env() {
678 compiler
679 } else {
680 self
681 }
682 }
683}
684
685/// Dictate the behavior of fences in OpenGL.
686#[derive(Clone, Copy, Debug, PartialEq, Eq, Default)]
687pub enum GlFenceBehavior {
688 /// Fences in OpenGL behave normally. If you don't know what to pick, this is what you want.
689 #[default]
690 Normal,
691 /// Fences in OpenGL are short-circuited to always return `true` immediately.
692 ///
693 /// This solves a very specific issue that arose due to a bug in wgpu-core that made
694 /// many WebGL programs work when they "shouldn't" have. If you have code that is trying
695 /// to call `device.poll(wgpu::PollType::Wait)` on WebGL, you need to enable this option
696 /// for the "Wait" to behave how you would expect.
697 ///
698 /// Previously all `poll(Wait)` acted like the OpenGL fences were signalled even if they weren't.
699 /// See <https://github.com/gfx-rs/wgpu/issues/4589> for more information.
700 ///
701 /// When this is set `Queue::on_completed_work_done` will always return the next time the device
702 /// is maintained, not when the work is actually done on the GPU.
703 AutoFinish,
704}
705
706impl GlFenceBehavior {
707 /// Returns true if the fence behavior is `AutoFinish`.
708 pub fn is_auto_finish(&self) -> bool {
709 matches!(self, Self::AutoFinish)
710 }
711
712 /// Returns true if the fence behavior is `Normal`.
713 pub fn is_normal(&self) -> bool {
714 matches!(self, Self::Normal)
715 }
716
717 /// Choose which minor OpenGL ES version to use from the environment variable `WGPU_GL_FENCE_BEHAVIOR`.
718 ///
719 /// Possible values are `Normal` or `AutoFinish`. Case insensitive.
720 ///
721 /// Use with `unwrap_or_default()` to get the default value if the environment variable is not set.
722 #[must_use]
723 pub fn from_env() -> Option<Self> {
724 let value = crate::env::var("WGPU_GL_FENCE_BEHAVIOR")
725 .as_deref()?
726 .to_lowercase();
727 match value.as_str() {
728 "normal" => Some(Self::Normal),
729 "autofinish" => Some(Self::AutoFinish),
730 _ => None,
731 }
732 }
733
734 /// Takes the given compiler, modifies it based on the `WGPU_GL_FENCE_BEHAVIOR` environment variable, and returns the result.
735 ///
736 /// See `from_env` for more information.
737 #[must_use]
738 pub fn with_env(self) -> Self {
739 if let Some(fence) = Self::from_env() {
740 fence
741 } else {
742 self
743 }
744 }
745}