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#[derive(Clone)]
14pub enum WgpuSettingsPriority {
15 Compatibility,
17 Functionality,
19 WebGL2,
21}
22
23#[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 pub features: WgpuFeatures,
41 pub disabled_features: Option<WgpuFeatures>,
43 pub limits: WgpuLimits,
45 pub constrained_limits: Option<WgpuLimits>,
47 pub dx12_shader_compiler: Dx12Compiler,
49 pub gles3_minor_version: Gles3MinorVersion,
52 pub instance_flags: InstanceFlags,
54 pub memory_hints: MemoryHints,
56 pub instance_memory_budget_thresholds: MemoryBudgetThresholds,
58 pub force_fallback_adapter: bool,
60 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#[expect(
160 clippy::large_enum_variant,
161 reason = "See https://github.com/bevyengine/bevy/issues/19220"
162)]
163pub enum RenderCreation {
164 Manual(RenderResources),
166 Automatic(WgpuSettings),
168}
169
170impl RenderCreation {
171 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
212pub 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}