Skip to main content

arcane_engine/renderer/
gpu.rs

1use anyhow::{Context, Result};
2use std::sync::Arc;
3
4/// Holds the wgpu device, queue, surface, and configuration.
5pub struct GpuContext {
6    pub device: wgpu::Device,
7    pub queue: wgpu::Queue,
8    pub surface: wgpu::Surface<'static>,
9    pub config: wgpu::SurfaceConfiguration,
10}
11
12impl GpuContext {
13    /// Initialize wgpu with the given window.
14    pub fn new(window: Arc<winit::window::Window>) -> Result<Self> {
15        let instance = wgpu::Instance::new(&wgpu::InstanceDescriptor {
16            backends: wgpu::Backends::all(),
17            ..Default::default()
18        });
19
20        let surface = instance
21            .create_surface(window.clone())
22            .context("Failed to create wgpu surface")?;
23
24        let adapter = pollster::block_on(instance.request_adapter(&wgpu::RequestAdapterOptions {
25            power_preference: wgpu::PowerPreference::default(),
26            compatible_surface: Some(&surface),
27            force_fallback_adapter: false,
28        }))
29        .context("No suitable GPU adapter found")?;
30
31        let (device, queue) = pollster::block_on(adapter.request_device(
32            &wgpu::DeviceDescriptor {
33                label: Some("arcane_device"),
34                required_features: wgpu::Features::empty(),
35                required_limits: wgpu::Limits::default(),
36                ..Default::default()
37            },
38            None,
39        ))
40        .context("Failed to create GPU device")?;
41
42        let size = window.inner_size();
43        let surface_caps = surface.get_capabilities(&adapter);
44        let surface_format = surface_caps
45            .formats
46            .iter()
47            .find(|f| f.is_srgb())
48            .copied()
49            .unwrap_or(surface_caps.formats[0]);
50
51        let config = wgpu::SurfaceConfiguration {
52            usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
53            format: surface_format,
54            width: size.width.max(1),
55            height: size.height.max(1),
56            present_mode: wgpu::PresentMode::AutoVsync,
57            alpha_mode: surface_caps.alpha_modes[0],
58            view_formats: vec![],
59            desired_maximum_frame_latency: 2,
60        };
61
62        surface.configure(&device, &config);
63
64        Ok(Self {
65            device,
66            queue,
67            surface,
68            config,
69        })
70    }
71}