bevy_render/
settings.rs

1use crate::renderer::{
2    RenderAdapter, RenderAdapterInfo, RenderDevice, RenderInstance, RenderQueue,
3};
4use alloc::borrow::Cow;
5
6pub use wgpu::{
7    Backends, Dx12Compiler, Features as WgpuFeatures, Gles3MinorVersion, InstanceFlags,
8    Limits as WgpuLimits, MemoryHints, PowerPreference,
9};
10use wgpu::{DxcShaderModel, MemoryBudgetThresholds};
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) and enable the `gles` feature. This is
31/// because wgpu requires EGL to 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 thresholds for device memory budget.
57    pub instance_memory_budget_thresholds: MemoryBudgetThresholds,
58    /// If true, will force wgpu to use a software renderer, if available.
59    pub force_fallback_adapter: bool,
60    /// The name of the adapter to use.
61    pub adapter_name: Option<String>,
62}
63
64impl Default for WgpuSettings {
65    fn default() -> Self {
66        let default_backends = if cfg!(all(
67            feature = "webgl",
68            target_arch = "wasm32",
69            not(feature = "webgpu")
70        )) {
71            Backends::GL
72        } else if cfg!(all(feature = "webgpu", target_arch = "wasm32")) {
73            Backends::BROWSER_WEBGPU
74        } else {
75            Backends::all()
76        };
77
78        let backends = Some(Backends::from_env().unwrap_or(default_backends));
79
80        let power_preference =
81            PowerPreference::from_env().unwrap_or(PowerPreference::HighPerformance);
82
83        let priority = settings_priority_from_env().unwrap_or(WgpuSettingsPriority::Functionality);
84
85        let limits = if cfg!(all(
86            feature = "webgl",
87            target_arch = "wasm32",
88            not(feature = "webgpu")
89        )) || matches!(priority, WgpuSettingsPriority::WebGL2)
90        {
91            wgpu::Limits::downlevel_webgl2_defaults()
92        } else {
93            #[expect(clippy::allow_attributes, reason = "`unused_mut` is not always linted")]
94            #[allow(
95                unused_mut,
96                reason = "This variable needs to be mutable if the `ci_limits` feature is enabled"
97            )]
98            let mut limits = wgpu::Limits::default();
99            #[cfg(feature = "ci_limits")]
100            {
101                limits.max_storage_textures_per_shader_stage = 4;
102                limits.max_texture_dimension_3d = 1024;
103            }
104            limits
105        };
106
107        let dx12_shader_compiler =
108            Dx12Compiler::from_env().unwrap_or(if cfg!(feature = "statically-linked-dxc") {
109                Dx12Compiler::StaticDxc
110            } else {
111                let dxc = "dxcompiler.dll";
112
113                if cfg!(target_os = "windows") && std::fs::metadata(dxc).is_ok() {
114                    Dx12Compiler::DynamicDxc {
115                        dxc_path: String::from(dxc),
116                        max_shader_model: DxcShaderModel::V6_7,
117                    }
118                } else {
119                    Dx12Compiler::Fxc
120                }
121            });
122
123        let gles3_minor_version = Gles3MinorVersion::from_env().unwrap_or_default();
124
125        let instance_flags = InstanceFlags::default().with_env();
126
127        Self {
128            device_label: Default::default(),
129            backends,
130            power_preference,
131            priority,
132            features: wgpu::Features::TEXTURE_ADAPTER_SPECIFIC_FORMAT_FEATURES,
133            disabled_features: None,
134            limits,
135            constrained_limits: None,
136            dx12_shader_compiler,
137            gles3_minor_version,
138            instance_flags,
139            memory_hints: MemoryHints::default(),
140            instance_memory_budget_thresholds: MemoryBudgetThresholds::default(),
141            force_fallback_adapter: false,
142            adapter_name: None,
143        }
144    }
145}
146
147#[derive(Clone)]
148pub struct RenderResources(
149    pub RenderDevice,
150    pub RenderQueue,
151    pub RenderAdapterInfo,
152    pub RenderAdapter,
153    pub RenderInstance,
154    #[cfg(feature = "raw_vulkan_init")]
155    pub  crate::renderer::raw_vulkan_init::AdditionalVulkanFeatures,
156);
157
158/// An enum describing how the renderer will initialize resources. This is used when creating the [`RenderPlugin`](crate::RenderPlugin).
159#[expect(
160    clippy::large_enum_variant,
161    reason = "See https://github.com/bevyengine/bevy/issues/19220"
162)]
163pub enum RenderCreation {
164    /// Allows renderer resource initialization to happen outside of the rendering plugin.
165    Manual(RenderResources),
166    /// Lets the rendering plugin create resources itself.
167    Automatic(WgpuSettings),
168}
169
170impl RenderCreation {
171    /// Function to create a [`RenderCreation::Manual`] variant.
172    pub fn manual(
173        device: RenderDevice,
174        queue: RenderQueue,
175        adapter_info: RenderAdapterInfo,
176        adapter: RenderAdapter,
177        instance: RenderInstance,
178        #[cfg(feature = "raw_vulkan_init")]
179        additional_vulkan_features: crate::renderer::raw_vulkan_init::AdditionalVulkanFeatures,
180    ) -> Self {
181        RenderResources(
182            device,
183            queue,
184            adapter_info,
185            adapter,
186            instance,
187            #[cfg(feature = "raw_vulkan_init")]
188            additional_vulkan_features,
189        )
190        .into()
191    }
192}
193
194impl From<RenderResources> for RenderCreation {
195    fn from(value: RenderResources) -> Self {
196        Self::Manual(value)
197    }
198}
199
200impl Default for RenderCreation {
201    fn default() -> Self {
202        Self::Automatic(Default::default())
203    }
204}
205
206impl From<WgpuSettings> for RenderCreation {
207    fn from(value: WgpuSettings) -> Self {
208        Self::Automatic(value)
209    }
210}
211
212/// Get a features/limits priority from the environment variable `WGPU_SETTINGS_PRIO`
213pub fn settings_priority_from_env() -> Option<WgpuSettingsPriority> {
214    Some(
215        match std::env::var("WGPU_SETTINGS_PRIO")
216            .as_deref()
217            .map(str::to_lowercase)
218            .as_deref()
219        {
220            Ok("compatibility") => WgpuSettingsPriority::Compatibility,
221            Ok("functionality") => WgpuSettingsPriority::Functionality,
222            Ok("webgl2") => WgpuSettingsPriority::WebGL2,
223            _ => return None,
224        },
225    )
226}