diff --git a/src/render/mod.rs b/src/render/mod.rs index 159b448..644622c 100644 --- a/src/render/mod.rs +++ b/src/render/mod.rs @@ -1,4 +1,6 @@ mod pipelines; pub use pipelines::utils::create_render_pipeline; -pub use pipelines::{GlobalBindLayout, Pipelines}; \ No newline at end of file +pub use pipelines::{GlobalBindLayout, Pipelines}; + +mod renderer; \ No newline at end of file diff --git a/src/render/renderer/display.rs b/src/render/renderer/display.rs new file mode 100644 index 0000000..c7f4e33 --- /dev/null +++ b/src/render/renderer/display.rs @@ -0,0 +1,93 @@ +use winit::{ + event::{ElementState, Event, KeyboardInput, VirtualKeyCode, WindowEvent}, + event_loop::{ControlFlow, EventLoop}, + window::Window, +}; + +pub struct Display { + window: Window, + event_loop: EventLoop<()>, +} + +impl Display { + pub async fn init(title: &str) -> Self { + cfg_if::cfg_if! { + if #[cfg(target_arch = "wasm32")] { + std::panic::set_hook(Box::new(console_error_panic_hook::hook)); + console_log::init_with_level(log::Level::Info).expect("Could't initialize logger"); + } else { + env_logger::init(); + } + } + + let event_loop = EventLoop::new(); + let window = winit::window::WindowBuilder::new() + .with_title(title) + .build(&event_loop) + .unwrap(); + + #[cfg(target_arch = "wasm32")] + { + // Winit prevents sizing with CSS, so we have to set + // the size manually when on web. + use winit::dpi::PhysicalSize; + window.set_inner_size(PhysicalSize::new(450, 400)); + + use winit::platform::web::WindowExtWebSys; + web_sys::window() + .and_then(|win| win.document()) + .and_then(|doc| { + let dst = doc.get_element_by_id("wasm-example")?; + let canvas = web_sys::Element::from(window.canvas()); + dst.append_child(&canvas).ok()?; + Some(()) + }) + .expect("Couldn't append canvas to document body."); + } + + Self { window, event_loop } + } + + pub fn run(self) { + // let mut last_render_time = instant::Instant::now(); + self.event_loop.run(move |event, _, control_flow| { + *control_flow = ControlFlow::Poll; + match event { + Event::MainEventsCleared => self.window.request_redraw(), + Event::WindowEvent { + ref event, + window_id, + } if window_id == self.window.id() => match event { + #[cfg(not(target_arch = "wasm32"))] + WindowEvent::CloseRequested + | WindowEvent::KeyboardInput { + input: + KeyboardInput { + state: ElementState::Pressed, + virtual_keycode: Some(VirtualKeyCode::Escape), + .. + }, + .. + } => *control_flow = ControlFlow::Exit, + _ => {} + }, + // Event::RedrawRequested(window_id) if window_id == self.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"), + // } + // } + _ => {} + } + }); + } +} diff --git a/src/render/renderer/mod.rs b/src/render/renderer/mod.rs index e69de29..b965575 100644 --- a/src/render/renderer/mod.rs +++ b/src/render/renderer/mod.rs @@ -0,0 +1,4 @@ +mod renderer; +mod display; + +pub use renderer::Renderer; \ No newline at end of file diff --git a/src/render/renderer/renderer.rs b/src/render/renderer/renderer.rs new file mode 100644 index 0000000..67f351b --- /dev/null +++ b/src/render/renderer/renderer.rs @@ -0,0 +1,101 @@ +use std::iter; + +use winit::{event::WindowEvent, window::Window}; + +pub struct Renderer { + surface: wgpu::Surface, + device: wgpu::Device, + queue: wgpu::Queue, + size: winit::dpi::PhysicalSize, + config: wgpu::SurfaceConfiguration, +} + +impl Renderer { + async fn new(window: &Window) -> Self { + 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::Backends::all()); + let surface = unsafe { instance.create_surface(window) }; + let adapter = instance + .request_adapter(&wgpu::RequestAdapterOptions { + power_preference: wgpu::PowerPreference::default(), + compatible_surface: Some(&surface), + force_fallback_adapter: false, + }) + .await + .unwrap(); + let (device, queue) = adapter + .request_device( + &wgpu::DeviceDescriptor { + label: None, + 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") { + wgpu::Limits::downlevel_webgl2_defaults() + } else { + wgpu::Limits::default() + }, + }, + None, // Trace path + ) + .await + .unwrap(); + + let config = wgpu::SurfaceConfiguration { + usage: wgpu::TextureUsages::RENDER_ATTACHMENT, + format: surface.get_preferred_format(&adapter).unwrap(), + width: size.width, + height: size.height, + present_mode: wgpu::PresentMode::Fifo, + }; + + surface.configure(&device, &config); + + Self { + surface, + device, + queue, + config, + size, + } + } + + fn resize(&mut self, new_size: winit::dpi::PhysicalSize) { + if new_size.width > 0 && new_size.height > 0 { + self.size = new_size; + self.config.width = new_size.width; + self.config.height = new_size.height; + self.surface.configure(&self.device, &self.config); + } + } + + fn input(&mut self, event: &WindowEvent) -> bool { + false + } + + fn update(&mut self, dt: instant::Duration) { + + } + + fn render(&mut self) -> Result<(), wgpu::SurfaceError> { + let output = self.surface.get_current_texture()?; + let view = output + .texture + .create_view(&wgpu::TextureViewDescriptor::default()); + + let mut encoder = self + .device + .create_command_encoder(&wgpu::CommandEncoderDescriptor { + label: Some("Render Encoder"), + }); + + + self.queue.submit(iter::once(encoder.finish())); + output.present(); + + Ok(()) + } +} diff --git a/src/render/renderer/vertex.rs b/src/render/renderer/vertex.rs deleted file mode 100644 index e69de29..0000000