diff --git a/Cargo.lock b/Cargo.lock index 972091d..95b5884 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1688,6 +1688,14 @@ dependencies = [ "winapi", ] +[[package]] +name = "render" +version = "0.1.0" +dependencies = [ + "wgpu", + "winit", +] + [[package]] name = "renderdoc-sys" version = "0.7.1" @@ -2061,6 +2069,7 @@ dependencies = [ "log", "pollster", "rayon", + "render", "reqwest", "tobj", "wasm-bindgen", diff --git a/Cargo.toml b/Cargo.toml index 504c73b..a6b3794 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,6 +8,8 @@ edition = "2021" crate-type = ["cdylib", "rlib"] [dependencies] +render = { path = "crates/render" } + cfg-if = "1" anyhow = "1.0" bytemuck = { version = "1.9.1", features = [ "derive" ] } diff --git a/crates/render/Cargo.toml b/crates/render/Cargo.toml new file mode 100644 index 0000000..bc49a82 --- /dev/null +++ b/crates/render/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "render" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[lib] +crate-type = ["cdylib", "rlib"] + +[dependencies] +winit = "0.26" +wgpu = { version = "0.13"} \ No newline at end of file diff --git a/src/render/renderer/renderer.rs b/crates/render/src/graphics_renderer.rs similarity index 71% rename from src/render/renderer/renderer.rs rename to crates/render/src/graphics_renderer.rs index b170676..efb0272 100644 --- a/src/render/renderer/renderer.rs +++ b/crates/render/src/graphics_renderer.rs @@ -1,20 +1,18 @@ use std::iter; -use winit::{event::Event, window::Window}; +use wgpu::{CommandEncoder, TextureView}; +use winit::window::Window; -use super::State; - -pub struct Renderer { +pub struct GraphicsRenderer { pub surface: wgpu::Surface, pub device: wgpu::Device, pub queue: wgpu::Queue, pub size: winit::dpi::PhysicalSize, pub config: wgpu::SurfaceConfiguration, - state: Option>, } -impl Renderer { - pub async fn new(window: &Window) -> Self { +impl GraphicsRenderer { + pub async fn initialize(window: &Window) -> Self { let size = window.inner_size(); // The instance is a handle to our GPU @@ -63,7 +61,6 @@ impl Renderer { queue, config, size, - state: None, } } @@ -73,27 +70,13 @@ impl Renderer { self.config.width = new_size.width; self.config.height = new_size.height; self.surface.configure(&self.device, &self.config); - - if let Some(state) = self.state.as_mut() { - state.resize(&self.device, &self.config, new_size); - } } } - pub fn input(&mut self, event: &Event<()>) -> bool { - if let Some(state) = self.state.as_mut() { - return state.input(event); - } - false - } - - pub fn update(&mut self, dt: instant::Duration) { - if let Some(state) = self.state.as_mut() { - state.update(&self.queue, dt); - } - } - - pub fn render(&mut self) -> Result<(), wgpu::SurfaceError> { + pub fn render_frame(&mut self, render: T) -> Result<(), wgpu::SurfaceError> + where + T: Fn(&TextureView, &mut CommandEncoder) -> Result<(), wgpu::SurfaceError>, + { let output = self.surface.get_current_texture()?; let view = output .texture @@ -105,16 +88,10 @@ impl Renderer { label: Some("Render Encoder"), }); - if let Some(state) = self.state.as_mut() { - state.render(&view, &mut encoder)?; - self.queue.submit(iter::once(encoder.finish())); - output.present(); - } + render(&view, &mut encoder)?; + self.queue.submit(iter::once(encoder.finish())); + output.present(); Ok(()) } - - pub fn set_state(&mut self, state: Option>) { - self.state = state; - } } diff --git a/crates/render/src/lib.rs b/crates/render/src/lib.rs new file mode 100644 index 0000000..602e58f --- /dev/null +++ b/crates/render/src/lib.rs @@ -0,0 +1,10 @@ +pub mod graphics_renderer; + +#[cfg(test)] +mod tests { + #[test] + fn it_works() { + let result = 2 + 2; + assert_eq!(result, 4); + } +} diff --git a/src/lib.rs b/src/lib.rs index d6ae721..048c267 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,7 @@ use std::{ops::Deref, sync::Arc}; use cgmath::prelude::*; +use ::render::graphics_renderer::GraphicsRenderer; use winit::{ event::*, event_loop::{ControlFlow, EventLoop}, @@ -9,7 +10,7 @@ use winit::{ #[cfg(target_arch = "wasm32")] use wasm_bindgen::prelude::*; -use crate::render::{DefaultState, Renderer}; +use crate::render::{DefaultState, State}; mod camera; mod model; @@ -156,22 +157,21 @@ pub async fn run() { .expect("Couldn't append canvas to document body."); } - let mut renderer = Arc::from(Renderer::new(&window).await); - let default_state = Box::from(DefaultState::new(renderer.deref()).await); - Arc::get_mut(&mut renderer) - .unwrap() - .set_state(Some(default_state)); + let mut renderer = Arc::from(GraphicsRenderer::initialize(&window).await); + let mut default_state = Arc::from(DefaultState::new(renderer.deref()).await); + let mut last_render_time = instant::Instant::now(); event_loop.run(move |base_event, _, control_flow| { *control_flow = ControlFlow::Poll; let renderer = Arc::get_mut(&mut renderer).unwrap(); + let state = Arc::get_mut(&mut default_state).unwrap(); match base_event { Event::MainEventsCleared => window.request_redraw(), Event::WindowEvent { ref event, window_id, - } if window_id == window.id() && !renderer.input(&base_event) => match event { + } if window_id == window.id() && !state.input(&base_event) => match event { #[cfg(not(target_arch = "wasm32"))] WindowEvent::CloseRequested | WindowEvent::KeyboardInput { @@ -190,15 +190,20 @@ pub async fn run() { renderer.resize(**new_inner_size); } _ => { - renderer.input(&base_event); + state.input(&base_event); } }, Event::RedrawRequested(window_id) if window_id == window.id() => { let now = instant::Instant::now(); let dt = now - last_render_time; last_render_time = now; - renderer.update(dt); - match renderer.render() { + state.update(&renderer.queue, dt); + + match renderer.render_frame(|view, command| { + let mut renderable = Arc::clone(&default_state); + let state = Arc::get_mut(&mut renderable).unwrap(); + state.render(view, command) + }) { Ok(_) => {} Err(wgpu::SurfaceError::Lost | wgpu::SurfaceError::Outdated) => { renderer.resize(renderer.size) @@ -208,7 +213,7 @@ pub async fn run() { } } _ => { - renderer.input(&base_event); + state.input(&base_event); } } }); diff --git a/src/render/mod.rs b/src/render/mod.rs index 9c10d9d..c2cc5fc 100644 --- a/src/render/mod.rs +++ b/src/render/mod.rs @@ -4,4 +4,4 @@ pub use pipelines::utils::create_render_pipeline; pub use pipelines::{GlobalBindLayout, Pipelines}; mod renderer; -pub use renderer::{DefaultState, Renderer, State}; +pub use renderer::{DefaultState, State}; diff --git a/src/render/renderer/default_state.rs b/src/render/renderer/default_state.rs index eceac72..3e9a6b7 100644 --- a/src/render/renderer/default_state.rs +++ b/src/render/renderer/default_state.rs @@ -2,6 +2,7 @@ use cgmath::prelude::*; #[cfg(not(target_arch="wasm32"))] use rayon::prelude::*; +use ::render::graphics_renderer::GraphicsRenderer; use wgpu::{util::DeviceExt, Queue}; use winit::event::{DeviceEvent, ElementState, Event, KeyboardInput, MouseButton, WindowEvent}; @@ -11,8 +12,6 @@ use crate::{ render, resources, texture, CameraUniform, Instance, LightUniform, NUM_INSTANCES_PER_ROW, }; -use super::Renderer; - pub struct DefaultState { obj_model: model::Model, camera: camera::Camera, @@ -35,7 +34,7 @@ pub struct DefaultState { } impl DefaultState { - pub async fn new(renderer: &Renderer) -> Self + pub async fn new(renderer: &GraphicsRenderer) -> Self { let global_bind_layout = render::GlobalBindLayout::new(&renderer.device); let pipelines = diff --git a/src/render/renderer/mod.rs b/src/render/renderer/mod.rs index 5d9acc9..b3bb9e2 100644 --- a/src/render/renderer/mod.rs +++ b/src/render/renderer/mod.rs @@ -1,7 +1,3 @@ -mod renderer; - -pub use renderer::Renderer; - mod default_state; pub use default_state::DefaultState;