From a7bbf4c7d34675927e31a5ba2710f018fbf20e27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20H=C3=BCbner?= Date: Wed, 26 Feb 2025 14:51:44 +0100 Subject: [PATCH] Start reordering code to fit into new ecs concept --- context/Cargo.toml | 1 + context/src/core/context.rs | 150 +++---------- ecs/src/resources.rs | 10 +- ecs/src/world.rs | 22 ++ engine/src/engine/engine.rs | 204 ++++-------------- engine/src/scene/scene/scene_base.rs | 125 +++++------ examples/simple_window/Cargo.toml | 1 + examples/simple_window/src/main.rs | 28 ++- loading-screen/src/loadingscreen.rs | 4 +- presentation/Cargo.toml | 2 + presentation/src/lib.rs | 23 +- presentation/src/presentationcore.rs | 8 +- presentation/src/renderbackend.rs | 46 ++-- presentation/src/traits.rs | 9 +- presentation/src/vri/mod.rs | 16 +- .../src/wsi/vulkanwindowrendercore.rs | 68 ++---- .../src/wsi/windowsystemintegration.rs | 10 +- presentation/src/xri/mod.rs | 16 +- 18 files changed, 262 insertions(+), 481 deletions(-) diff --git a/context/Cargo.toml b/context/Cargo.toml index d71433f..9c251ea 100644 --- a/context/Cargo.toml +++ b/context/Cargo.toml @@ -11,6 +11,7 @@ assetpath = { workspace = true } anyhow = { workspace = true } presentation = { path = "../presentation" } +ecs = { path = "../ecs" } [target.'cfg(target_os = "linux")'.dependencies] shared_library = { workspace = true } diff --git a/context/src/core/context.rs b/context/src/core/context.rs index 7650680..3ac99c5 100644 --- a/context/src/core/context.rs +++ b/context/src/core/context.rs @@ -6,6 +6,7 @@ use super::vulkancore::VulkanCore; #[cfg(feature = "sound")] use audio::SoundHandler; +use ecs::World; use crate::prelude::*; use anyhow::Result; @@ -39,16 +40,7 @@ pub struct Context { os_specific: OsSpecific, - application_start_time: Instant, - - context_object: Arc>>>, - - fallback: Mutex Result<()> + Send + Sync>>>, - - push_events: Mutex Result<()> + Send + Sync>>>, - - // queue timer - last_check: Mutex, + fallback: Option Result<()> + Send + Sync>>, } impl Context { @@ -56,20 +48,6 @@ impl Context { ContextBuilder::default() } - pub fn set_context_object(&self, context_object: Option) - where - C: ContextObject + Send + Sync + 'static, - { - let tmp = self.context_object.clone(); - - self.push_event(move || { - *tmp.write().unwrap() = - context_object.map(|c| Box::new(c) as Box); - - Ok(()) - }) - } - pub fn window_config(&self) -> WindowConfig<'_> { match self.presentation.backend() { PresentationBackend::Window(wsi) => WindowConfig::new(wsi), @@ -82,30 +60,25 @@ impl Context { } } - pub fn push_event(&self, event: impl FnOnce() -> Result<()> + 'static + Send + Sync) { - self.push_events.lock().unwrap().push(Box::new(event)); - } - #[cfg(feature = "sound")] pub fn sound(&self) -> MutexGuard<'_, SoundHandler> { self.sound_handler.lock().unwrap() } - pub fn run(&self) -> Result<()> { + pub fn run(&self, world: &mut World) -> Result<()> { 'running: loop { + let render_core = self.render_core.clone(); + match self.presentation.poll_events( |event| { - if let Some(ctx_obj) = &mut *self.context_object.write().unwrap() { - ctx_obj.event(event)?; - } + // TODO + // if let Some(ctx_obj) = world.resources.get_mut_opt::() { + // ctx_obj.event(event)?; + // } Ok(()) }, - { - let render_core = self.render_core.clone(); - - move |w, h| render_core.write().unwrap().resize(w, h) - }, + |w, h| render_core.write().unwrap().resize(world, w, h), ) { Ok(res) => { if !res { @@ -113,24 +86,17 @@ impl Context { } } Err(err) => { - if let Some(fallback) = self.fallback.lock().unwrap().as_ref() { + if let Some(fallback) = &self.fallback { (fallback)(err)?; } } } - if let Err(err) = self.update() { - if let Some(fallback) = &self.fallback.lock().unwrap().as_ref() { - (fallback)(err)?; - } - } - - if !self.render_core_mut().next_frame()? { + if !self.render_core_mut().next_frame(world)? { break 'running; } } - *self.context_object.write().unwrap() = None; self.render_core_mut().clear_post_processing_routines(); Ok(()) @@ -144,11 +110,11 @@ impl Context { self.render_core.write().unwrap() } - pub fn set_fallback(&self, fallback: F) + pub fn set_fallback(&mut self, fallback: F) where F: Fn(anyhow::Error) -> Result<()> + 'static + Send + Sync, { - *self.fallback.lock().unwrap() = Some(Box::new(fallback)); + self.fallback = Some(Box::new(fallback)); } pub fn close(&self) -> Result<()> { @@ -163,10 +129,6 @@ impl Context { self.core.queue() } - pub fn time(&self) -> Duration { - self.application_start_time.elapsed() - } - pub fn controllers(&self) -> RwLockReadGuard<'_, Vec>>> { self.presentation.event_system().controllers() } @@ -188,42 +150,6 @@ impl std::fmt::Debug for Context { } } -impl Context { - #[inline] - fn update(&self) -> Result<()> { - if let Some(ctx_obj) = &mut *self.context_object.write().unwrap() { - if let Err(err) = ctx_obj.update() { - return Err(err); - } - } - - let mut events = Vec::new(); - - { - let mut push_events_lock = self.push_events.lock().unwrap(); - mem::swap(&mut events, &mut push_events_lock); - } - - for event in events { - event()?; - } - - let one_second = Duration::from_secs(1); - let mut last_check = self.last_check.lock().unwrap(); - - if (self.time() - *last_check) > one_second { - *last_check += one_second; - - #[cfg(feature = "sound")] - { - self.sound().check_clear_queue()?; - } - } - - Ok(()) - } -} - impl ContextInterface for Context { fn device(&self) -> &Arc { self.device() @@ -465,19 +391,10 @@ impl ContextBuilder { self } - pub fn build(self, create_scene: F) -> Result> - where - SCENE: TScene + 'static, - F: FnOnce( - &Arc, - &Arc>, - (f32, f32), - &TargetMode>>, - ) -> Result, - { + pub fn build(self) -> Result { if self.enable_backtrace { // set environment variable for Rust-debug-trace - set_var("RUST_BACKTRACE", "1"); + unsafe { set_var("RUST_BACKTRACE", "1") }; } #[cfg(feature = "openxr")] @@ -515,12 +432,11 @@ impl ContextBuilder { let os_specific = OsSpecific::new(&self.os_specific_config); - let (render_core, _target_mode) = create_render_core( + let (render_core, _target_mode) = create_render_core::( &presentation, core.device(), core.queue(), self.render_core_create_info, - create_scene, )?; if self.enable_mouse { @@ -535,7 +451,7 @@ impl ContextBuilder { presentation.event_system().enable_controller(); } - Ok(Arc::new(Context { + Ok(Context { core, presentation, render_core: Arc::new(RwLock::new(render_core)), @@ -545,16 +461,8 @@ impl ContextBuilder { os_specific, - application_start_time: Instant::now(), - - context_object: Arc::new(RwLock::new(None)), - - fallback: Mutex::new(None), - - push_events: Mutex::new(Vec::new()), - - last_check: Mutex::new(Duration::from_secs(0)), - })) + fallback: None, + }) } #[cfg(feature = "openxr")] @@ -568,13 +476,14 @@ impl ContextBuilder { fn get_vr_mode(&self) -> Option { #[cfg(any(feature = "openvr", feature = "openxr"))] // if we requested a VR mode, check if it is available - match self.vr_mode { - Some(vr_mode) => { + return self + .vr_mode + .map(|vr_mode| { let available_vr_modes = PresentationCore::enabled_vr_modes(); // if requested VR mode is enabled, use it if available_vr_modes.contains(&vr_mode) { - return Some(vr_mode); + Some(vr_mode) } // fallback to the first available else if !available_vr_modes.is_empty() { @@ -585,19 +494,16 @@ impl ContextBuilder { vr_mode, mode ); - return Some(mode); + Some(mode) } // use default desktop, as last resort else { println!("No VRMode present, fallback to Window"); - return None; + None } - } - None => { - return None; - } - } + }) + .flatten(); #[cfg(not(any(feature = "openvr", feature = "openxr")))] None diff --git a/ecs/src/resources.rs b/ecs/src/resources.rs index 175ddf1..32b2101 100644 --- a/ecs/src/resources.rs +++ b/ecs/src/resources.rs @@ -29,17 +29,23 @@ impl Resources { } pub fn get(&self) -> &T { + self.get_opt::().unwrap() + } + + pub fn get_opt(&self) -> Option<&T> { self.map .get(&TypeId::of::()) .map(|any| Self::downcast_ref_unchecked(any)) - .unwrap() } pub fn get_mut(&mut self) -> &mut T { + self.get_mut_opt::().unwrap() + } + + pub fn get_mut_opt(&mut self) -> Option<&mut T> { self.map .get_mut(&TypeId::of::()) .map(|any| Self::downcast_mut_unchecked(any)) - .unwrap() } pub fn multi_mut(&mut self) -> ResourceMultiMut<'_> { diff --git a/ecs/src/world.rs b/ecs/src/world.rs index 2404dcd..c21109c 100644 --- a/ecs/src/world.rs +++ b/ecs/src/world.rs @@ -14,6 +14,16 @@ pub struct WorldBuilder { pub(crate) updates: Updates, pub events: Events, pub resources: Resources, + systems: Vec Result<()> + Send + Sync + 'static>>, +} + +impl WorldBuilder { + pub fn add_system(&mut self, f: F) + where + F: Fn(&mut World) -> Result<()> + Send + Sync + 'static, + { + self.systems.push(Box::new(f)); + } } impl WorldBuilder { @@ -31,6 +41,8 @@ impl WorldBuilder { entity_object_manager: Default::default(), start_time: Instant::now(), + + systems: self.systems, } } } @@ -53,6 +65,8 @@ pub struct World { entity_object_manager: EntityObjectManager, start_time: Instant, + + systems: Vec Result<()> + Send + Sync + 'static>>, } impl World { @@ -61,6 +75,7 @@ impl World { updates: Default::default(), events: Default::default(), resources: Default::default(), + systems: Default::default(), } } @@ -311,7 +326,10 @@ impl World { impl World { pub fn run(&mut self) -> Result<()> { + let systems = std::mem::take(&mut self.systems); + loop { + // we need to take all events because of borrowing rules let mut events = self.events.take_events(); events.fire_events(self)?; @@ -325,6 +343,10 @@ impl World { } self.commit_entity_changes()?; + + for system in systems.iter() { + system(self)?; + } } } } diff --git a/engine/src/engine/engine.rs b/engine/src/engine/engine.rs index 14af51d..8fa2a39 100644 --- a/engine/src/engine/engine.rs +++ b/engine/src/engine/engine.rs @@ -72,8 +72,9 @@ impl context::prelude::PostProcess for GuiPostProcess { } } -struct GraphicsObjects { - context: Arc, +pub struct Engine { + engine_settings: Arc, + gui_handler: Arc, gui_post_process: Arc, input: Arc>, @@ -84,24 +85,8 @@ struct GraphicsObjects { resource_base_path: String, } -impl Drop for GraphicsObjects { - fn drop(&mut self) { - self.context - .render_core() - .remove_post_processing_routine(self.gui_post_process.clone()); - } -} - -pub struct Engine { - engine_settings: Arc, - - graphical: GraphicsObjects, - - entity_object_manager: EntityObjectManager, -} - impl Engine { - pub fn new(#[allow(unused)] mut create_info: EngineCreateInfo<'_>) -> Result> { + pub fn new(#[allow(unused)] mut create_info: EngineCreateInfo<'_>) -> Result { if let Font::Path(path) = &mut create_info.gui_info.font { path.set_prefix(&create_info.resource_base_path); } @@ -193,17 +178,7 @@ impl Engine { context_builder = context_builder.enable_backtrace(); } - context_builder.build(|device, queue, window_extents, images| { - Scene::new( - device, - queue, - window_extents, - images, - create_info.rasterizer_info, - create_info.raytracing_info, - create_info.graphics_info, - ) - })? + context_builder.build::()? }; // update sound handler center @@ -234,97 +209,41 @@ impl Engine { create_info.resource_base_path.clone(), )?); - let engine = Arc::new(Engine { - graphical: { - let asset_manager = AssetManager::new(engine_settings.clone())?; + let asset_manager = AssetManager::new(engine_settings.clone())?; - let gui_handler = GuiHandler::new( - create_info.gui_info, - &(context.clone() as Arc), - )?; + let gui_handler = GuiHandler::new( + create_info.gui_info, + &(context.clone() as Arc), + )?; - // default keyboard navigation - let mut direction_mapping = HashMap::new(); - // direction_mapping.insert(Keycode::A, GuiDirection::Left); - // direction_mapping.insert(Keycode::D, GuiDirection::Right); - // direction_mapping.insert(Keycode::W, GuiDirection::Up); - // direction_mapping.insert(Keycode::S, GuiDirection::Down); - direction_mapping.insert(Keycode::Left, GuiDirection::Left); - direction_mapping.insert(Keycode::Right, GuiDirection::Right); - direction_mapping.insert(Keycode::Up, GuiDirection::Up); - direction_mapping.insert(Keycode::Down, GuiDirection::Down); + // default keyboard navigation + let mut direction_mapping = HashMap::new(); + // direction_mapping.insert(Keycode::A, GuiDirection::Left); + // direction_mapping.insert(Keycode::D, GuiDirection::Right); + // direction_mapping.insert(Keycode::W, GuiDirection::Up); + // direction_mapping.insert(Keycode::S, GuiDirection::Down); + direction_mapping.insert(Keycode::Left, GuiDirection::Left); + direction_mapping.insert(Keycode::Right, GuiDirection::Right); + direction_mapping.insert(Keycode::Up, GuiDirection::Up); + direction_mapping.insert(Keycode::Down, GuiDirection::Down); - let input = Input { direction_mapping }; + let input = Input { direction_mapping }; - let gui_post_process = Arc::new(GuiPostProcess(gui_handler.clone())); - context - .render_core() - .add_post_processing_routine(gui_post_process.clone()); + let gui_post_process = Arc::new(GuiPostProcess(gui_handler.clone())); + context + .render_core() + .add_post_processing_routine(gui_post_process.clone()); - GraphicsObjects { - context, - gui_post_process, - gui_handler, - input: Arc::new(RwLock::new(input)), + Ok(Engine { + gui_post_process, + gui_handler, + input: Arc::new(RwLock::new(input)), - asset_manager: RwLock::new(asset_manager), + asset_manager: RwLock::new(asset_manager), - resource_base_path: create_info.resource_base_path, - } - }, - - entity_object_manager: EntityObjectManager::default(), + resource_base_path: create_info.resource_base_path, engine_settings, - }); - - Ok(engine) - } - - fn convert_scene_ref(tscene: &Box) -> Option> { - unsafe { - let ptr_to_ptr: *const *mut Scene = - std::mem::transmute(destructure_traitobject::data(tscene as *const _)); - - NonNull::new(*ptr_to_ptr) - } - } - - pub fn scene(&self) -> &Scene { - unsafe { - Self::convert_scene_ref(self.graphical.context.render_core_mut().scene_mut()) - .unwrap() - .as_ref() - } - } - - pub fn on_scene<'a, F>(&'a self, f: F) -> Result<()> - where - F: FnOnce(&Scene) -> Result<()> + 'a, - { - f(unsafe { - Self::convert_scene_ref(self.graphical.context.render_core().scene()) - .unwrap() - .as_ref() - }) - } - - pub fn scene_mut(&self) -> &mut Scene { - unsafe { - Self::convert_scene_ref(self.graphical.context.render_core_mut().scene_mut()) - .unwrap() - .as_mut() - } - } - - pub fn on_scene_mut<'a, F>(&'a self, f: F) -> Result<()> - where - F: FnOnce(&mut Scene) -> Result<()> + 'a, - { - f(unsafe { - Self::convert_scene_ref(self.graphical.context.render_core_mut().scene_mut()) - .unwrap() - .as_mut() }) } @@ -360,17 +279,6 @@ impl Engine { LoadingScreen::load(self.context(), gui, loader, on_ready) } - pub fn set_fallback(&self, fallback: F) - where - F: Fn(anyhow::Error) -> anyhow::Result<()> + 'static + Send + Sync, - { - self.context().set_fallback(fallback); - } - - pub fn run(self: &Arc) -> Result<()> { - self.graphical.context.run() - } - pub fn new_point_light(&self) -> Result { Light::point_light(self.context().device()) } @@ -383,42 +291,6 @@ impl Engine { Light::spot_light(self.context().device()) } - pub fn window_config(&self) -> WindowConfig<'_> { - self.context().window_config() - } - - pub fn quit(&self) -> Result<()> { - self.context().close() - } - - pub fn gui_handler(&self) -> &Arc { - &self.graphical.gui_handler - } - - pub fn device(&self) -> &Arc { - self.context().device() - } - - pub fn queue(&self) -> &Arc> { - self.context().queue() - } - - pub fn sound(&self) -> MutexGuard<'_, SoundHandler> { - self.context().sound() - } - - pub fn controllers(&self) -> RwLockReadGuard<'_, Vec>>> { - self.context().controllers() - } - - pub fn active_controller(&self) -> Result>>> { - self.context().active_controller() - } - - pub fn set_active_controller(&self, controller: &Arc>) { - self.context().set_active_controller(controller); - } - pub fn controller_icon(&self, button: ControllerButton) -> Result> { Ok(self.settings().controller_icon(self, button)?.unwrap_or( self.settings() @@ -426,12 +298,8 @@ impl Engine { )) } - pub fn context(&self) -> &Arc { - &self.graphical.context - } - pub fn build_path(&self, path: &str) -> AssetPath { - (self.graphical.resource_base_path.as_str(), path).into() + (self.resource_base_path.as_str(), path).into() } pub fn assets(&self) -> AssetHandler<'_> { @@ -455,3 +323,11 @@ impl Engine { &self.engine_settings } } + +impl Drop for Engine { + fn drop(&mut self) { + self.context + .render_core() + .remove_post_processing_routine(self.gui_post_process.clone()); + } +} diff --git a/engine/src/scene/scene/scene_base.rs b/engine/src/scene/scene/scene_base.rs index 0ea1a63..95988d9 100644 --- a/engine/src/scene/scene/scene_base.rs +++ b/engine/src/scene/scene/scene_base.rs @@ -341,16 +341,71 @@ impl Scene { (((v + 1.0) / 2.0) * max) as i32 } + pub fn world_to_screen_space(&self, world_space: Vector3) -> Result<(i32, i32)> { + Self::_world_to_screen_space( + (self.screen_width, self.screen_height), + world_space, + self.view(), + ) + } + + pub fn screen_space_to_world(&self, x: u32, y: u32) -> Result>> { + let scale = self.renderer.render_scale(); + + self.renderer + .screen_to_world((x as f32 * scale) as u32, (y as f32 * scale) as u32) + } + + pub fn particle_system_vulkan_objects_mut(&mut self) -> &mut ParticleSystemVulkanObjects { + &mut self.particle_system_vulkan_objects + } + + pub fn particle_system_vulkan_objects(&self) -> &ParticleSystemVulkanObjects { + &self.particle_system_vulkan_objects + } + + pub fn add_light(&mut self, light: Light) -> Result<()> { + self.renderer.add_light(light)?; + + Ok(()) + } + + pub fn remove_light(&mut self, light: Light) -> Result<()> { + self.renderer.remove_light(light)?; + + Ok(()) + } + + pub fn clear_lights(&mut self) -> Result<()> { + self.renderer.clear_lights()?; + + Ok(()) + } + pub fn view(&self) -> &View { self.renderer.view() } - fn _process( + pub fn view_mut(&mut self) -> &mut View { + self.renderer.view_mut() + } + + pub fn render_type(&self) -> SceneType { + self.render_type + } + + pub fn frame_time(&self) -> Duration { + self.frame_time + } +} + +impl TScene for Scene { + fn process( &mut self, buffer_recorder: &mut CommandBufferRecorder<'_>, images: &TargetMode>>, indices: &TargetMode, - ) -> Result<()> { + ) -> anyhow::Result<()> { self.frame_time = { let now = self.now(); @@ -402,7 +457,7 @@ impl Scene { let frustum = view.frustum(); let planes = frustum.planes(); - let content: Vec>> = self + let content: Vec> = self .entities .par_values() .map(|entity_object| { @@ -439,70 +494,6 @@ impl Scene { Ok(()) } - pub fn world_to_screen_space(&self, world_space: Vector3) -> Result<(i32, i32)> { - Self::_world_to_screen_space( - (self.screen_width, self.screen_height), - world_space, - self.view(), - ) - } - - pub fn screen_space_to_world(&self, x: u32, y: u32) -> Result>> { - let scale = self.renderer.render_scale(); - - self.renderer - .screen_to_world((x as f32 * scale) as u32, (y as f32 * scale) as u32) - } - - pub fn particle_system_vulkan_objects_mut(&mut self) -> &mut ParticleSystemVulkanObjects { - &mut self.particle_system_vulkan_objects - } - - pub fn particle_system_vulkan_objects(&self) -> &ParticleSystemVulkanObjects { - &self.particle_system_vulkan_objects - } - - pub fn add_light(&mut self, light: Light) -> Result<()> { - self.renderer.add_light(light)?; - - Ok(()) - } - - pub fn remove_light(&mut self, light: Light) -> Result<()> { - self.renderer.remove_light(light)?; - - Ok(()) - } - - pub fn clear_lights(&mut self) -> Result<()> { - self.renderer.clear_lights()?; - - Ok(()) - } - - pub fn view_mut(&mut self) -> &mut View { - self.renderer.view_mut() - } - - pub fn render_type(&self) -> SceneType { - self.render_type - } - - pub fn frame_time(&self) -> Duration { - self.frame_time - } -} - -impl TScene for Scene { - fn process( - &mut self, - buffer_recorder: &mut CommandBufferRecorder<'_>, - images: &TargetMode>>, - indices: &TargetMode, - ) -> anyhow::Result<()> { - self._process(buffer_recorder, images, indices) - } - fn resize( &mut self, window_width: f32, diff --git a/examples/simple_window/Cargo.toml b/examples/simple_window/Cargo.toml index c833f43..30d9629 100644 --- a/examples/simple_window/Cargo.toml +++ b/examples/simple_window/Cargo.toml @@ -7,3 +7,4 @@ edition = "2024" anyhow.workspace = true ecs = { path = "../../ecs" } +engine = { path = "../../engine" } diff --git a/examples/simple_window/src/main.rs b/examples/simple_window/src/main.rs index 2c71064..3ab8015 100644 --- a/examples/simple_window/src/main.rs +++ b/examples/simple_window/src/main.rs @@ -1,9 +1,35 @@ use anyhow::Result; + use ecs::*; +use engine::prelude::*; fn main() -> Result<()> { let mut world_builder = World::builder(); - // world_builder. + + let (context, engine, scene) = Engine::new(EngineCreateInfo { + app_info: todo!(), + window_info: todo!(), + os_specific_config: todo!(), + vulkan_debug_info: todo!(), + volume_info: todo!(), + gui_info: todo!(), + enable_backtrace: todo!(), + enable_mouse: todo!(), + enable_keyboard: todo!(), + enable_controller: todo!(), + controller_deadzones: todo!(), + resource_base_path: todo!(), + controller_directories: todo!(), + asset_directories: todo!(), + graphics_info: todo!(), + raytracing_info: todo!(), + rasterizer_info: todo!(), + key_backgrounds: todo!(), + })?; + + world_builder.resources.insert(context); + world_builder.resources.insert(engine); + world_builder.resources.insert(scene); world_builder.build().run() } diff --git a/loading-screen/src/loadingscreen.rs b/loading-screen/src/loadingscreen.rs index 14d7d31..25e3f4d 100644 --- a/loading-screen/src/loadingscreen.rs +++ b/loading-screen/src/loadingscreen.rs @@ -16,7 +16,6 @@ impl LoadingScreen { where R: Fn(T) -> Result<()> + Send + Sync + 'static, T: Send + Sync + 'static, - L: FnOnce() -> T + Send + Sync + 'static, G: TopLevelGui + TopGui + Send + Sync + 'static, { @@ -32,7 +31,8 @@ impl LoadingScreen { gui.disable().unwrap(); } - context.push_event(move || (on_ready)(result)); + todo!(); + // context.push_event(move || (on_ready)(result)); }); Ok(()) diff --git a/presentation/Cargo.toml b/presentation/Cargo.toml index 06b6ea8..d97e826 100644 --- a/presentation/Cargo.toml +++ b/presentation/Cargo.toml @@ -13,6 +13,8 @@ anyhow = { workspace = true } openxr = { workspace = true, optional = true } openvr = { workspace = true, optional = true } +ecs = { path = "../ecs" } + [features] OpenXR = ["openxr"] OpenVR = ["openvr"] diff --git a/presentation/src/lib.rs b/presentation/src/lib.rs index 7933dfa..72f1eb7 100644 --- a/presentation/src/lib.rs +++ b/presentation/src/lib.rs @@ -16,6 +16,7 @@ use anyhow::Result; use traits::RenderCore; use ui::prelude::*; use vulkan_rs::prelude::*; +use wsi::vulkanwindowrendercore::VulkanWindowRenderCore; use crate::prelude::*; @@ -28,32 +29,16 @@ pub struct RenderCoreCreateInfo { pub vsync: bool, } -pub fn create_render_core( +pub fn create_render_core( presentation_core: &PresentationCore, device: &Arc, queue: &Arc>, create_info: RenderCoreCreateInfo, - create_scene: F, -) -> Result<(Box, TargetMode<()>)> -where - SCENE: TScene + 'static, - F: FnOnce( - &Arc, - &Arc>, - (f32, f32), - &TargetMode>>, - ) -> Result, -{ +) -> Result<(Box, TargetMode<()>)> { match presentation_core.backend() { PresentationBackend::Window(wsi) => { let (render_core, target_mode) = - wsi::vulkanwindowrendercore::VulkanWindowRenderCore::new( - wsi.clone(), - device, - queue, - create_info, - create_scene, - )?; + VulkanWindowRenderCore::::new(wsi.clone(), device, queue, create_info)?; Ok((Box::new(render_core), target_mode)) } diff --git a/presentation/src/presentationcore.rs b/presentation/src/presentationcore.rs index 33a6f97..f92b551 100644 --- a/presentation/src/presentationcore.rs +++ b/presentation/src/presentationcore.rs @@ -114,7 +114,7 @@ impl PresentationCore { pub fn poll_events(&self, event_callback: F, resize_event: R) -> Result where F: Fn(Event) -> Result<()>, - R: Fn(u32, u32) -> Result<()>, + R: FnMut(u32, u32) -> Result<()>, { self.event_system.poll_events(event_callback, resize_event) } @@ -169,7 +169,11 @@ impl PresentationCore { impl std::fmt::Debug for PresentationCore { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "WindowSystemIntegration {{ sdl_context: SDL2, eventsystem: EventSystem, backend: {:#?} }}", self.backend) + write!( + f, + "WindowSystemIntegration {{ sdl_context: SDL2, eventsystem: EventSystem, backend: {:#?} }}", + self.backend + ) } } diff --git a/presentation/src/renderbackend.rs b/presentation/src/renderbackend.rs index b57ae4c..48fc328 100644 --- a/presentation/src/renderbackend.rs +++ b/presentation/src/renderbackend.rs @@ -1,14 +1,16 @@ -use crate::prelude::*; use crate::Result; +use crate::prelude::*; use cgmath::{Matrix4, SquareMatrix}; +use ecs::World; use ui::prelude::*; use vulkan_rs::prelude::*; +use std::marker::PhantomData; use std::ops::Deref; use std::sync::{ - atomic::{AtomicUsize, Ordering::SeqCst}, Arc, Mutex, RwLock, + atomic::{AtomicUsize, Ordering::SeqCst}, }; #[derive(Debug, Clone, Copy, PartialEq)] @@ -47,7 +49,7 @@ impl Default for VRTransformations { } } -pub struct RenderBackend { +pub struct RenderBackend { device: Arc, queue: Arc>, @@ -59,16 +61,16 @@ pub struct RenderBackend { command_buffer: Arc, - scene: Box, post_processes: Mutex>>, + + s: PhantomData, } -impl RenderBackend { - pub fn new( +impl RenderBackend { + pub fn new( device: &Arc, queue: &Arc>, images: TargetMode>>, - scene: SCENE, ) -> Result { let image_count = match &images { TargetMode::Mono(images) => images.len(), @@ -92,8 +94,9 @@ impl RenderBackend { command_buffer, - scene: Box::new(scene), post_processes: Mutex::new(Vec::new()), + + s: PhantomData, }) } @@ -102,7 +105,7 @@ impl RenderBackend { } } -impl RenderBackend { +impl RenderBackend { pub fn device(&self) -> &Arc { &self.device } @@ -115,7 +118,11 @@ impl RenderBackend { *self.clear_color.write().unwrap() = VkClearColorValue::float32(clear_color); } - pub fn render(&mut self, image_indices: TargetMode) -> Result<&Arc> { + pub fn render( + &mut self, + world: &mut World, + image_indices: TargetMode, + ) -> Result<&Arc> { // begin main command buffer let mut buffer_recorder = self.command_buffer.begin(VkCommandBufferBeginInfo::new( VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, @@ -164,7 +171,7 @@ impl RenderBackend { } // make a call to the connected scene - self.scene.process( + world.resources.get_mut::().process( &mut buffer_recorder, &*self.swapchain_images.lock().unwrap(), &image_indices, @@ -180,6 +187,7 @@ impl RenderBackend { pub fn resize( &mut self, + world: &mut World, images: TargetMode>>, width: u32, height: u32, @@ -195,7 +203,10 @@ impl RenderBackend { SeqCst, ); - self.scene.resize(width as f32, height as f32, &images)?; + world + .resources + .get_mut::() + .resize(width as f32, height as f32, &images)?; *self.swapchain_images.lock().unwrap() = images; for post_process in self.post_processes.lock().unwrap().iter() { @@ -205,15 +216,6 @@ impl RenderBackend { Ok(()) } - // scene handling - pub fn scene(&self) -> &Box { - &self.scene - } - - pub fn scene_mut(&mut self) -> &mut Box { - &mut self.scene - } - pub fn add_post_processing_routine(&self, post_process: Arc) { let mut post_processes = self.post_processes.lock().unwrap(); @@ -254,7 +256,7 @@ impl RenderBackend { } } -impl RenderBackend { +impl RenderBackend { #[inline] fn clear_image( buffer_recorder: &mut CommandBufferRecorder<'_>, diff --git a/presentation/src/traits.rs b/presentation/src/traits.rs index 8bb84d8..494eb26 100644 --- a/presentation/src/traits.rs +++ b/presentation/src/traits.rs @@ -1,3 +1,4 @@ +use ecs::World; use ui::prelude::*; use vulkan_rs::prelude::*; @@ -36,9 +37,9 @@ pub trait PostProcess: Send + Sync { } pub trait RenderCore: std::fmt::Debug + Send + Sync { - fn next_frame(&mut self) -> Result; + fn next_frame(&mut self, world: &mut World) -> Result; - fn resize(&mut self, w: u32, h: u32) -> Result<()>; + fn resize(&mut self, world: &mut World, w: u32, h: u32) -> Result<()>; fn format(&self) -> VkFormat; fn image_layout(&self) -> VkImageLayout { @@ -47,10 +48,6 @@ pub trait RenderCore: std::fmt::Debug + Send + Sync { fn set_clear_color(&self, color: [f32; 4]); - // scene handling - fn scene(&self) -> &Box; - fn scene_mut(&mut self) -> &mut Box; - // post process handling fn add_post_processing_routine(&self, post_process: Arc); fn remove_post_processing_routine(&self, post_process: Arc); diff --git a/presentation/src/vri/mod.rs b/presentation/src/vri/mod.rs index 57a4bab..6415aa0 100644 --- a/presentation/src/vri/mod.rs +++ b/presentation/src/vri/mod.rs @@ -48,6 +48,7 @@ pub mod openvrrendercore; #[cfg(not(feature = "OpenVR"))] pub mod openvrrendercore { use crate::Result; + use ecs::World; use ui::prelude::*; use vulkan_rs::prelude::*; @@ -55,8 +56,8 @@ pub mod openvrrendercore { use super::openvrintegration::OpenVRIntegration; - use crate::prelude::*; use crate::RenderCoreCreateInfo; + use crate::prelude::*; pub struct OpenVRRenderCore { _dummy: u32, @@ -78,11 +79,11 @@ pub mod openvrrendercore { unimplemented!() } - fn resize(&mut self, _: u32, _: u32) -> Result<()> { + fn resize(&mut self, _: &mut World, _: u32, _: u32) -> Result<()> { unimplemented!() } - fn next_frame(&mut self) -> Result { + fn next_frame(&mut self, _: &mut World) -> Result { unimplemented!() } @@ -90,15 +91,6 @@ pub mod openvrrendercore { unimplemented!() } - // scene handling - fn scene(&self) -> &Box { - unimplemented!() - } - - fn scene_mut(&mut self) -> &mut Box { - unimplemented!() - } - // post process handling fn add_post_processing_routine(&self, _post_process: Arc) { unimplemented!() diff --git a/presentation/src/wsi/vulkanwindowrendercore.rs b/presentation/src/wsi/vulkanwindowrendercore.rs index 207e1d2..6f52fda 100644 --- a/presentation/src/wsi/vulkanwindowrendercore.rs +++ b/presentation/src/wsi/vulkanwindowrendercore.rs @@ -1,19 +1,20 @@ -use crate::{prelude::*, renderbackend::RenderBackend, RenderCoreCreateInfo}; +use crate::{RenderCoreCreateInfo, prelude::*, renderbackend::RenderBackend}; use super::windowsystemintegration::WindowSystemIntegration; use crate::Result; +use ecs::World; // use ui::prelude::*; use vulkan_rs::prelude::*; use std::sync::{ - atomic::{AtomicUsize, Ordering::SeqCst}, Arc, Mutex, RwLock, + atomic::{AtomicUsize, Ordering::SeqCst}, }; use std::time::Duration; use std::u64; -pub struct VulkanWindowRenderCore { +pub struct VulkanWindowRenderCore { device: Arc, // driver provided images @@ -26,30 +27,20 @@ pub struct VulkanWindowRenderCore { render_finished_sem: Arc, render_fence: Arc, - render_backend: RenderBackend, + render_backend: RenderBackend, current_image_index: AtomicUsize, wsi: Arc, } -impl VulkanWindowRenderCore { - pub fn new( +impl VulkanWindowRenderCore { + pub fn new( wsi: Arc, device: &Arc, queue: &Arc>, create_info: RenderCoreCreateInfo, - create_scene: F, - ) -> Result<(Self, TargetMode<()>)> - where - SCENE: TScene + 'static, - F: FnOnce( - &Arc, - &Arc>, - (f32, f32), - &TargetMode>>, - ) -> Result, - { + ) -> Result<(Self, TargetMode<()>)> { // check swapchain extension if !device.enabled_extensions().swapchain { return Err(anyhow::Error::msg("Swapchain Extension must be enabled")); @@ -66,7 +57,7 @@ impl VulkanWindowRenderCore { ))); } - let usage = create_info.usage | RenderBackend::required_image_usage(); + let usage = create_info.usage | RenderBackend::::required_image_usage(); // create swapchain let swapchain = Swapchain::new( @@ -87,14 +78,8 @@ impl VulkanWindowRenderCore { let fence = Fence::builder().build(device.clone())?; let images = TargetMode::Mono(swapchain_images); - let scene = create_scene( - device, - queue, - (swapchain.width() as f32, swapchain.height() as f32), - &images, - )?; - let render_backend = RenderBackend::new(device, queue, images, scene)?; + let render_backend = RenderBackend::new(device, queue, images)?; let window_render_core = VulkanWindowRenderCore { device: device.clone(), @@ -118,7 +103,7 @@ impl VulkanWindowRenderCore { Ok((window_render_core, TargetMode::Mono(()))) } - fn aquire_next_image_index(&mut self) -> Result<()> { + fn aquire_next_image_index(&mut self, world: &mut World) -> Result<()> { // there was a bug that a windows never reacted after it was minimized // with this timeout, the window has 250ms delay #[cfg(target_os = "windows")] @@ -141,7 +126,7 @@ impl VulkanWindowRenderCore { } OutOfDate::OutOfDate => { let (w, h) = self.wsi.window_size(); - resize_mut.resize(w, h)?; + resize_mut.resize(world, w, h)?; *semaphore = Semaphore::new(self.device.clone())?; } @@ -155,12 +140,12 @@ impl VulkanWindowRenderCore { } } -impl RenderCore for VulkanWindowRenderCore { +impl RenderCore for VulkanWindowRenderCore { fn format(&self) -> VkFormat { self.format } - fn resize(&mut self, w: u32, h: u32) -> Result<()> { + fn resize(&mut self, world: &mut World, w: u32, h: u32) -> Result<()> { self.swapchain.recreate((w, h))?; let swapchain_images = self.swapchain.wrap_images( @@ -170,6 +155,7 @@ impl RenderCore for VulkanWindowRenderCore { )?; self.render_backend.resize( + world, TargetMode::Mono(swapchain_images), self.swapchain.width(), self.swapchain.height(), @@ -178,12 +164,13 @@ impl RenderCore for VulkanWindowRenderCore { Ok(()) } - fn next_frame(&mut self) -> Result { - self.aquire_next_image_index()?; + fn next_frame(&mut self, world: &mut World) -> Result { + self.aquire_next_image_index(world)?; - let command_buffer = self - .render_backend - .render(TargetMode::Mono(self.current_image_index.load(SeqCst)))?; + let command_buffer = self.render_backend.render( + world, + TargetMode::Mono(self.current_image_index.load(SeqCst)), + )?; let submits = &[SubmitInfo::default() .add_wait_semaphore( @@ -205,7 +192,7 @@ impl RenderCore for VulkanWindowRenderCore { )? } { let (w, h) = self.wsi.window_size(); - self.resize(w, h)?; + self.resize(world, w, h)?; self.render_fence.reset(); return Ok(true); } @@ -225,15 +212,6 @@ impl RenderCore for VulkanWindowRenderCore { self.render_backend.set_clear_color(color); } - // scene handling - fn scene(&self) -> &Box { - self.render_backend.scene() - } - - fn scene_mut(&mut self) -> &mut Box { - self.render_backend.scene_mut() - } - // post process handling fn add_post_processing_routine(&self, post_process: Arc) { self.render_backend @@ -271,7 +249,7 @@ impl RenderCore for VulkanWindowRenderCore { } } -impl std::fmt::Debug for VulkanWindowRenderCore { +impl std::fmt::Debug for VulkanWindowRenderCore { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "VulkanWindowRenderCore {{ }}") } diff --git a/presentation/src/wsi/windowsystemintegration.rs b/presentation/src/wsi/windowsystemintegration.rs index 5d06fc7..bad05c1 100644 --- a/presentation/src/wsi/windowsystemintegration.rs +++ b/presentation/src/wsi/windowsystemintegration.rs @@ -3,13 +3,13 @@ use anyhow::Error; use sdl2; +use sdl2::Sdl; use sdl2::clipboard::ClipboardUtil; -use sdl2::messagebox::{show_simple_message_box, MessageBoxFlag}; +use sdl2::messagebox::{MessageBoxFlag, show_simple_message_box}; use sdl2::mouse::Cursor; use sdl2::surface::Surface as SDL_Surface; use sdl2::sys::SDL_Window; use sdl2::video::{FullscreenType, WindowPos}; -use sdl2::Sdl; use crate::Result; use vulkan_rs::prelude::*; @@ -18,8 +18,8 @@ use std::mem::MaybeUninit; use std::ops::Deref; use std::path::Path; use std::sync::{ - atomic::{AtomicI32, AtomicU32, Ordering::SeqCst}, Arc, Mutex, + atomic::{AtomicI32, AtomicU32, Ordering::SeqCst}, }; const SDL_SYSWM_WINDOWS: u32 = 0x1; @@ -35,7 +35,7 @@ struct SdlSysWmInfo { info: [u64; 32], } -extern "C" { +unsafe extern "C" { fn SDL_GetWindowWMInfo(window: *const sdl2::sys::SDL_Window, info: *mut SdlSysWmInfo) -> bool; } @@ -421,7 +421,7 @@ impl WindowSystemIntegration { return Err(anyhow::Error::msg(format!( "Unsupported window subsystem flag {}", sys_wm_info.subsystem - ))) + ))); } } diff --git a/presentation/src/xri/mod.rs b/presentation/src/xri/mod.rs index 8eca206..7d17581 100644 --- a/presentation/src/xri/mod.rs +++ b/presentation/src/xri/mod.rs @@ -46,6 +46,7 @@ pub mod openxrrendercore; #[cfg(not(feature = "OpenXR"))] pub mod openxrrendercore { use crate::Result; + use ecs::World; use ui::prelude::*; use vulkan_rs::prelude::*; @@ -53,8 +54,8 @@ pub mod openxrrendercore { use super::openxrintegration::OpenXRIntegration; - use crate::prelude::*; use crate::RenderCoreCreateInfo; + use crate::prelude::*; pub struct OpenXRRenderCore { _dummy: u32, @@ -76,11 +77,11 @@ pub mod openxrrendercore { unimplemented!() } - fn resize(&mut self, _: u32, _: u32) -> Result<()> { + fn resize(&mut self, _: &mut World, _: u32, _: u32) -> Result<()> { unimplemented!() } - fn next_frame(&mut self) -> Result { + fn next_frame(&mut self, _: &mut World) -> Result { unimplemented!() } @@ -88,15 +89,6 @@ pub mod openxrrendercore { unimplemented!() } - // scene handling - fn scene(&self) -> &Box { - unimplemented!() - } - - fn scene_mut(&mut self) -> &mut Box { - unimplemented!() - } - // post process handling fn add_post_processing_routine(&self, _post_process: Arc) { unimplemented!()