1use std::sync::Arc;
2
3#[derive(Debug, Clone, Copy, PartialEq, Eq)]
5pub enum BackendType {
6 WebGPU,
7 WebGL2,
8}
9
10pub struct GPUBackend {
20 pub backend_type: BackendType,
21 pub device: Option<Arc<wgpu::Device>>,
22 pub queue: Option<Arc<wgpu::Queue>>,
23 pub surface: Option<wgpu::Surface<'static>>,
24 pub config: Option<wgpu::SurfaceConfiguration>,
25}
26
27impl GPUBackend {
28 pub async fn new() -> Result<Self, String> {
30 match Self::init_webgpu().await {
32 Ok(backend) => {
33 log::info!("Initialized WebGPU backend");
34 Ok(backend)
35 }
36 Err(e) => {
37 log::warn!("WebGPU initialization failed: {}, falling back to WebGL2", e);
38 Err(format!("WebGPU failed: {}", e))
40 }
41 }
42 }
43
44 async fn init_webgpu() -> Result<Self, String> {
46 let instance = wgpu::Instance::new(wgpu::InstanceDescriptor {
47 backends: wgpu::Backends::all(),
48 ..Default::default()
49 });
50
51 let adapter = instance
52 .request_adapter(&wgpu::RequestAdapterOptions {
53 power_preference: wgpu::PowerPreference::HighPerformance,
54 compatible_surface: None,
55 force_fallback_adapter: false,
56 })
57 .await
58 .ok_or("Failed to find GPU adapter")?;
59
60 let (device, queue) = adapter
61 .request_device(
62 &wgpu::DeviceDescriptor {
63 label: Some("Helion Device"),
64 required_features: wgpu::Features::empty(),
65 required_limits: wgpu::Limits::default(),
66 memory_hints: Default::default(),
67 },
68 None,
69 )
70 .await
71 .map_err(|e| format!("Failed to create device: {}", e))?;
72
73 Ok(GPUBackend {
74 backend_type: BackendType::WebGPU,
75 device: Some(Arc::new(device)),
76 queue: Some(Arc::new(queue)),
77 surface: None,
78 config: None,
79 })
80 }
81
82 pub fn configure_surface(
84 &mut self,
85 surface: wgpu::Surface<'static>,
86 width: u32,
87 height: u32,
88 ) -> Result<(), String> {
89 let device = self.device.as_ref().ok_or("Device not initialized")?;
90
91 let config = wgpu::SurfaceConfiguration {
92 usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
93 format: wgpu::TextureFormat::Bgra8UnormSrgb,
94 width,
95 height,
96 present_mode: wgpu::PresentMode::Fifo,
97 alpha_mode: wgpu::CompositeAlphaMode::Opaque,
98 view_formats: vec![],
99 desired_maximum_frame_latency: 2,
100 };
101
102 surface.configure(device.as_ref(), &config);
103
104 self.surface = Some(surface);
105 self.config = Some(config);
106
107 Ok(())
108 }
109
110 pub fn device(&self) -> Result<&wgpu::Device, String> {
112 self.device
113 .as_ref()
114 .map(|d| d.as_ref())
115 .ok_or("Device not initialized".to_string())
116 }
117
118 pub fn queue(&self) -> Result<&wgpu::Queue, String> {
120 self.queue
121 .as_ref()
122 .map(|q| q.as_ref())
123 .ok_or("Queue not initialized".to_string())
124 }
125}