Skip to main content

ff_render/
context.rs

1use crate::error::RenderError;
2
3/// Owns the wgpu device and queue used by the render pipeline.
4///
5/// Share via `Arc<RenderContext>` when multiple components (graph, sink, etc.)
6/// need access to the same GPU device.
7pub struct RenderContext {
8    pub device: wgpu::Device,
9    pub queue: wgpu::Queue,
10}
11
12impl RenderContext {
13    /// Wrap an existing wgpu device (e.g. shared with the window renderer).
14    #[must_use]
15    pub fn new(device: wgpu::Device, queue: wgpu::Queue) -> Self {
16        Self { device, queue }
17    }
18
19    /// Initialise wgpu using the default (best available) backend.
20    ///
21    /// Backend priority: Metal → Vulkan → DX12 → WebGPU → OpenGL.
22    ///
23    /// # Errors
24    ///
25    /// Returns [`RenderError::DeviceCreation`] if no suitable adapter is found or
26    /// the device request fails.
27    pub async fn init() -> Result<Self, RenderError> {
28        Self::init_with_backend(wgpu::Backends::all()).await
29    }
30
31    /// Initialise wgpu with an explicit backend set.
32    ///
33    /// Useful in CI where only `wgpu::Backends::GL` may be available.
34    ///
35    /// # Errors
36    ///
37    /// Returns [`RenderError::DeviceCreation`] if no suitable adapter is found or
38    /// the device request fails.
39    pub async fn init_with_backend(backends: wgpu::Backends) -> Result<Self, RenderError> {
40        let instance = wgpu::Instance::new(wgpu::InstanceDescriptor {
41            backends,
42            flags: wgpu::InstanceFlags::default(),
43            memory_budget_thresholds: wgpu::MemoryBudgetThresholds::default(),
44            backend_options: wgpu::BackendOptions::default(),
45            display: None,
46        });
47
48        let adapter = instance
49            .request_adapter(&wgpu::RequestAdapterOptions {
50                power_preference: wgpu::PowerPreference::HighPerformance,
51                force_fallback_adapter: false,
52                compatible_surface: None,
53            })
54            .await
55            .map_err(|e| RenderError::DeviceCreation {
56                message: e.to_string(),
57            })?;
58
59        log::info!(
60            "render adapter selected backend={:?} name={}",
61            adapter.get_info().backend,
62            adapter.get_info().name
63        );
64
65        let (device, queue) = adapter
66            .request_device(&wgpu::DeviceDescriptor {
67                label: Some("ff-render"),
68                ..Default::default()
69            })
70            .await
71            .map_err(|e| RenderError::DeviceCreation {
72                message: e.to_string(),
73            })?;
74
75        Ok(Self { device, queue })
76    }
77}