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#[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 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(Backends::from_env().unwrap_or(default_backends));
75
76 let power_preference =
77 PowerPreference::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 #[expect(clippy::allow_attributes, reason = "`unused_mut` is not always linted")]
90 #[allow(
91 unused_mut,
92 reason = "This variable needs to be mutable if the `ci_limits` feature is enabled"
93 )]
94 let mut limits = wgpu::Limits::default();
95 #[cfg(feature = "ci_limits")]
96 {
97 limits.max_storage_textures_per_shader_stage = 4;
98 limits.max_texture_dimension_3d = 1024;
99 }
100 limits
101 };
102
103 let dx12_shader_compiler =
104 Dx12Compiler::from_env().unwrap_or(if cfg!(feature = "statically-linked-dxc") {
105 Dx12Compiler::StaticDxc
106 } else {
107 let dxc = "dxcompiler.dll";
108 let dxil = "dxil.dll";
109
110 if cfg!(target_os = "windows")
111 && std::fs::metadata(dxc).is_ok()
112 && std::fs::metadata(dxil).is_ok()
113 {
114 Dx12Compiler::DynamicDxc {
115 dxc_path: String::from(dxc),
116 dxil_path: String::from(dxil),
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 trace_path: None,
141 }
142 }
143}
144
145#[derive(Clone)]
146pub struct RenderResources(
147 pub RenderDevice,
148 pub RenderQueue,
149 pub RenderAdapterInfo,
150 pub RenderAdapter,
151 pub RenderInstance,
152);
153
154pub enum RenderCreation {
156 Manual(RenderResources),
158 Automatic(WgpuSettings),
160}
161
162impl RenderCreation {
163 pub fn manual(
165 device: RenderDevice,
166 queue: RenderQueue,
167 adapter_info: RenderAdapterInfo,
168 adapter: RenderAdapter,
169 instance: RenderInstance,
170 ) -> Self {
171 RenderResources(device, queue, adapter_info, adapter, instance).into()
172 }
173}
174
175impl From<RenderResources> for RenderCreation {
176 fn from(value: RenderResources) -> Self {
177 Self::Manual(value)
178 }
179}
180
181impl Default for RenderCreation {
182 fn default() -> Self {
183 Self::Automatic(Default::default())
184 }
185}
186
187impl From<WgpuSettings> for RenderCreation {
188 fn from(value: WgpuSettings) -> Self {
189 Self::Automatic(value)
190 }
191}
192
193pub fn settings_priority_from_env() -> Option<WgpuSettingsPriority> {
195 Some(
196 match std::env::var("WGPU_SETTINGS_PRIO")
197 .as_deref()
198 .map(str::to_lowercase)
199 .as_deref()
200 {
201 Ok("compatibility") => WgpuSettingsPriority::Compatibility,
202 Ok("functionality") => WgpuSettingsPriority::Functionality,
203 Ok("webgl2") => WgpuSettingsPriority::WebGL2,
204 _ => return None,
205 },
206 )
207}