1use std::cell::RefCell;
2
3use wgpu::{
4 Adapter, Device, DeviceDescriptor, Features, Instance, Limits, MemoryHints, PowerPreference,
5 Queue, RenderPipeline, RequestAdapterOptions, Surface, SurfaceConfiguration,
6};
7use winit::{dpi::PhysicalSize, event_loop::EventLoopProxy, window::Window};
8
9use crate::plinth_app::PlinthApp;
10
11#[cfg(target_arch = "wasm32")]
12pub type Rc<T> = std::rc::Rc<T>;
13
14#[cfg(not(target_arch = "wasm32"))]
15pub type Rc<T> = std::sync::Arc<T>;
16
17pub async fn create_graphics(
18 window: Rc<Window>,
19 proxy: EventLoopProxy<Graphics>,
20 user_app: Rc<RefCell<dyn PlinthApp>>,
21) {
22 let instance = Instance::default();
23 let surface = instance.create_surface(Rc::clone(&window)).unwrap();
24 let adapter = instance
25 .request_adapter(&RequestAdapterOptions {
26 power_preference: PowerPreference::default(), force_fallback_adapter: false, compatible_surface: Some(&surface), })
30 .await
31 .expect("Could not get an adapter (GPU).");
32
33 let (device, queue) = adapter
34 .request_device(
35 &DeviceDescriptor {
36 label: None,
37 required_features: Features::empty(), required_limits: Limits::downlevel_webgl2_defaults()
39 .using_resolution(adapter.limits()),
40 memory_hints: MemoryHints::Performance,
41 },
42 None,
43 )
44 .await
45 .expect("Failed to get device");
46
47 let size = window.inner_size();
49 let width = size.width.max(1);
51 let height = size.height.max(1);
52 let surface_config = surface.get_default_config(&adapter, width, height).unwrap();
53
54 #[cfg(not(target_arch = "wasm32"))]
55 surface.configure(&device, &surface_config);
56
57 let render_pipelines = vec![];
58
59 let mut gfx = Graphics {
60 window: window.clone(),
61 _instance: instance,
62 surface,
63 surface_config,
64 _adapter: adapter,
65 device,
66 queue,
67 render_pipelines,
68 };
69
70 let render_pipeline = user_app.borrow_mut().create_pipeline(&mut gfx);
71
72 gfx.render_pipelines.push(render_pipeline);
73
74 let _ = proxy.send_event(gfx);
75}
76
77#[derive(Debug)]
78pub struct Graphics {
79 pub window: Rc<Window>,
80 pub _instance: Instance,
81 pub surface: Surface<'static>,
82 pub surface_config: SurfaceConfiguration,
83 pub _adapter: Adapter,
84 pub device: Device,
85 pub queue: Queue,
86 pub render_pipelines: Vec<RenderPipeline>,
87}
88
89impl Graphics {
90 pub fn resize(&mut self, new_size: PhysicalSize<u32>) {
91 self.surface_config.width = new_size.width.max(1);
92 self.surface_config.height = new_size.height.max(1);
93 self.surface.configure(&self.device, &self.surface_config);
94 }
95}