glaze/
state.rs

1use pollster::FutureExt;
2use winit::event::Event;
3
4use crate::renderer::Renderer;
5
6pub struct State {
7    renderer: Renderer,
8    window: winit::window::Window,
9    size: winit::dpi::PhysicalSize<u32>,
10    surface: wgpu::Surface,
11    surface_config: wgpu::SurfaceConfiguration,
12}
13
14impl State {
15    pub fn new(window: winit::window::Window) -> Self {
16        let size = window.inner_size();
17
18        let instance = wgpu::Instance::new(wgpu::InstanceDescriptor {
19            backends: wgpu::Backends::all(),
20            dx12_shader_compiler: Default::default(),
21        });
22
23        let surface = unsafe { instance.create_surface(&window).unwrap() };
24
25        let adapter = instance
26            .enumerate_adapters(wgpu::Backends::all())
27            .filter(|adapter| adapter.is_surface_supported(&surface))
28            .next()
29            .unwrap();
30
31        let surface_capabilities = surface.get_capabilities(&adapter);
32
33        let surface_texture_format = surface_capabilities
34            .formats
35            .iter()
36            .copied()
37            .filter(|format| format.describe().srgb)
38            .next()
39            .unwrap_or(surface_capabilities.formats[0]);
40
41        let surface_config = wgpu::SurfaceConfiguration {
42            alpha_mode: surface_capabilities.alpha_modes[0],
43            format: surface_texture_format,
44            present_mode: wgpu::PresentMode::Fifo,
45            width: size.width,
46            height: size.height,
47            usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
48            view_formats: vec![],
49        };
50
51        let (device, queue) = adapter
52            .request_device(
53                &wgpu::DeviceDescriptor {
54                    features: wgpu::Features::empty(),
55                    label: None,
56                    limits: wgpu::Limits::default(),
57                },
58                None,
59            )
60            .block_on()
61            .unwrap();
62
63        surface.configure(&device, &surface_config);
64
65        let renderer = Renderer::new(device, queue, adapter);
66
67        Self {
68            renderer,
69            window,
70            size,
71            surface,
72            surface_config,
73        }
74    }
75
76    pub fn handle_event(&mut self, event: &Event<'_, ()>) {
77        match event {
78            Event::WindowEvent { ref event, .. } => match event {
79                winit::event::WindowEvent::Resized(new_size) => self.resize(*new_size),
80                _ => {}
81            },
82            Event::RedrawRequested(id) => {
83                if self.window.id() == *id {
84                    self.render().unwrap_or_else(|err| println!("{err}"));
85                }
86            }
87            _ => {}
88        }
89    }
90
91    fn resize(&mut self, new_size: winit::dpi::PhysicalSize<u32>) {
92        if new_size.width > 0 && new_size.height > 0 {
93            self.size = new_size;
94            self.surface_config.width = new_size.width;
95            self.surface_config.height = new_size.height;
96            self.surface
97                .configure(&self.renderer.device, &self.surface_config);
98        }
99    }
100
101    fn render(&mut self) -> Result<(), wgpu::SurfaceError> {
102        let output_texture = self.surface.get_current_texture()?;
103        self.renderer.render(output_texture);
104
105        Ok(())
106    }
107}