From 2e326306d9d626e67ba748a1c01bf47c0e7e8ae3 Mon Sep 17 00:00:00 2001 From: Steins7 Date: Sat, 22 Oct 2022 22:24:23 +0200 Subject: [PATCH] Clean up frame implementation Sprites no longer need to handle the frame creation as it is fully handled by the renderer itself. The fields order in the renderer have also been swapped to drop things in the right order --- src/canvas.rs | 5 +- src/main.rs | 2 +- src/renderer.rs | 140 ++++++++++++++++++++++++----------- src/sprite/texture_sprite.rs | 27 ++----- 4 files changed, 106 insertions(+), 68 deletions(-) diff --git a/src/canvas.rs b/src/canvas.rs index c9216c1..e93196f 100644 --- a/src/canvas.rs +++ b/src/canvas.rs @@ -27,9 +27,10 @@ pub trait Application { //--Canvas struct----------------------------------------------------------------------------------- pub struct Canvas { - renderer: WgpuRenderer, - clear_color: Pixel, default_texture: TextureHandle, + clear_color: Pixel, + + renderer: WgpuRenderer, } impl Canvas { diff --git a/src/main.rs b/src/main.rs index 29b709e..d842145 100644 --- a/src/main.rs +++ b/src/main.rs @@ -30,7 +30,7 @@ fn setup_logger() -> Result<(), fern::InitError> { message )) }) - .level(log::LevelFilter::Info) + .level(log::LevelFilter::Debug) .chain(std::io::stdout()) .chain(fern::log_file("output.log")?) .apply()?; Ok(()) diff --git a/src/renderer.rs b/src/renderer.rs index ff8e644..7e7a61b 100644 --- a/src/renderer.rs +++ b/src/renderer.rs @@ -22,21 +22,22 @@ pub use matrix::ModelMatrix as ModelMatrix; //--Renderer struct--------------------------------------------------------------------------------- pub struct WgpuRenderer { - surface: wgpu::Surface, - pub device: wgpu::Device, - pub queue: wgpu::Queue, - pub config: wgpu::SurfaceConfiguration, - - surface_size: Size, - pub output: Option, - - pub matrix_layout: wgpu::BindGroupLayout, - pub texture_layout: wgpu::BindGroupLayout, #[allow(dead_code)] shape_render_pipeline: wgpu::RenderPipeline, #[allow(dead_code)] quad_mesh: GpuMesh, //TODO temporary, to be moved to shapes.rs + + pub texture_layout: wgpu::BindGroupLayout, + pub matrix_layout: wgpu::BindGroupLayout, + + frame: Option, + surface: wgpu::Surface, + surface_size: Size, + + pub config: wgpu::SurfaceConfiguration, + pub queue: wgpu::Queue, + pub device: wgpu::Device, } impl WgpuRenderer { @@ -92,8 +93,8 @@ impl WgpuRenderer { // Matrix3::from_nonuniform_scale(1.0, 1.0) //}; - let output = Some(surface.get_current_texture() - .map_err(|_| "Failed to create SurfaceTexture")?); + let frame = Some(surface.get_current_texture() + .map_err(|_| "Failed to create frame")?); let matrix_layout = utils::new_matrix_layout(&device); let texture_layout = utils::new_texture_layout(&device); @@ -174,16 +175,19 @@ impl WgpuRenderer { }; Ok(Self { - surface, - device, - queue, - config, - surface_size, - output, - matrix_layout, - texture_layout, shape_render_pipeline, quad_mesh, + + texture_layout, + matrix_layout, + + frame, + surface, + surface_size, + + config, + queue, + device, }) } @@ -193,15 +197,7 @@ impl WgpuRenderer { pub fn clear(&mut self, color: Pixel) { - let output = match &self.output { - Some(out) => out, - None => { - self.create_output(); - &self.output.as_ref().unwrap() - }, - }; - - let view = output.texture.create_view(&wgpu::TextureViewDescriptor::default()); + let view = self.create_texture_view(); let mut encoder = self.device.create_command_encoder(&wgpu::CommandEncoderDescriptor { label: Some("Clear Encoder"), }); @@ -224,37 +220,86 @@ impl WgpuRenderer { self.queue.submit(std::iter::once(encoder.finish())); } + /// Resizes the render area to fit the given size. + /// + /// The current frame is dropped, clearing any of the rendering done. The underlying surface is + /// then reconfigured to the right size before a new frame can be created. + /// + /// # Panics + /// + /// The function will panic is the given size has any of its values equal to 0 or if the + /// renderer fails to create a new frame pub fn resize(&mut self, size: Size) { + + trace!("resizing render area..."); + + // check for valid size if size.w == 0 || size.h == 0 { panic!("window has zero as at least one of its dimensions"); } - self.surface_size = size; - //self.aspect_matrix = { - // use cgmath::{Basis3, Rotation3, Deg}; + //destroy current frame + match self.frame.take() { + Some(out) => drop(out), + None => {}//nothing to do + } - // //Matrix3::from(Basis3::from_angle_x(Deg(-0.0))) - // //* Matrix3::identity() - // // * Matrix3::from_nonuniform_scale(1.0 / size.w as f32, 1.0 / size.h as f32) - // Matrix3::from_nonuniform_scale(1.0, 1.0) - - //}; + //reconfigure surface self.config.width = size.w; self.config.height = size.h; self.surface.configure(&self.device, &self.config); + + //generate new frame from new surface + let frame = self.create_frame(); + let _ = self.frame.insert(frame); + + debug!("render area resized !"); } + /// Presents the current frame to the screen. + /// + /// The current frame is presented and a new one is created for the future renders + /// + /// # Panics + /// + /// The function will panic if the renderer fails to create a new frame pub fn present(&mut self) { - match self.output.take() { + trace!("presenting frame..."); + match self.frame.take() { Some(out) => out.present(), - None => { - }//nothing to do + None => {}//nothing to do } + debug!("frame presented !"); + + //generate next frame + let frame = self.create_frame(); + let _ = self.frame.insert(frame); } - pub fn create_output(&mut self) { - self.output = Some( + pub fn create_texture_view(&self) -> wgpu::TextureView { + + self.frame + .as_ref() + .unwrap() + .texture + .create_view(&wgpu::TextureViewDescriptor::default()) + } + + /// Creates a new frame to be rendered on. + /// + /// In case of a lost surface, will try to reconfigure it before creating the frame. + /// + /// #Panics + /// + /// The underlying backend will panic if a new frame is created while the previous one is still + /// alive. Only call this function after the previous frame was either dropped or presented. + /// + /// The function will panic if the frame can't be created. + fn create_frame(&mut self) -> wgpu::SurfaceTexture { + + trace!("creating new frame..."); + let surface_texture = { self.surface.get_current_texture() .map_err(|err| match err { wgpu::SurfaceError::Lost => { @@ -263,8 +308,13 @@ impl WgpuRenderer { self.surface.get_current_texture() }, _ => Err(err) - }).unwrap() - ); + }) + .map_err(|_| "Failed to acquire to SurfaceTexture, giving up") + .unwrap() + }; + debug!("frame created !"); + + surface_texture } } diff --git a/src/sprite/texture_sprite.rs b/src/sprite/texture_sprite.rs index 1b9eb0b..fec02e8 100644 --- a/src/sprite/texture_sprite.rs +++ b/src/sprite/texture_sprite.rs @@ -1,7 +1,9 @@ #[allow(unused_imports)] use log::{debug, error, info, trace, warn}; -use wgpu; +//--Internal imports-------------------------------------------------------------------------------- + +use super::Sprite; use crate::{ texture::TextureHandle, @@ -12,8 +14,9 @@ use crate::{ utils::{Size, Position, Pixel}, }; -use super::Sprite; +//--External imports-------------------------------------------------------------------------------- +use wgpu; use std::cell::RefCell; thread_local!(static PIPELINE : RefCell> = RefCell::new(None)); @@ -118,11 +121,6 @@ impl TextureSprite { //TODO take scale into account self.texture.for_each_in_area(func, self.texture_offset, self.inner_size); } - - pub fn render(&mut self) - { - todo!(); - } } fn initialize_pipeline(renderer: &WgpuRenderer) -> wgpu::RenderPipeline { @@ -196,7 +194,7 @@ impl Sprite for TextureSprite { } fn set_alpha(&mut self, _alpha: u8) { - unimplemented!(); + todo!(); } fn set_scale(&mut self, scale: f32) { @@ -205,19 +203,7 @@ impl Sprite for TextureSprite { fn render(&mut self, renderer: &mut WgpuRenderer) { - let output = match &renderer.output { - Some(out) => out, - None => { - renderer.create_output(); - &renderer.output.as_ref().unwrap() - }, - }; - - //TODO move that to output struct ? - let view = output.texture.create_view(&wgpu::TextureViewDescriptor::default()); - let texture = &self.texture.texture(); - if texture.borrow().is_synced == false { //TODO modify that texture.borrow_mut().update(&mut renderer.queue); @@ -236,6 +222,7 @@ impl Sprite for TextureSprite { let pipeline = pipeline.borrow(); let texture_bind_group = &texture.borrow().bind_group; + let view = renderer.create_texture_view(); let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor { label: Some("Render Pass"), color_attachments: &[Some(wgpu::RenderPassColorAttachment {