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}