kas_wgpu/
options.rs

1// Licensed under the Apache License, Version 2.0 (the "License");
2// you may not use this file except in compliance with the License.
3// You may obtain a copy of the License in the LICENSE-APACHE file or at:
4//     https://www.apache.org/licenses/LICENSE-2.0
5
6//! Options
7
8use std::env::var;
9use std::path::PathBuf;
10pub use wgpu::{Backends, PowerPreference};
11
12/// Graphics backend options
13#[derive(Clone, PartialEq, Eq, Hash)]
14pub struct Options {
15    /// Adapter power preference. Default value: low power.
16    pub power_preference: PowerPreference,
17    /// Adapter backend. Default value: PRIMARY (Vulkan/Metal/DX12).
18    pub backends: Backends,
19    /// WGPU's API tracing path
20    pub wgpu_trace_path: Option<PathBuf>,
21}
22
23impl Default for Options {
24    fn default() -> Self {
25        Options {
26            power_preference: PowerPreference::LowPower,
27            backends: Backends::PRIMARY,
28            wgpu_trace_path: None,
29        }
30    }
31}
32
33impl Options {
34    /// Read values from environment variables
35    ///
36    /// This replaces values in self where specified via env vars.
37    /// Use e.g. `Options::default().load_from_env()`.
38    ///
39    /// The following environment variables are read, in case-insensitive mode.
40    ///
41    /// # Graphics options
42    ///
43    /// The `KAS_POWER_PREFERENCE` variable supports:
44    ///
45    /// -   `Default`
46    /// -   `LowPower`
47    /// -   `HighPerformance`
48    ///
49    /// The `KAS_BACKENDS` variable supports:
50    ///
51    /// -   `Vulkan`
52    /// -   `GL`
53    /// -   `Metal`
54    /// -   `DX11`
55    /// -   `DX12`
56    /// -   `BROWSER_WEBGPU`: web target through webassembly
57    /// -   `PRIMARY`: any of Vulkan, Metal or DX12
58    /// -   `SECONDARY`: any of GL or DX11
59    /// -   `FALLBACK`: force use of fallback (CPU) rendering
60    ///
61    /// The default backend is `PRIMARY`. Note that secondary backends are less
62    /// well supported by WGPU, possibly leading to other issues.
63    ///
64    /// ~~WGPU has an [API tracing] feature for debugging.~~
65    /// NOTE: WGPU has temporarily removed this feature.
66    /// To use this, ensure the `wgpu/trace` feature is enabled and set the output path:
67    /// ```sh
68    /// export KAS_WGPU_TRACE_PATH="api_trace"
69    /// ```
70    ///
71    /// [API tracing]: https://github.com/gfx-rs/wgpu/wiki/Debugging-wgpu-Applications#tracing-infrastructure
72    pub fn load_from_env(&mut self) {
73        if let Ok(mut v) = var("KAS_POWER_PREFERENCE") {
74            v.make_ascii_uppercase();
75            self.power_preference = match v.as_str() {
76                "DEFAULT" | "LOWPOWER" => PowerPreference::LowPower,
77                "HIGHPERFORMANCE" => PowerPreference::HighPerformance,
78                other => {
79                    log::error!("from_env: bad var KAS_POWER_PREFERENCE={other}");
80                    log::error!(
81                        "from_env: supported power modes: DEFAULT, LOWPOWER, HIGHPERFORMANCE"
82                    );
83                    self.power_preference
84                }
85            }
86        }
87
88        if let Ok(mut v) = var("KAS_BACKENDS") {
89            v.make_ascii_uppercase();
90            self.backends = match v.as_str() {
91                "VULKAN" => Backends::VULKAN,
92                "GL" => Backends::GL,
93                "METAL" => Backends::METAL,
94                "DX12" => Backends::DX12,
95                "BROWSER_WEBGPU" => Backends::BROWSER_WEBGPU,
96                "PRIMARY" => Backends::PRIMARY,
97                "SECONDARY" => Backends::SECONDARY,
98                "FALLBACK" => Backends::empty(),
99                other => {
100                    log::error!("from_env: bad var KAS_BACKENDS={other}");
101                    log::error!(
102                        "from_env: supported backends: VULKAN, GL, METAL, DX12, BROWSER_WEBGPU, PRIMARY, SECONDARY, FALLBACK"
103                    );
104                    self.backends
105                }
106            }
107        }
108
109        if let Ok(v) = var("KAS_WGPU_TRACE_PATH") {
110            self.wgpu_trace_path = Some(v.into());
111        }
112    }
113
114    pub(crate) fn adapter_options(&self) -> wgpu::RequestAdapterOptions<'_, '_> {
115        wgpu::RequestAdapterOptions {
116            power_preference: self.power_preference,
117            force_fallback_adapter: self.backends.is_empty(),
118            compatible_surface: None,
119        }
120    }
121
122    pub(crate) fn backend(&self) -> Backends {
123        if self.backends.is_empty() {
124            Backends::PRIMARY
125        } else {
126            self.backends
127        }
128    }
129}