diff --git a/desktop/src/cli.rs b/desktop/src/cli.rs index 3af8e10c4a..30650325de 100644 --- a/desktop/src/cli.rs +++ b/desktop/src/cli.rs @@ -6,4 +6,7 @@ pub struct Cli { #[arg(long, action = clap::ArgAction::SetTrue, help = "Disable hardware accelerated UI rendering")] pub disable_ui_acceleration: bool, + + #[arg(long, action = clap::ArgAction::SetTrue, help = "List available GPU adapters and exit")] + pub list_gpu_adapters: bool, } diff --git a/desktop/src/gpu_context.rs b/desktop/src/gpu_context.rs index 9b25f30fd9..b1c14a13ff 100644 --- a/desktop/src/gpu_context.rs +++ b/desktop/src/gpu_context.rs @@ -1,23 +1,39 @@ use crate::wrapper::{WgpuContext, WgpuContextBuilder, WgpuFeatures}; +const ADAPTER_ENV_VAR: &str = "GRAPHITE_WGPU_ADAPTER"; + +fn create_context_builder() -> WgpuContextBuilder { + WgpuContextBuilder::new().with_features(WgpuFeatures::PUSH_CONSTANTS) +} + +/// Lists all available WGPU adapters to stdout. +/// +/// This is intended for use with the `--list-gpu-adapters` CLI flag, +/// allowing users to identify available GPU adapters before selecting one +/// via the `GRAPHITE_WGPU_ADAPTER` environment variable. +pub(super) async fn list_adapters() { + let builder = create_context_builder(); + println!("\nAvailable WGPU adapters:\n{}", builder.available_adapters_fmt().await); + println!("\nTo select a specific adapter, set the {} environment variable to the adapter index.", ADAPTER_ENV_VAR); +} + +/// Creates and initializes the WGPU context for GPU rendering. +/// +/// Adapter selection can be overridden by setting the `GRAPHITE_WGPU_ADAPTER` +/// environment variable to the desired adapter index. pub(super) async fn create_wgpu_context() -> WgpuContext { - let wgpu_context_builder = WgpuContextBuilder::new().with_features(WgpuFeatures::PUSH_CONSTANTS); + let builder = create_context_builder(); - // TODO: add a cli flag to list adapters and exit instead of always printing - println!("\nAvailable WGPU adapters:\n{}", wgpu_context_builder.available_adapters_fmt().await); + let adapter_override = std::env::var(ADAPTER_ENV_VAR).ok().and_then(|s| s.parse().ok()); - // TODO: make this configurable via cli flags instead - let wgpu_context = match std::env::var("GRAPHITE_WGPU_ADAPTER").ok().and_then(|s| s.parse().ok()) { - None => wgpu_context_builder.build().await, + let wgpu_context = match adapter_override { + None => builder.build().await, Some(adapter_index) => { tracing::info!("Overriding WGPU adapter selection with adapter index {adapter_index}"); - wgpu_context_builder.build_with_adapter_selection(|_| Some(adapter_index)).await + builder.build_with_adapter_selection(|_| Some(adapter_index)).await } } .expect("Failed to create WGPU context"); - // TODO: add a cli flag to list adapters and exit instead of always printing - println!("Using WGPU adapter: {:?}", wgpu_context.adapter.get_info()); - wgpu_context } diff --git a/desktop/src/lib.rs b/desktop/src/lib.rs index 692adbab06..a91570dbee 100644 --- a/desktop/src/lib.rs +++ b/desktop/src/lib.rs @@ -58,8 +58,12 @@ pub fn start() { let cli = Cli::parse(); - let wgpu_context = futures::executor::block_on(gpu_context::create_wgpu_context()); + if cli.list_gpu_adapters { + futures::executor::block_on(gpu_context::list_adapters()); + return; + } + let wgpu_context = futures::executor::block_on(gpu_context::create_wgpu_context()); let event_loop = EventLoop::new().unwrap(); let (app_event_sender, app_event_receiver) = std::sync::mpsc::channel(); let app_event_scheduler = event_loop.create_app_event_scheduler(app_event_sender);