use std::{error::Error, sync::Arc}; use glam::{Mat4, vec3}; use winit::{ application::ApplicationHandler, event::WindowEvent, event_loop::{ActiveEventLoop, ControlFlow, EventLoop}, window::Window, }; use crate::render::lines::{LookParams, Mesh, Pipeline, Vertex}; mod camera; mod render; const TITLE: &str = "WGPU example"; const OUTPUT_FORMAT: wgpu::TextureFormat = wgpu::TextureFormat::Bgra8UnormSrgb; struct MainWindow { handle: Arc, device: wgpu::Device, queue: wgpu::Queue, surface: wgpu::Surface<'static>, surface_configured: bool, pipeline: Pipeline, tripod: Mesh, } pub fn new_tripod(device: &wgpu::Device) -> Mesh { Mesh::new( device, &[ Vertex::new(vec3(0., 0., 0.), vec3(1., 0., 0.)), Vertex::new(vec3(1., 0., 0.), vec3(1., 0., 0.)), Vertex::new(vec3(0., 0., 0.), vec3(0., 1., 0.)), Vertex::new(vec3(0., 1., 0.), vec3(0., 1., 0.)), Vertex::new(vec3(0., 0., 0.), vec3(0., 0., 1.)), Vertex::new(vec3(0., 0., 1.), vec3(0., 0., 1.)), ], ) } impl MainWindow { fn new(event_loop: &ActiveEventLoop) -> Self { let handle = event_loop .create_window(Window::default_attributes().with_title(TITLE)) .unwrap(); let handle = Arc::new(handle); let (device, queue, surface) = pollster::block_on(init_gpu(Arc::clone(&handle))).unwrap(); let pipeline = Pipeline::new(&device, OUTPUT_FORMAT); let tripod = new_tripod(&device); queue.submit([]); // flush buffer updates Self { handle, device, queue, surface, surface_configured: false, pipeline, tripod, } } fn render(&self, output: &wgpu::Texture) { self.pipeline .set_look(&self.queue, LookParams { m: Mat4::IDENTITY }); self.queue.submit([]); // flush buffer updates let view = output.create_view(&wgpu::TextureViewDescriptor::default()); let mut encoder = self .device .create_command_encoder(&wgpu::CommandEncoderDescriptor::default()); let mut pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor { color_attachments: &[Some(wgpu::RenderPassColorAttachment { view: &view, depth_slice: None, resolve_target: None, ops: wgpu::Operations { load: wgpu::LoadOp::Clear(wgpu::Color { r: 0.1, g: 0.2, b: 0.8, a: 1.0, }), store: wgpu::StoreOp::Store, }, })], depth_stencil_attachment: None, ..Default::default() }); self.pipeline.render(&mut pass, [&self.tripod]); drop(pass); self.queue.submit(std::iter::once(encoder.finish())); } fn event(&mut self, event_loop: &ActiveEventLoop, event: WindowEvent) { match event { WindowEvent::CloseRequested => event_loop.exit(), WindowEvent::Resized(physical_size) => { self.surface.configure( &self.device, &wgpu::SurfaceConfiguration { usage: wgpu::TextureUsages::RENDER_ATTACHMENT | wgpu::TextureUsages::COPY_DST, format: OUTPUT_FORMAT, width: physical_size.width, height: physical_size.height, present_mode: wgpu::PresentMode::Fifo, alpha_mode: wgpu::CompositeAlphaMode::Auto, view_formats: vec![], desired_maximum_frame_latency: 2, }, ); self.surface_configured = true; } WindowEvent::RedrawRequested => { self.handle.request_redraw(); if !self.surface_configured { return; } let output = self.surface.get_current_texture().unwrap(); self.render(&output.texture); output.present(); } _ => {} } } } struct Application { main_window: Option, } impl Application { fn new() -> Self { Self { main_window: None } } } impl ApplicationHandler for Application { fn resumed(&mut self, event_loop: &ActiveEventLoop) { self.main_window = Some(MainWindow::new(event_loop)); } fn window_event( &mut self, event_loop: &ActiveEventLoop, window_id: winit::window::WindowId, event: WindowEvent, ) { let window = self .main_window .as_mut() .expect("window must exist to recieve events"); assert_eq!(window.handle.id(), window_id); window.event(event_loop, event); } } async fn init_gpu<'window>( wnd: impl wgpu::WindowHandle + 'window, ) -> Result<(wgpu::Device, wgpu::Queue, wgpu::Surface<'window>), Box> { let instance = wgpu::Instance::new(&wgpu::InstanceDescriptor { backends: wgpu::Backends::PRIMARY, ..Default::default() }); let surface = instance.create_surface(wnd)?; let adapter = instance .request_adapter(&wgpu::RequestAdapterOptions { power_preference: wgpu::PowerPreference::default(), compatible_surface: Some(&surface), force_fallback_adapter: false, }) .await .unwrap(); let (device, queue) = adapter .request_device(&wgpu::DeviceDescriptor::default()) .await .unwrap(); Ok((device, queue, surface)) } fn main() { let event_loop = EventLoop::new().unwrap(); event_loop.set_control_flow(ControlFlow::Wait); let mut app = Application::new(); event_loop.run_app(&mut app).unwrap(); }