diff --git a/context/src/core/context.rs b/context/src/core/context.rs index b50037c..88c9d4c 100644 --- a/context/src/core/context.rs +++ b/context/src/core/context.rs @@ -58,18 +58,18 @@ impl Context { &mut self.sound_handler } - pub fn next_frame<'a, C, F>(&mut self, world: &mut World, mut f: F) -> Result + pub fn events<'a, F>(&mut self, world: &World, mut f: F) -> Result where - C: ResourceTrait + Send + Sync + 'static, - F: FnMut(&mut World, &mut C, Event<'_>) -> Result<()> + Send + Sync + 'a, + F: FnMut(Event<'_>) -> Result<()> + Send + Sync + 'a, { let render_core = self.render_core.clone(); - let consumer = world.resources.get_mut_unchecked::(); - let w = unsafe { remove_life_time_mut(world) }; match self.presentation.poll_events( - |event| f(w, consumer, event), - |w, h| render_core.write().unwrap().resize(world, w, h), + |event| f(event), + |w, h| { + render_core.write().unwrap().resize(world, w, h); + Ok(()) + }, ) { Ok(res) => { if !res { @@ -84,13 +84,28 @@ impl Context { } } - if !self.render_core_mut().next_frame(world)? { - return Ok(false); - } - Ok(true) } + pub fn start_frame(&self, world: &World) -> Result<()> { + self.render_core_mut().begin_frame(world) + } + + pub fn render(&self, render: F) -> Result<()> + where + F: FnOnce( + &mut CommandBufferRecorder<'_>, + &TargetMode>>, + &TargetMode, + ) -> Result<()>, + { + self.render_core_mut().render(render) + } + + pub fn end_frame(&self, world: &World) -> Result<()> { + self.render_core_mut().end_frame(world) + } + pub fn render_core(&self) -> impl Deref + '_ { self.render_core.read().unwrap() } diff --git a/engine/src/engine/engine.rs b/engine/src/engine/engine.rs index 5af6829..32efd44 100644 --- a/engine/src/engine/engine.rs +++ b/engine/src/engine/engine.rs @@ -14,33 +14,6 @@ use crate::prelude::*; use std::collections::HashMap; use std::sync::Arc; -#[derive(Resource)] -pub struct GuiHandlerRenderer; - -impl TScene for GuiHandlerRenderer { - fn process( - &mut self, - buffer_recorder: &mut CommandBufferRecorder<'_>, - _images: &TargetMode>>, - indices: &TargetMode, - world: &mut World, - ) -> Result<()> { - let gui_handler: &mut GuiHandler = world.resources.get_mut()?; - gui_handler.process(buffer_recorder, indices) - } - - fn resize( - &mut self, - window_width: f32, - window_height: f32, - images: &TargetMode>>, - world: &mut World, - ) -> Result<()> { - let gui_handler: &mut GuiHandler = world.resources.get_mut()?; - gui_handler.resize(window_width as u32, window_height as u32, images) - } -} - #[derive(Resource)] pub struct Engine { pub(crate) resource_base_path: String, @@ -173,11 +146,6 @@ impl Engine { let asset_manager = AssetManager::new(&engine_settings)?; let gui_handler = GuiHandler::new(create_info.gui_info, &context)?; - context - .render_core_mut() - .add_render_routine::(10_000_000); - context.render_core_mut().add_render_routine::(100); - world.resources.insert(context); Scene::new( @@ -195,7 +163,6 @@ impl Engine { direction_mapping.insert(Keycode::Down, GuiDirection::Down); world.resources.insert(gui_handler); - world.resources.insert(GuiHandlerRenderer); world.resources.insert(InputMap { direction_mapping }); world.resources.insert(asset_manager); world.resources.insert(Engine { @@ -203,7 +170,12 @@ impl Engine { }); world.resources.insert(engine_settings); - world.add_system(1_000_000, Self::main_system::); + world.add_system(0, Self::event_system::); + world.add_system(1, Self::start_frame); + world.add_system(u32::MAX, Self::end_frame); + + world.add_system(100, Self::render_scene); + world.add_system(10_000_000, Self::render_gui); Ok(()) } @@ -246,20 +218,63 @@ impl Engine { } impl Engine { - fn main_system(world: &mut World) -> Result { - let gui_handler = world.resources.get_mut_unchecked::(); - let input_map = world.resources.get_unchecked::(); - let context = world.resources.get_unchecked::(); + fn event_system( + world: &World, + commands: &mut Commands, + consumer: &mut T, + gui_handler: &mut GuiHandler, + input_map: &mut InputMap, + context: &mut Context, + ) -> Result { + let res = context.events(world, |event| { + Self::event(commands, gui_handler, input_map, consumer, event) + })?; - let res = world.resources.get_mut_unchecked::().next_frame( - world, - |world, consumer: &mut T, event| { - Self::event(world, context, gui_handler, input_map, consumer, event) - }, - )?; - - gui_handler.process_callbacks(world)?; + gui_handler.process_callbacks(commands)?; Ok(res) } + + fn start_frame(world: &World, _commands: &mut Commands, context: &mut Context) -> Result { + context.start_frame(world)?; + + Ok(true) + } + + fn end_frame(world: &World, _commands: &mut Commands, context: &mut Context) -> Result { + context.end_frame(world)?; + + Ok(true) + } + + fn render_scene( + world: &World, + _commands: &mut Commands, + context: &mut Context, + scene: &mut Scene, + ) -> Result { + context.render( + |recorder: &mut CommandBufferRecorder<'_>, + images: &TargetMode>>, + indices: &TargetMode| { + scene.process(recorder, images, indices, world) + }, + )?; + + Ok(true) + } + + fn render_gui( + _commands: &mut Commands, + context: &mut Context, + gui_handler: &mut GuiHandler, + ) -> Result { + context.render( + |recorder: &mut CommandBufferRecorder<'_>, + _images: &TargetMode>>, + indices: &TargetMode| { gui_handler.process(recorder, indices) }, + )?; + + Ok(true) + } } diff --git a/engine/src/engine/engine_event_handling.rs b/engine/src/engine/engine_event_handling.rs index 6e9a925..051db78 100644 --- a/engine/src/engine/engine_event_handling.rs +++ b/engine/src/engine/engine_event_handling.rs @@ -29,7 +29,7 @@ pub enum EngineEvent<'a> { } pub trait EventConsumer: Send + Sync + 'static { - fn event(&mut self, world: &mut World, event: EngineEvent<'_>) -> Result<()>; + fn event(&mut self, commands: &mut Commands, event: EngineEvent<'_>) -> Result<()>; } #[derive(Resource)] @@ -39,8 +39,7 @@ pub struct InputMap { impl Engine { pub(crate) fn event( - world: &mut World, - context: &Context, + commands: &mut Commands, gui_handler: &mut GuiHandler, input: &InputMap, consumer: &mut T, @@ -49,68 +48,70 @@ impl Engine { match event { Event::MouseMotion(x, y) => { gui_handler.set_mouse_pos(x, y)?; - consumer.event(world, EngineEvent::MouseMotion(x, y))?; + consumer.event(commands, EngineEvent::MouseMotion(x, y))?; } Event::MouseButtonDown(mouse_button) => { if !gui_handler.mouse_down(mouse_button)? { - consumer.event(world, EngineEvent::MouseButtonDown(mouse_button))?; + consumer.event(commands, EngineEvent::MouseButtonDown(mouse_button))?; } } Event::MouseButtonUp(mouse_button) => { if !gui_handler.mouse_up(mouse_button)? { - consumer.event(world, EngineEvent::MouseButtonUp(mouse_button))?; + consumer.event(commands, EngineEvent::MouseButtonUp(mouse_button))?; } } Event::MouseWheel(x, y, direction) => { - consumer.event(world, EngineEvent::MouseWheel(x, y, direction))? + consumer.event(commands, EngineEvent::MouseWheel(x, y, direction))? } Event::KeyDown(keycode) => { - Self::key_down_event(world, context, gui_handler, input, consumer, keycode)?; + Self::key_down_event(commands, gui_handler, input, consumer, keycode)?; } Event::KeyUp(keycode) => { - Self::key_up_event(world, gui_handler, input, consumer, keycode)?; + Self::key_up_event(commands, gui_handler, input, consumer, keycode)?; } Event::TextInput(text) => { Self::text_input(gui_handler, text)?; } Event::ControllerButtonDown(controller, button) => { - Self::button_down_event(world, gui_handler, consumer, controller, button)?; + Self::button_down_event(commands, gui_handler, consumer, controller, button)?; } Event::ControllerButtonUp(controller, button) => { - Self::button_up_event(world, consumer, controller, button)?; + Self::button_up_event(commands, consumer, controller, button)?; } Event::ControllerAxis(controller) => { if !gui_handler.check_navigatable() { - Self::axis_event(world, consumer, &controller)? + Self::axis_event(commands, consumer, &controller)? } else { gui_handler.update_selection(controller.direction())?; } } Event::ControllerAdded(controller) => { - Self::controller_added(world, consumer, controller)? + Self::controller_added(commands, consumer, controller)? } Event::ControllerRemoved(controller) => { - Self::controller_removed(world, consumer, controller)? + Self::controller_removed(commands, consumer, controller)? } Event::JoystickAxis(joystick, axis_index, value) => consumer.event( - world, + commands, EngineEvent::JoystickAxis(joystick, axis_index, value), )?, Event::JoystickButtonDown(joystick) => { - consumer.event(world, EngineEvent::JoystickButtonDown(joystick))? + consumer.event(commands, EngineEvent::JoystickButtonDown(joystick))? } Event::JoystickButtonUp(joystick) => { - consumer.event(world, EngineEvent::JoystickButtonUp(joystick))? + consumer.event(commands, EngineEvent::JoystickButtonUp(joystick))? } Event::JoystickAdded(joystick) => { - consumer.event(world, EngineEvent::JoystickAdded(joystick))? + consumer.event(commands, EngineEvent::JoystickAdded(joystick))? } Event::JoystickRemoved(joystick) => { - consumer.event(world, EngineEvent::JoystickRemoved(joystick))? + consumer.event(commands, EngineEvent::JoystickRemoved(joystick))? } - Event::FileDrop(filename) => consumer.event(world, EngineEvent::FileDrop(filename))?, + Event::FileDrop(filename) => { + consumer.event(commands, EngineEvent::FileDrop(filename))? + } } Ok(()) @@ -120,29 +121,29 @@ impl Engine { impl Engine { #[inline] fn controller_added( - world: &mut World, + commands: &mut Commands, consumer: &mut T, controller: &Controller, ) -> Result<()> { - consumer.event(world, EngineEvent::ControllerAdded(controller))?; + consumer.event(commands, EngineEvent::ControllerAdded(controller))?; Ok(()) } #[inline] fn controller_removed( - world: &mut World, + commands: &mut Commands, consumer: &mut T, controller: &Controller, ) -> Result<()> { - consumer.event(world, EngineEvent::ControllerRemoved(controller))?; + consumer.event(commands, EngineEvent::ControllerRemoved(controller))?; Ok(()) } #[inline] fn key_up_event( - world: &mut World, + commands: &mut Commands, gui_handler: &mut GuiHandler, input: &InputMap, consumer: &mut T, @@ -154,15 +155,14 @@ impl Engine { return Ok(()); } - consumer.event(world, EngineEvent::KeyUp(keycode))?; + consumer.event(commands, EngineEvent::KeyUp(keycode))?; Ok(()) } #[inline] fn key_down_event( - world: &mut World, - context: &Context, + commands: &mut Commands, gui_handler: &mut GuiHandler, input: &InputMap, consumer: &mut T, @@ -186,50 +186,49 @@ impl Engine { } } Keycode::Escape => { - if gui_handler.decline_topgui(world)? { + if gui_handler.decline_topgui(commands)? { return Ok(()); } } - Keycode::V => { - if let Some(writeable) = gui_handler.writeable() { - if let Some(content) = context.window_config().clipboard_content()? { - writeable.set_text(gui_handler, content)?; - } - } - } _ => (), } - consumer.event(world, EngineEvent::KeyDown(keycode))?; + consumer.event(commands, EngineEvent::KeyDown(keycode))?; Ok(()) } #[inline] fn button_up_event( - world: &mut World, + commands: &mut Commands, consumer: &mut T, controller: &Controller, button: ControllerButton, ) -> Result<()> { - consumer.event(world, EngineEvent::ControllerButtonUp(controller, button))?; + consumer.event( + commands, + EngineEvent::ControllerButtonUp(controller, button), + )?; Ok(()) } #[inline] fn button_down_event( - world: &mut World, + commands: &mut Commands, gui_handler: &mut GuiHandler, consumer: &mut T, controller: &Controller, button: ControllerButton, ) -> Result<()> { if gui_handler.check_navigatable() { - Self::check_button_down(world, gui_handler, consumer, controller, button)?; + Self::check_button_down(commands, gui_handler, consumer, controller, button)?; } else { - consumer.event(world, EngineEvent::ControllerButtonDown(controller, button))?; + consumer.event( + commands, + EngineEvent::ControllerButtonDown(controller, button), + )?; } Ok(()) @@ -237,12 +236,12 @@ impl Engine { #[inline] fn axis_event( - world: &mut World, + commands: &mut Commands, consumer: &mut T, controller: &Controller, ) -> Result<()> { consumer.event( - world, + commands, EngineEvent::ControllerAxis(controller, controller.controller_axis()), )?; @@ -251,7 +250,7 @@ impl Engine { #[inline] fn check_button_down( - world: &mut World, + commands: &mut Commands, gui_handler: &mut GuiHandler, consumer: &mut T, controller: &Controller, @@ -265,31 +264,31 @@ impl Engine { } ControllerButton::B => { - if gui_handler.decline_topgui(world)? { + if gui_handler.decline_topgui(commands)? { return Ok(()); } } ControllerButton::RightButton => { - if gui_handler.next_tab_topgui(world, false)? { + if gui_handler.next_tab_topgui(commands, false)? { return Ok(()); } } ControllerButton::LeftButton => { - if gui_handler.previous_tab_topgui(world, false)? { + if gui_handler.previous_tab_topgui(commands, false)? { return Ok(()); } } ControllerButton::RightTrigger => { - if gui_handler.next_tab_topgui(world, true)? { + if gui_handler.next_tab_topgui(commands, true)? { return Ok(()); } } ControllerButton::LeftTrigger => { - if gui_handler.previous_tab_topgui(world, true)? { + if gui_handler.previous_tab_topgui(commands, true)? { return Ok(()); } } @@ -333,8 +332,11 @@ impl Engine { _ => (), } - if !gui_handler.accept_custom_selection(world, button)? { - consumer.event(world, EngineEvent::ControllerButtonDown(controller, button))?; + if !gui_handler.accept_custom_selection(commands, button)? { + consumer.event( + commands, + EngineEvent::ControllerButtonDown(controller, button), + )?; } Ok(()) diff --git a/engine/src/scene/scene/scene_base.rs b/engine/src/scene/scene/scene_base.rs index 59ff82c..e434f53 100644 --- a/engine/src/scene/scene/scene_base.rs +++ b/engine/src/scene/scene/scene_base.rs @@ -383,7 +383,7 @@ impl TScene for Scene { buffer_recorder: &mut CommandBufferRecorder<'_>, images: &TargetMode>>, indices: &TargetMode, - world: &mut World, + world: &World, ) -> anyhow::Result<()> { self.frame_time = { let now = world.now(); @@ -484,7 +484,7 @@ impl TScene for Scene { window_width: f32, window_height: f32, images: &TargetMode>>, - _world: &mut World, + _world: &World, ) -> anyhow::Result<()> { self.screen_width = window_width; self.screen_height = window_height; diff --git a/examples/free_space/src/game.rs b/examples/free_space/src/game.rs index c2a390f..c2c74eb 100644 --- a/examples/free_space/src/game.rs +++ b/examples/free_space/src/game.rs @@ -109,11 +109,14 @@ impl InputSettings { pub struct Game; impl Game { - pub fn update(&mut self, world: &mut World) -> Result<()> { + pub fn update( + &mut self, + commands: &mut Commands, + scene: &mut Scene, + camera_control: &mut FreeCameraControl, + ) -> Result<()> { if FREE_CAMERA_CONTROL { - let now = world.now(); - let (scene, camera_control): (&mut Scene, &mut FreeCameraControl) = - world.resources.get_mut()?; + let now = commands.now(); camera_control.update(now, scene.view_mut())?; } @@ -121,7 +124,7 @@ impl Game { Ok(()) } - pub fn event(&mut self, world: &mut World, event: EngineEvent<'_>) -> Result<()> { + pub fn event(&mut self, commands: &mut Commands, event: EngineEvent<'_>) -> Result<()> { if let Some(event) = Self::motion_concepts(world, event)? { match event { EngineEvent::JoystickAdded(joystick) => { diff --git a/examples/free_space/src/game_state.rs b/examples/free_space/src/game_state.rs index d234e96..1f0964d 100644 --- a/examples/free_space/src/game_state.rs +++ b/examples/free_space/src/game_state.rs @@ -14,12 +14,15 @@ pub enum GameState { } impl GameState { - pub fn update(world: &mut World) -> Result { - let me = world.resources.get_mut_unchecked::(); - - match me { - GameState::Startup => *me = GameState::Game(Game), - GameState::Game(game) => game.update(world)?, + pub fn update( + commands: &mut Commands, + game_state: &mut GameState, + scene: &mut Scene, + camera_control: &mut FreeCameraControl, + ) -> Result { + match game_state { + GameState::Startup => *game_state = GameState::Game(Game), + GameState::Game(game) => game.update(commands, scene, camera_control)?, } Ok(true) @@ -27,10 +30,10 @@ impl GameState { } impl EventConsumer for GameState { - fn event(&mut self, world: &mut World, event: EngineEvent<'_>) -> Result<()> { + fn event(&mut self, commands: &mut Commands, event: EngineEvent<'_>) -> Result<()> { match self { GameState::Startup => (), - GameState::Game(game) => game.event(world, event)?, + GameState::Game(game) => game.event(commands, event)?, } Ok(()) diff --git a/examples/simple_window/src/main.rs b/examples/simple_window/src/main.rs index 75f103e..1e96a73 100644 --- a/examples/simple_window/src/main.rs +++ b/examples/simple_window/src/main.rs @@ -3,6 +3,13 @@ use anyhow::Result; use ecs::*; use engine::prelude::*; +struct CameraControlStart; +struct CameraControlEnd; +struct CameraControlMove { + x: u32, + y: u32, +} + fn main() -> Result<()> { let mut world_builder = World::builder(); @@ -11,6 +18,16 @@ fn main() -> Result<()> { world_builder.add_system(10, GameState::update); world_builder.resources.insert(GameState::default()); + world_builder.events.register_event::(); + world_builder.events.register_event::(); + world_builder.events.register_event::(); + + world_builder.events.add_reader(Game::enable_camera_control); + world_builder + .events + .add_reader(Game::disable_camera_control); + world_builder.events.add_reader(Game::update_mouse); + let scene: &mut Scene = world_builder.resources.get_mut()?; let view = scene.view_mut(); let camera_control = FreeCameraControl::new(view)?; @@ -28,12 +45,10 @@ enum GameState { } impl GameState { - fn update(world: &mut World) -> Result { - let me = world.resources.get_mut_unchecked::(); - - match me { - GameState::Startup => *me = GameState::Game(Game), - GameState::Game(game) => game.update(world)?, + fn update(commands: &mut Commands, game_state: &mut GameState) -> Result { + match game_state { + GameState::Startup => *game_state = GameState::Game(Game), + GameState::Game(game) => game.update(commands)?, } Ok(true) @@ -41,10 +56,10 @@ impl GameState { } impl EventConsumer for GameState { - fn event(&mut self, world: &mut World, event: EngineEvent<'_>) -> Result<()> { + fn event(&mut self, commands: &mut Commands, event: EngineEvent<'_>) -> Result<()> { match self { GameState::Startup => (), - GameState::Game(game) => game.event(world, event)?, + GameState::Game(game) => game.event(commands, event)?, } Ok(()) @@ -54,26 +69,48 @@ impl EventConsumer for GameState { struct Game; impl Game { - fn update(&mut self, _world: &mut World) -> Result<()> { + fn enable_camera_control( + _: &CameraControlStart, + _commands: &mut Commands, + camera_control: &mut FreeCameraControl, + ) -> Result<()> { + camera_control.mouse_down(); + Ok(()) } - fn event(&mut self, world: &mut World, event: EngineEvent<'_>) -> Result<()> { + fn disable_camera_control( + _: &CameraControlEnd, + _commands: &mut Commands, + camera_control: &mut FreeCameraControl, + ) -> Result<()> { + camera_control.mouse_release(); + + Ok(()) + } + + fn update_mouse( + camera_move: &CameraControlMove, + _commands: &mut Commands, + camera_control: &mut FreeCameraControl, + scene: &mut Scene, + ) -> Result<()> { + camera_control.mouse_move(camera_move.x, camera_move.y, scene.view_mut())?; + + Ok(()) + } + + fn update(&mut self, _commands: &mut Commands) -> Result<()> { + Ok(()) + } + + fn event(&mut self, commands: &mut Commands, event: EngineEvent<'_>) -> Result<()> { match event { EngineEvent::MouseButtonDown(MouseButton::Left) => { - let camera_control: &mut FreeCameraControl = world.resources.get_mut()?; - camera_control.mouse_down(); - } - EngineEvent::MouseButtonUp(MouseButton::Left) => { - let camera_control: &mut FreeCameraControl = world.resources.get_mut()?; - camera_control.mouse_release(); - } - EngineEvent::MouseMotion(x, y) => { - let (scene, camera_control): (&mut Scene, &mut FreeCameraControl) = - world.resources.get_mut()?; - - camera_control.mouse_move(x, y, scene.view_mut())?; + commands.write_event(CameraControlStart) } + EngineEvent::MouseButtonUp(MouseButton::Left) => commands.write_event(CameraControlEnd), + EngineEvent::MouseMotion(x, y) => commands.write_event(CameraControlMove { x, y }), _ => (), } diff --git a/loading-screen/src/loadingscreen.rs b/loading-screen/src/loadingscreen.rs index 50aef93..44579af 100644 --- a/loading-screen/src/loadingscreen.rs +++ b/loading-screen/src/loadingscreen.rs @@ -1,5 +1,5 @@ use context::prelude::*; -use ecs::World; +use ecs::Commands; use std::{ sync::{ @@ -26,13 +26,18 @@ where T: Send + Sync + 'static, G: TopLevelGui + TopGui + Send + Sync + 'static, { - pub fn load(world: &mut World, gui: Arc, loader: L) -> Result + pub fn load( + commands: &mut Commands, + gui_handler: &mut GuiHandler, + gui: Arc, + loader: L, + ) -> Result where R: Fn(T) -> Result<()> + Send + Sync + 'static, T: Send + Sync + 'static, L: FnOnce() -> T + Send + Sync + 'static, { - gui.enable(world)?; + gui.enable(commands, gui_handler)?; let (sender, receiver) = channel(); @@ -61,8 +66,12 @@ where } } - pub fn take_result(mut self, world: &mut World) -> Result { - self.gui.disable(world)?; + pub fn take_result( + mut self, + commands: &mut Commands, + gui_handler: &mut GuiHandler, + ) -> Result { + self.gui.disable(commands, gui_handler)?; self.result .take() .ok_or(anyhow!("missing loading screen payload!")) diff --git a/presentation/src/renderbackend.rs b/presentation/src/renderbackend.rs index 669335f..be75df5 100644 --- a/presentation/src/renderbackend.rs +++ b/presentation/src/renderbackend.rs @@ -1,12 +1,10 @@ use crate::Result; -use crate::prelude::*; use cgmath::{Matrix4, SquareMatrix}; use ecs::World; use ui::prelude::*; use vulkan_rs::prelude::*; -use std::any::TypeId; use std::ops::Deref; use std::sync::{ Arc, Mutex, RwLock, @@ -49,52 +47,6 @@ impl Default for VRTransformations { } } -struct SceneHandle { - type_id: TypeId, - priority: u32, - - render: Box< - dyn FnMut( - &mut CommandBufferRecorder<'_>, - &TargetMode>>, - &TargetMode, - &mut World, - ) -> Result<()> - + Send - + Sync - + 'static, - >, - - resize: Box< - dyn FnMut(f32, f32, &TargetMode>>, &mut World) -> Result<()> - + Send - + Sync - + 'static, - >, -} - -impl SceneHandle { - fn new(priority: u32) -> Self { - Self { - type_id: TypeId::of::(), - priority, - render: Box::new(|recorder, images, indices, world| { - world - .resources - .get_mut_unchecked::() - .process(recorder, images, indices, world) - }), - - resize: Box::new(|width, height, images, world| { - world - .resources - .get_mut_unchecked::() - .resize(width, height, images, world) - }), - } - } -} - pub struct RenderBackend { device: Arc, queue: Arc>, @@ -106,10 +58,12 @@ pub struct RenderBackend { clear_color: RwLock, command_buffer: Arc, - - render_routines: Vec, + buffer_recorder: Option>, } +unsafe impl Send for RenderBackend {} +unsafe impl Sync for RenderBackend {} + impl RenderBackend { pub fn new( device: &Arc, @@ -137,8 +91,7 @@ impl RenderBackend { clear_color: RwLock::new(VkClearColorValue::float32([0.0, 0.0, 0.0, 1.0])), command_buffer, - - render_routines: Vec::new(), + buffer_recorder: None, }) } @@ -160,11 +113,7 @@ impl RenderBackend { *self.clear_color.write().unwrap() = VkClearColorValue::float32(clear_color); } - pub fn render( - &mut self, - world: &mut World, - image_indices: TargetMode, - ) -> Result<&Arc> { + pub fn begin_frame(&mut self, image_indices: TargetMode) -> Result<()> { // begin main command buffer let mut buffer_recorder = self.command_buffer.begin(VkCommandBufferBeginInfo::new( VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, @@ -212,27 +161,39 @@ impl RenderBackend { } } - // make a call to the connected scenes - self.render_routines - .iter_mut() - .try_for_each(|scene_handle| { - (scene_handle.render)( - &mut buffer_recorder, - &*self.swapchain_images.lock().unwrap(), - &image_indices, - world, - ) - })?; + self.buffer_recorder = Some(unsafe { std::mem::transmute(buffer_recorder) }); - Ok(&self.command_buffer) + Ok(()) + } + + pub fn render(&mut self, image_indices: TargetMode, render: F) -> Result<()> + where + F: FnOnce( + &mut CommandBufferRecorder<'_>, + &TargetMode>>, + &TargetMode, + ) -> Result<()>, + { + render( + self.buffer_recorder.as_mut().unwrap(), + &*self.swapchain_images.lock().unwrap(), + &image_indices, + )?; + + Ok(()) + } + + pub fn end_frame(&mut self) -> &Arc { + self.buffer_recorder = None; + &self.command_buffer } pub fn resize( &mut self, - world: &mut World, + _world: &World, images: TargetMode>>, - width: u32, - height: u32, + _width: u32, + _height: u32, ) -> Result<()> { self.image_count.store( match &images { @@ -245,32 +206,16 @@ impl RenderBackend { SeqCst, ); - self.render_routines - .iter_mut() - .try_for_each(|scene_handle| { - (scene_handle.resize)(width as f32, height as f32, &images, world) - })?; + // TODO + // self.render_routines + // .iter_mut() + // .try_for_each(|scene_handle| { + // (scene_handle.resize)(width as f32, height as f32, &images, world) + // })?; Ok(()) } - /// lower priority means it is more important - pub fn add_render_routine(&mut self, priority: u32) { - self.render_routines.push(SceneHandle::new::(priority)); - self.render_routines - .sort_by_key(|scene_handle| scene_handle.priority); - } - - pub fn remove_render_routine(&mut self) { - if let Some(index) = self - .render_routines - .iter() - .position(|scene_handle| scene_handle.type_id == TypeId::of::()) - { - self.render_routines.remove(index as usize); - } - } - // getter pub fn image_count(&self) -> usize { self.image_count.load(SeqCst) diff --git a/presentation/src/traits.rs b/presentation/src/traits.rs index c1f29dc..1397e98 100644 --- a/presentation/src/traits.rs +++ b/presentation/src/traits.rs @@ -17,7 +17,7 @@ pub trait TScene: Resource + Send + Sync + 'static { buffer_recorder: &mut CommandBufferRecorder<'_>, images: &TargetMode>>, indices: &TargetMode, - world: &mut World, + world: &World, ) -> Result<()>; fn resize( @@ -25,7 +25,7 @@ pub trait TScene: Resource + Send + Sync + 'static { window_width: f32, window_height: f32, images: &TargetMode>>, - world: &mut World, + world: &World, ) -> Result<()>; } @@ -37,15 +37,35 @@ pub enum RenderCore { } impl RenderCore { - pub fn next_frame(&mut self, world: &mut World) -> Result { + pub fn begin_frame(&mut self, world: &World) -> Result<()> { match self { - RenderCore::Wsi(rc) => rc.next_frame(world), - RenderCore::OpenVR(rc) => rc.next_frame(world), - RenderCore::OpenXR(rc) => rc.next_frame(world), + RenderCore::Wsi(rc) => rc.start_frame(world), + _ => todo!(), } } - pub fn resize(&mut self, world: &mut World, w: u32, h: u32) -> Result<()> { + pub fn render(&mut self, render: F) -> Result<()> + where + F: FnOnce( + &mut CommandBufferRecorder<'_>, + &TargetMode>>, + &TargetMode, + ) -> Result<()>, + { + match self { + RenderCore::Wsi(rc) => rc.render(render), + _ => todo!(), + } + } + + pub fn end_frame(&mut self, world: &World) -> Result<()> { + match self { + RenderCore::Wsi(rc) => rc.end_frame(world), + _ => todo!(), + } + } + + pub fn resize(&mut self, world: &World, w: u32, h: u32) -> Result<()> { match self { RenderCore::Wsi(rc) => rc.resize(world, w, h), RenderCore::OpenVR(rc) => rc.resize(world, w, h), @@ -65,23 +85,6 @@ impl RenderCore { VK_IMAGE_LAYOUT_PRESENT_SRC_KHR } - /// lower priority means it is more important - pub fn add_render_routine(&mut self, priority: u32) { - match self { - RenderCore::Wsi(rc) => rc.add_render_routine::(priority), - RenderCore::OpenVR(rc) => rc.add_render_routine::(priority), - RenderCore::OpenXR(rc) => rc.add_render_routine::(priority), - } - } - - pub fn remove_render_routine(&mut self) { - match self { - RenderCore::Wsi(rc) => rc.remove_render_routine::(), - RenderCore::OpenVR(rc) => rc.remove_render_routine::(), - RenderCore::OpenXR(rc) => rc.remove_render_routine::(), - } - } - pub fn set_clear_color(&self, color: [f32; 4]) { match self { RenderCore::Wsi(rc) => rc.set_clear_color(color), diff --git a/presentation/src/vri/mod.rs b/presentation/src/vri/mod.rs index b88b96a..0da5731 100644 --- a/presentation/src/vri/mod.rs +++ b/presentation/src/vri/mod.rs @@ -79,11 +79,11 @@ pub mod openvrrendercore { unimplemented!() } - pub fn resize(&mut self, _: &mut World, _: u32, _: u32) -> Result<()> { + pub fn resize(&mut self, _: &World, _: u32, _: u32) -> Result<()> { unimplemented!() } - pub fn next_frame(&mut self, _: &mut World) -> Result { + pub fn next_frame(&mut self, _: &World) -> Result { unimplemented!() } diff --git a/presentation/src/wsi/vulkanwindowrendercore.rs b/presentation/src/wsi/vulkanwindowrendercore.rs index e3edd34..d8e4e4c 100644 --- a/presentation/src/wsi/vulkanwindowrendercore.rs +++ b/presentation/src/wsi/vulkanwindowrendercore.rs @@ -103,7 +103,7 @@ impl VulkanWindowRenderCore { Ok((window_render_core, TargetMode::Mono(()))) } - fn aquire_next_image_index(&mut self, world: &mut World) -> Result<()> { + fn aquire_next_image_index(&mut self, world: &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")] @@ -145,7 +145,7 @@ impl VulkanWindowRenderCore { self.format } - pub fn resize(&mut self, world: &mut World, w: u32, h: u32) -> Result<()> { + pub fn resize(&mut self, world: &World, w: u32, h: u32) -> Result<()> { self.swapchain.recreate((w, h))?; let swapchain_images = self.swapchain.wrap_images( @@ -164,14 +164,33 @@ impl VulkanWindowRenderCore { Ok(()) } - pub fn next_frame(&mut self, world: &mut World) -> Result { + pub fn start_frame(&mut self, world: &World) -> Result<()> { self.aquire_next_image_index(world)?; + self.render_backend + .begin_frame(TargetMode::Mono(self.current_image_index.load(SeqCst)))?; - let command_buffer = self.render_backend.render( - world, + Ok(()) + } + + pub fn render(&mut self, render: F) -> Result<()> + where + F: FnOnce( + &mut CommandBufferRecorder<'_>, + &TargetMode>>, + &TargetMode, + ) -> Result<()>, + { + self.render_backend.render( TargetMode::Mono(self.current_image_index.load(SeqCst)), + render, )?; + Ok(()) + } + + pub fn end_frame(&mut self, world: &World) -> Result<()> { + let command_buffer = self.render_backend.end_frame(); + let submits = &[SubmitInfo::default() .add_wait_semaphore( &*self.image_available_sem.read().unwrap(), @@ -194,7 +213,7 @@ impl VulkanWindowRenderCore { let (w, h) = self.wsi.window_size(); self.resize(world, w, h)?; self.render_fence.reset(); - return Ok(true); + return Ok(()); } // make sure command_buffer is ready @@ -205,22 +224,13 @@ impl VulkanWindowRenderCore { )?; self.render_fence.reset(); - Ok(true) + Ok(()) } pub fn set_clear_color(&self, color: [f32; 4]) { self.render_backend.set_clear_color(color); } - // post process handling - pub fn add_render_routine(&mut self, priority: u32) { - self.render_backend.add_render_routine::(priority); - } - - pub fn remove_render_routine(&mut self) { - self.render_backend.remove_render_routine::(); - } - // getter pub fn image_count(&self) -> usize { self.render_backend.image_count() diff --git a/presentation/src/xri/mod.rs b/presentation/src/xri/mod.rs index 3f2e530..6ca2b34 100644 --- a/presentation/src/xri/mod.rs +++ b/presentation/src/xri/mod.rs @@ -77,11 +77,11 @@ pub mod openxrrendercore { unimplemented!() } - pub fn resize(&mut self, _: &mut World, _: u32, _: u32) -> Result<()> { + pub fn resize(&mut self, _: &World, _: u32, _: u32) -> Result<()> { unimplemented!() } - pub fn next_frame(&mut self, _: &mut World) -> Result { + pub fn next_frame(&mut self, _: &World) -> Result { unimplemented!() } diff --git a/skybox/src/lib.rs b/skybox/src/lib.rs index 9b6daff..ed83637 100644 --- a/skybox/src/lib.rs +++ b/skybox/src/lib.rs @@ -55,7 +55,6 @@ impl SkyBox { .sample_count; let context = world.resources.get_mut_unchecked::(); - context.render_core_mut().add_render_routine::(10); let images = images.into(); let cube_map = Image::cube_map([ @@ -166,6 +165,7 @@ impl SkyBox { descriptor_set, }; world.resources.insert(me); + world.add_system(10, Self::render_sky_box); Ok(()) } @@ -178,6 +178,23 @@ impl SkyBox { self.enabled = false; } + fn render_sky_box( + world: &World, + _commands: &mut Commands, + context: &mut Context, + sky_box: &mut SkyBox, + ) -> Result { + context.render( + |recorder: &mut CommandBufferRecorder<'_>, + images: &TargetMode>>, + indices: &TargetMode| { + sky_box.process(recorder, images, indices, world) + }, + )?; + + Ok(true) + } + fn create_render_target( context: &Context, images: &TargetMode>>, @@ -258,7 +275,7 @@ impl TScene for SkyBox { buffer_recorder: &mut CommandBufferRecorder<'_>, _images: &TargetMode>>, indices: &TargetMode, - _world: &mut World, + _world: &World, ) -> Result<()> { if !self.enabled { return Ok(()); @@ -290,7 +307,7 @@ impl TScene for SkyBox { _window_width: f32, _window_height: f32, images: &TargetMode>>, - world: &mut World, + world: &World, ) -> Result<()> { let sample_count = world .resources