1use crate::{GpuInitError, GpuRendererSettings, PowerPreference};
13
14pub struct HeadlessGpu {
17 pub device: wgpu::Device,
18 pub queue: wgpu::Queue,
19 pub adapter_info: String,
20}
21
22impl HeadlessGpu {
23 pub async fn new(settings: GpuRendererSettings) -> Result<Self, GpuInitError> {
28 let instance = wgpu::Instance::new(wgpu::InstanceDescriptor::new_without_display_handle());
29 let power_preference = match settings.power_preference {
30 PowerPreference::Low => wgpu::PowerPreference::LowPower,
31 PowerPreference::High => wgpu::PowerPreference::HighPerformance,
32 };
33 let adapter = instance
34 .request_adapter(&wgpu::RequestAdapterOptions {
35 power_preference,
36 compatible_surface: None,
37 force_fallback_adapter: false,
38 })
39 .await
40 .map_err(|_| GpuInitError::NoAdapter)?;
41 let info = adapter.get_info();
42 let adapter_info = format!(
43 "{name} ({backend:?}, {device_type:?})",
44 name = info.name,
45 backend = info.backend,
46 device_type = info.device_type,
47 );
48 let (device, queue) = adapter
49 .request_device(&wgpu::DeviceDescriptor {
50 label: Some("roxlap-gpu headless device"),
51 required_features: wgpu::Features::empty(),
52 required_limits: crate::pick_required_limits(&adapter.limits()),
53 experimental_features: wgpu::ExperimentalFeatures::disabled(),
54 memory_hints: wgpu::MemoryHints::default(),
55 trace: wgpu::Trace::Off,
56 })
57 .await?;
58 Ok(Self {
59 device,
60 queue,
61 adapter_info,
62 })
63 }
64
65 pub fn new_blocking(settings: GpuRendererSettings) -> Result<Self, GpuInitError> {
70 pollster::block_on(Self::new(settings))
71 }
72}