From 852fb84aa2b65cb7262b0b176a278178932afa28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?charlotte=20=F0=9F=8C=B8?= Date: Thu, 3 Jul 2025 15:26:34 -0700 Subject: [PATCH] Add options for selecting adapter by name and forcing fallback (#19921) Adds support for: - `WGPU_ADAPTER_NAME` which will attempt to select a specific adapter with a given name. - `WGPU_FORCE_FALLBACK_ADAPTER` which will force fallback to a fallback (software) renderer, if available. The first has higher specificity than the second. --- crates/bevy_render/src/lib.rs | 12 +++++++- crates/bevy_render/src/renderer/mod.rs | 38 ++++++++++++++++++++++---- crates/bevy_render/src/settings.rs | 6 ++++ 3 files changed, 50 insertions(+), 6 deletions(-) diff --git a/crates/bevy_render/src/lib.rs b/crates/bevy_render/src/lib.rs index 526d75dccd..76d8cb78e1 100644 --- a/crates/bevy_render/src/lib.rs +++ b/crates/bevy_render/src/lib.rs @@ -399,10 +399,19 @@ impl Plugin for RenderPlugin { } }); + let force_fallback_adapter = std::env::var("WGPU_FORCE_FALLBACK_ADAPTER") + .map_or(settings.force_fallback_adapter, |v| { + !(v.is_empty() || v == "0" || v == "false") + }); + + let desired_adapter_name = std::env::var("WGPU_ADAPTER_NAME") + .as_deref() + .map_or(settings.adapter_name.clone(), |x| Some(x.to_lowercase())); + let request_adapter_options = wgpu::RequestAdapterOptions { power_preference: settings.power_preference, compatible_surface: surface.as_ref(), - ..Default::default() + force_fallback_adapter, }; let (device, queue, adapter_info, render_adapter) = @@ -410,6 +419,7 @@ impl Plugin for RenderPlugin { &instance, &settings, &request_adapter_options, + desired_adapter_name, ) .await; debug!("Configured wgpu adapter Limits: {:#?}", device.limits()); diff --git a/crates/bevy_render/src/renderer/mod.rs b/crates/bevy_render/src/renderer/mod.rs index 5df4967757..7cb8023de1 100644 --- a/crates/bevy_render/src/renderer/mod.rs +++ b/crates/bevy_render/src/renderer/mod.rs @@ -7,7 +7,7 @@ use bevy_tasks::ComputeTaskPool; use bevy_utils::WgpuWrapper; pub use graph_runner::*; pub use render_device::*; -use tracing::{error, info, info_span, warn}; +use tracing::{debug, error, info, info_span, trace, warn}; use crate::{ diagnostic::{internal::DiagnosticsRecorder, RecordDiagnostics}, @@ -151,12 +151,40 @@ pub async fn initialize_renderer( instance: &Instance, options: &WgpuSettings, request_adapter_options: &RequestAdapterOptions<'_, '_>, + desired_adapter_name: Option, ) -> (RenderDevice, RenderQueue, RenderAdapterInfo, RenderAdapter) { - let adapter = instance - .request_adapter(request_adapter_options) - .await - .expect(GPU_NOT_FOUND_ERROR_MESSAGE); + let mut selected_adapter = None; + if let Some(adapter_name) = &desired_adapter_name { + debug!("Searching for adapter with name: {}", adapter_name); + for adapter in instance.enumerate_adapters(options.backends.expect( + "The `backends` field of `WgpuSettings` must be set to use a specific adapter.", + )) { + trace!("Checking adapter: {:?}", adapter.get_info()); + let info = adapter.get_info(); + if let Some(surface) = request_adapter_options.compatible_surface { + if !adapter.is_surface_supported(surface) { + continue; + } + } + if info + .name + .to_lowercase() + .contains(&adapter_name.to_lowercase()) + { + selected_adapter = Some(adapter); + break; + } + } + } else { + debug!( + "Searching for adapter with options: {:?}", + request_adapter_options + ); + selected_adapter = instance.request_adapter(request_adapter_options).await.ok(); + }; + + let adapter = selected_adapter.expect(GPU_NOT_FOUND_ERROR_MESSAGE); let adapter_info = adapter.get_info(); info!("{:?}", adapter_info); diff --git a/crates/bevy_render/src/settings.rs b/crates/bevy_render/src/settings.rs index 715bbb35f8..d4456953af 100644 --- a/crates/bevy_render/src/settings.rs +++ b/crates/bevy_render/src/settings.rs @@ -53,6 +53,10 @@ pub struct WgpuSettings { pub instance_flags: InstanceFlags, /// This hints to the WGPU device about the preferred memory allocation strategy. pub memory_hints: MemoryHints, + /// If true, will force wgpu to use a software renderer, if available. + pub force_fallback_adapter: bool, + /// The name of the adapter to use. + pub adapter_name: Option, } impl Default for WgpuSettings { @@ -136,6 +140,8 @@ impl Default for WgpuSettings { gles3_minor_version, instance_flags, memory_hints: MemoryHints::default(), + force_fallback_adapter: false, + adapter_name: None, } } }