diff --git a/Cargo.toml b/Cargo.toml index e03758d..22c0d38 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,7 +17,6 @@ tracing = "0.1.40" tracing-subscriber = "0.3.18" vk-mem = "0.4.0" vk-sync = "0.1.6" -winit = "0.30.5" tinyvec = "1.8" rand = "0.8.5" tokio = "1.42.0" @@ -25,3 +24,9 @@ tokio = "1.42.0" futures = "0.3" smol = "2.0" rayon = "1.10" + +winit = {version = "0.30.5", features = ["rwh_06"]} +raw-window-handle = "0.6" + +egui = "0.30.0" +egui_winit_platform = "0.24.0" \ No newline at end of file diff --git a/crates/game/Cargo.toml b/crates/game/Cargo.toml index 2b7b124..b132a68 100644 --- a/crates/game/Cargo.toml +++ b/crates/game/Cargo.toml @@ -7,4 +7,7 @@ edition = "2021" winit = { workspace = true } tracing = { workspace = true } tracing-subscriber = { workspace = true } -renderer = { path = "../renderer" } \ No newline at end of file +renderer = { path = "../renderer" } + +egui = { workspace = true } +egui_winit_platform = { workspace = true } diff --git a/crates/game/src/main.rs b/crates/game/src/main.rs index 297c44c..9a367e2 100644 --- a/crates/game/src/main.rs +++ b/crates/game/src/main.rs @@ -12,21 +12,31 @@ use winit::{ }; struct WindowState { - last_resize_events: BTreeMap>, - window_attrs: WindowAttributes, - windows: BTreeMap, - renderer: Renderer, + window: Window, + egui_platform: egui_winit_platform::Platform, } -impl WindowState { - fn new(window_title: String, display: DisplayHandle) -> WindowState { +struct WinitState { + last_resize_events: BTreeMap>, + window_attrs: WindowAttributes, + windows2: BTreeMap, + renderer: Renderer, +} + +impl WinitState { + const BASE_WIDTH: u32 = 800; + const BASE_HEIGHT: u32 = 600; + fn new(window_title: String, display: DisplayHandle) -> WinitState { Self { - windows: BTreeMap::new(), + windows2: BTreeMap::new(), last_resize_events: BTreeMap::new(), window_attrs: WindowAttributes::default() .with_title(window_title) .with_resizable(true) - .with_inner_size(LogicalSize::new(800, 600)), + .with_inner_size(LogicalSize::new( + Self::BASE_WIDTH, + Self::BASE_HEIGHT, + )), // TODO: pass down this error and add some kind of error handling UI or dump renderer: Renderer::new(display.as_raw()).expect("renderer"), } @@ -54,7 +64,30 @@ impl WindowState { window_id = u64::from(window_id), "TODO: implement draw request" ); - self.renderer.debug_draw().expect("drawing"); + if let Some(window) = self.windows2.get_mut(&window_id) { + // egui + + window.egui_platform.begin_frame(); + let output = window.egui_platform.end_frame(Some(&window.window)); + + let _draw_data = window + .egui_platform + .context() + .tessellate(output.shapes, output.pixels_per_point); + + // rendering + self.renderer + .debug_draw(&window_id, || window.window.pre_present_notify()) + .expect("drawing"); + window.window.request_redraw(); + } + } + + fn remove_window(&mut self, window_id: WindowId) { + tracing::info!(window = u64::from(window_id), "window close requested"); + + self.windows2.remove(&window_id); + self.renderer.window_contexts.remove(&window_id); } fn create_window( @@ -87,11 +120,24 @@ impl WindowState { window.window_handle().expect("window handle"), ); - self.windows.insert(window.id(), window); + self.windows2.insert( + window_id, + WindowState { + window, + egui_platform: egui_winit_platform::Platform::new( + egui_winit_platform::PlatformDescriptor { + physical_width: size.width, + physical_height: size.height, + scale_factor: 1.0, + ..Default::default() + }, + ), + }, + ); } } -impl ApplicationHandler for WindowState { +impl ApplicationHandler for WinitState { fn resumed(&mut self, event_loop: &winit::event_loop::ActiveEventLoop) { tracing::info!("winit::resumed"); @@ -100,13 +146,17 @@ impl ApplicationHandler for WindowState { fn about_to_wait( &mut self, - _event_loop: &winit::event_loop::ActiveEventLoop, + event_loop: &winit::event_loop::ActiveEventLoop, ) { tracing::info!("winit::about_to_wait"); for (&window, &resize) in self.last_resize_events.clone().iter() { self.handle_final_resize(window, resize); } self.last_resize_events.clear(); + + if self.windows2.is_empty() { + event_loop.exit(); + } } fn window_event( @@ -115,28 +165,35 @@ impl ApplicationHandler for WindowState { window_id: winit::window::WindowId, event: winit::event::WindowEvent, ) { - if !matches!(event, winit::event::WindowEvent::Resized(_)) { - if let Some(resize) = self.last_resize_events.remove(&window_id) { - self.handle_final_resize(window_id, resize); - } + // if !matches!(event, winit::event::WindowEvent::Resized(_)) { + // if let Some(resize) = self.last_resize_events.remove(&window_id) { + // self.handle_final_resize(window_id, resize); + // } + // } + + if let Some(window) = self.windows2.get_mut(&window_id) { + window.egui_platform.handle_event(&event); } match event { winit::event::WindowEvent::Resized(physical_size) => { _ = self.last_resize_events.insert(window_id, physical_size); } - winit::event::WindowEvent::CloseRequested => { - tracing::info!( - window = u64::from(window_id), - "window close requested" - ); - - self.windows.remove(&window_id); - self.renderer.window_contexts.remove(&window_id); - - if self.windows.is_empty() { - event_loop.exit(); - } + winit::event::WindowEvent::CloseRequested + | winit::event::WindowEvent::KeyboardInput { + event: + winit::event::KeyEvent { + physical_key: + winit::keyboard::PhysicalKey::Code( + winit::keyboard::KeyCode::KeyQ, + ), + state: ElementState::Pressed, + repeat: false, + .. + }, + .. + } => { + self.remove_window(window_id); } winit::event::WindowEvent::KeyboardInput { event: @@ -153,30 +210,6 @@ impl ApplicationHandler for WindowState { } => { self.create_window(event_loop); } - winit::event::WindowEvent::KeyboardInput { - event: - winit::event::KeyEvent { - physical_key: - winit::keyboard::PhysicalKey::Code( - winit::keyboard::KeyCode::KeyQ, - ), - state: ElementState::Pressed, - repeat: false, - .. - }, - .. - } => { - tracing::info!( - window = u64::from(window_id), - "window close requested" - ); - - self.windows.remove(&window_id); - self.renderer.window_contexts.remove(&window_id); - if self.windows.is_empty() { - event_loop.exit(); - } - } winit::event::WindowEvent::KeyboardInput { device_id, event, @@ -199,9 +232,6 @@ impl ApplicationHandler for WindowState { } winit::event::WindowEvent::RedrawRequested => { self.handle_draw_request(window_id); - if let Some(window) = self.windows.get(&window_id) { - window.request_redraw(); - } } _ => {} // unhandled event } @@ -214,6 +244,6 @@ fn main() { ev.set_control_flow(winit::event_loop::ControlFlow::Poll); let display = ev.display_handle().expect("display handle"); - let mut game = WindowState::new("Vidya".to_owned(), display); + let mut game = WinitState::new("Vidya".to_owned(), display); ev.run_app(&mut game).unwrap(); } diff --git a/crates/renderer/Cargo.toml b/crates/renderer/Cargo.toml index 390553a..6d5da6d 100644 --- a/crates/renderer/Cargo.toml +++ b/crates/renderer/Cargo.toml @@ -17,8 +17,11 @@ tracing = "0.1.40" tracing-subscriber = "0.3.18" vk-mem = "0.4.0" vk-sync = "0.1.6" -winit = "0.30.5" crossbeam = "0.8.4" parking_lot = "0.12.3" smol.workspace = true tracing-test = "0.2.5" + +raw-window-handle = { workspace = true } +egui = { workspace = true } +egui_winit_platform = { workspace = true } \ No newline at end of file diff --git a/crates/renderer/src/lib.rs b/crates/renderer/src/lib.rs index 32d1a2c..c96f65d 100644 --- a/crates/renderer/src/lib.rs +++ b/crates/renderer/src/lib.rs @@ -29,12 +29,13 @@ use ash::{ }; use dyn_clone::DynClone; use rand::{Rng, SeedableRng}; +use raw_window_handle::{DisplayHandle, RawDisplayHandle}; use tinyvec::{array_vec, ArrayVec}; use tracing::info; -use winit::raw_window_handle::{DisplayHandle, RawDisplayHandle}; mod commands; mod images; +mod render_graph; mod sync; type VkAllocator = Arc; @@ -1166,7 +1167,7 @@ impl Surface { fn create( instance: Arc, display_handle: RawDisplayHandle, - window_handle: winit::raw_window_handle::RawWindowHandle, + window_handle: raw_window_handle::RawWindowHandle, ) -> Result { let surface = unsafe { ash_window::create_surface( @@ -1887,7 +1888,7 @@ impl Vulkan { } } -use winit::raw_window_handle::RawWindowHandle; +use raw_window_handle::RawWindowHandle; pub struct WindowContext { window_handle: RawWindowHandle, @@ -1935,7 +1936,7 @@ impl WindowContext { instance: Arc, device: Device, extent: vk::Extent2D, - window_handle: winit::raw_window_handle::RawWindowHandle, + window_handle: raw_window_handle::RawWindowHandle, display: RawDisplayHandle, ) -> Result { let surface = Arc::new(Surface::create( @@ -2005,15 +2006,15 @@ impl WindowContext { } } -pub struct Renderer { +pub struct Renderer { vulkan: Vulkan, display: RawDisplayHandle, - pub window_contexts: HashMap, + pub window_contexts: HashMap, } pub use vk::Extent2D; -impl Renderer { +impl Renderer { pub fn new(display: RawDisplayHandle) -> Result { let vulkan = Vulkan::new("Vidya", &[], &[], Some(display))?; Ok(Self { @@ -2023,7 +2024,15 @@ impl Renderer { }) } - pub fn debug_draw(&mut self) -> Result<()> { + pub fn debug_draw( + &mut self, + window: &K, + pre_present_cb: F, + ) -> Result<()> + where + K: core::hash::Hash + Eq, + W: core::hash::Hash + Eq + Borrow, + { let dev = self.vulkan.device.clone(); unsafe { dev.dev().device_wait_idle()? }; @@ -2033,7 +2042,7 @@ impl Renderer { dev.graphics_queue().clone(), )?; - for ctx in self.window_contexts.values() { + if let Some(ctx) = self.window_contexts.get(window) { let cmd = pool.alloc()?; let buffer = cmd.buffer(); @@ -2125,6 +2134,9 @@ impl Renderer { Arc::new(sync::Fence::create(dev.clone())?), )?; + // call pre_present_notify + pre_present_cb(); + frame.present(); future.block()?; @@ -2139,9 +2151,12 @@ impl Renderer { pub fn new_window_context( &mut self, extent: vk::Extent2D, - window_id: winit::window::WindowId, - window: winit::raw_window_handle::WindowHandle, - ) -> Result<()> { + window_id: W, + window: raw_window_handle::WindowHandle, + ) -> Result<()> + where + W: core::hash::Hash + Eq, + { use std::collections::hash_map::Entry; match self.window_contexts.entry(window_id) { Entry::Vacant(entry) => { @@ -2827,7 +2842,7 @@ mod test_swapchain { let window_ctx = WindowContext { window_handle: RawWindowHandle::Web( - winit::raw_window_handle::WebWindowHandle::new(0), + raw_window_handle::WebWindowHandle::new(0), ), surface, current_swapchain: RwLock::new(swapchain), diff --git a/crates/renderer/src/render_graph.rs b/crates/renderer/src/render_graph.rs new file mode 100644 index 0000000..1c6cc05 --- /dev/null +++ b/crates/renderer/src/render_graph.rs @@ -0,0 +1,27 @@ +use ash::vk; + +struct Rgba([f32;4]); + +enum LoadOp { + Clear(Rgba), + Load, + DontCare, +} + +enum StoreOp { + DontCare,Store, +} + +struct AttachmentInfo { + size: glam::UVec2, + format: vk::Format, + load: LoadOp, + store: StoreOp, +} + +struct Texture { + texture: vk::Image, +} + +pub struct RenderGraph { +}