From 12f115dfa1182d2fb59af5c8b99b571d0fd2d416 Mon Sep 17 00:00:00 2001 From: Benjamin Hansen Date: Sat, 2 Mar 2024 11:24:58 -0700 Subject: [PATCH] code is working again --- code/beginner/tutorial1-window/src/lib.rs | 41 ++--- .../tutorial2-surface/src/challenge.rs | 85 ++++++----- code/beginner/tutorial2-surface/src/lib.rs | 94 ++++++------ .../tutorial3-pipeline/src/challenge.rs | 127 ++++++++-------- code/beginner/tutorial3-pipeline/src/lib.rs | 123 ++++++++------- .../tutorial4-buffer/src/challenge.rs | 125 +++++++-------- code/beginner/tutorial4-buffer/src/lib.rs | 121 +++++++-------- .../tutorial5-textures/src/challenge.rs | 124 +++++++-------- code/beginner/tutorial5-textures/src/lib.rs | 125 ++++++++------- .../tutorial6-uniforms/src/challenge.rs | 139 +++++++++-------- code/beginner/tutorial6-uniforms/src/lib.rs | 143 +++++++++--------- .../tutorial7-instancing/src/challenge.rs | 139 +++++++++-------- code/beginner/tutorial7-instancing/src/lib.rs | 141 +++++++++-------- .../beginner/tutorial8-depth/src/challenge.rs | 137 +++++++++-------- code/beginner/tutorial8-depth/src/lib.rs | 141 +++++++++-------- code/beginner/tutorial9-models/src/lib.rs | 137 +++++++++-------- .../tutorial10-lighting/src/lib.rs | 137 +++++++++-------- .../tutorial11-normals/src/lib.rs | 137 +++++++++-------- .../tutorial12-camera/src/camera.rs | 15 +- .../intermediate/tutorial12-camera/src/lib.rs | 91 ++++++----- .../intermediate/tutorial13-hdr/src/camera.rs | 15 +- code/intermediate/tutorial13-hdr/src/lib.rs | 97 ++++++------ .../tutorial13-hdr/src/resources.rs | 8 +- .../tutorial13-hdr/src/texture.rs | 13 +- .../wip-terrain/src/bindgroups.rs | 4 +- code/intermediate/wip-terrain/src/camera.rs | 15 +- code/intermediate/wip-terrain/src/lib.rs | 83 +++++----- code/intermediate/wip-terrain/src/terrain.rs | 3 +- code/intermediate/wip-terrain/src/texture.rs | 11 +- code/showcase/compute/src/camera.rs | 15 +- code/showcase/compute/src/main.rs | 66 ++++---- code/showcase/compute/src/model.rs | 5 +- code/showcase/framework/src/camera.rs | 15 +- code/showcase/framework/src/lib.rs | 89 ++++++----- code/showcase/framework/src/texture.rs | 2 +- code/showcase/gifs/src/main.rs | 4 +- code/showcase/lost-window/src/main.rs | 4 +- code/showcase/mouse-picking/src/camera.rs | 15 +- code/showcase/mouse-picking/src/lib.rs | 80 +++++----- code/showcase/pong/src/lib.rs | 4 +- code/showcase/pong/src/render/mod.rs | 11 +- code/showcase/snow/src/camera.rs | 21 +-- code/showcase/snow/src/main.rs | 33 ++-- code/showcase/threading/src/camera.rs | 2 +- docs/beginner/tutorial1-window/README.md | 2 +- docs/beginner/tutorial2-surface/README.md | 29 ++-- docs/beginner/tutorial3-pipeline/README.md | 4 +- docs/beginner/tutorial4-buffer/README.md | 6 +- docs/beginner/tutorial5-textures/README.md | 8 +- docs/beginner/tutorial6-uniforms/README.md | 13 +- docs/beginner/tutorial7-instancing/README.md | 4 +- .../tutorial10-lighting/README.md | 2 +- .../intermediate/tutorial11-normals/README.md | 2 +- docs/intermediate/tutorial12-camera/README.md | 20 ++- docs/intermediate/tutorial13-hdr/readme.md | 10 +- 55 files changed, 1524 insertions(+), 1513 deletions(-) diff --git a/code/beginner/tutorial1-window/src/lib.rs b/code/beginner/tutorial1-window/src/lib.rs index e346eed2..d8d9e30a 100644 --- a/code/beginner/tutorial1-window/src/lib.rs +++ b/code/beginner/tutorial1-window/src/lib.rs @@ -1,7 +1,8 @@ use winit::{ event::*, event_loop::EventLoop, - window::WindowBuilder, keyboard::{KeyCode, PhysicalKey}, + keyboard::{KeyCode, PhysicalKey}, + window::WindowBuilder, }; #[cfg(target_arch = "wasm32")] @@ -40,23 +41,25 @@ pub fn run() { .expect("Couldn't append canvas to document body."); } - event_loop.run(move |event, control_flow| match event { - Event::WindowEvent { - ref event, - window_id, - } if window_id == window.id() => match event { - WindowEvent::CloseRequested - | WindowEvent::KeyboardInput { - event: - KeyEvent { - state: ElementState::Pressed, - physical_key: PhysicalKey::Code(KeyCode::Escape), - .. - }, - .. - } => control_flow.exit(), + event_loop + .run(move |event, control_flow| match event { + Event::WindowEvent { + ref event, + window_id, + } if window_id == window.id() => match event { + WindowEvent::CloseRequested + | WindowEvent::KeyboardInput { + event: + KeyEvent { + state: ElementState::Pressed, + physical_key: PhysicalKey::Code(KeyCode::Escape), + .. + }, + .. + } => control_flow.exit(), + _ => {} + }, _ => {} - }, - _ => {} - }).unwrap(); + }) + .unwrap(); } diff --git a/code/beginner/tutorial2-surface/src/challenge.rs b/code/beginner/tutorial2-surface/src/challenge.rs index 29d26262..95ed4f25 100644 --- a/code/beginner/tutorial2-surface/src/challenge.rs +++ b/code/beginner/tutorial2-surface/src/challenge.rs @@ -84,6 +84,7 @@ impl<'a> State<'a> { alpha_mode: surface_caps.alpha_modes[0], desired_maximum_frame_latency: 2, view_formats: vec![], + desired_maximum_frame_latency: 2, }; surface.configure(&device, &config); @@ -180,50 +181,54 @@ async fn run() { // State::new uses async code, so we're going to wait for it to finish let mut state = State::new(&window).await; - event_loop.run(move |event, control_flow| { - match event { - Event::WindowEvent { - ref event, - window_id, - } if window_id == state.window().id() => { - if !state.input(event) { - match event { - WindowEvent::CloseRequested - | WindowEvent::KeyboardInput { - event: - KeyEvent { - state: ElementState::Pressed, - physical_key: PhysicalKey::Code(KeyCode::Escape), - .. - }, - .. - } => control_flow.exit(), - WindowEvent::Resized(physical_size) => { - state.resize(*physical_size); - } - WindowEvent::RedrawRequested => { - state.window().request_redraw(); - state.update(); - match state.render() { - Ok(_) => {} - // Reconfigure the surface if it's lost or outdated - Err(wgpu::SurfaceError::Lost | wgpu::SurfaceError::Outdated) => { - state.resize(state.size) - } - // The system is out of memory, we should probably quit - Err(wgpu::SurfaceError::OutOfMemory) => { - log::error!("OutOfMemory"); - control_flow.exit(); + event_loop + .run(move |event, control_flow| { + match event { + Event::WindowEvent { + ref event, + window_id, + } if window_id == state.window().id() => { + if !state.input(event) { + match event { + WindowEvent::CloseRequested + | WindowEvent::KeyboardInput { + event: + KeyEvent { + state: ElementState::Pressed, + physical_key: PhysicalKey::Code(KeyCode::Escape), + .. + }, + .. + } => control_flow.exit(), + WindowEvent::Resized(physical_size) => { + state.resize(*physical_size); + } + WindowEvent::RedrawRequested => { + state.window().request_redraw(); + state.update(); + match state.render() { + Ok(_) => {} + // Reconfigure the surface if it's lost or outdated + Err( + wgpu::SurfaceError::Lost | wgpu::SurfaceError::Outdated, + ) => state.resize(state.size), + // The system is out of memory, we should probably quit + Err(wgpu::SurfaceError::OutOfMemory) => { + log::error!("OutOfMemory"); + control_flow.exit(); + } + // We're ignoring timeouts + Err(wgpu::SurfaceError::Timeout) => { + log::warn!("Surface timeout") + } } - // We're ignoring timeouts - Err(wgpu::SurfaceError::Timeout) => log::warn!("Surface timeout"), } + _ => {} } - _ => {} } } + _ => {} } - _ => {} - } - }).unwrap(); + }) + .unwrap(); } diff --git a/code/beginner/tutorial2-surface/src/lib.rs b/code/beginner/tutorial2-surface/src/lib.rs index 469605fe..acaa55af 100644 --- a/code/beginner/tutorial2-surface/src/lib.rs +++ b/code/beginner/tutorial2-surface/src/lib.rs @@ -3,7 +3,8 @@ use std::iter; use winit::{ event::*, event_loop::EventLoop, - window::{Window, WindowBuilder}, keyboard::{PhysicalKey, KeyCode}, + keyboard::{KeyCode, PhysicalKey}, + window::{Window, WindowBuilder}, }; #[cfg(target_arch = "wasm32")] @@ -81,6 +82,7 @@ impl<'a> State<'a> { alpha_mode: surface_caps.alpha_modes[0], desired_maximum_frame_latency: 2, view_formats: vec![], + desired_maximum_frame_latency: 2, }; surface.configure(&device, &config); @@ -191,53 +193,57 @@ pub async fn run() { // State::new uses async code, so we're going to wait for it to finish let mut state = State::new(&window).await; - event_loop.run(move |event, control_flow| { - match event { - Event::WindowEvent { - ref event, - window_id, - } if window_id == state.window().id() => { - if !state.input(event) { - // UPDATED! - match event { - WindowEvent::CloseRequested - | WindowEvent::KeyboardInput { - event: - KeyEvent { - state: ElementState::Pressed, - physical_key: PhysicalKey::Code(KeyCode::Escape), - .. - }, - .. - } => control_flow.exit(), - WindowEvent::Resized(physical_size) => { - state.resize(*physical_size); - } - WindowEvent::RedrawRequested => { - // This tells winit that we want another frame after this one - state.window().request_redraw(); - state.update(); - match state.render() { - Ok(_) => {} - // Reconfigure the surface if it's lost or outdated - Err(wgpu::SurfaceError::Lost | wgpu::SurfaceError::Outdated) => { - state.resize(state.size) - } - // The system is out of memory, we should probably quit - Err(wgpu::SurfaceError::OutOfMemory) => { - log::error!("OutOfMemory"); - control_flow.exit(); + event_loop + .run(move |event, control_flow| { + match event { + Event::WindowEvent { + ref event, + window_id, + } if window_id == state.window().id() => { + if !state.input(event) { + // UPDATED! + match event { + WindowEvent::CloseRequested + | WindowEvent::KeyboardInput { + event: + KeyEvent { + state: ElementState::Pressed, + physical_key: PhysicalKey::Code(KeyCode::Escape), + .. + }, + .. + } => control_flow.exit(), + WindowEvent::Resized(physical_size) => { + state.resize(*physical_size); + } + WindowEvent::RedrawRequested => { + // This tells winit that we want another frame after this one + state.window().request_redraw(); + state.update(); + match state.render() { + Ok(_) => {} + // Reconfigure the surface if it's lost or outdated + Err( + wgpu::SurfaceError::Lost | wgpu::SurfaceError::Outdated, + ) => state.resize(state.size), + // The system is out of memory, we should probably quit + Err(wgpu::SurfaceError::OutOfMemory) => { + log::error!("OutOfMemory"); + control_flow.exit(); + } + + // This happens when the a frame takes too long to present + Err(wgpu::SurfaceError::Timeout) => { + log::warn!("Surface timeout") + } } - - // This happens when the a frame takes too long to present - Err(wgpu::SurfaceError::Timeout) => log::warn!("Surface timeout"), } + _ => {} } - _ => {} } } + _ => {} } - _ => {} - } - }).unwrap(); + }) + .unwrap(); } diff --git a/code/beginner/tutorial3-pipeline/src/challenge.rs b/code/beginner/tutorial3-pipeline/src/challenge.rs index 5bcdf59d..a359a77a 100644 --- a/code/beginner/tutorial3-pipeline/src/challenge.rs +++ b/code/beginner/tutorial3-pipeline/src/challenge.rs @@ -3,11 +3,12 @@ use std::iter; use winit::{ event::*, event_loop::{ControlFlow, EventLoop}, + keyboard::{KeyCode, PhysicalKey}, window::{Window, WindowBuilder}, }; -struct State { - surface: wgpu::Surface, +struct State<'a> { + surface: wgpu::Surface<'a>, device: wgpu::Device, queue: wgpu::Queue, config: wgpu::SurfaceConfiguration, @@ -15,11 +16,11 @@ struct State { render_pipeline: wgpu::RenderPipeline, challenge_render_pipeline: wgpu::RenderPipeline, use_color: bool, - window: Window, + window: &'a Window, } -impl State { - async fn new(window: Window) -> Self { +impl<'a> State<'a> { + async fn new(window: &'a Window) -> State<'a> { let size = window.inner_size(); // The instance is a handle to our GPU @@ -29,11 +30,7 @@ impl State { ..Default::default() }); - // # Safety - // - // The surface needs to live as long as the window that created it. - // State owns the window so this should be safe. - let surface = unsafe { instance.create_surface(&window) }.unwrap(); + let surface = instance.create_surface(window).unwrap(); let adapter = instance .request_adapter(&wgpu::RequestAdapterOptions { @@ -48,10 +45,10 @@ impl State { .request_device( &wgpu::DeviceDescriptor { label: None, - features: wgpu::Features::empty(), + required_features: wgpu::Features::empty(), // WebGL doesn't support all of wgpu's features, so if // we're building for the web we'll have to disable some. - limits: if cfg!(target_arch = "wasm32") { + required_limits: if cfg!(target_arch = "wasm32") { wgpu::Limits::downlevel_webgl2_defaults() } else { wgpu::Limits::default() @@ -80,6 +77,7 @@ impl State { present_mode: surface_caps.present_modes[0], alpha_mode: surface_caps.alpha_modes[0], view_formats: vec![], + desired_maximum_frame_latency: 2, }; surface.configure(&device, &config); @@ -213,10 +211,10 @@ impl State { fn input(&mut self, event: &WindowEvent) -> bool { match event { WindowEvent::KeyboardInput { - input: - KeyboardInput { + event: + KeyEvent { state, - virtual_keycode: Some(VirtualKeyCode::Space), + physical_key: PhysicalKey::Code(KeyCode::Space), .. }, .. @@ -284,61 +282,62 @@ fn main() { async fn run() { env_logger::init(); - let event_loop = EventLoop::new(); + let event_loop = EventLoop::new().unwrap(); let window = WindowBuilder::new().build(&event_loop).unwrap(); // State::new uses async code, so we're going to wait for it to finish - let mut state = State::new(window).await; + let mut state = State::new(&window).await; - event_loop.run(move |event, _, control_flow| { - match event { - Event::WindowEvent { - ref event, - window_id, - } if window_id == state.window().id() => { - if !state.input(event) { - match event { - WindowEvent::CloseRequested - | WindowEvent::KeyboardInput { - input: - KeyboardInput { - state: ElementState::Pressed, - virtual_keycode: Some(VirtualKeyCode::Escape), - .. - }, - .. - } => *control_flow = ControlFlow::Exit, - WindowEvent::Resized(physical_size) => { - state.resize(*physical_size); - } - WindowEvent::ScaleFactorChanged { new_inner_size, .. } => { - // new_inner_size is &mut so w have to dereference it twice - state.resize(**new_inner_size); + event_loop + .run(move |event, control_flow| { + match event { + Event::WindowEvent { + ref event, + window_id, + } if window_id == state.window().id() => { + if !state.input(event) { + match event { + WindowEvent::CloseRequested + | WindowEvent::KeyboardInput { + event: + KeyEvent { + state: ElementState::Pressed, + physical_key: PhysicalKey::Code(KeyCode::Escape), + .. + }, + .. + } => control_flow.exit(), + WindowEvent::Resized(physical_size) => { + state.resize(*physical_size); + } + WindowEvent::RedrawRequested => { + // This tells winit that we want another frame after this one + state.window().request_redraw(); + state.update(); + match state.render() { + Ok(_) => {} + // Reconfigure the surface if it's lost or outdated + Err( + wgpu::SurfaceError::Lost | wgpu::SurfaceError::Outdated, + ) => state.resize(state.size), + // The system is out of memory, we should probably quit + Err(wgpu::SurfaceError::OutOfMemory) => { + log::error!("OutOfMemory"); + control_flow.exit(); + } + + // This happens when the a frame takes too long to present + Err(wgpu::SurfaceError::Timeout) => { + log::warn!("Surface timeout") + } + } + } + _ => {} } - _ => {} - } - } - } - Event::RedrawRequested(window_id) if window_id == state.window().id() => { - state.update(); - match state.render() { - Ok(_) => {} - // Reconfigure the surface if it's lost or outdated - Err(wgpu::SurfaceError::Lost | wgpu::SurfaceError::Outdated) => { - state.resize(state.size) } - // The system is out of memory, we should probably quit - Err(wgpu::SurfaceError::OutOfMemory) => *control_flow = ControlFlow::Exit, - // We're ignoring timeouts - Err(wgpu::SurfaceError::Timeout) => log::warn!("Surface timeout"), } + _ => {} } - Event::MainEventsCleared => { - // RedrawRequested will only trigger once, unless we manually - // request it. - state.window().request_redraw(); - } - _ => {} - } - }); + }) + .unwrap(); } diff --git a/code/beginner/tutorial3-pipeline/src/lib.rs b/code/beginner/tutorial3-pipeline/src/lib.rs index c7fde053..07454652 100644 --- a/code/beginner/tutorial3-pipeline/src/lib.rs +++ b/code/beginner/tutorial3-pipeline/src/lib.rs @@ -2,26 +2,27 @@ use std::iter; use winit::{ event::*, - event_loop::{ControlFlow, EventLoop}, + event_loop::EventLoop, + keyboard::{KeyCode, PhysicalKey}, window::{Window, WindowBuilder}, }; #[cfg(target_arch = "wasm32")] use wasm_bindgen::prelude::*; -struct State { - surface: wgpu::Surface, +struct State<'a> { + surface: wgpu::Surface<'a>, device: wgpu::Device, queue: wgpu::Queue, config: wgpu::SurfaceConfiguration, size: winit::dpi::PhysicalSize, // NEW! render_pipeline: wgpu::RenderPipeline, - window: Window, + window: &'a Window, } -impl State { - async fn new(window: Window) -> Self { +impl<'a> State<'a> { + async fn new(window: &'a Window) -> State<'a> { let size = window.inner_size(); // The instance is a handle to our GPU @@ -31,11 +32,7 @@ impl State { ..Default::default() }); - // # Safety - // - // The surface needs to live as long as the window that created it. - // State owns the window so this should be safe. - let surface = unsafe { instance.create_surface(&window) }.unwrap(); + let surface = instance.create_surface(window).unwrap(); let adapter = instance .request_adapter(&wgpu::RequestAdapterOptions { @@ -50,10 +47,10 @@ impl State { .request_device( &wgpu::DeviceDescriptor { label: None, - features: wgpu::Features::empty(), + required_features: wgpu::Features::empty(), // WebGL doesn't support all of wgpu's features, so if // we're building for the web we'll have to disable some. - limits: if cfg!(target_arch = "wasm32") { + required_limits: if cfg!(target_arch = "wasm32") { wgpu::Limits::downlevel_webgl2_defaults() } else { wgpu::Limits::default() @@ -82,6 +79,7 @@ impl State { present_mode: surface_caps.present_modes[0], alpha_mode: surface_caps.alpha_modes[0], view_formats: vec![], + desired_maximum_frame_latency: 2, }; surface.configure(&device, &config); @@ -227,7 +225,7 @@ pub async fn run() { } } - let event_loop = EventLoop::new(); + let event_loop = EventLoop::new().unwrap(); let window = WindowBuilder::new().build(&event_loop).unwrap(); #[cfg(target_arch = "wasm32")] @@ -250,57 +248,58 @@ pub async fn run() { } // State::new uses async code, so we're going to wait for it to finish - let mut state = State::new(window).await; + let mut state = State::new(&window).await; - event_loop.run(move |event, _, control_flow| { - match event { - Event::WindowEvent { - ref event, - window_id, - } if window_id == state.window().id() => { - if !state.input(event) { - match event { - WindowEvent::CloseRequested - | WindowEvent::KeyboardInput { - input: - KeyboardInput { - state: ElementState::Pressed, - virtual_keycode: Some(VirtualKeyCode::Escape), - .. - }, - .. - } => *control_flow = ControlFlow::Exit, - WindowEvent::Resized(physical_size) => { - state.resize(*physical_size); - } - WindowEvent::ScaleFactorChanged { new_inner_size, .. } => { - // new_inner_size is &mut so w have to dereference it twice - state.resize(**new_inner_size); + event_loop + .run(move |event, control_flow| { + match event { + Event::WindowEvent { + ref event, + window_id, + } if window_id == state.window().id() => { + if !state.input(event) { + match event { + WindowEvent::CloseRequested + | WindowEvent::KeyboardInput { + event: + KeyEvent { + state: ElementState::Pressed, + physical_key: PhysicalKey::Code(KeyCode::Escape), + .. + }, + .. + } => control_flow.exit(), + WindowEvent::Resized(physical_size) => { + state.resize(*physical_size); + } + WindowEvent::RedrawRequested => { + // This tells winit that we want another frame after this one + state.window().request_redraw(); + state.update(); + match state.render() { + Ok(_) => {} + // Reconfigure the surface if it's lost or outdated + Err( + wgpu::SurfaceError::Lost | wgpu::SurfaceError::Outdated, + ) => state.resize(state.size), + // The system is out of memory, we should probably quit + Err(wgpu::SurfaceError::OutOfMemory) => { + log::error!("OutOfMemory"); + control_flow.exit(); + } + + // This happens when the a frame takes too long to present + Err(wgpu::SurfaceError::Timeout) => { + log::warn!("Surface timeout") + } + } + } + _ => {} } - _ => {} } } + _ => {} } - Event::RedrawRequested(window_id) if window_id == state.window().id() => { - state.update(); - match state.render() { - Ok(_) => {} - // Reconfigure the surface if it's lost or outdated - Err(wgpu::SurfaceError::Lost | wgpu::SurfaceError::Outdated) => { - state.resize(state.size) - } - // The system is out of memory, we should probably quit - Err(wgpu::SurfaceError::OutOfMemory) => *control_flow = ControlFlow::Exit, - // We're ignoring timeouts - Err(wgpu::SurfaceError::Timeout) => log::warn!("Surface timeout"), - } - } - Event::MainEventsCleared => { - // RedrawRequested will only trigger once, unless we manually - // request it. - state.window().request_redraw(); - } - _ => {} - } - }); + }) + .unwrap(); } diff --git a/code/beginner/tutorial4-buffer/src/challenge.rs b/code/beginner/tutorial4-buffer/src/challenge.rs index 81f0f51c..6edada60 100644 --- a/code/beginner/tutorial4-buffer/src/challenge.rs +++ b/code/beginner/tutorial4-buffer/src/challenge.rs @@ -4,6 +4,7 @@ use wgpu::util::DeviceExt; use winit::{ event::*, event_loop::{ControlFlow, EventLoop}, + keyboard::{KeyCode, PhysicalKey}, window::{Window, WindowBuilder}, }; @@ -60,8 +61,8 @@ const VERTICES: &[Vertex] = &[ const INDICES: &[u16] = &[0, 1, 4, 1, 2, 4, 2, 3, 4]; -struct State { - surface: wgpu::Surface, +struct State<'a> { + surface: wgpu::Surface<'a>, device: wgpu::Device, queue: wgpu::Queue, config: wgpu::SurfaceConfiguration, @@ -78,11 +79,11 @@ struct State { use_complex: bool, size: winit::dpi::PhysicalSize, - window: Window, + window: &'a Window, } -impl State { - async fn new(window: Window) -> Self { +impl<'a> State<'a> { + async fn new(window: &'a Window) -> State<'a> { let size = window.inner_size(); // The instance is a handle to our GPU @@ -96,7 +97,7 @@ impl State { // // The surface needs to live as long as the window that created it. // State owns the window so this should be safe. - let surface = unsafe { instance.create_surface(&window) }.unwrap(); + let surface = instance.create_surface(window).unwrap(); let adapter = instance .request_adapter(&wgpu::RequestAdapterOptions { @@ -111,10 +112,10 @@ impl State { .request_device( &wgpu::DeviceDescriptor { label: None, - features: wgpu::Features::empty(), + required_features: wgpu::Features::empty(), // WebGL doesn't support all of wgpu's features, so if // we're building for the web we'll have to disable some. - limits: if cfg!(target_arch = "wasm32") { + required_limits: if cfg!(target_arch = "wasm32") { wgpu::Limits::downlevel_webgl2_defaults() } else { wgpu::Limits::default() @@ -143,6 +144,7 @@ impl State { present_mode: surface_caps.present_modes[0], alpha_mode: surface_caps.alpha_modes[0], view_formats: vec![], + desired_maximum_frame_latency: 2, }; surface.configure(&device, &config); @@ -281,10 +283,10 @@ impl State { fn input(&mut self, event: &WindowEvent) -> bool { match event { WindowEvent::KeyboardInput { - input: - KeyboardInput { + event: + KeyEvent { state, - virtual_keycode: Some(VirtualKeyCode::Space), + physical_key: PhysicalKey::Code(KeyCode::Space), .. }, .. @@ -361,61 +363,62 @@ fn main() { async fn run() { env_logger::init(); - let event_loop = EventLoop::new(); + let event_loop = EventLoop::new().unwrap(); let window = WindowBuilder::new().build(&event_loop).unwrap(); // State::new uses async code, so we're going to wait for it to finish - let mut state = State::new(window).await; - - event_loop.run(move |event, _, control_flow| { - match event { - Event::WindowEvent { - ref event, - window_id, - } if window_id == state.window().id() => { - if !state.input(event) { - match event { - WindowEvent::CloseRequested - | WindowEvent::KeyboardInput { - input: - KeyboardInput { - state: ElementState::Pressed, - virtual_keycode: Some(VirtualKeyCode::Escape), - .. - }, - .. - } => *control_flow = ControlFlow::Exit, - WindowEvent::Resized(physical_size) => { - state.resize(*physical_size); + let mut state = State::new(&window).await; + + event_loop + .run(move |event, control_flow| { + match event { + Event::WindowEvent { + ref event, + window_id, + } if window_id == state.window().id() => { + if !state.input(event) { + match event { + WindowEvent::CloseRequested + | WindowEvent::KeyboardInput { + event: + KeyEvent { + state: ElementState::Pressed, + physical_key: PhysicalKey::Code(KeyCode::Escape), + .. + }, + .. + } => control_flow.exit(), + WindowEvent::Resized(physical_size) => { + state.resize(*physical_size); + } + WindowEvent::RedrawRequested => { + // This tells winit that we want another frame after this one + state.window().request_redraw(); + state.update(); + match state.render() { + Ok(_) => {} + // Reconfigure the surface if it's lost or outdated + Err( + wgpu::SurfaceError::Lost | wgpu::SurfaceError::Outdated, + ) => state.resize(state.size), + // The system is out of memory, we should probably quit + Err(wgpu::SurfaceError::OutOfMemory) => { + log::error!("OutOfMemory"); + control_flow.exit(); + } + + // This happens when the a frame takes too long to present + Err(wgpu::SurfaceError::Timeout) => { + log::warn!("Surface timeout") + } + } + } + _ => {} } - WindowEvent::ScaleFactorChanged { new_inner_size, .. } => { - // new_inner_size is &mut so w have to dereference it twice - state.resize(**new_inner_size); - } - _ => {} - } - } - } - Event::RedrawRequested(window_id) if window_id == state.window().id() => { - state.update(); - match state.render() { - Ok(_) => {} - // Reconfigure the surface if it's lost or outdated - Err(wgpu::SurfaceError::Lost | wgpu::SurfaceError::Outdated) => { - state.resize(state.size) } - // The system is out of memory, we should probably quit - Err(wgpu::SurfaceError::OutOfMemory) => *control_flow = ControlFlow::Exit, - // We're ignoring timeouts - Err(wgpu::SurfaceError::Timeout) => log::warn!("Surface timeout"), } + _ => {} } - Event::MainEventsCleared => { - // RedrawRequested will only trigger once, unless we manually - // request it. - state.window().request_redraw(); - } - _ => {} - } - }); + }) + .unwrap(); } diff --git a/code/beginner/tutorial4-buffer/src/lib.rs b/code/beginner/tutorial4-buffer/src/lib.rs index b28090cf..62f286e4 100644 --- a/code/beginner/tutorial4-buffer/src/lib.rs +++ b/code/beginner/tutorial4-buffer/src/lib.rs @@ -3,7 +3,8 @@ use std::iter; use wgpu::util::DeviceExt; use winit::{ event::*, - event_loop::{ControlFlow, EventLoop}, + event_loop::EventLoop, + keyboard::{KeyCode, PhysicalKey}, window::{Window, WindowBuilder}, }; @@ -63,8 +64,8 @@ const VERTICES: &[Vertex] = &[ const INDICES: &[u16] = &[0, 1, 4, 1, 2, 4, 2, 3, 4, /* padding */ 0]; -struct State { - surface: wgpu::Surface, +struct State<'a> { + surface: wgpu::Surface<'a>, device: wgpu::Device, queue: wgpu::Queue, config: wgpu::SurfaceConfiguration, @@ -74,11 +75,11 @@ struct State { vertex_buffer: wgpu::Buffer, index_buffer: wgpu::Buffer, num_indices: u32, - window: Window, + window: &'a Window, } -impl State { - async fn new(window: Window) -> Self { +impl<'a> State<'a> { + async fn new(window: &'a Window) -> State<'a> { let size = window.inner_size(); // The instance is a handle to our GPU @@ -92,7 +93,7 @@ impl State { // // The surface needs to live as long as the window that created it. // State owns the window so this should be safe. - let surface = unsafe { instance.create_surface(&window) }.unwrap(); + let surface = instance.create_surface(window).unwrap(); let adapter = instance .request_adapter(&wgpu::RequestAdapterOptions { @@ -107,10 +108,10 @@ impl State { .request_device( &wgpu::DeviceDescriptor { label: None, - features: wgpu::Features::empty(), + required_features: wgpu::Features::empty(), // WebGL doesn't support all of wgpu's features, so if // we're building for the web we'll have to disable some. - limits: if cfg!(target_arch = "wasm32") { + required_limits: if cfg!(target_arch = "wasm32") { wgpu::Limits::downlevel_webgl2_defaults() } else { wgpu::Limits::default() @@ -139,6 +140,7 @@ impl State { present_mode: surface_caps.present_modes[0], alpha_mode: surface_caps.alpha_modes[0], view_formats: vec![], + desired_maximum_frame_latency: 2, }; surface.configure(&device, &config); @@ -301,7 +303,7 @@ pub async fn run() { } } - let event_loop = EventLoop::new(); + let event_loop = EventLoop::new().unwrap(); let window = WindowBuilder::new().build(&event_loop).unwrap(); #[cfg(target_arch = "wasm32")] @@ -324,57 +326,58 @@ pub async fn run() { } // State::new uses async code, so we're going to wait for it to finish - let mut state = State::new(window).await; - - event_loop.run(move |event, _, control_flow| { - match event { - Event::WindowEvent { - ref event, - window_id, - } if window_id == state.window().id() => { - if !state.input(event) { - match event { - WindowEvent::CloseRequested - | WindowEvent::KeyboardInput { - input: - KeyboardInput { - state: ElementState::Pressed, - virtual_keycode: Some(VirtualKeyCode::Escape), - .. - }, - .. - } => *control_flow = ControlFlow::Exit, - WindowEvent::Resized(physical_size) => { - state.resize(*physical_size); + let mut state = State::new(&window).await; + + event_loop + .run(move |event, control_flow| { + match event { + Event::WindowEvent { + ref event, + window_id, + } if window_id == state.window().id() => { + if !state.input(event) { + match event { + WindowEvent::CloseRequested + | WindowEvent::KeyboardInput { + event: + KeyEvent { + state: ElementState::Pressed, + physical_key: PhysicalKey::Code(KeyCode::Escape), + .. + }, + .. + } => control_flow.exit(), + WindowEvent::Resized(physical_size) => { + state.resize(*physical_size); + } + WindowEvent::RedrawRequested => { + // This tells winit that we want another frame after this one + state.window().request_redraw(); + state.update(); + match state.render() { + Ok(_) => {} + // Reconfigure the surface if it's lost or outdated + Err( + wgpu::SurfaceError::Lost | wgpu::SurfaceError::Outdated, + ) => state.resize(state.size), + // The system is out of memory, we should probably quit + Err(wgpu::SurfaceError::OutOfMemory) => { + log::error!("OutOfMemory"); + control_flow.exit(); + } + + // This happens when the a frame takes too long to present + Err(wgpu::SurfaceError::Timeout) => { + log::warn!("Surface timeout") + } + } + } + _ => {} } - WindowEvent::ScaleFactorChanged { new_inner_size, .. } => { - // new_inner_size is &mut so w have to dereference it twice - state.resize(**new_inner_size); - } - _ => {} - } - } - } - Event::RedrawRequested(window_id) if window_id == state.window().id() => { - state.update(); - match state.render() { - Ok(_) => {} - // Reconfigure the surface if it's lost or outdated - Err(wgpu::SurfaceError::Lost | wgpu::SurfaceError::Outdated) => { - state.resize(state.size) } - // The system is out of memory, we should probably quit - Err(wgpu::SurfaceError::OutOfMemory) => *control_flow = ControlFlow::Exit, - // We're ignoring timeouts - Err(wgpu::SurfaceError::Timeout) => log::warn!("Surface timeout"), } + _ => {} } - Event::MainEventsCleared => { - // RedrawRequested will only trigger once, unless we manually - // request it. - state.window().request_redraw(); - } - _ => {} - } - }); + }) + .unwrap(); } diff --git a/code/beginner/tutorial5-textures/src/challenge.rs b/code/beginner/tutorial5-textures/src/challenge.rs index 74d2808b..3ce6963b 100644 --- a/code/beginner/tutorial5-textures/src/challenge.rs +++ b/code/beginner/tutorial5-textures/src/challenge.rs @@ -4,6 +4,7 @@ use wgpu::util::DeviceExt; use winit::{ event::*, event_loop::{ControlFlow, EventLoop}, + keyboard::{KeyCode, PhysicalKey}, window::{Window, WindowBuilder}, }; @@ -63,8 +64,8 @@ const VERTICES: &[Vertex] = &[ const INDICES: &[u16] = &[0, 1, 4, 1, 2, 4, 2, 3, 4]; -struct State { - surface: wgpu::Surface, +struct State<'a> { + surface: wgpu::Surface<'a>, device: wgpu::Device, queue: wgpu::Queue, config: wgpu::SurfaceConfiguration, @@ -80,11 +81,11 @@ struct State { cartoon_texture: texture::Texture, cartoon_bind_group: wgpu::BindGroup, is_space_pressed: bool, - window: Window, + window: &'a Window, } -impl State { - async fn new(window: Window) -> Self { +impl<'a> State<'a> { + async fn new(window: &'a Window) -> State<'a> { let size = window.inner_size(); // The instance is a handle to our GPU @@ -98,7 +99,7 @@ impl State { // // The surface needs to live as long as the window that created it. // State owns the window so this should be safe. - let surface = unsafe { instance.create_surface(&window) }.unwrap(); + let surface = instance.create_surface(window).unwrap(); let adapter = instance .request_adapter(&wgpu::RequestAdapterOptions { @@ -112,10 +113,10 @@ impl State { .request_device( &wgpu::DeviceDescriptor { label: None, - features: wgpu::Features::empty(), + required_features: wgpu::Features::empty(), // WebGL doesn't support all of wgpu's features, so if // we're building for the web we'll have to disable some. - limits: if cfg!(target_arch = "wasm32") { + required_limits: if cfg!(target_arch = "wasm32") { wgpu::Limits::downlevel_webgl2_defaults() } else { wgpu::Limits::default() @@ -144,6 +145,7 @@ impl State { present_mode: surface_caps.present_modes[0], alpha_mode: surface_caps.alpha_modes[0], view_formats: vec![], + desired_maximum_frame_latency: 2, }; surface.configure(&device, &config); @@ -312,10 +314,10 @@ impl State { fn input(&mut self, event: &WindowEvent) -> bool { match event { WindowEvent::KeyboardInput { - input: - KeyboardInput { + event: + KeyEvent { state, - virtual_keycode: Some(VirtualKeyCode::Space), + physical_key: PhysicalKey::Code(KeyCode::Space), .. }, .. @@ -388,61 +390,61 @@ fn main() { async fn run() { env_logger::init(); - let event_loop = EventLoop::new(); + let event_loop = EventLoop::new().unwrap(); let window = WindowBuilder::new().build(&event_loop).unwrap(); // State::new uses async code, so we're going to wait for it to finish - let mut state = State::new(window).await; - - event_loop.run(move |event, _, control_flow| { - match event { - Event::WindowEvent { - ref event, - window_id, - } if window_id == state.window().id() => { - if !state.input(event) { - match event { - WindowEvent::CloseRequested - | WindowEvent::KeyboardInput { - input: - KeyboardInput { - state: ElementState::Pressed, - virtual_keycode: Some(VirtualKeyCode::Escape), - .. - }, - .. - } => *control_flow = ControlFlow::Exit, - WindowEvent::Resized(physical_size) => { - state.resize(*physical_size); + let mut state = State::new(&window).await; + + event_loop + .run(move |event, control_flow| { + match event { + Event::WindowEvent { + ref event, + window_id, + } if window_id == state.window().id() => { + if !state.input(event) { + match event { + WindowEvent::CloseRequested + | WindowEvent::KeyboardInput { + event: + KeyEvent { + state: ElementState::Pressed, + physical_key: PhysicalKey::Code(KeyCode::Escape), + .. + }, + .. + } => control_flow.exit(), + WindowEvent::Resized(physical_size) => { + state.resize(*physical_size); + } + WindowEvent::RedrawRequested => { + // This tells winit that we want another frame after this one + state.window().request_redraw(); + state.update(); + match state.render() { + Ok(_) => {} + // Reconfigure the surface if it's lost or outdated + Err( + wgpu::SurfaceError::Lost | wgpu::SurfaceError::Outdated, + ) => state.resize(state.size), + // The system is out of memory, we should probably quit + Err(wgpu::SurfaceError::OutOfMemory) => { + log::error!("OutOfMemory"); + control_flow.exit(); + } + // This happens when the a frame takes too long to present + Err(wgpu::SurfaceError::Timeout) => { + log::warn!("Surface timeout") + } + } + } + _ => {} } - WindowEvent::ScaleFactorChanged { new_inner_size, .. } => { - // new_inner_size is &mut so we have to dereference it twice - state.resize(**new_inner_size); - } - _ => {} - } - } - } - Event::RedrawRequested(window_id) if window_id == state.window().id() => { - state.update(); - match state.render() { - Ok(_) => {} - // Reconfigure the surface if it's lost or outdated - Err(wgpu::SurfaceError::Lost | wgpu::SurfaceError::Outdated) => { - state.resize(state.size) } - // The system is out of memory, we should probably quit - Err(wgpu::SurfaceError::OutOfMemory) => *control_flow = ControlFlow::Exit, - // We're ignoring timeouts - Err(wgpu::SurfaceError::Timeout) => log::warn!("Surface timeout"), } + _ => {} } - Event::MainEventsCleared => { - // RedrawRequested will only trigger once, unless we manually - // request it. - state.window().request_redraw(); - } - _ => {} - } - }); + }) + .unwrap(); } diff --git a/code/beginner/tutorial5-textures/src/lib.rs b/code/beginner/tutorial5-textures/src/lib.rs index ed0b539e..406ae0db 100644 --- a/code/beginner/tutorial5-textures/src/lib.rs +++ b/code/beginner/tutorial5-textures/src/lib.rs @@ -3,7 +3,8 @@ use std::iter; use wgpu::util::DeviceExt; use winit::{ event::*, - event_loop::{ControlFlow, EventLoop}, + event_loop::EventLoop, + keyboard::{KeyCode, PhysicalKey}, window::{Window, WindowBuilder}, }; @@ -66,8 +67,8 @@ const VERTICES: &[Vertex] = &[ const INDICES: &[u16] = &[0, 1, 4, 1, 2, 4, 2, 3, 4, /* padding */ 0]; -struct State { - surface: wgpu::Surface, +struct State<'a> { + surface: wgpu::Surface<'a>, device: wgpu::Device, queue: wgpu::Queue, config: wgpu::SurfaceConfiguration, @@ -80,11 +81,11 @@ struct State { #[allow(dead_code)] diffuse_texture: texture::Texture, diffuse_bind_group: wgpu::BindGroup, - window: Window, + window: &'a Window, } -impl State { - async fn new(window: Window) -> Self { +impl<'a> State<'a> { + async fn new(window: &'a Window) -> State<'a> { let size = window.inner_size(); // The instance is a handle to our GPU @@ -94,11 +95,7 @@ impl State { ..Default::default() }); - // # Safety - // - // The surface needs to live as long as the window that created it. - // State owns the window so this should be safe. - let surface = unsafe { instance.create_surface(&window) }.unwrap(); + let surface = instance.create_surface(window).unwrap(); let adapter = instance .request_adapter(&wgpu::RequestAdapterOptions { @@ -112,10 +109,10 @@ impl State { .request_device( &wgpu::DeviceDescriptor { label: None, - features: wgpu::Features::empty(), + required_features: wgpu::Features::empty(), // WebGL doesn't support all of wgpu's features, so if // we're building for the web we'll have to disable some. - limits: if cfg!(target_arch = "wasm32") { + required_limits: if cfg!(target_arch = "wasm32") { wgpu::Limits::downlevel_webgl2_defaults() } else { wgpu::Limits::default() @@ -144,6 +141,7 @@ impl State { present_mode: surface_caps.present_modes[0], alpha_mode: surface_caps.alpha_modes[0], view_formats: vec![], + desired_maximum_frame_latency: 2, }; surface.configure(&device, &config); @@ -351,7 +349,7 @@ pub async fn run() { } } - let event_loop = EventLoop::new(); + let event_loop = EventLoop::new().unwrap(); let window = WindowBuilder::new().build(&event_loop).unwrap(); #[cfg(target_arch = "wasm32")] @@ -374,57 +372,58 @@ pub async fn run() { } // State::new uses async code, so we're going to wait for it to finish - let mut state = State::new(window).await; - - event_loop.run(move |event, _, control_flow| { - match event { - Event::WindowEvent { - ref event, - window_id, - } if window_id == state.window().id() => { - if !state.input(event) { - match event { - WindowEvent::CloseRequested - | WindowEvent::KeyboardInput { - input: - KeyboardInput { - state: ElementState::Pressed, - virtual_keycode: Some(VirtualKeyCode::Escape), - .. - }, - .. - } => *control_flow = ControlFlow::Exit, - WindowEvent::Resized(physical_size) => { - state.resize(*physical_size); + let mut state = State::new(&window).await; + + event_loop + .run(move |event, control_flow| { + match event { + Event::WindowEvent { + ref event, + window_id, + } if window_id == state.window().id() => { + if !state.input(event) { + match event { + WindowEvent::CloseRequested + | WindowEvent::KeyboardInput { + event: + KeyEvent { + state: ElementState::Pressed, + physical_key: PhysicalKey::Code(KeyCode::Escape), + .. + }, + .. + } => control_flow.exit(), + WindowEvent::Resized(physical_size) => { + state.resize(*physical_size); + } + WindowEvent::RedrawRequested => { + // This tells winit that we want another frame after this one + state.window().request_redraw(); + state.update(); + match state.render() { + Ok(_) => {} + // Reconfigure the surface if it's lost or outdated + Err( + wgpu::SurfaceError::Lost | wgpu::SurfaceError::Outdated, + ) => state.resize(state.size), + // The system is out of memory, we should probably quit + Err(wgpu::SurfaceError::OutOfMemory) => { + log::error!("OutOfMemory"); + control_flow.exit(); + } + + // This happens when the a frame takes too long to present + Err(wgpu::SurfaceError::Timeout) => { + log::warn!("Surface timeout") + } + } + } + _ => {} } - WindowEvent::ScaleFactorChanged { new_inner_size, .. } => { - // new_inner_size is &mut so w have to dereference it twice - state.resize(**new_inner_size); - } - _ => {} - } - } - } - Event::RedrawRequested(window_id) if window_id == state.window().id() => { - state.update(); - match state.render() { - Ok(_) => {} - // Reconfigure the surface if it's lost or outdated - Err(wgpu::SurfaceError::Lost | wgpu::SurfaceError::Outdated) => { - state.resize(state.size) } - // The system is out of memory, we should probably quit - Err(wgpu::SurfaceError::OutOfMemory) => *control_flow = ControlFlow::Exit, - // We're ignoring timeouts - Err(wgpu::SurfaceError::Timeout) => log::warn!("Surface timeout"), } + _ => {} } - Event::MainEventsCleared => { - // RedrawRequested will only trigger once, unless we manually - // request it. - state.window().request_redraw(); - } - _ => {} - } - }); + }) + .unwrap(); } diff --git a/code/beginner/tutorial6-uniforms/src/challenge.rs b/code/beginner/tutorial6-uniforms/src/challenge.rs index 6f6bd9d4..31b8109a 100644 --- a/code/beginner/tutorial6-uniforms/src/challenge.rs +++ b/code/beginner/tutorial6-uniforms/src/challenge.rs @@ -3,7 +3,8 @@ use std::iter; use wgpu::util::DeviceExt; use winit::{ event::*, - event_loop::{ControlFlow, EventLoop}, + event_loop::EventLoop, + keyboard::{KeyCode, PhysicalKey}, window::{Window, WindowBuilder}, }; @@ -146,29 +147,29 @@ impl CameraController { fn process_events(&mut self, event: &WindowEvent) -> bool { match event { WindowEvent::KeyboardInput { - input: - KeyboardInput { + event: + KeyEvent { state, - virtual_keycode: Some(keycode), + physical_key: PhysicalKey::Code(keycode), .. }, .. } => { let is_pressed = *state == ElementState::Pressed; match keycode { - VirtualKeyCode::W | VirtualKeyCode::Up => { + KeyCode::KeyW | KeyCode::ArrowUp => { self.is_forward_pressed = is_pressed; true } - VirtualKeyCode::A | VirtualKeyCode::Left => { + KeyCode::KeyA | KeyCode::ArrowLeft => { self.is_left_pressed = is_pressed; true } - VirtualKeyCode::S | VirtualKeyCode::Down => { + KeyCode::KeyS | KeyCode::ArrowDown => { self.is_backward_pressed = is_pressed; true } - VirtualKeyCode::D | VirtualKeyCode::Right => { + KeyCode::KeyD | KeyCode::ArrowRight => { self.is_right_pressed = is_pressed; true } @@ -212,8 +213,8 @@ impl CameraController { } } -struct State { - surface: wgpu::Surface, +struct State<'a> { + surface: wgpu::Surface<'a>, device: wgpu::Device, queue: wgpu::Queue, config: wgpu::SurfaceConfiguration, @@ -230,11 +231,11 @@ struct State { camera_buffer: wgpu::Buffer, camera_bind_group: wgpu::BindGroup, size: winit::dpi::PhysicalSize, - window: Window, + window: &'a Window, } -impl State { - async fn new(window: Window) -> Self { +impl<'a> State<'a> { + async fn new(window: &'a Window) -> State<'a> { let size = window.inner_size(); // The instance is a handle to our GPU @@ -244,11 +245,7 @@ impl State { ..Default::default() }); - // # Safety - // - // The surface needs to live as long as the window that created it. - // State owns the window so this should be safe. - let surface = unsafe { instance.create_surface(&window) }.unwrap(); + let surface = instance.create_surface(window).unwrap(); let adapter = instance .request_adapter(&wgpu::RequestAdapterOptions { @@ -262,10 +259,10 @@ impl State { .request_device( &wgpu::DeviceDescriptor { label: None, - features: wgpu::Features::empty(), + required_features: wgpu::Features::empty(), // WebGL doesn't support all of wgpu's features, so if // we're building for the web we'll have to disable some. - limits: if cfg!(target_arch = "wasm32") { + required_limits: if cfg!(target_arch = "wasm32") { wgpu::Limits::downlevel_webgl2_defaults() } else { wgpu::Limits::default() @@ -294,6 +291,7 @@ impl State { present_mode: surface_caps.present_modes[0], alpha_mode: surface_caps.alpha_modes[0], view_formats: vec![], + desired_maximum_frame_latency: 2, }; surface.configure(&device, &config); @@ -559,61 +557,62 @@ fn main() { async fn run() { env_logger::init(); - let event_loop = EventLoop::new(); + let event_loop = EventLoop::new().unwrap(); let window = WindowBuilder::new().build(&event_loop).unwrap(); // State::new uses async code, so we're going to wait for it to finish - let mut state = State::new(window).await; - - event_loop.run(move |event, _, control_flow| { - match event { - Event::WindowEvent { - ref event, - window_id, - } if window_id == state.window().id() => { - if !state.input(event) { - match event { - WindowEvent::CloseRequested - | WindowEvent::KeyboardInput { - input: - KeyboardInput { - state: ElementState::Pressed, - virtual_keycode: Some(VirtualKeyCode::Escape), - .. - }, - .. - } => *control_flow = ControlFlow::Exit, - WindowEvent::Resized(physical_size) => { - state.resize(*physical_size); + let mut state = State::new(&window).await; + + event_loop + .run(move |event, control_flow| { + match event { + Event::WindowEvent { + ref event, + window_id, + } if window_id == state.window().id() => { + if !state.input(event) { + match event { + WindowEvent::CloseRequested + | WindowEvent::KeyboardInput { + event: + KeyEvent { + state: ElementState::Pressed, + physical_key: PhysicalKey::Code(KeyCode::Escape), + .. + }, + .. + } => control_flow.exit(), + WindowEvent::Resized(physical_size) => { + state.resize(*physical_size); + } + WindowEvent::RedrawRequested => { + // This tells winit that we want another frame after this one + state.window().request_redraw(); + state.update(); + match state.render() { + Ok(_) => {} + // Reconfigure the surface if it's lost or outdated + Err( + wgpu::SurfaceError::Lost | wgpu::SurfaceError::Outdated, + ) => state.resize(state.size), + // The system is out of memory, we should probably quit + Err(wgpu::SurfaceError::OutOfMemory) => { + log::error!("OutOfMemory"); + control_flow.exit(); + } + + // This happens when the a frame takes too long to present + Err(wgpu::SurfaceError::Timeout) => { + log::warn!("Surface timeout") + } + } + } + _ => {} } - WindowEvent::ScaleFactorChanged { new_inner_size, .. } => { - // new_inner_size is &mut so w have to dereference it twice - state.resize(**new_inner_size); - } - _ => {} - } - } - } - Event::RedrawRequested(window_id) if window_id == state.window().id() => { - state.update(); - match state.render() { - Ok(_) => {} - // Reconfigure the surface if it's lost or outdated - Err(wgpu::SurfaceError::Lost | wgpu::SurfaceError::Outdated) => { - state.resize(state.size) } - // The system is out of memory, we should probably quit - Err(wgpu::SurfaceError::OutOfMemory) => *control_flow = ControlFlow::Exit, - // We're ignoring timeouts - Err(wgpu::SurfaceError::Timeout) => log::warn!("Surface timeout"), } + _ => {} } - Event::MainEventsCleared => { - // RedrawRequested will only trigger once, unless we manually - // request it. - state.window().request_redraw(); - } - _ => {} - } - }); + }) + .unwrap(); } diff --git a/code/beginner/tutorial6-uniforms/src/lib.rs b/code/beginner/tutorial6-uniforms/src/lib.rs index b226d20e..3efdca10 100644 --- a/code/beginner/tutorial6-uniforms/src/lib.rs +++ b/code/beginner/tutorial6-uniforms/src/lib.rs @@ -3,7 +3,8 @@ use std::iter; use wgpu::util::DeviceExt; use winit::{ event::*, - event_loop::{ControlFlow, EventLoop}, + event_loop::EventLoop, + keyboard::{KeyCode, PhysicalKey}, window::{Window, WindowBuilder}, }; @@ -137,37 +138,37 @@ impl CameraController { fn process_events(&mut self, event: &WindowEvent) -> bool { match event { WindowEvent::KeyboardInput { - input: - KeyboardInput { + event: + KeyEvent { state, - virtual_keycode: Some(keycode), + physical_key: PhysicalKey::Code(keycode), .. }, .. } => { let is_pressed = *state == ElementState::Pressed; match keycode { - VirtualKeyCode::Space => { + KeyCode::Space => { self.is_up_pressed = is_pressed; true } - VirtualKeyCode::LShift => { + KeyCode::ShiftLeft => { self.is_down_pressed = is_pressed; true } - VirtualKeyCode::W | VirtualKeyCode::Up => { + KeyCode::KeyW | KeyCode::ArrowUp => { self.is_forward_pressed = is_pressed; true } - VirtualKeyCode::A | VirtualKeyCode::Left => { + KeyCode::KeyA | KeyCode::ArrowLeft => { self.is_left_pressed = is_pressed; true } - VirtualKeyCode::S | VirtualKeyCode::Down => { + KeyCode::KeyS | KeyCode::ArrowDown => { self.is_backward_pressed = is_pressed; true } - VirtualKeyCode::D | VirtualKeyCode::Right => { + KeyCode::KeyD | KeyCode::ArrowRight => { self.is_right_pressed = is_pressed; true } @@ -211,8 +212,8 @@ impl CameraController { } } -struct State { - surface: wgpu::Surface, +struct State<'a> { + surface: wgpu::Surface<'a>, device: wgpu::Device, queue: wgpu::Queue, config: wgpu::SurfaceConfiguration, @@ -230,11 +231,11 @@ struct State { camera_uniform: CameraUniform, camera_buffer: wgpu::Buffer, camera_bind_group: wgpu::BindGroup, - window: Window, + window: &'a Window, } -impl State { - async fn new(window: Window) -> Self { +impl<'a> State<'a> { + async fn new(window: &'a Window) -> State<'a> { let size = window.inner_size(); // The instance is a handle to our GPU @@ -244,11 +245,7 @@ impl State { ..Default::default() }); - // # Safety - // - // The surface needs to live as long as the window that created it. - // State owns the window so this should be safe. - let surface = unsafe { instance.create_surface(&window) }.unwrap(); + let surface = instance.create_surface(window).unwrap(); let adapter = instance .request_adapter(&wgpu::RequestAdapterOptions { @@ -262,10 +259,10 @@ impl State { .request_device( &wgpu::DeviceDescriptor { label: None, - features: wgpu::Features::empty(), + required_features: wgpu::Features::empty(), // WebGL doesn't support all of wgpu's features, so if // we're building for the web we'll have to disable some. - limits: if cfg!(target_arch = "wasm32") { + required_limits: if cfg!(target_arch = "wasm32") { wgpu::Limits::downlevel_webgl2_defaults() } else { wgpu::Limits::default() @@ -294,6 +291,7 @@ impl State { present_mode: surface_caps.present_modes[0], alpha_mode: surface_caps.alpha_modes[0], view_formats: vec![], + desired_maximum_frame_latency: 2, }; surface.configure(&device, &config); @@ -560,7 +558,7 @@ pub async fn run() { } } - let event_loop = EventLoop::new(); + let event_loop = EventLoop::new().unwrap(); let window = WindowBuilder::new().build(&event_loop).unwrap(); #[cfg(target_arch = "wasm32")] @@ -583,57 +581,58 @@ pub async fn run() { } // State::new uses async code, so we're going to wait for it to finish - let mut state = State::new(window).await; - - event_loop.run(move |event, _, control_flow| { - match event { - Event::WindowEvent { - ref event, - window_id, - } if window_id == state.window().id() => { - if !state.input(event) { - match event { - WindowEvent::CloseRequested - | WindowEvent::KeyboardInput { - input: - KeyboardInput { - state: ElementState::Pressed, - virtual_keycode: Some(VirtualKeyCode::Escape), - .. - }, - .. - } => *control_flow = ControlFlow::Exit, - WindowEvent::Resized(physical_size) => { - state.resize(*physical_size); + let mut state = State::new(&window).await; + + event_loop + .run(move |event, control_flow| { + match event { + Event::WindowEvent { + ref event, + window_id, + } if window_id == state.window().id() => { + if !state.input(event) { + match event { + WindowEvent::CloseRequested + | WindowEvent::KeyboardInput { + event: + KeyEvent { + state: ElementState::Pressed, + physical_key: PhysicalKey::Code(KeyCode::Escape), + .. + }, + .. + } => control_flow.exit(), + WindowEvent::Resized(physical_size) => { + state.resize(*physical_size); + } + WindowEvent::RedrawRequested => { + // This tells winit that we want another frame after this one + state.window().request_redraw(); + state.update(); + match state.render() { + Ok(_) => {} + // Reconfigure the surface if it's lost or outdated + Err( + wgpu::SurfaceError::Lost | wgpu::SurfaceError::Outdated, + ) => state.resize(state.size), + // The system is out of memory, we should probably quit + Err(wgpu::SurfaceError::OutOfMemory) => { + log::error!("OutOfMemory"); + control_flow.exit(); + } + + // This happens when the a frame takes too long to present + Err(wgpu::SurfaceError::Timeout) => { + log::warn!("Surface timeout") + } + } + } + _ => {} } - WindowEvent::ScaleFactorChanged { new_inner_size, .. } => { - // new_inner_size is &mut so w have to dereference it twice - state.resize(**new_inner_size); - } - _ => {} - } - } - } - Event::RedrawRequested(window_id) if window_id == state.window().id() => { - state.update(); - match state.render() { - Ok(_) => {} - // Reconfigure the surface if it's lost or outdated - Err(wgpu::SurfaceError::Lost | wgpu::SurfaceError::Outdated) => { - state.resize(state.size) } - // The system is out of memory, we should probably quit - Err(wgpu::SurfaceError::OutOfMemory) => *control_flow = ControlFlow::Exit, - // We're ignoring timeouts - Err(wgpu::SurfaceError::Timeout) => log::warn!("Surface timeout"), } + _ => {} } - Event::MainEventsCleared => { - // RedrawRequested will only trigger once, unless we manually - // request it. - state.window().request_redraw(); - } - _ => {} - } - }); + }) + .unwrap(); } diff --git a/code/beginner/tutorial7-instancing/src/challenge.rs b/code/beginner/tutorial7-instancing/src/challenge.rs index 3aa7b6d9..8286e352 100644 --- a/code/beginner/tutorial7-instancing/src/challenge.rs +++ b/code/beginner/tutorial7-instancing/src/challenge.rs @@ -4,7 +4,8 @@ use cgmath::prelude::*; use wgpu::util::DeviceExt; use winit::{ event::*, - event_loop::{ControlFlow, EventLoop}, + event_loop::EventLoop, + keyboard::{KeyCode, PhysicalKey}, window::{Window, WindowBuilder}, }; @@ -137,29 +138,29 @@ impl CameraController { fn process_events(&mut self, event: &WindowEvent) -> bool { match event { WindowEvent::KeyboardInput { - input: - KeyboardInput { + event: + KeyEvent { state, - virtual_keycode: Some(keycode), + physical_key: PhysicalKey::Code(keycode), .. }, .. } => { let is_pressed = *state == ElementState::Pressed; match keycode { - VirtualKeyCode::W | VirtualKeyCode::Up => { + KeyCode::KeyW | KeyCode::ArrowUp => { self.is_forward_pressed = is_pressed; true } - VirtualKeyCode::A | VirtualKeyCode::Left => { + KeyCode::KeyA | KeyCode::ArrowLeft => { self.is_left_pressed = is_pressed; true } - VirtualKeyCode::S | VirtualKeyCode::Down => { + KeyCode::KeyS | KeyCode::ArrowDown => { self.is_backward_pressed = is_pressed; true } - VirtualKeyCode::D | VirtualKeyCode::Right => { + KeyCode::KeyD | KeyCode::ArrowRight => { self.is_right_pressed = is_pressed; true } @@ -264,8 +265,8 @@ impl InstanceRaw { } } -struct State { - surface: wgpu::Surface, +struct State<'a> { + surface: wgpu::Surface<'a>, device: wgpu::Device, queue: wgpu::Queue, config: wgpu::SurfaceConfiguration, @@ -284,11 +285,11 @@ struct State { size: winit::dpi::PhysicalSize, instances: Vec, instance_buffer: wgpu::Buffer, - window: Window, + window: &'a Window, } -impl State { - async fn new(window: Window) -> Self { +impl<'a> State<'a> { + async fn new(window: &'a Window) -> State<'a> { let size = window.inner_size(); // The instance is a handle to our GPU @@ -298,11 +299,7 @@ impl State { ..Default::default() }); - // # Safety - // - // The surface needs to live as long as the window that created it. - // State owns the window so this should be safe. - let surface = unsafe { instance.create_surface(&window) }.unwrap(); + let surface = instance.create_surface(window).unwrap(); let adapter = instance .request_adapter(&wgpu::RequestAdapterOptions { @@ -316,10 +313,10 @@ impl State { .request_device( &wgpu::DeviceDescriptor { label: None, - features: wgpu::Features::empty(), + required_features: wgpu::Features::empty(), // WebGL doesn't support all of wgpu's features, so if // we're building for the web we'll have to disable some. - limits: if cfg!(target_arch = "wasm32") { + required_limits: if cfg!(target_arch = "wasm32") { wgpu::Limits::downlevel_webgl2_defaults() } else { wgpu::Limits::default() @@ -348,6 +345,7 @@ impl State { present_mode: surface_caps.present_modes[0], alpha_mode: surface_caps.alpha_modes[0], view_formats: vec![], + desired_maximum_frame_latency: 2, }; surface.configure(&device, &config); @@ -660,61 +658,62 @@ fn main() { async fn run() { env_logger::init(); - let event_loop = EventLoop::new(); + let event_loop = EventLoop::new().unwrap(); let window = WindowBuilder::new().build(&event_loop).unwrap(); // State::new uses async code, so we're going to wait for it to finish - let mut state = State::new(window).await; - - event_loop.run(move |event, _, control_flow| { - match event { - Event::WindowEvent { - ref event, - window_id, - } if window_id == state.window().id() => { - if !state.input(event) { - match event { - WindowEvent::CloseRequested - | WindowEvent::KeyboardInput { - input: - KeyboardInput { - state: ElementState::Pressed, - virtual_keycode: Some(VirtualKeyCode::Escape), - .. - }, - .. - } => *control_flow = ControlFlow::Exit, - WindowEvent::Resized(physical_size) => { - state.resize(*physical_size); + let mut state = State::new(&window).await; + + event_loop + .run(move |event, control_flow| { + match event { + Event::WindowEvent { + ref event, + window_id, + } if window_id == state.window().id() => { + if !state.input(event) { + match event { + WindowEvent::CloseRequested + | WindowEvent::KeyboardInput { + event: + KeyEvent { + state: ElementState::Pressed, + physical_key: PhysicalKey::Code(KeyCode::Escape), + .. + }, + .. + } => control_flow.exit(), + WindowEvent::Resized(physical_size) => { + state.resize(*physical_size); + } + WindowEvent::RedrawRequested => { + // This tells winit that we want another frame after this one + state.window().request_redraw(); + state.update(); + match state.render() { + Ok(_) => {} + // Reconfigure the surface if it's lost or outdated + Err( + wgpu::SurfaceError::Lost | wgpu::SurfaceError::Outdated, + ) => state.resize(state.size), + // The system is out of memory, we should probably quit + Err(wgpu::SurfaceError::OutOfMemory) => { + log::error!("OutOfMemory"); + control_flow.exit(); + } + + // This happens when the a frame takes too long to present + Err(wgpu::SurfaceError::Timeout) => { + log::warn!("Surface timeout") + } + } + } + _ => {} } - WindowEvent::ScaleFactorChanged { new_inner_size, .. } => { - // new_inner_size is &mut so w have to dereference it twice - state.resize(**new_inner_size); - } - _ => {} - } - } - } - Event::RedrawRequested(window_id) if window_id == state.window().id() => { - state.update(); - match state.render() { - Ok(_) => {} - // Reconfigure the surface if it's lost or outdated - Err(wgpu::SurfaceError::Lost | wgpu::SurfaceError::Outdated) => { - state.resize(state.size) } - // The system is out of memory, we should probably quit - Err(wgpu::SurfaceError::OutOfMemory) => *control_flow = ControlFlow::Exit, - // We're ignoring timeouts - Err(wgpu::SurfaceError::Timeout) => log::warn!("Surface timeout"), } + _ => {} } - Event::MainEventsCleared => { - // RedrawRequested will only trigger once, unless we manually - // request it. - state.window().request_redraw(); - } - _ => {} - } - }); + }) + .unwrap(); } diff --git a/code/beginner/tutorial7-instancing/src/lib.rs b/code/beginner/tutorial7-instancing/src/lib.rs index 2aab25bc..2fa16e7c 100644 --- a/code/beginner/tutorial7-instancing/src/lib.rs +++ b/code/beginner/tutorial7-instancing/src/lib.rs @@ -5,6 +5,7 @@ use wgpu::util::DeviceExt; use winit::{ event::*, event_loop::{ControlFlow, EventLoop}, + keyboard::{KeyCode, PhysicalKey}, window::{Window, WindowBuilder}, }; @@ -144,37 +145,37 @@ impl CameraController { fn process_events(&mut self, event: &WindowEvent) -> bool { match event { WindowEvent::KeyboardInput { - input: - KeyboardInput { + event: + KeyEvent { state, - virtual_keycode: Some(keycode), + physical_key: PhysicalKey::Code(keycode), .. }, .. } => { let is_pressed = *state == ElementState::Pressed; match keycode { - VirtualKeyCode::Space => { + KeyCode::Space => { self.is_up_pressed = is_pressed; true } - VirtualKeyCode::LShift => { + KeyCode::ShiftLeft => { self.is_down_pressed = is_pressed; true } - VirtualKeyCode::W | VirtualKeyCode::Up => { + KeyCode::KeyW | KeyCode::ArrowUp => { self.is_forward_pressed = is_pressed; true } - VirtualKeyCode::A | VirtualKeyCode::Left => { + KeyCode::KeyA | KeyCode::ArrowLeft => { self.is_left_pressed = is_pressed; true } - VirtualKeyCode::S | VirtualKeyCode::Down => { + KeyCode::KeyS | KeyCode::ArrowDown => { self.is_backward_pressed = is_pressed; true } - VirtualKeyCode::D | VirtualKeyCode::Right => { + KeyCode::KeyD | KeyCode::ArrowRight => { self.is_right_pressed = is_pressed; true } @@ -269,8 +270,8 @@ impl InstanceRaw { } } -struct State { - surface: wgpu::Surface, +struct State<'a> { + surface: wgpu::Surface<'a>, device: wgpu::Device, queue: wgpu::Queue, config: wgpu::SurfaceConfiguration, @@ -291,11 +292,11 @@ struct State { instances: Vec, #[allow(dead_code)] instance_buffer: wgpu::Buffer, - window: Window, + window: &'a Window, } -impl State { - async fn new(window: Window) -> Self { +impl<'a> State<'a> { + async fn new(window: &'a Window) -> State<'a> { let size = window.inner_size(); // The instance is a handle to our GPU @@ -305,11 +306,7 @@ impl State { ..Default::default() }); - // # Safety - // - // The surface needs to live as long as the window that created it. - // State owns the window so this should be safe. - let surface = unsafe { instance.create_surface(&window) }.unwrap(); + let surface = instance.create_surface(window).unwrap(); let adapter = instance .request_adapter(&wgpu::RequestAdapterOptions { @@ -323,10 +320,10 @@ impl State { .request_device( &wgpu::DeviceDescriptor { label: None, - features: wgpu::Features::empty(), + required_features: wgpu::Features::empty(), // WebGL doesn't support all of wgpu's features, so if // we're building for the web we'll have to disable some. - limits: if cfg!(target_arch = "wasm32") { + required_limits: if cfg!(target_arch = "wasm32") { wgpu::Limits::downlevel_webgl2_defaults() } else { wgpu::Limits::default() @@ -355,6 +352,7 @@ impl State { present_mode: surface_caps.present_modes[0], alpha_mode: surface_caps.alpha_modes[0], view_formats: vec![], + desired_maximum_frame_latency: 2, }; surface.configure(&device, &config); @@ -658,7 +656,7 @@ pub async fn run() { } } - let event_loop = EventLoop::new(); + let event_loop = EventLoop::new().unwrap(); let window = WindowBuilder::new().build(&event_loop).unwrap(); #[cfg(target_arch = "wasm32")] @@ -681,57 +679,58 @@ pub async fn run() { } // State::new uses async code, so we're going to wait for it to finish - let mut state = State::new(window).await; - - event_loop.run(move |event, _, control_flow| { - match event { - Event::WindowEvent { - ref event, - window_id, - } if window_id == state.window().id() => { - if !state.input(event) { - match event { - WindowEvent::CloseRequested - | WindowEvent::KeyboardInput { - input: - KeyboardInput { - state: ElementState::Pressed, - virtual_keycode: Some(VirtualKeyCode::Escape), - .. - }, - .. - } => *control_flow = ControlFlow::Exit, - WindowEvent::Resized(physical_size) => { - state.resize(*physical_size); + let mut state = State::new(&window).await; + + event_loop + .run(move |event, control_flow| { + match event { + Event::WindowEvent { + ref event, + window_id, + } if window_id == state.window().id() => { + if !state.input(event) { + match event { + WindowEvent::CloseRequested + | WindowEvent::KeyboardInput { + event: + KeyEvent { + state: ElementState::Pressed, + physical_key: PhysicalKey::Code(KeyCode::Escape), + .. + }, + .. + } => control_flow.exit(), + WindowEvent::Resized(physical_size) => { + state.resize(*physical_size); + } + WindowEvent::RedrawRequested => { + // This tells winit that we want another frame after this one + state.window().request_redraw(); + state.update(); + match state.render() { + Ok(_) => {} + // Reconfigure the surface if it's lost or outdated + Err( + wgpu::SurfaceError::Lost | wgpu::SurfaceError::Outdated, + ) => state.resize(state.size), + // The system is out of memory, we should probably quit + Err(wgpu::SurfaceError::OutOfMemory) => { + log::error!("OutOfMemory"); + control_flow.exit(); + } + + // This happens when the a frame takes too long to present + Err(wgpu::SurfaceError::Timeout) => { + log::warn!("Surface timeout") + } + } + } + _ => {} } - WindowEvent::ScaleFactorChanged { new_inner_size, .. } => { - // new_inner_size is &mut so w have to dereference it twice - state.resize(**new_inner_size); - } - _ => {} - } - } - } - Event::RedrawRequested(window_id) if window_id == state.window().id() => { - state.update(); - match state.render() { - Ok(_) => {} - // Reconfigure the surface if it's lost or outdated - Err(wgpu::SurfaceError::Lost | wgpu::SurfaceError::Outdated) => { - state.resize(state.size) } - // The system is out of memory, we should probably quit - Err(wgpu::SurfaceError::OutOfMemory) => *control_flow = ControlFlow::Exit, - // We're ignoring timeouts - Err(wgpu::SurfaceError::Timeout) => log::warn!("Surface timeout"), } + _ => {} } - Event::MainEventsCleared => { - // RedrawRequested will only trigger once, unless we manually - // request it. - state.window().request_redraw(); - } - _ => {} - } - }); + }) + .unwrap(); } diff --git a/code/beginner/tutorial8-depth/src/challenge.rs b/code/beginner/tutorial8-depth/src/challenge.rs index ade6b0e7..5616f4e3 100644 --- a/code/beginner/tutorial8-depth/src/challenge.rs +++ b/code/beginner/tutorial8-depth/src/challenge.rs @@ -6,6 +6,7 @@ use wgpu::util::DeviceExt; use winit::{ event::*, event_loop::{ControlFlow, EventLoop}, + keyboard::{KeyCode, PhysicalKey}, window::{Window, WindowBuilder}, }; @@ -159,29 +160,29 @@ impl CameraController { fn process_events(&mut self, event: &WindowEvent) -> bool { match event { WindowEvent::KeyboardInput { - input: - KeyboardInput { + event: + KeyEvent { state, - virtual_keycode: Some(keycode), + physical_key: PhysicalKey::Code(keycode), .. }, .. } => { let is_pressed = *state == ElementState::Pressed; match keycode { - VirtualKeyCode::W | VirtualKeyCode::Up => { + KeyCode::KeyW | KeyCode::ArrowUp => { self.is_forward_pressed = is_pressed; true } - VirtualKeyCode::A | VirtualKeyCode::Left => { + KeyCode::KeyA | KeyCode::ArrowLeft => { self.is_left_pressed = is_pressed; true } - VirtualKeyCode::S | VirtualKeyCode::Down => { + KeyCode::KeyS | KeyCode::ArrowDown => { self.is_backward_pressed = is_pressed; true } - VirtualKeyCode::D | VirtualKeyCode::Right => { + KeyCode::KeyD | KeyCode::ArrowRight => { self.is_right_pressed = is_pressed; true } @@ -461,8 +462,8 @@ impl DepthPass { } } -struct State { - surface: wgpu::Surface, +struct State<'a> { + surface: wgpu::Surface<'a>, device: wgpu::Device, queue: wgpu::Queue, config: wgpu::SurfaceConfiguration, @@ -483,11 +484,11 @@ struct State { #[allow(dead_code)] instance_buffer: wgpu::Buffer, depth_pass: DepthPass, - window: Window, + window: &'a Window, } -impl State { - async fn new(window: Window) -> Self { +impl<'a> State<'a> { + async fn new(window: &'a Window) -> State<'a> { let size = window.inner_size(); // The instance is a handle to our GPU @@ -497,11 +498,7 @@ impl State { ..Default::default() }); - // # Safety - // - // The surface needs to live as long as the window that created it. - // State owns the window so this should be safe. - let surface = unsafe { instance.create_surface(&window) }.unwrap(); + let surface = instance.create_surface(window).unwrap(); let adapter = instance .request_adapter(&wgpu::RequestAdapterOptions { @@ -515,10 +512,10 @@ impl State { .request_device( &wgpu::DeviceDescriptor { label: None, - features: wgpu::Features::empty(), + required_features: wgpu::Features::empty(), // WebGL doesn't support all of wgpu's features, so if // we're building for the web we'll have to disable some. - limits: if cfg!(target_arch = "wasm32") { + required_limits: if cfg!(target_arch = "wasm32") { wgpu::Limits::downlevel_webgl2_defaults() } else { wgpu::Limits::default() @@ -547,6 +544,7 @@ impl State { present_mode: surface_caps.present_modes[0], alpha_mode: surface_caps.alpha_modes[0], view_formats: vec![], + desired_maximum_frame_latency: 2, }; surface.configure(&device, &config); @@ -867,61 +865,62 @@ fn main() { async fn run() { env_logger::init(); - let event_loop = EventLoop::new(); + let event_loop = EventLoop::new().unwrap(); let window = WindowBuilder::new().build(&event_loop).unwrap(); // State::new uses async code, so we're going to wait for it to finish - let mut state = State::new(window).await; - - event_loop.run(move |event, _, control_flow| { - match event { - Event::WindowEvent { - ref event, - window_id, - } if window_id == state.window().id() => { - if !state.input(event) { - match event { - WindowEvent::CloseRequested - | WindowEvent::KeyboardInput { - input: - KeyboardInput { - state: ElementState::Pressed, - virtual_keycode: Some(VirtualKeyCode::Escape), - .. - }, - .. - } => *control_flow = ControlFlow::Exit, - WindowEvent::Resized(physical_size) => { - state.resize(*physical_size); + let mut state = State::new(&window).await; + + event_loop + .run(move |event, control_flow| { + match event { + Event::WindowEvent { + ref event, + window_id, + } if window_id == state.window().id() => { + if !state.input(event) { + match event { + WindowEvent::CloseRequested + | WindowEvent::KeyboardInput { + event: + KeyEvent { + state: ElementState::Pressed, + physical_key: PhysicalKey::Code(KeyCode::Escape), + .. + }, + .. + } => control_flow.exit(), + WindowEvent::Resized(physical_size) => { + state.resize(*physical_size); + } + WindowEvent::RedrawRequested => { + // This tells winit that we want another frame after this one + state.window().request_redraw(); + state.update(); + match state.render() { + Ok(_) => {} + // Reconfigure the surface if it's lost or outdated + Err( + wgpu::SurfaceError::Lost | wgpu::SurfaceError::Outdated, + ) => state.resize(state.size), + // The system is out of memory, we should probably quit + Err(wgpu::SurfaceError::OutOfMemory) => { + log::error!("OutOfMemory"); + control_flow.exit(); + } + + // This happens when the a frame takes too long to present + Err(wgpu::SurfaceError::Timeout) => { + log::warn!("Surface timeout") + } + } + } + _ => {} } - WindowEvent::ScaleFactorChanged { new_inner_size, .. } => { - // new_inner_size is &mut so w have to dereference it twice - state.resize(**new_inner_size); - } - _ => {} - } - } - } - Event::RedrawRequested(window_id) if window_id == state.window().id() => { - state.update(); - match state.render() { - Ok(_) => {} - // Reconfigure the surface if it's lost or outdated - Err(wgpu::SurfaceError::Lost | wgpu::SurfaceError::Outdated) => { - state.resize(state.size) } - // The system is out of memory, we should probably quit - Err(wgpu::SurfaceError::OutOfMemory) => *control_flow = ControlFlow::Exit, - // We're ignoring timeouts - Err(wgpu::SurfaceError::Timeout) => log::warn!("Surface timeout"), } + _ => {} } - Event::MainEventsCleared => { - // RedrawRequested will only trigger once, unless we manually - // request it. - state.window().request_redraw(); - } - _ => {} - } - }); + }) + .unwrap(); } diff --git a/code/beginner/tutorial8-depth/src/lib.rs b/code/beginner/tutorial8-depth/src/lib.rs index 900128bf..b67ed79a 100644 --- a/code/beginner/tutorial8-depth/src/lib.rs +++ b/code/beginner/tutorial8-depth/src/lib.rs @@ -5,6 +5,7 @@ use wgpu::util::DeviceExt; use winit::{ event::*, event_loop::{ControlFlow, EventLoop}, + keyboard::{KeyCode, PhysicalKey}, window::{Window, WindowBuilder}, }; @@ -144,37 +145,37 @@ impl CameraController { fn process_events(&mut self, event: &WindowEvent) -> bool { match event { WindowEvent::KeyboardInput { - input: - KeyboardInput { + event: + KeyEvent { state, - virtual_keycode: Some(keycode), + physical_key: PhysicalKey::Code(keycode), .. }, .. } => { let is_pressed = *state == ElementState::Pressed; match keycode { - VirtualKeyCode::Space => { + KeyCode::Space => { self.is_up_pressed = is_pressed; true } - VirtualKeyCode::LShift => { + KeyCode::ShiftLeft => { self.is_down_pressed = is_pressed; true } - VirtualKeyCode::W | VirtualKeyCode::Up => { + KeyCode::KeyW | KeyCode::ArrowUp => { self.is_forward_pressed = is_pressed; true } - VirtualKeyCode::A | VirtualKeyCode::Left => { + KeyCode::KeyA | KeyCode::ArrowLeft => { self.is_left_pressed = is_pressed; true } - VirtualKeyCode::S | VirtualKeyCode::Down => { + KeyCode::KeyS | KeyCode::ArrowDown => { self.is_backward_pressed = is_pressed; true } - VirtualKeyCode::D | VirtualKeyCode::Right => { + KeyCode::KeyD | KeyCode::ArrowRight => { self.is_right_pressed = is_pressed; true } @@ -278,8 +279,8 @@ impl InstanceRaw { } } -struct State { - surface: wgpu::Surface, +struct State<'a> { + surface: wgpu::Surface<'a>, device: wgpu::Device, queue: wgpu::Queue, config: wgpu::SurfaceConfiguration, @@ -301,11 +302,11 @@ struct State { instance_buffer: wgpu::Buffer, // NEW! depth_texture: texture::Texture, - window: Window, + window: &'a Window, } -impl State { - async fn new(window: Window) -> Self { +impl<'a> State<'a> { + async fn new(window: &'a Window) -> State<'a> { let size = window.inner_size(); // The instance is a handle to our GPU @@ -315,11 +316,7 @@ impl State { ..Default::default() }); - // # Safety - // - // The surface needs to live as long as the window that created it. - // State owns the window so this should be safe. - let surface = unsafe { instance.create_surface(&window) }.unwrap(); + let surface = instance.create_surface(window).unwrap(); let adapter = instance .request_adapter(&wgpu::RequestAdapterOptions { @@ -333,10 +330,10 @@ impl State { .request_device( &wgpu::DeviceDescriptor { label: None, - features: wgpu::Features::empty(), + required_features: wgpu::Features::empty(), // WebGL doesn't support all of wgpu's features, so if // we're building for the web we'll have to disable some. - limits: if cfg!(target_arch = "wasm32") { + required_limits: if cfg!(target_arch = "wasm32") { wgpu::Limits::downlevel_webgl2_defaults() } else { wgpu::Limits::default() @@ -365,6 +362,7 @@ impl State { present_mode: surface_caps.present_modes[0], alpha_mode: surface_caps.alpha_modes[0], view_formats: vec![], + desired_maximum_frame_latency: 2, }; surface.configure(&device, &config); @@ -685,7 +683,7 @@ pub async fn run() { } } - let event_loop = EventLoop::new(); + let event_loop = EventLoop::new().unwrap(); let window = WindowBuilder::new().build(&event_loop).unwrap(); #[cfg(target_arch = "wasm32")] @@ -708,57 +706,58 @@ pub async fn run() { } // State::new uses async code, so we're going to wait for it to finish - let mut state = State::new(window).await; - - event_loop.run(move |event, _, control_flow| { - match event { - Event::WindowEvent { - ref event, - window_id, - } if window_id == state.window().id() => { - if !state.input(event) { - match event { - WindowEvent::CloseRequested - | WindowEvent::KeyboardInput { - input: - KeyboardInput { - state: ElementState::Pressed, - virtual_keycode: Some(VirtualKeyCode::Escape), - .. - }, - .. - } => *control_flow = ControlFlow::Exit, - WindowEvent::Resized(physical_size) => { - state.resize(*physical_size); + let mut state = State::new(&window).await; + + event_loop + .run(move |event, control_flow| { + match event { + Event::WindowEvent { + ref event, + window_id, + } if window_id == state.window().id() => { + if !state.input(event) { + match event { + WindowEvent::CloseRequested + | WindowEvent::KeyboardInput { + event: + KeyEvent { + state: ElementState::Pressed, + physical_key: PhysicalKey::Code(KeyCode::Escape), + .. + }, + .. + } => control_flow.exit(), + WindowEvent::Resized(physical_size) => { + state.resize(*physical_size); + } + WindowEvent::RedrawRequested => { + // This tells winit that we want another frame after this one + state.window().request_redraw(); + state.update(); + match state.render() { + Ok(_) => {} + // Reconfigure the surface if it's lost or outdated + Err( + wgpu::SurfaceError::Lost | wgpu::SurfaceError::Outdated, + ) => state.resize(state.size), + // The system is out of memory, we should probably quit + Err(wgpu::SurfaceError::OutOfMemory) => { + log::error!("OutOfMemory"); + control_flow.exit(); + } + + // This happens when the a frame takes too long to present + Err(wgpu::SurfaceError::Timeout) => { + log::warn!("Surface timeout") + } + } + } + _ => {} } - WindowEvent::ScaleFactorChanged { new_inner_size, .. } => { - // new_inner_size is &mut so w have to dereference it twice - state.resize(**new_inner_size); - } - _ => {} - } - } - } - Event::RedrawRequested(window_id) if window_id == state.window().id() => { - state.update(); - match state.render() { - Ok(_) => {} - // Reconfigure the surface if it's lost or outdated - Err(wgpu::SurfaceError::Lost | wgpu::SurfaceError::Outdated) => { - state.resize(state.size) } - // The system is out of memory, we should probably quit - Err(wgpu::SurfaceError::OutOfMemory) => *control_flow = ControlFlow::Exit, - // We're ignoring timeouts - Err(wgpu::SurfaceError::Timeout) => log::warn!("Surface timeout"), } + _ => {} } - Event::MainEventsCleared => { - // RedrawRequested will only trigger once, unless we manually - // request it. - state.window().request_redraw(); - } - _ => {} - } - }); + }) + .unwrap(); } diff --git a/code/beginner/tutorial9-models/src/lib.rs b/code/beginner/tutorial9-models/src/lib.rs index 90c0eeac..e28ac4dd 100644 --- a/code/beginner/tutorial9-models/src/lib.rs +++ b/code/beginner/tutorial9-models/src/lib.rs @@ -5,6 +5,7 @@ use wgpu::util::DeviceExt; use winit::{ event::*, event_loop::{ControlFlow, EventLoop}, + keyboard::{KeyCode, PhysicalKey}, window::Window, }; @@ -89,37 +90,37 @@ impl CameraController { fn process_events(&mut self, event: &WindowEvent) -> bool { match event { WindowEvent::KeyboardInput { - input: - KeyboardInput { + event: + KeyEvent { state, - virtual_keycode: Some(keycode), + physical_key: PhysicalKey::Code(keycode), .. }, .. } => { let is_pressed = *state == ElementState::Pressed; match keycode { - VirtualKeyCode::Space => { + KeyCode::Space => { self.is_up_pressed = is_pressed; true } - VirtualKeyCode::LShift => { + KeyCode::ShiftLeft => { self.is_down_pressed = is_pressed; true } - VirtualKeyCode::W | VirtualKeyCode::Up => { + KeyCode::KeyW | KeyCode::ArrowUp => { self.is_forward_pressed = is_pressed; true } - VirtualKeyCode::A | VirtualKeyCode::Left => { + KeyCode::KeyA | KeyCode::ArrowLeft => { self.is_left_pressed = is_pressed; true } - VirtualKeyCode::S | VirtualKeyCode::Down => { + KeyCode::KeyS | KeyCode::ArrowDown => { self.is_backward_pressed = is_pressed; true } - VirtualKeyCode::D | VirtualKeyCode::Right => { + KeyCode::KeyD | KeyCode::ArrowRight => { self.is_right_pressed = is_pressed; true } @@ -223,8 +224,8 @@ impl InstanceRaw { } } -struct State { - surface: wgpu::Surface, +struct State<'a> { + surface: wgpu::Surface<'a>, device: wgpu::Device, queue: wgpu::Queue, config: wgpu::SurfaceConfiguration, @@ -240,11 +241,11 @@ struct State { #[allow(dead_code)] instance_buffer: wgpu::Buffer, depth_texture: texture::Texture, - window: Window, + window: &'a Window, } -impl State { - async fn new(window: Window) -> Self { +impl<'a> State<'a> { + async fn new(window: &'a Window) -> State<'a> { let size = window.inner_size(); // The instance is a handle to our GPU @@ -255,11 +256,7 @@ impl State { ..Default::default() }); - // # Safety - // - // The surface needs to live as long as the window that created it. - // State owns the window so this should be safe. - let surface = unsafe { instance.create_surface(&window) }.unwrap(); + let surface = instance.create_surface(window).unwrap(); let adapter = instance .request_adapter(&wgpu::RequestAdapterOptions { @@ -274,10 +271,10 @@ impl State { .request_device( &wgpu::DeviceDescriptor { label: None, - features: wgpu::Features::empty(), + required_features: wgpu::Features::empty(), // WebGL doesn't support all of wgpu's features, so if // we're building for the web we'll have to disable some. - limits: if cfg!(target_arch = "wasm32") { + required_limits: if cfg!(target_arch = "wasm32") { wgpu::Limits::downlevel_webgl2_defaults() } else { wgpu::Limits::default() @@ -308,6 +305,7 @@ impl State { present_mode: surface_caps.present_modes[0], alpha_mode: surface_caps.alpha_modes[0], view_formats: vec![], + desired_maximum_frame_latency: 2, }; surface.configure(&device, &config); @@ -596,7 +594,7 @@ pub async fn run() { } } - let event_loop = EventLoop::new(); + let event_loop = EventLoop::new().unwrap(); let title = env!("CARGO_PKG_NAME"); let window = winit::window::WindowBuilder::new() .with_title(title) @@ -623,53 +621,58 @@ pub async fn run() { } // State::new uses async code, so we're going to wait for it to finish - let mut state = State::new(window).await; - - event_loop.run(move |event, _, control_flow| { - *control_flow = ControlFlow::Poll; - match event { - Event::MainEventsCleared => state.window().request_redraw(), - Event::WindowEvent { - ref event, - window_id, - } if window_id == state.window().id() => { - if !state.input(event) { - match event { - WindowEvent::CloseRequested - | WindowEvent::KeyboardInput { - input: - KeyboardInput { - state: ElementState::Pressed, - virtual_keycode: Some(VirtualKeyCode::Escape), - .. - }, - .. - } => *control_flow = ControlFlow::Exit, - WindowEvent::Resized(physical_size) => { - state.resize(*physical_size); + let mut state = State::new(&window).await; + + event_loop + .run(move |event, control_flow| { + match event { + Event::WindowEvent { + ref event, + window_id, + } if window_id == state.window().id() => { + if !state.input(event) { + match event { + WindowEvent::CloseRequested + | WindowEvent::KeyboardInput { + event: + KeyEvent { + state: ElementState::Pressed, + physical_key: PhysicalKey::Code(KeyCode::Escape), + .. + }, + .. + } => control_flow.exit(), + WindowEvent::Resized(physical_size) => { + state.resize(*physical_size); + } + WindowEvent::RedrawRequested => { + // This tells winit that we want another frame after this one + state.window().request_redraw(); + state.update(); + match state.render() { + Ok(_) => {} + // Reconfigure the surface if it's lost or outdated + Err( + wgpu::SurfaceError::Lost | wgpu::SurfaceError::Outdated, + ) => state.resize(state.size), + // The system is out of memory, we should probably quit + Err(wgpu::SurfaceError::OutOfMemory) => { + log::error!("OutOfMemory"); + control_flow.exit(); + } + + // This happens when the a frame takes too long to present + Err(wgpu::SurfaceError::Timeout) => { + log::warn!("Surface timeout") + } + } + } + _ => {} } - WindowEvent::ScaleFactorChanged { new_inner_size, .. } => { - state.resize(**new_inner_size); - } - _ => {} - } - } - } - Event::RedrawRequested(window_id) if window_id == state.window().id() => { - state.update(); - match state.render() { - Ok(_) => {} - // Reconfigure the surface if it's lost or outdated - Err(wgpu::SurfaceError::Lost | wgpu::SurfaceError::Outdated) => { - state.resize(state.size) } - // The system is out of memory, we should probably quit - Err(wgpu::SurfaceError::OutOfMemory) => *control_flow = ControlFlow::Exit, - // We're ignoring timeouts - Err(wgpu::SurfaceError::Timeout) => log::warn!("Surface timeout"), } + _ => {} } - _ => {} - } - }); + }) + .unwrap(); } diff --git a/code/intermediate/tutorial10-lighting/src/lib.rs b/code/intermediate/tutorial10-lighting/src/lib.rs index 1a19d47a..c05babf1 100644 --- a/code/intermediate/tutorial10-lighting/src/lib.rs +++ b/code/intermediate/tutorial10-lighting/src/lib.rs @@ -5,6 +5,7 @@ use wgpu::util::DeviceExt; use winit::{ event::*, event_loop::{ControlFlow, EventLoop}, + keyboard::{KeyCode, PhysicalKey}, window::Window, }; @@ -93,37 +94,37 @@ impl CameraController { fn process_events(&mut self, event: &WindowEvent) -> bool { match event { WindowEvent::KeyboardInput { - input: - KeyboardInput { + event: + KeyEvent { state, - virtual_keycode: Some(keycode), + physical_key: PhysicalKey::Code(keycode), .. }, .. } => { let is_pressed = *state == ElementState::Pressed; match keycode { - VirtualKeyCode::Space => { + KeyCode::Space => { self.is_up_pressed = is_pressed; true } - VirtualKeyCode::LShift => { + KeyCode::ShiftLeft => { self.is_down_pressed = is_pressed; true } - VirtualKeyCode::W | VirtualKeyCode::Up => { + KeyCode::KeyW | KeyCode::ArrowUp => { self.is_forward_pressed = is_pressed; true } - VirtualKeyCode::A | VirtualKeyCode::Left => { + KeyCode::KeyA | KeyCode::ArrowLeft => { self.is_left_pressed = is_pressed; true } - VirtualKeyCode::S | VirtualKeyCode::Down => { + KeyCode::KeyS | KeyCode::ArrowDown => { self.is_backward_pressed = is_pressed; true } - VirtualKeyCode::D | VirtualKeyCode::Right => { + KeyCode::KeyD | KeyCode::ArrowRight => { self.is_right_pressed = is_pressed; true } @@ -255,9 +256,9 @@ struct LightUniform { _padding2: u32, } -struct State { - window: Window, - surface: wgpu::Surface, +struct State<'a> { + window: &'a Window, + surface: wgpu::Surface<'a>, device: wgpu::Device, queue: wgpu::Queue, config: wgpu::SurfaceConfiguration, @@ -339,8 +340,8 @@ fn create_render_pipeline( }) } -impl State { - async fn new(window: Window) -> Self { +impl<'a> State<'a> { + async fn new(window: &'a Window) -> State<'a> { let size = window.inner_size(); // The instance is a handle to our GPU @@ -350,11 +351,7 @@ impl State { ..Default::default() }); - // # Safety - // - // The surface needs to live as long as the window that created it. - // State owns the window so this should be safe. - let surface = unsafe { instance.create_surface(&window) }.unwrap(); + let surface = instance.create_surface(window).unwrap(); let adapter = instance .request_adapter(&wgpu::RequestAdapterOptions { @@ -368,10 +365,10 @@ impl State { .request_device( &wgpu::DeviceDescriptor { label: None, - features: wgpu::Features::empty(), + required_features: wgpu::Features::empty(), // WebGL doesn't support all of wgpu's features, so if // we're building for the web we'll have to disable some. - limits: if cfg!(target_arch = "wasm32") { + required_limits: if cfg!(target_arch = "wasm32") { wgpu::Limits::downlevel_webgl2_defaults() } else { wgpu::Limits::default() @@ -400,6 +397,7 @@ impl State { present_mode: surface_caps.present_modes[0], alpha_mode: surface_caps.alpha_modes[0], view_formats: vec![], + desired_maximum_frame_latency: 2, }; surface.configure(&device, &config); @@ -733,7 +731,7 @@ pub async fn run() { } } - let event_loop = EventLoop::new(); + let event_loop = EventLoop::new().unwrap(); let title = env!("CARGO_PKG_NAME"); let window = winit::window::WindowBuilder::new() .with_title(title) @@ -763,53 +761,58 @@ pub async fn run() { } // State::new uses async code, so we're going to wait for it to finish - let mut state = State::new(window).await; - - event_loop.run(move |event, _, control_flow| { - *control_flow = ControlFlow::Poll; - match event { - Event::MainEventsCleared => state.window().request_redraw(), - Event::WindowEvent { - ref event, - window_id, - } if window_id == state.window().id() => { - if !state.input(event) { - match event { - WindowEvent::CloseRequested - | WindowEvent::KeyboardInput { - input: - KeyboardInput { - state: ElementState::Pressed, - virtual_keycode: Some(VirtualKeyCode::Escape), - .. - }, - .. - } => *control_flow = ControlFlow::Exit, - WindowEvent::Resized(physical_size) => { - state.resize(*physical_size); + let mut state = State::new(&window).await; + + event_loop + .run(move |event, control_flow| { + match event { + Event::WindowEvent { + ref event, + window_id, + } if window_id == state.window().id() => { + if !state.input(event) { + match event { + WindowEvent::CloseRequested + | WindowEvent::KeyboardInput { + event: + KeyEvent { + state: ElementState::Pressed, + physical_key: PhysicalKey::Code(KeyCode::Escape), + .. + }, + .. + } => control_flow.exit(), + WindowEvent::Resized(physical_size) => { + state.resize(*physical_size); + } + WindowEvent::RedrawRequested => { + // This tells winit that we want another frame after this one + state.window().request_redraw(); + state.update(); + match state.render() { + Ok(_) => {} + // Reconfigure the surface if it's lost or outdated + Err( + wgpu::SurfaceError::Lost | wgpu::SurfaceError::Outdated, + ) => state.resize(state.size), + // The system is out of memory, we should probably quit + Err(wgpu::SurfaceError::OutOfMemory) => { + log::error!("OutOfMemory"); + control_flow.exit(); + } + + // This happens when the a frame takes too long to present + Err(wgpu::SurfaceError::Timeout) => { + log::warn!("Surface timeout") + } + } + } + _ => {} } - WindowEvent::ScaleFactorChanged { new_inner_size, .. } => { - state.resize(**new_inner_size); - } - _ => {} - } - } - } - Event::RedrawRequested(window_id) if window_id == state.window().id() => { - state.update(); - match state.render() { - Ok(_) => {} - // Reconfigure the surface if it's lost or outdated - Err(wgpu::SurfaceError::Lost | wgpu::SurfaceError::Outdated) => { - state.resize(state.size) } - // The system is out of memory, we should probably quit - Err(wgpu::SurfaceError::OutOfMemory) => *control_flow = ControlFlow::Exit, - // We're ignoring timeouts - Err(wgpu::SurfaceError::Timeout) => log::warn!("Surface timeout"), } + _ => {} } - _ => {} - } - }); + }) + .unwrap(); } diff --git a/code/intermediate/tutorial11-normals/src/lib.rs b/code/intermediate/tutorial11-normals/src/lib.rs index f10bc174..0bf981c1 100644 --- a/code/intermediate/tutorial11-normals/src/lib.rs +++ b/code/intermediate/tutorial11-normals/src/lib.rs @@ -5,6 +5,7 @@ use wgpu::util::DeviceExt; use winit::{ event::*, event_loop::{ControlFlow, EventLoop}, + keyboard::{KeyCode, PhysicalKey}, window::Window, }; @@ -92,37 +93,37 @@ impl CameraController { fn process_events(&mut self, event: &WindowEvent) -> bool { match event { WindowEvent::KeyboardInput { - input: - KeyboardInput { + event: + KeyEvent { state, - virtual_keycode: Some(keycode), + physical_key: PhysicalKey::Code(keycode), .. }, .. } => { let is_pressed = *state == ElementState::Pressed; match keycode { - VirtualKeyCode::Space => { + KeyCode::Space => { self.is_up_pressed = is_pressed; true } - VirtualKeyCode::LShift => { + KeyCode::ShiftLeft => { self.is_down_pressed = is_pressed; true } - VirtualKeyCode::W | VirtualKeyCode::Up => { + KeyCode::KeyW | KeyCode::ArrowUp => { self.is_forward_pressed = is_pressed; true } - VirtualKeyCode::A | VirtualKeyCode::Left => { + KeyCode::KeyA | KeyCode::ArrowLeft => { self.is_left_pressed = is_pressed; true } - VirtualKeyCode::S | VirtualKeyCode::Down => { + KeyCode::KeyS | KeyCode::ArrowDown => { self.is_backward_pressed = is_pressed; true } - VirtualKeyCode::D | VirtualKeyCode::Right => { + KeyCode::KeyD | KeyCode::ArrowRight => { self.is_right_pressed = is_pressed; true } @@ -253,9 +254,9 @@ struct LightUniform { _padding2: u32, } -struct State { - window: Window, - surface: wgpu::Surface, +struct State<'a> { + window: &'a Window, + surface: wgpu::Surface<'a>, device: wgpu::Device, queue: wgpu::Queue, config: wgpu::SurfaceConfiguration, @@ -339,8 +340,8 @@ fn create_render_pipeline( }) } -impl State { - async fn new(window: Window) -> Self { +impl<'a> State<'a> { + async fn new(window: &'a Window) -> State<'a> { let size = window.inner_size(); // The instance is a handle to our GPU @@ -350,11 +351,7 @@ impl State { ..Default::default() }); - // # Safety - // - // The surface needs to live as long as the window that created it. - // State owns the window so this should be safe. - let surface = unsafe { instance.create_surface(&window) }.unwrap(); + let surface = instance.create_surface(window).unwrap(); let adapter = instance .request_adapter(&wgpu::RequestAdapterOptions { @@ -368,10 +365,10 @@ impl State { .request_device( &wgpu::DeviceDescriptor { label: None, - features: wgpu::Features::empty(), + required_features: wgpu::Features::empty(), // WebGL doesn't support all of wgpu's features, so if // we're building for the web we'll have to disable some. - limits: if cfg!(target_arch = "wasm32") { + required_limits: if cfg!(target_arch = "wasm32") { wgpu::Limits::downlevel_webgl2_defaults() } else { wgpu::Limits::default() @@ -400,6 +397,7 @@ impl State { present_mode: surface_caps.present_modes[0], alpha_mode: surface_caps.alpha_modes[0], view_formats: vec![], + desired_maximum_frame_latency: 2, }; surface.configure(&device, &config); @@ -784,7 +782,7 @@ pub async fn run() { } } - let event_loop = EventLoop::new(); + let event_loop = EventLoop::new().unwrap(); let title = env!("CARGO_PKG_NAME"); let window = winit::window::WindowBuilder::new() .with_title(title) @@ -811,53 +809,58 @@ pub async fn run() { } // State::new uses async code, so we're going to wait for it to finish - let mut state = State::new(window).await; - - event_loop.run(move |event, _, control_flow| { - *control_flow = ControlFlow::Poll; - match event { - Event::MainEventsCleared => state.window().request_redraw(), - Event::WindowEvent { - ref event, - window_id, - } if window_id == state.window().id() => { - if !state.input(event) { - match event { - WindowEvent::CloseRequested - | WindowEvent::KeyboardInput { - input: - KeyboardInput { - state: ElementState::Pressed, - virtual_keycode: Some(VirtualKeyCode::Escape), - .. - }, - .. - } => *control_flow = ControlFlow::Exit, - WindowEvent::Resized(physical_size) => { - state.resize(*physical_size); + let mut state = State::new(&window).await; + + event_loop + .run(move |event, control_flow| { + match event { + Event::WindowEvent { + ref event, + window_id, + } if window_id == state.window().id() => { + if !state.input(event) { + match event { + WindowEvent::CloseRequested + | WindowEvent::KeyboardInput { + event: + KeyEvent { + state: ElementState::Pressed, + physical_key: PhysicalKey::Code(KeyCode::Escape), + .. + }, + .. + } => control_flow.exit(), + WindowEvent::Resized(physical_size) => { + state.resize(*physical_size); + } + WindowEvent::RedrawRequested => { + // This tells winit that we want another frame after this one + state.window().request_redraw(); + state.update(); + match state.render() { + Ok(_) => {} + // Reconfigure the surface if it's lost or outdated + Err( + wgpu::SurfaceError::Lost | wgpu::SurfaceError::Outdated, + ) => state.resize(state.size), + // The system is out of memory, we should probably quit + Err(wgpu::SurfaceError::OutOfMemory) => { + log::error!("OutOfMemory"); + control_flow.exit(); + } + + // This happens when the a frame takes too long to present + Err(wgpu::SurfaceError::Timeout) => { + log::warn!("Surface timeout") + } + } + } + _ => {} } - WindowEvent::ScaleFactorChanged { new_inner_size, .. } => { - state.resize(**new_inner_size); - } - _ => {} - } - } - } - Event::RedrawRequested(window_id) if window_id == state.window().id() => { - state.update(); - match state.render() { - Ok(_) => {} - // Reconfigure the surface if it's lost or outdated - Err(wgpu::SurfaceError::Lost | wgpu::SurfaceError::Outdated) => { - state.resize(state.size) } - // The system is out of memory, we should probably quit - Err(wgpu::SurfaceError::OutOfMemory) => *control_flow = ControlFlow::Exit, - // We're ignoring timeouts - Err(wgpu::SurfaceError::Timeout) => log::warn!("Surface timeout"), } + _ => {} } - _ => {} - } - }); + }) + .unwrap(); } diff --git a/code/intermediate/tutorial12-camera/src/camera.rs b/code/intermediate/tutorial12-camera/src/camera.rs index 0dc592b7..66b92fd4 100644 --- a/code/intermediate/tutorial12-camera/src/camera.rs +++ b/code/intermediate/tutorial12-camera/src/camera.rs @@ -3,6 +3,7 @@ use std::f32::consts::FRAC_PI_2; use std::time::Duration; use winit::dpi::PhysicalPosition; use winit::event::*; +use winit::keyboard::KeyCode; #[rustfmt::skip] pub const OPENGL_TO_WGPU_MATRIX: cgmath::Matrix4 = cgmath::Matrix4::new( @@ -104,34 +105,34 @@ impl CameraController { } } - pub fn process_keyboard(&mut self, key: VirtualKeyCode, state: ElementState) -> bool { + pub fn process_keyboard(&mut self, key: KeyCode, state: ElementState) -> bool { let amount = if state == ElementState::Pressed { 1.0 } else { 0.0 }; match key { - VirtualKeyCode::W | VirtualKeyCode::Up => { + KeyCode::KeyW | KeyCode::ArrowUp => { self.amount_forward = amount; true } - VirtualKeyCode::S | VirtualKeyCode::Down => { + KeyCode::KeyS | KeyCode::ArrowDown => { self.amount_backward = amount; true } - VirtualKeyCode::A | VirtualKeyCode::Left => { + KeyCode::KeyA | KeyCode::ArrowLeft => { self.amount_left = amount; true } - VirtualKeyCode::D | VirtualKeyCode::Right => { + KeyCode::KeyD | KeyCode::ArrowRight => { self.amount_right = amount; true } - VirtualKeyCode::Space => { + KeyCode::Space => { self.amount_up = amount; true } - VirtualKeyCode::LShift => { + KeyCode::ShiftLeft => { self.amount_down = amount; true } diff --git a/code/intermediate/tutorial12-camera/src/lib.rs b/code/intermediate/tutorial12-camera/src/lib.rs index 3314bb58..23fc31b8 100644 --- a/code/intermediate/tutorial12-camera/src/lib.rs +++ b/code/intermediate/tutorial12-camera/src/lib.rs @@ -1,10 +1,11 @@ -use std::iter; +use std::{f32::consts::PI, iter}; use cgmath::prelude::*; use wgpu::util::DeviceExt; use winit::{ event::*, event_loop::{ControlFlow, EventLoop}, + keyboard::{KeyCode, PhysicalKey}, window::Window, }; @@ -130,9 +131,9 @@ struct LightUniform { _padding2: u32, } -struct State { - window: Window, - surface: wgpu::Surface, +struct State<'a> { + window: &'a Window, + surface: wgpu::Surface<'a>, device: wgpu::Device, queue: wgpu::Queue, config: wgpu::SurfaceConfiguration, @@ -219,8 +220,8 @@ fn create_render_pipeline( }) } -impl State { - async fn new(window: Window) -> Self { +impl<'a> State<'a> { + async fn new(window: &'a Window) -> State<'a> { let size = window.inner_size(); // The instance is a handle to our GPU @@ -230,11 +231,7 @@ impl State { ..Default::default() }); - // # Safety - // - // The surface needs to live as long as the window that created it. - // State owns the window so this should be safe. - let surface = unsafe { instance.create_surface(&window) }.unwrap(); + let surface = instance.create_surface(window).unwrap(); let adapter = instance .request_adapter(&wgpu::RequestAdapterOptions { @@ -248,10 +245,10 @@ impl State { .request_device( &wgpu::DeviceDescriptor { label: None, - features: wgpu::Features::empty(), + required_features: wgpu::Features::empty(), // WebGL doesn't support all of wgpu's features, so if // we're building for the web we'll have to disable some. - limits: if cfg!(target_arch = "wasm32") { + required_limits: if cfg!(target_arch = "wasm32") { wgpu::Limits::downlevel_webgl2_defaults() } else { wgpu::Limits::default() @@ -280,6 +277,7 @@ impl State { present_mode: surface_caps.present_modes[0], alpha_mode: surface_caps.alpha_modes[0], view_formats: vec![], + desired_maximum_frame_latency: 2, }; surface.configure(&device, &config); @@ -564,9 +562,9 @@ impl State { fn input(&mut self, event: &WindowEvent) -> bool { match event { WindowEvent::KeyboardInput { - input: - KeyboardInput { - virtual_keycode: Some(key), + event: + KeyEvent { + physical_key: PhysicalKey::Code(key), state, .. }, @@ -601,10 +599,11 @@ impl State { // Update the light let old_position: cgmath::Vector3<_> = self.light_uniform.position.into(); - self.light_uniform.position = - (cgmath::Quaternion::from_axis_angle((0.0, 1.0, 0.0).into(), cgmath::Deg(1.0)) - * old_position) - .into(); + self.light_uniform.position = (cgmath::Quaternion::from_axis_angle( + (0.0, 1.0, 0.0).into(), + cgmath::Deg(PI * dt.as_secs_f32()), + ) * old_position) + .into(); self.queue.write_buffer( &self.light_buffer, 0, @@ -686,7 +685,7 @@ pub async fn run() { } } - let event_loop = EventLoop::new(); + let event_loop = EventLoop::new().unwrap(); let title = env!("CARGO_PKG_NAME"); let window = winit::window::WindowBuilder::new() .with_title(title) @@ -712,12 +711,10 @@ pub async fn run() { .expect("Couldn't append canvas to document body."); } - let mut state = State::new(window).await; // NEW! + let mut state = State::new(&window).await; // NEW! let mut last_render_time = instant::Instant::now(); - event_loop.run(move |event, _, control_flow| { - *control_flow = ControlFlow::Poll; + event_loop.run(move |event, control_flow| { match event { - Event::MainEventsCleared => state.window().request_redraw(), // NEW! Event::DeviceEvent { event: DeviceEvent::MouseMotion{ delta, }, @@ -734,40 +731,38 @@ pub async fn run() { #[cfg(not(target_arch="wasm32"))] WindowEvent::CloseRequested | WindowEvent::KeyboardInput { - input: - KeyboardInput { + event: + KeyEvent { state: ElementState::Pressed, - virtual_keycode: Some(VirtualKeyCode::Escape), + physical_key: PhysicalKey::Code(KeyCode::Escape), .. }, .. - } => *control_flow = ControlFlow::Exit, + } => control_flow.exit(), WindowEvent::Resized(physical_size) => { state.resize(*physical_size); } - WindowEvent::ScaleFactorChanged { new_inner_size, .. } => { - state.resize(**new_inner_size); + // UPDATED! + WindowEvent::RedrawRequested => { + state.window().request_redraw(); + let now = instant::Instant::now(); + let dt = now - last_render_time; + last_render_time = now; + state.update(dt); + match state.render() { + Ok(_) => {} + // Reconfigure the surface if it's lost or outdated + Err(wgpu::SurfaceError::Lost | wgpu::SurfaceError::Outdated) => state.resize(state.size), + // The system is out of memory, we should probably quit + Err(wgpu::SurfaceError::OutOfMemory) => control_flow.exit(), + // We're ignoring timeouts + Err(wgpu::SurfaceError::Timeout) => log::warn!("Surface timeout"), + } } _ => {} } } - // UPDATED! - Event::RedrawRequested(window_id) if window_id == state.window().id() => { - let now = instant::Instant::now(); - let dt = now - last_render_time; - last_render_time = now; - state.update(dt); - match state.render() { - Ok(_) => {} - // Reconfigure the surface if it's lost or outdated - Err(wgpu::SurfaceError::Lost | wgpu::SurfaceError::Outdated) => state.resize(state.size), - // The system is out of memory, we should probably quit - Err(wgpu::SurfaceError::OutOfMemory) => *control_flow = ControlFlow::Exit, - // We're ignoring timeouts - Err(wgpu::SurfaceError::Timeout) => log::warn!("Surface timeout"), - } - } _ => {} } - }); + }).unwrap(); } diff --git a/code/intermediate/tutorial13-hdr/src/camera.rs b/code/intermediate/tutorial13-hdr/src/camera.rs index 2b7532f5..6d6d6bb9 100644 --- a/code/intermediate/tutorial13-hdr/src/camera.rs +++ b/code/intermediate/tutorial13-hdr/src/camera.rs @@ -3,6 +3,7 @@ use std::f32::consts::FRAC_PI_2; use std::time::Duration; use winit::dpi::PhysicalPosition; use winit::event::*; +use winit::keyboard::KeyCode; const SAFE_FRAC_PI_2: f32 = FRAC_PI_2 - 0.0001; @@ -97,34 +98,34 @@ impl CameraController { } } - pub fn process_keyboard(&mut self, key: VirtualKeyCode, state: ElementState) -> bool { + pub fn process_keyboard(&mut self, key: KeyCode, state: ElementState) -> bool { let amount = if state == ElementState::Pressed { 1.0 } else { 0.0 }; match key { - VirtualKeyCode::W | VirtualKeyCode::Up => { + KeyCode::KeyW | KeyCode::ArrowUp => { self.amount_forward = amount; true } - VirtualKeyCode::S | VirtualKeyCode::Down => { + KeyCode::KeyS | KeyCode::ArrowDown => { self.amount_backward = amount; true } - VirtualKeyCode::A | VirtualKeyCode::Left => { + KeyCode::KeyA | KeyCode::ArrowLeft => { self.amount_left = amount; true } - VirtualKeyCode::D | VirtualKeyCode::Right => { + KeyCode::KeyD | KeyCode::ArrowRight => { self.amount_right = amount; true } - VirtualKeyCode::Space => { + KeyCode::Space => { self.amount_up = amount; true } - VirtualKeyCode::LShift => { + KeyCode::ShiftLeft => { self.amount_down = amount; true } diff --git a/code/intermediate/tutorial13-hdr/src/lib.rs b/code/intermediate/tutorial13-hdr/src/lib.rs index 1446a3ea..01360f35 100644 --- a/code/intermediate/tutorial13-hdr/src/lib.rs +++ b/code/intermediate/tutorial13-hdr/src/lib.rs @@ -1,10 +1,11 @@ -use std::iter; +use std::{f32::consts::PI, iter}; use cgmath::prelude::*; use wgpu::util::DeviceExt; use winit::{ event::*, - event_loop::{ControlFlow, EventLoop}, + event_loop::EventLoop, + keyboard::{KeyCode, PhysicalKey}, window::Window, }; @@ -146,9 +147,9 @@ struct LightUniform { _padding2: u32, } -struct State { - window: Window, - surface: wgpu::Surface, +struct State<'a> { + window: &'a Window, + surface: wgpu::Surface<'a>, device: wgpu::Device, queue: wgpu::Queue, config: wgpu::SurfaceConfiguration, @@ -238,26 +239,22 @@ fn create_render_pipeline( }) } -impl State { - async fn new(window: Window) -> anyhow::Result { +impl<'a> State<'a> { + async fn new(window: &'a Window) -> anyhow::Result> { let size = window.inner_size(); // The instance is a handle to our GPU // BackendBit::PRIMARY => Vulkan + Metal + DX12 + Browser WebGPU let instance = wgpu::Instance::new(wgpu::InstanceDescriptor { // UPDATED - #[cfg(target_arch="wasm32")] + #[cfg(target_arch = "wasm32")] backends: wgpu::Backends::BROWSER_WEBGPU, - #[cfg(not(target_arch="wasm32"))] + #[cfg(not(target_arch = "wasm32"))] backends: wgpu::Backends::all(), ..Default::default() }); - // # Safety - // - // The surface needs to live as long as the window that created it. - // State owns the window so this should be safe. - let surface = unsafe { instance.create_surface(&window) }.unwrap(); + let surface = instance.create_surface(window).unwrap(); let adapter = instance .request_adapter(&wgpu::RequestAdapterOptions { @@ -272,9 +269,9 @@ impl State { &wgpu::DeviceDescriptor { label: None, // UPDATED! - features: wgpu::Features::empty(), + required_features: wgpu::Features::empty(), // UPDATED! - limits: wgpu::Limits::downlevel_defaults(), + required_limits: wgpu::Limits::downlevel_defaults(), }, None, // Trace path ) @@ -299,6 +296,7 @@ impl State { present_mode: surface_caps.present_modes[0], alpha_mode: surface_caps.alpha_modes[0], view_formats: vec![], + desired_maximum_frame_latency: 2, }; surface.configure(&device, &config); @@ -665,9 +663,9 @@ impl State { fn input(&mut self, event: &WindowEvent) -> bool { match event { WindowEvent::KeyboardInput { - input: - KeyboardInput { - virtual_keycode: Some(key), + event: + KeyEvent { + physical_key: PhysicalKey::Code(key), state, .. }, @@ -701,10 +699,11 @@ impl State { // Update the light let old_position: cgmath::Vector3<_> = self.light_uniform.position.into(); - self.light_uniform.position = - (cgmath::Quaternion::from_axis_angle((0.0, 1.0, 0.0).into(), cgmath::Deg(1.0)) - * old_position) - .into(); + self.light_uniform.position = (cgmath::Quaternion::from_axis_angle( + (0.0, 1.0, 0.0).into(), + cgmath::Deg(PI * dt.as_secs_f32()), + ) * old_position) + .into(); self.queue.write_buffer( &self.light_buffer, 0, @@ -816,7 +815,7 @@ pub async fn run() { } } - let event_loop = EventLoop::new(); + let event_loop = EventLoop::new().unwrap(); let title = env!("CARGO_PKG_NAME"); let window = winit::window::WindowBuilder::new() .with_title(title) @@ -842,12 +841,10 @@ pub async fn run() { .expect("Couldn't append canvas to document body."); } - let mut state = State::new(window).await.unwrap(); // NEW! + let mut state = State::new(&window).await.unwrap(); let mut last_render_time = instant::Instant::now(); - event_loop.run(move |event, _, control_flow| { - *control_flow = ControlFlow::Poll; + event_loop.run(move |event, control_flow| { match event { - Event::MainEventsCleared => state.window().request_redraw(), Event::DeviceEvent { event: DeviceEvent::MouseMotion{ delta, }, .. // We're not using device_id currently @@ -863,40 +860,38 @@ pub async fn run() { #[cfg(not(target_arch="wasm32"))] WindowEvent::CloseRequested | WindowEvent::KeyboardInput { - input: - KeyboardInput { + event: + KeyEvent { state: ElementState::Pressed, - virtual_keycode: Some(VirtualKeyCode::Escape), + physical_key: PhysicalKey::Code(KeyCode::Escape), .. }, .. - } => *control_flow = ControlFlow::Exit, + } => control_flow.exit(), WindowEvent::Resized(physical_size) => { state.resize(*physical_size); } - WindowEvent::ScaleFactorChanged { new_inner_size, .. } => { - state.resize(**new_inner_size); + // UPDATED! + WindowEvent::RedrawRequested => { + state.window().request_redraw(); + let now = instant::Instant::now(); + let dt = now - last_render_time; + last_render_time = now; + state.update(dt); + match state.render() { + Ok(_) => {} + // Reconfigure the surface if it's lost or outdated + Err(wgpu::SurfaceError::Lost | wgpu::SurfaceError::Outdated) => state.resize(state.size), + // The system is out of memory, we should probably quit + Err(wgpu::SurfaceError::OutOfMemory) => control_flow.exit(), + // We're ignoring timeouts + Err(wgpu::SurfaceError::Timeout) => log::warn!("Surface timeout"), + } } _ => {} } } - // UPDATED! - Event::RedrawRequested(window_id) if window_id == state.window().id() => { - let now = instant::Instant::now(); - let dt = now - last_render_time; - last_render_time = now; - state.update(dt); - match state.render() { - Ok(_) => {} - // Reconfigure the surface if it's lost or outdated - Err(wgpu::SurfaceError::Lost | wgpu::SurfaceError::Outdated) => state.resize(state.size), - // The system is out of memory, we should probably quit - Err(wgpu::SurfaceError::OutOfMemory) => *control_flow = ControlFlow::Exit, - // We're ignoring timeouts - Err(wgpu::SurfaceError::Timeout) => log::warn!("Surface timeout"), - } - } _ => {} } - }); + }).unwrap(); } diff --git a/code/intermediate/tutorial13-hdr/src/resources.rs b/code/intermediate/tutorial13-hdr/src/resources.rs index 954120a9..b82bc192 100644 --- a/code/intermediate/tutorial13-hdr/src/resources.rs +++ b/code/intermediate/tutorial13-hdr/src/resources.rs @@ -327,8 +327,7 @@ impl HdrLoader { dst_size, self.texture_format, 1, - wgpu::TextureUsages::STORAGE_BINDING - | wgpu::TextureUsages::TEXTURE_BINDING, + wgpu::TextureUsages::STORAGE_BINDING | wgpu::TextureUsages::TEXTURE_BINDING, wgpu::FilterMode::Nearest, label, ); @@ -356,7 +355,10 @@ impl HdrLoader { }); let mut encoder = device.create_command_encoder(&Default::default()); - let mut pass = encoder.begin_compute_pass(&wgpu::ComputePassDescriptor { label, timestamp_writes: None }); + let mut pass = encoder.begin_compute_pass(&wgpu::ComputePassDescriptor { + label, + timestamp_writes: None, + }); let num_workgroups = (dst_size + 15) / 16; pass.set_pipeline(&self.equirect_to_cubemap); diff --git a/code/intermediate/tutorial13-hdr/src/texture.rs b/code/intermediate/tutorial13-hdr/src/texture.rs index 0826a9c2..1ef186e6 100644 --- a/code/intermediate/tutorial13-hdr/src/texture.rs +++ b/code/intermediate/tutorial13-hdr/src/texture.rs @@ -239,10 +239,15 @@ impl CubeTexture { } } - pub fn texture(&self) -> &wgpu::Texture { &self.texture } - - pub fn view(&self) -> &wgpu::TextureView { &self.view } + pub fn texture(&self) -> &wgpu::Texture { + &self.texture + } - pub fn sampler(&self) -> &wgpu::Sampler { &self.sampler } + pub fn view(&self) -> &wgpu::TextureView { + &self.view + } + pub fn sampler(&self) -> &wgpu::Sampler { + &self.sampler + } } diff --git a/code/intermediate/wip-terrain/src/bindgroups.rs b/code/intermediate/wip-terrain/src/bindgroups.rs index fef1425a..e344bbfa 100644 --- a/code/intermediate/wip-terrain/src/bindgroups.rs +++ b/code/intermediate/wip-terrain/src/bindgroups.rs @@ -2,7 +2,7 @@ use std::marker::PhantomData; pub struct Binder { layout: wgpu::BindGroupLayout, - _marker: PhantomData + _marker: PhantomData, } -// pub trait Uniform \ No newline at end of file +// pub trait Uniform diff --git a/code/intermediate/wip-terrain/src/camera.rs b/code/intermediate/wip-terrain/src/camera.rs index 0dc592b7..66b92fd4 100644 --- a/code/intermediate/wip-terrain/src/camera.rs +++ b/code/intermediate/wip-terrain/src/camera.rs @@ -3,6 +3,7 @@ use std::f32::consts::FRAC_PI_2; use std::time::Duration; use winit::dpi::PhysicalPosition; use winit::event::*; +use winit::keyboard::KeyCode; #[rustfmt::skip] pub const OPENGL_TO_WGPU_MATRIX: cgmath::Matrix4 = cgmath::Matrix4::new( @@ -104,34 +105,34 @@ impl CameraController { } } - pub fn process_keyboard(&mut self, key: VirtualKeyCode, state: ElementState) -> bool { + pub fn process_keyboard(&mut self, key: KeyCode, state: ElementState) -> bool { let amount = if state == ElementState::Pressed { 1.0 } else { 0.0 }; match key { - VirtualKeyCode::W | VirtualKeyCode::Up => { + KeyCode::KeyW | KeyCode::ArrowUp => { self.amount_forward = amount; true } - VirtualKeyCode::S | VirtualKeyCode::Down => { + KeyCode::KeyS | KeyCode::ArrowDown => { self.amount_backward = amount; true } - VirtualKeyCode::A | VirtualKeyCode::Left => { + KeyCode::KeyA | KeyCode::ArrowLeft => { self.amount_left = amount; true } - VirtualKeyCode::D | VirtualKeyCode::Right => { + KeyCode::KeyD | KeyCode::ArrowRight => { self.amount_right = amount; true } - VirtualKeyCode::Space => { + KeyCode::Space => { self.amount_up = amount; true } - VirtualKeyCode::LShift => { + KeyCode::ShiftLeft => { self.amount_down = amount; true } diff --git a/code/intermediate/wip-terrain/src/lib.rs b/code/intermediate/wip-terrain/src/lib.rs index 8cdaf983..26e301e8 100644 --- a/code/intermediate/wip-terrain/src/lib.rs +++ b/code/intermediate/wip-terrain/src/lib.rs @@ -5,18 +5,19 @@ use wgpu::util::DeviceExt; use winit::{ event::*, event_loop::{ControlFlow, EventLoop}, + keyboard::{KeyCode, PhysicalKey}, window::Window, }; #[cfg(target_arch = "wasm32")] use wasm_bindgen::prelude::*; +mod bindgroups; mod camera; mod model; mod resources; mod terrain; -mod texture; -mod bindgroups; // NEW! +mod texture; // NEW! use model::{DrawLight, DrawModel, Vertex}; @@ -132,9 +133,9 @@ struct LightUniform { _padding2: u32, } -struct State { - window: Window, - surface: wgpu::Surface, +struct State<'a> { + window: &'a Window, + surface: wgpu::Surface<'a>, device: wgpu::Device, queue: wgpu::Queue, config: wgpu::SurfaceConfiguration, @@ -220,8 +221,8 @@ fn create_render_pipeline( }) } -impl State { - async fn new(window: Window) -> Self { +impl<'a> State<'a> { + async fn new(window: &'a Window) -> State<'a> { let size = window.inner_size(); // The instance is a handle to our GPU @@ -231,11 +232,7 @@ impl State { ..Default::default() }); - // # Safety - // - // The surface needs to live as long as the window that created it. - // State owns the window so this should be safe. - let surface = unsafe { instance.create_surface(&window) }.unwrap(); + let surface = instance.create_surface(window).unwrap(); let adapter = instance .request_adapter(&wgpu::RequestAdapterOptions { @@ -249,10 +246,10 @@ impl State { .request_device( &wgpu::DeviceDescriptor { label: None, - features: wgpu::Features::empty(), + required_features: wgpu::Features::empty(), // WebGL doesn't support all of wgpu's features, so if // we're building for the web we'll have to disable some. - limits: if cfg!(target_arch = "wasm32") { + required_limits: if cfg!(target_arch = "wasm32") { wgpu::Limits::downlevel_webgl2_defaults() } else { wgpu::Limits::default() @@ -281,6 +278,7 @@ impl State { present_mode: surface_caps.present_modes[0], alpha_mode: surface_caps.alpha_modes[0], view_formats: vec![], + desired_maximum_frame_latency: 2, }; surface.configure(&device, &config); @@ -606,9 +604,9 @@ impl State { fn input(&mut self, event: &WindowEvent) -> bool { match event { WindowEvent::KeyboardInput { - input: - KeyboardInput { - virtual_keycode: Some(key), + event: + KeyEvent { + physical_key: PhysicalKey::Code(key), state, .. }, @@ -736,7 +734,7 @@ pub async fn run() { } } - let event_loop = EventLoop::new(); + let event_loop = EventLoop::new().unwrap(); let title = env!("CARGO_PKG_NAME"); let window = winit::window::WindowBuilder::new() .with_title(title) @@ -763,13 +761,11 @@ pub async fn run() { .expect("Couldn't append canvas to document body."); } - let mut state = State::new(window).await; // NEW! + let mut state = State::new(&window).await; // NEW! state.window().set_visible(true); let mut last_render_time = instant::Instant::now(); - event_loop.run(move |event, _, control_flow| { - *control_flow = ControlFlow::Poll; + event_loop.run(move |event, control_flow| { match event { - Event::MainEventsCleared => state.window().request_redraw(), // NEW! Event::DeviceEvent { event: DeviceEvent::MouseMotion{ delta, }, @@ -786,40 +782,37 @@ pub async fn run() { #[cfg(not(target_arch="wasm32"))] WindowEvent::CloseRequested | WindowEvent::KeyboardInput { - input: - KeyboardInput { + event: + KeyEvent { state: ElementState::Pressed, - virtual_keycode: Some(VirtualKeyCode::Escape), + physical_key: PhysicalKey::Code(KeyCode::Escape), .. }, .. - } => *control_flow = ControlFlow::Exit, + } => control_flow.exit(), WindowEvent::Resized(physical_size) => { state.resize(*physical_size); } - WindowEvent::ScaleFactorChanged { new_inner_size, .. } => { - state.resize(**new_inner_size); + // UPDATED! + WindowEvent::RedrawRequested => { + let now = instant::Instant::now(); + let dt = now - last_render_time; + last_render_time = now; + state.update(dt); + match state.render() { + Ok(_) => {} + // Reconfigure the surface if it's lost or outdated + Err(wgpu::SurfaceError::Lost | wgpu::SurfaceError::Outdated) => state.resize(state.size), + // The system is out of memory, we should probably quit + Err(wgpu::SurfaceError::OutOfMemory) => control_flow.exit(), + // We're ignoring timeouts + Err(wgpu::SurfaceError::Timeout) => log::warn!("Surface timeout"), + } } _ => {} } } - // UPDATED! - Event::RedrawRequested(window_id) if window_id == state.window().id() => { - let now = instant::Instant::now(); - let dt = now - last_render_time; - last_render_time = now; - state.update(dt); - match state.render() { - Ok(_) => {} - // Reconfigure the surface if it's lost or outdated - Err(wgpu::SurfaceError::Lost | wgpu::SurfaceError::Outdated) => state.resize(state.size), - // The system is out of memory, we should probably quit - Err(wgpu::SurfaceError::OutOfMemory) => *control_flow = ControlFlow::Exit, - // We're ignoring timeouts - Err(wgpu::SurfaceError::Timeout) => log::warn!("Surface timeout"), - } - } _ => {} } - }); + }).unwrap(); } diff --git a/code/intermediate/wip-terrain/src/terrain.rs b/code/intermediate/wip-terrain/src/terrain.rs index e9ce0b4e..ea8b8397 100644 --- a/code/intermediate/wip-terrain/src/terrain.rs +++ b/code/intermediate/wip-terrain/src/terrain.rs @@ -241,8 +241,7 @@ impl GenerateChunk for TerrainPipeline { let gen_buffer = device.create_buffer(&wgpu::BufferDescriptor { label: Some("TerrainPipeline: ChunkData"), size: size_of_val(&data) as _, - usage: wgpu::BufferUsages::UNIFORM - | wgpu::BufferUsages::COPY_DST, + usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST, mapped_at_creation: false, }); queue.write_buffer(&gen_buffer, 0, bytemuck::bytes_of(&data)); diff --git a/code/intermediate/wip-terrain/src/texture.rs b/code/intermediate/wip-terrain/src/texture.rs index 0b8838ad..bb91b88e 100644 --- a/code/intermediate/wip-terrain/src/texture.rs +++ b/code/intermediate/wip-terrain/src/texture.rs @@ -63,7 +63,14 @@ impl Texture { address_mode: AddressMode, // NEW! ) -> Result { let img = image::load_from_memory(bytes)?; - Self::from_image(device, queue, &img, Some(label), is_normal_map, address_mode) // UPDATED! + Self::from_image( + device, + queue, + &img, + Some(label), + is_normal_map, + address_mode, + ) // UPDATED! } pub fn from_image( @@ -117,7 +124,7 @@ impl Texture { let view = texture.create_view(&wgpu::TextureViewDescriptor::default()); let sampler = device.create_sampler(&wgpu::SamplerDescriptor { // UPDATED! - address_mode_u: address_mode, + address_mode_u: address_mode, address_mode_v: address_mode, address_mode_w: address_mode, mag_filter: wgpu::FilterMode::Linear, diff --git a/code/showcase/compute/src/camera.rs b/code/showcase/compute/src/camera.rs index 62c135e5..14545e7c 100644 --- a/code/showcase/compute/src/camera.rs +++ b/code/showcase/compute/src/camera.rs @@ -3,6 +3,7 @@ use std::f32::consts::FRAC_PI_2; use std::time::Duration; use winit::dpi::PhysicalPosition; use winit::event::*; +use winit::keyboard::KeyCode; #[rustfmt::skip] pub const OPENGL_TO_WGPU_MATRIX: cgmath::Matrix4 = cgmath::Matrix4::new( @@ -104,34 +105,34 @@ impl CameraController { } } - pub fn process_keyboard(&mut self, key: VirtualKeyCode, state: ElementState) -> bool { + pub fn process_keyboard(&mut self, key: KeyCode, state: ElementState) -> bool { let amount = if state == ElementState::Pressed { 1.0 } else { 0.0 }; match key { - VirtualKeyCode::W | VirtualKeyCode::Up => { + KeyCode::KeyW | KeyCode::ArrowUp => { self.amount_forward = amount; true } - VirtualKeyCode::S | VirtualKeyCode::Down => { + KeyCode::KeyS | KeyCode::ArrowDown => { self.amount_backward = amount; true } - VirtualKeyCode::A | VirtualKeyCode::Left => { + KeyCode::KeyA | KeyCode::ArrowLeft => { self.amount_left = amount; true } - VirtualKeyCode::D | VirtualKeyCode::Right => { + KeyCode::KeyD | KeyCode::ArrowRight => { self.amount_right = amount; true } - VirtualKeyCode::Space => { + KeyCode::Space => { self.amount_up = amount; true } - VirtualKeyCode::LShift => { + KeyCode::ShiftLeft => { self.amount_down = amount; true } diff --git a/code/showcase/compute/src/main.rs b/code/showcase/compute/src/main.rs index 208fe093..5182b5f8 100644 --- a/code/showcase/compute/src/main.rs +++ b/code/showcase/compute/src/main.rs @@ -6,6 +6,7 @@ use winit::{ dpi::PhysicalPosition, event::*, event_loop::{ControlFlow, EventLoop}, + keyboard::{KeyCode, PhysicalKey}, window::Window, }; @@ -129,8 +130,8 @@ struct LightUniform { _padding2: u32, } -struct State { - surface: wgpu::Surface, +struct State<'a> { + surface: wgpu::Surface<'a>, device: wgpu::Device, queue: wgpu::Queue, config: wgpu::SurfaceConfiguration, @@ -155,11 +156,11 @@ struct State { debug_material: model::Material, last_mouse_pos: PhysicalPosition, mouse_pressed: bool, - window: Window, + window: &'a Window, } -impl State { - async fn new(window: Window) -> Self { +impl<'a> State<'a> { + async fn new(window: &'a Window) -> State<'a> { let size = window.inner_size(); // The instance is a handle to our GPU @@ -169,11 +170,7 @@ impl State { ..Default::default() }); - // # Safety - // - // The surface needs to live as long as the window that created it. - // State owns the window so this should be safe. - let surface = unsafe { instance.create_surface(&window) }.unwrap(); + let surface = instance.create_surface(window).unwrap(); let adapter = instance .request_adapter(&wgpu::RequestAdapterOptions { @@ -187,10 +184,10 @@ impl State { .request_device( &wgpu::DeviceDescriptor { label: None, - features: wgpu::Features::empty(), + required_features: wgpu::Features::empty(), // WebGL doesn't support all of wgpu's features, so if // we're building for the web we'll have to disable some. - limits: if cfg!(target_arch = "wasm32") { + required_limits: if cfg!(target_arch = "wasm32") { wgpu::Limits::downlevel_webgl2_defaults() } else { wgpu::Limits::default() @@ -219,6 +216,7 @@ impl State { present_mode: surface_caps.present_modes[0], alpha_mode: surface_caps.alpha_modes[0], view_formats: vec![], + desired_maximum_frame_latency: 2, }; surface.configure(&device, &config); @@ -506,9 +504,9 @@ impl State { fn input(&mut self, event: &WindowEvent) -> bool { match event { WindowEvent::KeyboardInput { - input: - KeyboardInput { - virtual_keycode: Some(key), + event: + KeyEvent { + physical_key: PhysicalKey::Code(key), state, .. }, @@ -636,18 +634,16 @@ fn main() { async fn run() { env_logger::init(); - let event_loop = EventLoop::new(); + let event_loop = EventLoop::new().unwrap(); let title = env!("CARGO_PKG_NAME"); let window = winit::window::WindowBuilder::new() .with_title(title) .build(&event_loop) .unwrap(); - let mut state = State::new(window).await; // NEW! + let mut state = State::new(&window).await; // NEW! let mut last_render_time = std::time::Instant::now(); - event_loop.run(move |event, _, control_flow| { - *control_flow = ControlFlow::Poll; - match event { - Event::MainEventsCleared => state.window().request_redraw(), + event_loop + .run(move |event, control_flow| match event { Event::WindowEvent { ref event, window_id, @@ -656,32 +652,30 @@ async fn run() { match event { WindowEvent::CloseRequested | WindowEvent::KeyboardInput { - input: - KeyboardInput { + event: + KeyEvent { state: ElementState::Pressed, - virtual_keycode: Some(VirtualKeyCode::Escape), + physical_key: PhysicalKey::Code(KeyCode::Escape), .. }, .. - } => *control_flow = ControlFlow::Exit, + } => control_flow.exit(), WindowEvent::Resized(physical_size) => { state.resize(*physical_size); } - WindowEvent::ScaleFactorChanged { new_inner_size, .. } => { - state.resize(**new_inner_size); + WindowEvent::RedrawRequested => { + state.window.request_redraw(); + let now = std::time::Instant::now(); + let dt = now - last_render_time; + last_render_time = now; + state.update(dt); + state.render(); } _ => {} } } } - Event::RedrawRequested(window_id) if window_id == state.window().id() => { - let now = std::time::Instant::now(); - let dt = now - last_render_time; - last_render_time = now; - state.update(dt); - state.render(); - } _ => {} - } - }); + }) + .unwrap(); } diff --git a/code/showcase/compute/src/model.rs b/code/showcase/compute/src/model.rs index 4d51142b..2c0fbc35 100644 --- a/code/showcase/compute/src/model.rs +++ b/code/showcase/compute/src/model.rs @@ -298,7 +298,10 @@ impl ModelLoader { m.mesh.positions[i * 3 + 2], ], // tex_coords: [m.mesh.texcoords[i * 2], m.mesh.texcoords[i * 2 + 1], 0.0] - tex_coords: [m.mesh.texcoords[i * 2], 1.0 - m.mesh.texcoords[i * 2 + 1]], + tex_coords: [ + m.mesh.texcoords[i * 2], + 1.0 - m.mesh.texcoords[i * 2 + 1], + ], normal: [ m.mesh.normals[i * 3], m.mesh.normals[i * 3 + 1], diff --git a/code/showcase/framework/src/camera.rs b/code/showcase/framework/src/camera.rs index 0dc592b7..66b92fd4 100644 --- a/code/showcase/framework/src/camera.rs +++ b/code/showcase/framework/src/camera.rs @@ -3,6 +3,7 @@ use std::f32::consts::FRAC_PI_2; use std::time::Duration; use winit::dpi::PhysicalPosition; use winit::event::*; +use winit::keyboard::KeyCode; #[rustfmt::skip] pub const OPENGL_TO_WGPU_MATRIX: cgmath::Matrix4 = cgmath::Matrix4::new( @@ -104,34 +105,34 @@ impl CameraController { } } - pub fn process_keyboard(&mut self, key: VirtualKeyCode, state: ElementState) -> bool { + pub fn process_keyboard(&mut self, key: KeyCode, state: ElementState) -> bool { let amount = if state == ElementState::Pressed { 1.0 } else { 0.0 }; match key { - VirtualKeyCode::W | VirtualKeyCode::Up => { + KeyCode::KeyW | KeyCode::ArrowUp => { self.amount_forward = amount; true } - VirtualKeyCode::S | VirtualKeyCode::Down => { + KeyCode::KeyS | KeyCode::ArrowDown => { self.amount_backward = amount; true } - VirtualKeyCode::A | VirtualKeyCode::Left => { + KeyCode::KeyA | KeyCode::ArrowLeft => { self.amount_left = amount; true } - VirtualKeyCode::D | VirtualKeyCode::Right => { + KeyCode::KeyD | KeyCode::ArrowRight => { self.amount_right = amount; true } - VirtualKeyCode::Space => { + KeyCode::Space => { self.amount_up = amount; true } - VirtualKeyCode::LShift => { + KeyCode::ShiftLeft => { self.amount_down = amount; true } diff --git a/code/showcase/framework/src/lib.rs b/code/showcase/framework/src/lib.rs index fb9cbc20..48b63cd6 100644 --- a/code/showcase/framework/src/lib.rs +++ b/code/showcase/framework/src/lib.rs @@ -21,24 +21,25 @@ use std::time::{Duration, Instant}; use wgpu::util::{BufferInitDescriptor, DeviceExt}; use winit::event::*; use winit::event_loop::{ControlFlow, EventLoop}; +use winit::keyboard::{KeyCode, PhysicalKey}; use winit::window::{Window, WindowBuilder}; -pub struct Display { - surface: wgpu::Surface, - pub window: Window, +pub struct Display<'a> { + surface: wgpu::Surface<'a>, + pub window: &'a Window, pub config: wgpu::SurfaceConfiguration, pub device: wgpu::Device, pub queue: wgpu::Queue, } -impl Display { - pub async fn new(window: Window) -> Result { +impl<'a> Display<'a> { + pub async fn new(window: &'a Window) -> Result, Error> { let size = window.inner_size(); let instance = wgpu::Instance::new(wgpu::InstanceDescriptor { backends: wgpu::Backends::all(), ..Default::default() }); - let surface = unsafe { instance.create_surface(&window) }.unwrap(); + let surface = instance.create_surface(window).unwrap(); let adapter = instance .request_adapter(&wgpu::RequestAdapterOptions { power_preference: wgpu::PowerPreference::default(), @@ -51,10 +52,10 @@ impl Display { .request_device( &wgpu::DeviceDescriptor { label: None, - features: wgpu::Features::empty(), + required_features: wgpu::Features::empty(), // WebGL doesn't support all of wgpu's features, so if // we're building for the web we'll have to disable some. - limits: if cfg!(target_arch = "wasm32") { + required_limits: if cfg!(target_arch = "wasm32") { wgpu::Limits::downlevel_webgl2_defaults() } else { wgpu::Limits::default() @@ -82,6 +83,7 @@ impl Display { present_mode: surface_caps.present_modes[0], alpha_mode: surface_caps.alpha_modes[0], view_formats: vec![], + desired_maximum_frame_latency: 2, }; surface.configure(&device, &config); @@ -214,7 +216,7 @@ impl UniformBinding { pub trait Demo: 'static + Sized { fn init(display: &Display) -> Result; fn process_mouse(&mut self, dx: f64, dy: f64); - fn process_keyboard(&mut self, key: VirtualKeyCode, pressed: bool); + fn process_keyboard(&mut self, key: KeyCode, pressed: bool); fn resize(&mut self, display: &Display); fn update(&mut self, display: &Display, dt: Duration); fn render(&mut self, display: &mut Display); @@ -223,74 +225,71 @@ pub trait Demo: 'static + Sized { pub async fn run() -> Result<(), Error> { wgpu_subscriber::initialize_default_subscriber(None); - let event_loop = EventLoop::new(); + let event_loop = EventLoop::new().unwrap(); let window = WindowBuilder::new() .with_title(env!("CARGO_PKG_NAME")) .build(&event_loop)?; - let mut display = Display::new(window).await?; + let mut display = Display::new(&window).await?; let mut demo = D::init(&display)?; let mut last_update = Instant::now(); let mut is_resumed = true; let mut is_focused = true; let mut is_redraw_requested = true; - event_loop.run(move |event, _, control_flow| { - *control_flow = if is_resumed && is_focused { - ControlFlow::Poll + event_loop.run(move |event, control_flow| { + if is_resumed && is_focused { + control_flow.set_control_flow(ControlFlow::Poll) } else { - ControlFlow::Wait + control_flow.set_control_flow(ControlFlow::Wait) }; match event { Event::Resumed => is_resumed = true, Event::Suspended => is_resumed = false, - Event::RedrawRequested(wid) => { - if wid == display.window().id() { - let now = Instant::now(); - let dt = now - last_update; - last_update = now; - - demo.update(&display, dt); - demo.render(&mut display); - is_redraw_requested = false; - } - } - Event::MainEventsCleared => { - if is_focused && is_resumed && !is_redraw_requested { - display.window().request_redraw(); - is_redraw_requested = true; - } else { - // Freeze time while the demo is not in the foreground - last_update = Instant::now(); - } - } Event::WindowEvent { event, window_id, .. } => { if window_id == display.window().id() { match event { - WindowEvent::CloseRequested => *control_flow = ControlFlow::Exit, + WindowEvent::CloseRequested => control_flow.exit(), WindowEvent::Focused(f) => is_focused = f, - WindowEvent::ScaleFactorChanged { new_inner_size, .. } => { - display.resize(new_inner_size.width, new_inner_size.height); - demo.resize(&display); - } WindowEvent::Resized(new_inner_size) => { display.resize(new_inner_size.width, new_inner_size.height); demo.resize(&display); } - WindowEvent::KeyboardInput { input: KeyboardInput { - virtual_keycode: Some(key), - state, + WindowEvent::KeyboardInput { + event: + KeyEvent { + physical_key: PhysicalKey::Code(key), + state, + .. + }, .. - }, .. } => { + } => { demo.process_keyboard(key, state == ElementState::Pressed); } + WindowEvent::RedrawRequested => { + let now = Instant::now(); + let dt = now - last_update; + last_update = now; + + demo.update(&display, dt); + demo.render(&mut display); + + if is_focused && is_resumed { + display.window().request_redraw(); + } else { + // Freeze time while the demo is not in the foreground + last_update = Instant::now(); + } + } _ => {} } } } _ => {} } - }); + })?; + + Ok(()) } diff --git a/code/showcase/framework/src/texture.rs b/code/showcase/framework/src/texture.rs index 23893ddb..4bde2f6f 100644 --- a/code/showcase/framework/src/texture.rs +++ b/code/showcase/framework/src/texture.rs @@ -1,7 +1,7 @@ use anyhow::*; use image::GenericImageView; -use std::path::Path; use std::mem; +use std::path::Path; use crate::buffer; diff --git a/code/showcase/gifs/src/main.rs b/code/showcase/gifs/src/main.rs index 9d9d690f..b2bbbad1 100644 --- a/code/showcase/gifs/src/main.rs +++ b/code/showcase/gifs/src/main.rs @@ -16,10 +16,10 @@ async fn run() { .request_device( &wgpu::DeviceDescriptor { label: Some("Device"), - features: wgpu::Features::empty(), + required_features: wgpu::Features::empty(), // WebGL doesn't support all of wgpu's features, so if // we're building for the web we'll have to disable some. - limits: if cfg!(target_arch = "wasm32") { + required_limits: if cfg!(target_arch = "wasm32") { wgpu::Limits::downlevel_webgl2_defaults() } else { wgpu::Limits::default() diff --git a/code/showcase/lost-window/src/main.rs b/code/showcase/lost-window/src/main.rs index d0f898f0..54139ed7 100644 --- a/code/showcase/lost-window/src/main.rs +++ b/code/showcase/lost-window/src/main.rs @@ -7,7 +7,7 @@ use winit::{ }; async fn run() -> anyhow::Result<()> { - let event_loop = EventLoop::new(); + let event_loop = EventLoop::new().unwrap(); let mut window = Some( WindowBuilder::new() .with_visible(false) @@ -31,7 +31,7 @@ async fn run() -> anyhow::Result<()> { &wgpu::DeviceDescriptor { label: None, features: Default::default(), - limits: Default::default(), + required_limits: Default::default(), }, None, ) diff --git a/code/showcase/mouse-picking/src/camera.rs b/code/showcase/mouse-picking/src/camera.rs index 0dc592b7..66b92fd4 100644 --- a/code/showcase/mouse-picking/src/camera.rs +++ b/code/showcase/mouse-picking/src/camera.rs @@ -3,6 +3,7 @@ use std::f32::consts::FRAC_PI_2; use std::time::Duration; use winit::dpi::PhysicalPosition; use winit::event::*; +use winit::keyboard::KeyCode; #[rustfmt::skip] pub const OPENGL_TO_WGPU_MATRIX: cgmath::Matrix4 = cgmath::Matrix4::new( @@ -104,34 +105,34 @@ impl CameraController { } } - pub fn process_keyboard(&mut self, key: VirtualKeyCode, state: ElementState) -> bool { + pub fn process_keyboard(&mut self, key: KeyCode, state: ElementState) -> bool { let amount = if state == ElementState::Pressed { 1.0 } else { 0.0 }; match key { - VirtualKeyCode::W | VirtualKeyCode::Up => { + KeyCode::KeyW | KeyCode::ArrowUp => { self.amount_forward = amount; true } - VirtualKeyCode::S | VirtualKeyCode::Down => { + KeyCode::KeyS | KeyCode::ArrowDown => { self.amount_backward = amount; true } - VirtualKeyCode::A | VirtualKeyCode::Left => { + KeyCode::KeyA | KeyCode::ArrowLeft => { self.amount_left = amount; true } - VirtualKeyCode::D | VirtualKeyCode::Right => { + KeyCode::KeyD | KeyCode::ArrowRight => { self.amount_right = amount; true } - VirtualKeyCode::Space => { + KeyCode::Space => { self.amount_up = amount; true } - VirtualKeyCode::LShift => { + KeyCode::ShiftLeft => { self.amount_down = amount; true } diff --git a/code/showcase/mouse-picking/src/lib.rs b/code/showcase/mouse-picking/src/lib.rs index d6ff79b8..c7dbd263 100644 --- a/code/showcase/mouse-picking/src/lib.rs +++ b/code/showcase/mouse-picking/src/lib.rs @@ -6,6 +6,7 @@ use wgpu::util::DeviceExt; use winit::{ event::*, event_loop::{ControlFlow, EventLoop}, + keyboard::{KeyCode, PhysicalKey}, window::Window, }; @@ -131,9 +132,9 @@ struct LightUniform { _padding2: u32, } -struct State { - window: Window, - surface: wgpu::Surface, +struct State<'a> { + window: &'a Window, + surface: wgpu::Surface<'a>, device: wgpu::Device, queue: wgpu::Queue, config: wgpu::SurfaceConfiguration, @@ -224,8 +225,8 @@ fn create_render_pipeline( }) } -impl State { - async fn new(window: Window) -> Self { +impl<'a> State<'a> { + async fn new(window: &'a Window) -> State<'a> { let size = window.inner_size(); // The instance is a handle to our GPU @@ -235,11 +236,7 @@ impl State { ..Default::default() }); - // # Safety - // - // The surface needs to live as long as the window that created it. - // State owns the window so this should be safe. - let surface = unsafe { instance.create_surface(&window) }.unwrap(); + let surface = instance.create_surface(window).unwrap(); let adapter = instance .request_adapter(&wgpu::RequestAdapterOptions { @@ -253,10 +250,10 @@ impl State { .request_device( &wgpu::DeviceDescriptor { label: None, - features: wgpu::Features::empty(), + required_features: wgpu::Features::empty(), // WebGL doesn't support all of wgpu's features, so if // we're building for the web we'll have to disable some. - limits: if cfg!(target_arch = "wasm32") { + required_limits: if cfg!(target_arch = "wasm32") { wgpu::Limits::downlevel_webgl2_defaults() } else { wgpu::Limits::default() @@ -285,6 +282,7 @@ impl State { present_mode: surface_caps.present_modes[0], alpha_mode: surface_caps.alpha_modes[0], view_formats: vec![], + desired_maximum_frame_latency: 2, }; surface.configure(&device, &config); @@ -577,9 +575,9 @@ impl State { fn input(&mut self, event: &WindowEvent) -> bool { match event { WindowEvent::KeyboardInput { - input: - KeyboardInput { - virtual_keycode: Some(key), + event: + KeyEvent { + physical_key: PhysicalKey::Code(key), state, .. }, @@ -733,7 +731,7 @@ pub async fn run() { } } - let event_loop = EventLoop::new(); + let event_loop = EventLoop::new().unwrap(); let title = env!("CARGO_PKG_NAME"); let window = winit::window::WindowBuilder::new() .with_title(title) @@ -759,12 +757,10 @@ pub async fn run() { .expect("Couldn't append canvas to document body."); } - let mut state = State::new(window).await; // NEW! + let mut state = State::new(&window).await; // NEW! let mut last_render_time = instant::Instant::now(); - event_loop.run(move |event, _, control_flow| { - *control_flow = ControlFlow::Poll; + event_loop.run(move |event, control_flow| { match event { - Event::MainEventsCleared => state.window().request_redraw(), // NEW! Event::DeviceEvent { event: DeviceEvent::MouseMotion{ delta, }, @@ -781,40 +777,38 @@ pub async fn run() { #[cfg(not(target_arch="wasm32"))] WindowEvent::CloseRequested | WindowEvent::KeyboardInput { - input: - KeyboardInput { + event: + KeyEvent { state: ElementState::Pressed, - virtual_keycode: Some(VirtualKeyCode::Escape), + physical_key: PhysicalKey::Code(KeyCode::Escape), .. }, .. - } => *control_flow = ControlFlow::Exit, + } => control_flow.exit(), WindowEvent::Resized(physical_size) => { state.resize(*physical_size); } - WindowEvent::ScaleFactorChanged { new_inner_size, .. } => { - state.resize(**new_inner_size); + // UPDATED! + WindowEvent::RedrawRequested => { + state.window.request_redraw(); + let now = instant::Instant::now(); + let dt = now - last_render_time; + last_render_time = now; + state.update(dt); + match state.render() { + Ok(_) => {} + // Reconfigure the surface if it's lost or outdated + Err(wgpu::SurfaceError::Lost | wgpu::SurfaceError::Outdated) => state.resize(state.size), + // The system is out of memory, we should probably quit + Err(wgpu::SurfaceError::OutOfMemory) => control_flow.exit(), + // We're ignoring timeouts + Err(wgpu::SurfaceError::Timeout) => log::warn!("Surface timeout"), + } } _ => {} } } - // UPDATED! - Event::RedrawRequested(window_id) if window_id == state.window().id() => { - let now = instant::Instant::now(); - let dt = now - last_render_time; - last_render_time = now; - state.update(dt); - match state.render() { - Ok(_) => {} - // Reconfigure the surface if it's lost or outdated - Err(wgpu::SurfaceError::Lost | wgpu::SurfaceError::Outdated) => state.resize(state.size), - // The system is out of memory, we should probably quit - Err(wgpu::SurfaceError::OutOfMemory) => *control_flow = ControlFlow::Exit, - // We're ignoring timeouts - Err(wgpu::SurfaceError::Timeout) => log::warn!("Surface timeout"), - } - } _ => {} } - }); + }).unwrap(); } diff --git a/code/showcase/pong/src/lib.rs b/code/showcase/pong/src/lib.rs index 98d582a7..cdb8fca0 100644 --- a/code/showcase/pong/src/lib.rs +++ b/code/showcase/pong/src/lib.rs @@ -27,7 +27,7 @@ pub fn start() { } } - let event_loop = EventLoop::new(); + let event_loop = EventLoop::new().unwrap(); let monitor = event_loop.primary_monitor().unwrap(); let video_mode = monitor.video_modes().next(); let size = video_mode @@ -159,7 +159,7 @@ pub fn start() { log::info!("Event Loop..."); - event_loop.run(move |event, _, control_flow| { + event_loop.run(move |event, control_flow| { *control_flow = if state.game_state == state::GameState::Quiting { ControlFlow::Exit } else { diff --git a/code/showcase/pong/src/render/mod.rs b/code/showcase/pong/src/render/mod.rs index 2cda1e9b..f5c6d9f7 100644 --- a/code/showcase/pong/src/render/mod.rs +++ b/code/showcase/pong/src/render/mod.rs @@ -45,11 +45,7 @@ impl Render { ..Default::default() }); - // # Safety - // - // The surface needs to live as long as the window that created it. - // State owns the window so this should be safe. - let surface = unsafe { instance.create_surface(&window) }.unwrap(); + let surface = instance.create_surface(window).unwrap(); let adapter = instance .request_adapter(&wgpu::RequestAdapterOptions { @@ -63,8 +59,8 @@ impl Render { .request_device( &wgpu::DeviceDescriptor { label: None, - features: wgpu::Features::empty(), - limits: wgpu::Limits::downlevel_webgl2_defaults(), + required_features: wgpu::Features::empty(), + required_limits: wgpu::Limits::downlevel_webgl2_defaults(), }, None, // Trace path ) @@ -89,6 +85,7 @@ impl Render { present_mode: surface_caps.present_modes[0], alpha_mode: surface_caps.alpha_modes[0], view_formats: vec![], + desired_maximum_frame_latency: 2, }; surface.configure(&device, &config); diff --git a/code/showcase/snow/src/camera.rs b/code/showcase/snow/src/camera.rs index 2fc03a21..e9ce29ae 100644 --- a/code/showcase/snow/src/camera.rs +++ b/code/showcase/snow/src/camera.rs @@ -1,6 +1,9 @@ -use std::{time::Duration, f32::consts::FRAC_PI_2}; +use std::{f32::consts::FRAC_PI_2, time::Duration}; -use winit::{event::{VirtualKeyCode, MouseScrollDelta}, dpi::PhysicalPosition}; +use winit::{ + dpi::PhysicalPosition, + event::{MouseScrollDelta, VirtualKeyCode}, +}; const SAFE_FRAC_PI_2: f32 = FRAC_PI_2 - 0.0001; @@ -12,11 +15,7 @@ pub struct Camera { } impl Camera { - pub fn new>( - position: V, - yaw: f32, - pitch: f32, - ) -> Self { + pub fn new>(position: V, yaw: f32, pitch: f32) -> Self { Self { position: position.into(), yaw, @@ -95,11 +94,7 @@ impl CameraController { } pub fn process_keyboard(&mut self, key: VirtualKeyCode, pressed: bool) -> bool { - let amount = if pressed { - 1.0 - } else { - 0.0 - }; + let amount = if pressed { 1.0 } else { 0.0 }; match key { VirtualKeyCode::W | VirtualKeyCode::Up => { self.amount_forward = amount; @@ -183,4 +178,4 @@ impl CameraController { camera.pitch = SAFE_FRAC_PI_2; } } -} \ No newline at end of file +} diff --git a/code/showcase/snow/src/main.rs b/code/showcase/snow/src/main.rs index 5be6ed65..bfeecf35 100644 --- a/code/showcase/snow/src/main.rs +++ b/code/showcase/snow/src/main.rs @@ -2,7 +2,7 @@ mod camera; use std::f32::consts::PI; -use camera::{Camera, Projection, CameraController}; +use camera::{Camera, CameraController, Projection}; use wgpu::util::{BufferInitDescriptor, DeviceExt}; const MAX_PARTICLES: u32 = 1000; @@ -181,21 +181,25 @@ impl framework::Demo for Snow { entries: &[wgpu::BindGroupLayoutEntry { binding: 0, visibility: wgpu::ShaderStages::VERTEX, - ty: wgpu::BindingType::Buffer { ty: wgpu::BufferBindingType::Uniform, has_dynamic_offset: false, min_binding_size: None }, + ty: wgpu::BindingType::Buffer { + ty: wgpu::BufferBindingType::Uniform, + has_dynamic_offset: false, + min_binding_size: None, + }, count: None, }], }); - let uniforms_bind_group = display.device.create_bind_group(&wgpu::BindGroupDescriptor { - label: Some("uniforms_bind_group"), - layout: &uniforms_bind_group_layout, - entries: &[ - wgpu::BindGroupEntry { + let uniforms_bind_group = display + .device + .create_bind_group(&wgpu::BindGroupDescriptor { + label: Some("uniforms_bind_group"), + layout: &uniforms_bind_group_layout, + entries: &[wgpu::BindGroupEntry { binding: 0, resource: uniform_buffer.as_entire_binding(), - } - ], - }); + }], + }); let draw_particles_layout = display @@ -260,14 +264,15 @@ impl framework::Demo for Snow { self.camera_controller.process_mouse(dx, dy); self.uniforms_dirty = true; } - + fn process_keyboard(&mut self, key: winit::event::VirtualKeyCode, pressed: bool) { self.camera_controller.process_keyboard(key, pressed); self.uniforms_dirty = true; } fn resize(&mut self, display: &framework::Display) { - self.projection.resize(display.config.width, display.config.height); + self.projection + .resize(display.config.width, display.config.height); self.uniforms_dirty = true; self.uniforms_dirty = true; } @@ -278,7 +283,9 @@ impl framework::Demo for Snow { self.uniforms_dirty = false; self.camera_controller.update_camera(&mut self.camera, dt); self.uniforms.view_proj = self.projection.calc_matrix() * self.camera.calc_matrix(); - display.queue.write_buffer(&self.uniform_buffer, 0, bytemuck::bytes_of(&self.uniforms)); + display + .queue + .write_buffer(&self.uniform_buffer, 0, bytemuck::bytes_of(&self.uniforms)); } let dt = dt.as_secs_f32(); diff --git a/code/showcase/threading/src/camera.rs b/code/showcase/threading/src/camera.rs index 29092be4..66b92fd4 100644 --- a/code/showcase/threading/src/camera.rs +++ b/code/showcase/threading/src/camera.rs @@ -1,9 +1,9 @@ use cgmath::*; -use winit::keyboard::KeyCode; use std::f32::consts::FRAC_PI_2; use std::time::Duration; use winit::dpi::PhysicalPosition; use winit::event::*; +use winit::keyboard::KeyCode; #[rustfmt::skip] pub const OPENGL_TO_WGPU_MATRIX: cgmath::Matrix4 = cgmath::Matrix4::new( diff --git a/docs/beginner/tutorial1-window/README.md b/docs/beginner/tutorial1-window/README.md index 6d58c1ad..d1e66f51 100644 --- a/docs/beginner/tutorial1-window/README.md +++ b/docs/beginner/tutorial1-window/README.md @@ -39,7 +39,7 @@ use winit::{ pub fn run() { env_logger::init(); - let event_loop = EventLoop::new(); + let event_loop = EventLoop::new().unwrap(); let window = WindowBuilder::new().build(&event_loop).unwrap(); event_loop.run(move |event, _, control_flow| match event { diff --git a/docs/beginner/tutorial2-surface/README.md b/docs/beginner/tutorial2-surface/README.md index 7b2d7f81..3567b7c7 100644 --- a/docs/beginner/tutorial2-surface/README.md +++ b/docs/beginner/tutorial2-surface/README.md @@ -7,8 +7,8 @@ For convenience, we're going to pack all the fields into a struct and create som // lib.rs use winit::window::Window; -struct State { - surface: wgpu::Surface, +struct State<'a> { + surface: wgpu::Surface<'a>, device: wgpu::Device, queue: wgpu::Queue, config: wgpu::SurfaceConfiguration, @@ -16,12 +16,12 @@ struct State { // The window must be declared after the surface so // it gets dropped after it as the surface contains // unsafe references to the window's resources. - window: Window, + window: &'a Window, } -impl State { +impl<'a> State<'a> { // Creating some of the wgpu types requires async code - async fn new(window: Window) -> Self { + async fn new(window: &'a Window) -> State<'a> { todo!() } @@ -53,9 +53,9 @@ I'm glossing over `State`s fields, but they'll make more sense as I explain the The code for this is pretty straightforward, but let's break it down a bit. ```rust -impl State { +impl<'a> State<'a> { // ... - async fn new(window: Window) -> Self { + async fn new(window: &'a Window) -> State<'a> { let size = window.inner_size(); // The instance is a handle to our GPU @@ -127,10 +127,10 @@ Let's use the `adapter` to create the device and queue. ```rust let (device, queue) = adapter.request_device( &wgpu::DeviceDescriptor { - features: wgpu::Features::empty(), + required_features: wgpu::Features::empty(), // WebGL doesn't support all of wgpu's features, so if // we're building for the web, we'll have to disable some. - limits: if cfg!(target_arch = "wasm32") { + required_limits: if cfg!(target_arch = "wasm32") { wgpu::Limits::downlevel_webgl2_defaults() } else { wgpu::Limits::default() @@ -145,7 +145,7 @@ The `features` field on `DeviceDescriptor` allows us to specify what extra featu
-The graphics card you have limits the features you can use. If you want to use certain features, you may need to limit what devices you support or provide workarounds. +The graphics card you haverequired_limits the features you can use. If you want to use certain features, you may need to limit what devices you support or provide workarounds. You can get a list of features supported by your device using `adapter.features()` or `device.features()`. @@ -153,7 +153,7 @@ You can view a full list of features [here](https://docs.rs/wgpu/latest/wgpu/str
-The `limits` field describes the limit of certain types of resources that we can create. We'll use the defaults for this tutorial so we can support most devices. You can view a list of limits [here](https://docs.rs/wgpu/latest/wgpu/struct.Limits.html). +The `limits` field describes the limit of certain types of resources that we can create. We'll use the defaults for this tutorial so we can support most devices. You can view a list ofrequired_limits [here](https://docs.rs/wgpu/latest/wgpu/struct.Limits.html). ```rust let surface_caps = surface.get_capabilities(&adapter); @@ -173,6 +173,7 @@ The `limits` field describes the limit of certain types of resources that we can present_mode: surface_caps.present_modes[0], alpha_mode: surface_caps.alpha_modes[0], view_formats: vec![], + desired_maximum_frame_latency: 2, }; surface.configure(&device, &config); ``` @@ -210,7 +211,7 @@ Regardless, `PresentMode::Fifo` will always be supported, and `PresentMode::Auto Now that we've configured our surface properly, we can add these new fields at the end of the method. ```rust - async fn new(window: Window) -> Self { + async fn new(window: &'a Window) -> State<'a> { // ... Self { @@ -233,9 +234,9 @@ Our `window` has beened moved to the State instance, we will need to update our pub async fn run() { // Window setup... - let mut state = State::new(window).await; + let mut state = State::new(&window).await; - event_loop.run(move |event, _, control_flow| { + event_loop.run(move |event, control_flow| { match event { Event::WindowEvent { ref event, diff --git a/docs/beginner/tutorial3-pipeline/README.md b/docs/beginner/tutorial3-pipeline/README.md index 4e46fd3b..1f6e113d 100644 --- a/docs/beginner/tutorial3-pipeline/README.md +++ b/docs/beginner/tutorial3-pipeline/README.md @@ -156,8 +156,8 @@ This is the part where we finally make the thing in the title: the pipeline. Fir ```rust // lib.rs -struct State { - surface: wgpu::Surface, +struct State<'a> { + surface: wgpu::Surface<'a>, device: wgpu::Device, queue: wgpu::Queue, config: wgpu::SurfaceConfiguration, diff --git a/docs/beginner/tutorial4-buffer/README.md b/docs/beginner/tutorial4-buffer/README.md index 0055eb5e..860a280a 100644 --- a/docs/beginner/tutorial4-buffer/README.md +++ b/docs/beginner/tutorial4-buffer/README.md @@ -247,7 +247,7 @@ struct State { num_vertices: u32, } -impl State { +impl<'a> State<'a> { // ... fn new(...) -> Self { // ... @@ -380,8 +380,8 @@ let num_indices = INDICES.len() as u32; We don't need to implement `Pod` and `Zeroable` for our indices because `bytemuck` has already implemented them for basic types such as `u16`. That means we can just add `index_buffer` and `num_indices` to the `State` struct. ```rust -struct State { - surface: wgpu::Surface, +struct State<'a> { + surface: wgpu::Surface<'a>, device: wgpu::Device, queue: wgpu::Queue, config: wgpu::SurfaceConfiguration, diff --git a/docs/beginner/tutorial5-textures/README.md b/docs/beginner/tutorial5-textures/README.md index 13f59c27..4432f7d2 100644 --- a/docs/beginner/tutorial5-textures/README.md +++ b/docs/beginner/tutorial5-textures/README.md @@ -242,8 +242,8 @@ Looking at this, you might get a bit of déjà vu! That's because a `BindGroup` Now that we have our `diffuse_bind_group`, let's add it to our `State` struct: ```rust -struct State { - surface: wgpu::Surface, +struct State<'a> { + surface: wgpu::Surface<'a>, device: wgpu::Device, queue: wgpu::Queue, config: wgpu::SurfaceConfiguration, @@ -259,7 +259,7 @@ struct State { Make sure we return these fields in the `new` method: ```rust -impl State { +impl<'a> State<'a> { async fn new() -> Self { // ... Self { @@ -593,7 +593,7 @@ struct State { ``` ```rust -impl State { +impl<'a> State<'a> { async fn new() -> Self { // ... Self { diff --git a/docs/beginner/tutorial6-uniforms/README.md b/docs/beginner/tutorial6-uniforms/README.md index d1819497..1df38f4a 100644 --- a/docs/beginner/tutorial6-uniforms/README.md +++ b/docs/beginner/tutorial6-uniforms/README.md @@ -310,20 +310,19 @@ impl CameraController { .. } => { let is_pressed = *state == ElementState::Pressed; - match keycode { - VirtualKeyCode::W | VirtualKeyCode::Up => { + match keycode {KeyCode::KeyW | KeyCode::ArrowUp => { self.is_forward_pressed = is_pressed; true } - VirtualKeyCode::A | VirtualKeyCode::Left => { + KeyCode::KeyA | KeyCode::ArrowLeft => { self.is_left_pressed = is_pressed; true } - VirtualKeyCode::S | VirtualKeyCode::Down => { + KeyCode::KeyS | KeyCode::ArrowDown => { self.is_backward_pressed = is_pressed; true } - VirtualKeyCode::D | VirtualKeyCode::Right => { + KeyCode::KeyD | KeyCode::ArrowRight => { self.is_right_pressed = is_pressed; true } @@ -381,8 +380,8 @@ struct State { // ... } // ... -impl State { - async fn new(window: Window) -> Self { +impl<'a> State<'a> { + async fn new(window: &'a Window) -> State<'a> { // ... let camera_controller = CameraController::new(0.2); // ... diff --git a/docs/beginner/tutorial7-instancing/README.md b/docs/beginner/tutorial7-instancing/README.md index 8490f601..09c90c99 100644 --- a/docs/beginner/tutorial7-instancing/README.md +++ b/docs/beginner/tutorial7-instancing/README.md @@ -97,8 +97,8 @@ const INSTANCE_DISPLACEMENT: cgmath::Vector3 = cgmath::Vector3::new(NUM_INS Now, we can create the actual instances. ```rust -impl State { - async fn new(window: Window) -> Self { +impl<'a> State<'a> { + async fn new(window: &'a Window) -> State<'a> { // ... let instances = (0..NUM_INSTANCES_PER_ROW).flat_map(|z| { (0..NUM_INSTANCES_PER_ROW).map(move |x| { diff --git a/docs/intermediate/tutorial10-lighting/README.md b/docs/intermediate/tutorial10-lighting/README.md index ba63b95e..a660cea7 100644 --- a/docs/intermediate/tutorial10-lighting/README.md +++ b/docs/intermediate/tutorial10-lighting/README.md @@ -453,7 +453,7 @@ where Finally, we want to add Light rendering to our render passes. ```rust -impl State { +impl<'a> State<'a> { // ... fn render(&mut self) -> Result<(), wgpu::SurfaceError> { // ... diff --git a/docs/intermediate/tutorial11-normals/README.md b/docs/intermediate/tutorial11-normals/README.md index 8d42d5d1..c789a055 100644 --- a/docs/intermediate/tutorial11-normals/README.md +++ b/docs/intermediate/tutorial11-normals/README.md @@ -568,7 +568,7 @@ I found a cobblestone texture with a matching normal map and created a `debug_ma ```rust // lib.rs -impl State { +impl<'a> State<'a> { async fn new(window: &Window) -> Result { // ... let debug_material = { diff --git a/docs/intermediate/tutorial12-camera/README.md b/docs/intermediate/tutorial12-camera/README.md index c6f43d80..21f779fe 100644 --- a/docs/intermediate/tutorial12-camera/README.md +++ b/docs/intermediate/tutorial12-camera/README.md @@ -293,8 +293,8 @@ You'll need to import `winit::dpi::PhysicalPosition` if you haven't already. We need to update `new()` as well. ```rust -impl State { - async fn new(window: Window) -> Self { +impl<'a> State<'a> { + async fn new(window: &'a Window) -> State<'a> { // ... // UPDATED! @@ -369,8 +369,7 @@ Here are the changes to `run()`: ```rust fn main() { // ... - event_loop.run(move |event, _, control_flow| { - *control_flow = ControlFlow::Poll; + event_loop.run(move |event, control_flow| { match event { // ... // NEW! @@ -389,14 +388,14 @@ fn main() { #[cfg(not(target_arch="wasm32"))] WindowEvent::CloseRequested | WindowEvent::KeyboardInput { - input: - KeyboardInput { + event: + KeyEvent { state: ElementState::Pressed, - virtual_keycode: Some(VirtualKeyCode::Escape), + physical_key: PhysicalKey::Code(KeyCode::Escape), .. }, .. - } => *control_flow = ControlFlow::Exit, + } => control_flow.exit(), WindowEvent::Resized(physical_size) => { state.resize(*physical_size); } @@ -437,10 +436,9 @@ We still need to calculate `dt`. Let's do that in the `main` function. ```rust fn main() { // ... - let mut state = State::new(window).await; + let mut state = State::new(&window).await; let mut last_render_time = instant::Instant::now(); // NEW! - event_loop.run(move |event, _, control_flow| { - *control_flow = ControlFlow::Poll; + event_loop.run(move |event, control_flow| { match event { // ... // UPDATED! diff --git a/docs/intermediate/tutorial13-hdr/readme.md b/docs/intermediate/tutorial13-hdr/readme.md index 2cc81025..24887d5e 100644 --- a/docs/intermediate/tutorial13-hdr/readme.md +++ b/docs/intermediate/tutorial13-hdr/readme.md @@ -1,6 +1,6 @@ # High Dynamic Range Rendering -Up to this point, we've been using the sRGB colorspace to render our scene. While this is fine, it limits what we can do with our lighting. We are using `TextureFormat::Bgra8UnormSrgb` (on most systems) for our surface texture. This means we have 8 bits for each red, green, blue and alpha channel. While the channels are stored as integers between 0 and 255 inclusively, they get converted to and from floating point values between 0.0 and 1.0. The TL:DR of this is that using 8-bit textures, we only get 256 possible values in each channel. +Up to this point, we've been using the sRGB colorspace to render our scene. While this is fine, itrequired_limits what we can do with our lighting. We are using `TextureFormat::Bgra8UnormSrgb` (on most systems) for our surface texture. This means we have 8 bits for each red, green, blue and alpha channel. While the channels are stored as integers between 0 and 255 inclusively, they get converted to and from floating point values between 0.0 and 1.0. The TL:DR of this is that using 8-bit textures, we only get 256 possible values in each channel. The kicker with this is most of the precision gets used to represent darker values of the scene. This means that bright objects like light bulbs have the same value as exceedingly bright objects like the sun. This inaccuracy makes realistic lighting difficult to do right. Because of this, we are going to switch our rendering system to use high dynamic range in order to give our scene more flexibility and enable us to leverage more advanced techniques such as Physically Based Rendering. @@ -290,7 +290,7 @@ struct State { hdr: hdr::HdrPipeline, } -impl State { +impl<'a> State<'a> { pub fn new(window: Window) -> anyhow::Result { // ... // NEW! @@ -477,7 +477,7 @@ let (device, queue) = adapter // UPDATED! features: wgpu::Features::all_webgpu_mask(), // UPDATED! - limits: wgpu::Limits::downlevel_defaults(), + required_limits: wgpu::Limits::downlevel_defaults(), }, None, // Trace path ) @@ -910,8 +910,8 @@ struct State { } // ... -impl State { - async fn new(window: Window) -> anyhow::Result { +impl<'a> State<'a> { + async fn new(window: &'a Window) -> anyhow::Result> { // ... Ok(Self { // ...