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
This commit is contained in:
parent
c2e884f68c
commit
2e326306d9
@ -27,9 +27,10 @@ pub trait Application<S> {
|
||||
|
||||
//--Canvas struct-----------------------------------------------------------------------------------
|
||||
pub struct Canvas {
|
||||
renderer: WgpuRenderer,
|
||||
clear_color: Pixel,
|
||||
default_texture: TextureHandle,
|
||||
clear_color: Pixel,
|
||||
|
||||
renderer: WgpuRenderer,
|
||||
}
|
||||
|
||||
impl Canvas {
|
||||
|
||||
@ -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(())
|
||||
|
||||
140
src/renderer.rs
140
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<wgpu::SurfaceTexture>,
|
||||
|
||||
pub matrix_layout: wgpu::BindGroupLayout,
|
||||
pub texture_layout: wgpu::BindGroupLayout,
|
||||
|
||||
#[allow(dead_code)]
|
||||
shape_render_pipeline: wgpu::RenderPipeline,
|
||||
#[allow(dead_code)]
|
||||
quad_mesh: GpuMesh<ColorVertex, 4, 6>, //TODO temporary, to be moved to shapes.rs
|
||||
|
||||
pub texture_layout: wgpu::BindGroupLayout,
|
||||
pub matrix_layout: wgpu::BindGroupLayout,
|
||||
|
||||
frame: Option<wgpu::SurfaceTexture>,
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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<Option<wgpu::RenderPipeline>> = 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 {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user