bevy_render/
settings.rs

1use crate::renderer::{
2    RenderAdapter, RenderAdapterInfo, RenderDevice, RenderInstance, RenderQueue,
3};
4use alloc::borrow::Cow;
5use std::path::PathBuf;
6
7pub use wgpu::{
8    Backends, Dx12Compiler, Features as WgpuFeatures, Gles3MinorVersion, InstanceFlags,
9    Limits as WgpuLimits, MemoryHints, PowerPreference,
10};
11
12/// Configures the priority used when automatically configuring the features/limits of `wgpu`.
13#[derive(Clone)]
14pub enum WgpuSettingsPriority {
15    /// WebGPU default features and limits
16    Compatibility,
17    /// The maximum supported features and limits of the adapter and backend
18    Functionality,
19    /// WebGPU default limits plus additional constraints in order to be compatible with WebGL2
20    WebGL2,
21}
22
23/// Provides configuration for renderer initialization. Use [`RenderDevice::features`](RenderDevice::features),
24/// [`RenderDevice::limits`](RenderDevice::limits), and the [`RenderAdapterInfo`]
25/// resource to get runtime information about the actual adapter, backend, features, and limits.
26/// NOTE: [`Backends::DX12`](Backends::DX12), [`Backends::METAL`](Backends::METAL), and
27/// [`Backends::VULKAN`](Backends::VULKAN) are enabled by default for non-web and the best choice
28/// is automatically selected. Web using the `webgl` feature uses [`Backends::GL`](Backends::GL).
29/// NOTE: If you want to use [`Backends::GL`](Backends::GL) in a native app on `Windows` and/or `macOS`, you must
30/// use [`ANGLE`](https://github.com/gfx-rs/wgpu#angle). This is because wgpu requires EGL to
31/// create a GL context without a window and only ANGLE supports that.
32#[derive(Clone)]
33pub struct WgpuSettings {
34    pub device_label: Option<Cow<'static, str>>,
35    pub backends: Option<Backends>,
36    pub power_preference: PowerPreference,
37    pub priority: WgpuSettingsPriority,
38    /// The features to ensure are enabled regardless of what the adapter/backend supports.
39    /// Setting these explicitly may cause renderer initialization to fail.
40    pub features: WgpuFeatures,
41    /// The features to ensure are disabled regardless of what the adapter/backend supports
42    pub disabled_features: Option<WgpuFeatures>,
43    /// The imposed limits.
44    pub limits: WgpuLimits,
45    /// The constraints on limits allowed regardless of what the adapter/backend supports
46    pub constrained_limits: Option<WgpuLimits>,
47    /// The shader compiler to use for the DX12 backend.
48    pub dx12_shader_compiler: Dx12Compiler,
49    /// Allows you to choose which minor version of GLES3 to use (3.0, 3.1, 3.2, or automatic)
50    /// This only applies when using ANGLE and the GL backend.
51    pub gles3_minor_version: Gles3MinorVersion,
52    /// These are for controlling WGPU's debug information to eg. enable validation and shader debug info in release builds.
53    pub instance_flags: InstanceFlags,
54    /// This hints to the WGPU device about the preferred memory allocation strategy.
55    pub memory_hints: MemoryHints,
56    /// The path to pass to wgpu for API call tracing. This only has an effect if wgpu's tracing functionality is enabled.
57    pub trace_path: Option<PathBuf>,
58}
59
60impl Default for WgpuSettings {
61    fn default() -> Self {
62        let default_backends = if cfg!(all(
63            feature = "webgl",
64            target_arch = "wasm32",
65            not(feature = "webgpu")
66        )) {
67            Backends::GL
68        } else if cfg!(all(feature = "webgpu", target_arch = "wasm32")) {
69            Backends::BROWSER_WEBGPU
70        } else {
71            Backends::all()
72        };
73
74        let backends = Some(wgpu::util::backend_bits_from_env().unwrap_or(default_backends));
75
76        let power_preference =
77            wgpu::util::power_preference_from_env().unwrap_or(PowerPreference::HighPerformance);
78
79        let priority = settings_priority_from_env().unwrap_or(WgpuSettingsPriority::Functionality);
80
81        let limits = if cfg!(all(
82            feature = "webgl",
83            target_arch = "wasm32",
84            not(feature = "webgpu")
85        )) || matches!(priority, WgpuSettingsPriority::WebGL2)
86        {
87            wgpu::Limits::downlevel_webgl2_defaults()
88        } else {
89            #[allow(unused_mut)]
90            let mut limits = wgpu::Limits::default();
91            #[cfg(feature = "ci_limits")]
92            {
93                limits.max_storage_textures_per_shader_stage = 4;
94                limits.max_texture_dimension_3d = 1024;
95            }
96            limits
97        };
98
99        let dx12_compiler =
100            wgpu::util::dx12_shader_compiler_from_env().unwrap_or(Dx12Compiler::Dxc {
101                dxil_path: None,
102                dxc_path: None,
103            });
104
105        let gles3_minor_version = wgpu::util::gles_minor_version_from_env().unwrap_or_default();
106
107        let instance_flags = InstanceFlags::default().with_env();
108
109        Self {
110            device_label: Default::default(),
111            backends,
112            power_preference,
113            priority,
114            features: wgpu::Features::TEXTURE_ADAPTER_SPECIFIC_FORMAT_FEATURES,
115            disabled_features: None,
116            limits,
117            constrained_limits: None,
118            dx12_shader_compiler: dx12_compiler,
119            gles3_minor_version,
120            instance_flags,
121            memory_hints: MemoryHints::default(),
122            trace_path: None,
123        }
124    }
125}
126
127/// An enum describing how the renderer will initialize resources. This is used when creating the [`RenderPlugin`](crate::RenderPlugin).
128pub enum RenderCreation {
129    /// Allows renderer resource initialization to happen outside of the rendering plugin.
130    Manual(
131        RenderDevice,
132        RenderQueue,
133        RenderAdapterInfo,
134        RenderAdapter,
135        RenderInstance,
136    ),
137    /// Lets the rendering plugin create resources itself.
138    Automatic(WgpuSettings),
139}
140
141impl RenderCreation {
142    /// Function to create a [`RenderCreation::Manual`] variant.
143    pub fn manual(
144        device: RenderDevice,
145        queue: RenderQueue,
146        adapter_info: RenderAdapterInfo,
147        adapter: RenderAdapter,
148        instance: RenderInstance,
149    ) -> Self {
150        Self::Manual(device, queue, adapter_info, adapter, instance)
151    }
152}
153
154impl Default for RenderCreation {
155    fn default() -> Self {
156        Self::Automatic(Default::default())
157    }
158}
159
160impl From<WgpuSettings> for RenderCreation {
161    fn from(value: WgpuSettings) -> Self {
162        Self::Automatic(value)
163    }
164}
165
166/// Get a features/limits priority from the environment variable `WGPU_SETTINGS_PRIO`
167pub fn settings_priority_from_env() -> Option<WgpuSettingsPriority> {
168    Some(
169        match std::env::var("WGPU_SETTINGS_PRIO")
170            .as_deref()
171            .map(str::to_lowercase)
172            .as_deref()
173        {
174            Ok("compatibility") => WgpuSettingsPriority::Compatibility,
175            Ok("functionality") => WgpuSettingsPriority::Functionality,
176            Ok("webgl2") => WgpuSettingsPriority::WebGL2,
177            _ => return None,
178        },
179    )
180}