ready_paint/gfx/
mod.rs

1use crate::time::{now, TimeStamp};
2use std::sync::Arc;
3use wgpu::{Backends, RequestAdapterOptions, SurfaceTarget};
4pub struct Gfx {
5    pub adapter: wgpu::Adapter,
6    pub device: wgpu::Device,
7    pub queue: wgpu::Queue,
8    pub surface: wgpu::Surface<'static>,
9    pub surface_config: Option<wgpu::SurfaceConfiguration>,
10    pub last_update: TimeStamp,
11    pub time: Arc<std::sync::Mutex<f32>>,
12    pub limit_fps: LimitFPS,
13    pub fps_history: Vec<f32>,
14    pub delta_time: f32,
15}
16impl Gfx {
17    pub async fn new(window: impl Into<SurfaceTarget<'static>>) -> Self {
18        #[cfg(target_arch = "wasm32")]
19        {
20            console_error_panic_hook::set_once();
21        }
22
23        #[cfg(target_arch = "wasm32")]
24        let instance = {
25            wgpu::Instance::new(&wgpu::InstanceDescriptor {
26                backends: Backends::BROWSER_WEBGPU,
27                ..Default::default()
28            })
29        };
30        #[cfg(not(target_arch = "wasm32"))]
31        let instance = wgpu::Instance::default();
32
33        let adapter = instance
34            .request_adapter(&RequestAdapterOptions::default())
35            .await
36            .unwrap();
37
38        let (device, queue) = adapter
39            .request_device(&wgpu::DeviceDescriptor::default(), None)
40            .await
41            .unwrap();
42
43        let surface = instance.create_surface(window).unwrap();
44
45        Gfx {
46            device,
47            queue,
48            surface,
49            adapter,
50            surface_config: None,
51            last_update: now(),
52            time: Arc::new(std::sync::Mutex::new(0.0)),
53            limit_fps: LimitFPS::default(),
54            fps_history: Vec::new(),
55            delta_time: 0.0,
56        }
57    }
58    pub fn set_zero_dt(&mut self) {
59        self.delta_time = 0.;
60    }
61    pub fn with_fps(mut self, fps: f32) -> Self {
62        self.limit_fps = LimitFPS::Limit(fps);
63        self
64    }
65    pub fn with_no_fps_limit(mut self) -> Self {
66        self.limit_fps = LimitFPS::NoLimit;
67        self
68    }
69
70    pub fn resize(&mut self, width: u32, height: u32) {
71        let mut surface_config = self
72            .surface
73            .get_default_config(&self.adapter, width, height)
74            .unwrap();
75        self.surface.configure(&self.device, &surface_config);
76        let view_format = surface_config.format.add_srgb_suffix();
77        surface_config.view_formats.push(view_format);
78        self.surface_config = Some(surface_config);
79    }
80
81    pub fn test(&self) -> Result<(), wgpu::SurfaceError> {
82        let output = self.surface.get_current_texture()?;
83        let view = output
84            .texture
85            .create_view(&wgpu::TextureViewDescriptor::default());
86
87        let mut encoder = self
88            .device
89            .create_command_encoder(&wgpu::CommandEncoderDescriptor {
90                label: Some("Render Encoder"),
91            });
92        {
93            let _render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
94                label: Some("Render Pass"),
95                color_attachments: &[Some(wgpu::RenderPassColorAttachment {
96                    view: &view,
97                    resolve_target: None,
98                    ops: wgpu::Operations {
99                        load: wgpu::LoadOp::Clear(wgpu::Color {
100                            r: 0.1,
101                            g: 0.2,
102                            b: 0.3,
103                            a: 1.0,
104                        }),
105                        store: wgpu::StoreOp::Store,
106                    },
107                })],
108                depth_stencil_attachment: None,
109                occlusion_query_set: None,
110                timestamp_writes: None,
111            });
112        }
113
114        // submit will accept anything that implements IntoIter
115        self.queue.submit(std::iter::once(encoder.finish()));
116        output.present();
117        Ok(())
118    }
119}
120
121#[derive(PartialEq)]
122pub enum LimitFPS {
123    Limit(f32),
124    NoLimit,
125}
126impl Default for LimitFPS {
127    fn default() -> Self {
128        LimitFPS::Limit(30.0)
129    }
130}