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                apply_limit_buckets: false,
54            })
55            .await
56            .map_err(|e| RenderError::DeviceCreation {
57                message: e.to_string(),
58            })?;
59
60        log::info!(
61            "render adapter selected backend={:?} name={}",
62            adapter.get_info().backend,
63            adapter.get_info().name
64        );
65
66        let (device, queue) = adapter
67            .request_device(&wgpu::DeviceDescriptor {
68                label: Some("ff-render"),
69                ..Default::default()
70            })
71            .await
72            .map_err(|e| RenderError::DeviceCreation {
73                message: e.to_string(),
74            })?;
75
76        Ok(Self { device, queue })
77    }
78}