From 7f37ee7a24b2824fcd812dd4a218164d4f035abd Mon Sep 17 00:00:00 2001 From: Steins7 Date: Sat, 7 Nov 2020 11:23:24 +0100 Subject: [PATCH] Implemented Controller * reworked input system + added Subengines system + added Subengines pipeline system !(old) some framebuffer error present !(old) may crash during swapchain recreation ! crashes randomly while running --- doc/architecture | 2 +- src/controller.rs | 166 ++++++++++++++++++++++++++ src/input.rs | 42 ------- src/io.rs | 98 +++++++++++++++ src/lib.rs | 116 +++++++++++++----- src/renderer.rs | 29 ++--- src/renderer/gpu.rs | 23 ++-- src/renderer/output.rs | 43 ------- src/subengine.rs | 22 ++++ src/subengine/subengine_controller.rs | 140 ++++++++++++++++++++++ src/subengine/subengine_pipeline.rs | 72 +++++++++++ src/subengine/test_subengine.rs | 36 ++++++ src/winit_window.rs | 88 ++++++++++++-- 13 files changed, 724 insertions(+), 153 deletions(-) create mode 100644 src/controller.rs delete mode 100644 src/input.rs create mode 100644 src/io.rs delete mode 100644 src/renderer/output.rs create mode 100644 src/subengine.rs create mode 100644 src/subengine/subengine_controller.rs create mode 100644 src/subengine/subengine_pipeline.rs create mode 100644 src/subengine/test_subengine.rs diff --git a/doc/architecture b/doc/architecture index 242354c..4990374 100644 --- a/doc/architecture +++ b/doc/architecture @@ -1 +1 @@ -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 \ No newline at end of file +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 \ No newline at end of file diff --git a/src/controller.rs b/src/controller.rs new file mode 100644 index 0000000..a335776 --- /dev/null +++ b/src/controller.rs @@ -0,0 +1,166 @@ +#[allow(unused_imports)] +use log::{debug, error, info, trace, warn}; + +use crate::{ + io::{Input, Output}, + subengine::SubenginePipeline, +}; + +//--Controller Implementation----------------------------------------------------------------------- +pub struct Controller<'a, I, W, O> +where + I: Input, + W: raw_window_handle::HasRawWindowHandle, + O: Output, +{ + pipelines: Vec>, + color: [f32; 4], +} + +impl Controller<'_, I, W, O> +where + I: Input, + W: raw_window_handle::HasRawWindowHandle, + O: Output, +{ + + pub fn new<'a, Ip>(pipelines: Ip) -> Controller<'a, I, W, O> + where + I: 'a + Input, + W: raw_window_handle::HasRawWindowHandle, + O: 'a + Output, + Ip: IntoIterator>, + { + let pipelines_vec = pipelines + .into_iter() + .map(|pipeline| pipeline) + .collect(); + + Controller { + pipelines: pipelines_vec, + color: [0.0, 1.0, 0.0, 0.0], + } + } + + pub fn run(&mut self) { + use std::time::Duration; + + use crate::{ + subengine::subengine_controller::SubengineCommand, + io::Key, + }; + + let mut input_keys: Vec = Vec::new(); + + for pipeline in &mut self.pipelines { + for input in &pipeline.inputs { + match input.borrow().read(1) { + Ok(key) => input_keys.push(key), + Err(_err) => (), + } + } + for input_key in &input_keys { + match input_key { + Key::MouseMove{x,y} => self.color = [ + (x/1280.0) as f32, + (y/720.0) as f32, + ((x/1280.0 + y/720.0)/2.0) as f32, + 1.0], + _ => (), + }; + } + for subengines in &pipeline.subengines { + for subengine in subengines { + subengine.exec(SubengineCommand::Run); + } + for subengine in subengines { + subengine.wait_for_exec(Duration::from_millis(1)).unwrap(); + } + } + for (renderer, output) in &mut pipeline.renderers { + match renderer.draw_clear_frame(output, self.color) { + Err(err) => warn!("{}", err), + _ => (), + } + } + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + use std::iter; + + use crate::{ + winit_window::WinitWindow, + renderer::Renderer, + utils::Rect, + subengine::{SubengineController, TestSubengine}, + }; + + use gfx_backend_vulkan as vk_back; + + #[test] + fn test_new() { + use std::cell::RefCell; + + //creating windows + let window1 = RefCell::new(WinitWindow::new("IV", Rect {w: 1280, h: 720}).unwrap()); + let window2 = RefCell::new(WinitWindow::new("IV 2", Rect {w: 720, h: 480}).unwrap()); + + //creating renderers + let renderer1 = Renderer::::new(&mut iter::once(&window1)).unwrap(); + let renderer2 = Renderer::::new(&mut iter::once(&window2)).unwrap(); + + //creating subengines + let (test_subengine1, _test_rx1) = TestSubengine::new("run1"); + let test_controller1 = SubengineController::new(test_subengine1); + let (test_subengine2, _test_rx2) = TestSubengine::new("run2"); + let test_controller2 = SubengineController::new(test_subengine2); + + //preparing data + let inputs = vec![&window1, &window2]; + let subengines = vec![vec![test_controller1, test_controller2]]; + let renderers = vec![(renderer1, &window1), (renderer2, &window2)]; + + //creating pipeline + let subengine_pipeline = SubenginePipeline::new(inputs, subengines, renderers); + + //creating controller + let controller = Controller::new(vec![subengine_pipeline]); + } + + #[test] + fn test_run() { + use std::cell::RefCell; + + //creating windows + let window1 = RefCell::new(WinitWindow::new("IV", Rect {w: 1280, h: 720}).unwrap()); + let window2 = RefCell::new(WinitWindow::new("IV 2", Rect {w: 720, h: 480}).unwrap()); + + //creating renderers + let renderer1 = Renderer::::new(&mut iter::once(&window1)).unwrap(); + let renderer2 = Renderer::::new(&mut iter::once(&window2)).unwrap(); + + //creating subengines + let (test_subengine1, _test_rx1) = TestSubengine::new("run1"); + let test_controller1 = SubengineController::new(test_subengine1); + let (test_subengine2, _test_rx2) = TestSubengine::new("run2"); + let test_controller2 = SubengineController::new(test_subengine2); + + //preparing data + let inputs = vec![&window1, &window2]; + let subengines = vec![vec![test_controller1, test_controller2]]; + let renderers = vec![(renderer1, &window1), (renderer2, &window2)]; + + //creating pipeline + let subengine_pipeline = SubenginePipeline::new(inputs, subengines, renderers); + + //running controller + let mut controller = Controller::new(vec![subengine_pipeline]); + controller.run(); + } +} + diff --git a/src/input.rs b/src/input.rs deleted file mode 100644 index bdf7450..0000000 --- a/src/input.rs +++ /dev/null @@ -1,42 +0,0 @@ -#[allow(unused_imports)] -use log::{debug, error, info, trace, warn}; - -use winit::{ - event::{Event, WindowEvent}, - event_loop::{ControlFlow, EventLoop}, -}; - -#[derive(Debug)] -pub struct Input { - pub close_request: bool, - pub new_frame_size: Option<(f64, f64)>, - pub new_mouse_pos: Option<(f64, f64)>, -} - -impl Input { - - pub fn poll_events_loop(event_loop: &mut EventLoop<()>) -> Self { - let mut input = Input::default(); - event_loop.run(|event, _, control_flow| { - *control_flow = ControlFlow::Wait; - - match event { - Event::WindowEvent{window_id: _, event} => match event { - WindowEvent::CloseRequested => (), - _ => (), - } - _ => (), - } - }); - input - } - - pub fn default() -> Self { - Input { - close_request: false, - new_frame_size: None, - new_mouse_pos: None, - } - } -} - diff --git a/src/io.rs b/src/io.rs new file mode 100644 index 0000000..9dd067a --- /dev/null +++ b/src/io.rs @@ -0,0 +1,98 @@ +#[allow(unused_imports)] +use log::{debug, error, info, trace, warn}; + +use raw_window_handle::HasRawWindowHandle; + +use crate::utils::Rect; + +//--Output trait------------------------------------------------------------------------------------ +/// A trait for the ability of a type to be used as an output by the engine. +/// +/// The `Output` trait defines functions to be used by different components of the engine. This +/// allows to display with any window manager as long as the trait is defined for it. +/// +/// Types that implement the `Output` trait should manage the underlying window and settings. +/// +/// Implementation : the ID and size stored by the type implementing this trait don't need to be +/// initialized to anything specific as the engine will take care of it. +pub trait Output +where + W: HasRawWindowHandle, +{ + /// Return the ID stored internally. Used to select the right swapchain by the render engine. + /// For internal use only. + fn get_id(&self) -> usize; + + /// Store the given ID internally. For internal use only. + fn set_id(&mut self, id: usize); + + //TODO clean that + /// Give mutable acces to the size of the output. The size is a simple rectangle containing the + /// width and height of the `Output`. + fn size(&mut self) -> &mut Rect; + + /// Give reference acces to the underlying window. This is used by the engine during setup to + /// create the revelant ressources. + fn window(&self) -> &W; +} + +//impl<'a, W, O> Output for &'a mut O +//where +// W: HasRawWindowHandle, +// O: Output, +//{ +// fn get_id(&self) -> usize { Output::get_id(*self) } +// fn set_id(&mut self, id: usize) { Output::set_id(*self, id); } +// +// fn size(&mut self) -> &mut Rect { Output::size(*self) } +// +// fn window(&self) -> &W { Output::window(*self) } +//} + +//impl<'a, W, O> Output for Box +//where +// W: HasRawWindowHandle, +// O: Output, +//{ +// fn get_id(&self) -> usize { Output::get_id(self) } +// fn set_id(&mut self, id: usize) { Output::set_id(self, id); } +// +// fn size(&mut self) -> &mut Rect { Output::size(self) } +// +// fn window(&self) -> &W { Output::window(self) } +//} + +//--Input trait------------------------------------------------------------------------------------ +/// A trait for the ability of a type to be used as an input by the engine +/// +/// The `Input` trait defines functions used by different components of the engine. The allow to +/// read inputs from any window manzger as long as the is defined for it. +/// +/// Types that implement the `Input` trait should manage the EventLoop. This can be done in any way +/// (polling, interrupt, synchronous, asynchronous, ...) depending on how the input should be +/// handled. +pub trait Input { + /// Return the next input available or a ReadError if an error occured of the timeout duration + /// was reached. How inputs are handled depends on the implementation. + //TODO change timeout + fn read(&self, timeout_ms: u32) -> Result; +} + +//impl<'a, I> Input for &'a mut I +//where +// I: Input, +//{ +// fn read(&self, timeout_ms: u32) -> Result { Input::read(*self, timeout_ms) } +//} + +//--Key enum---------------------------------------------------------------------------------------- +pub enum Key { + Close, + MouseMove { x: f64, y: f64 }, +} + +//--ReadError enum---------------------------------------------------------------------------------- +pub enum ReadError { + Timeout, +} + diff --git a/src/lib.rs b/src/lib.rs index 3dbb978..d97c6b0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -5,31 +5,32 @@ #[allow(unused_imports)] use log::{debug, error, info, trace, warn}; -//use std::{ -// sync::mpsc, -// thread, -// collections::HashMap, -// cell::RefCell, -//}; - use gfx_backend_vulkan as vk_back; +pub mod io; + +pub mod subengine; +use subengine::SubenginePipeline; + +pub mod controller; +use controller::Controller; + pub mod utils; -use crate::utils::Rect; +//use utils::Rect; mod winit_window; -use winit_window::WinitWindow; - -//use winit::{ -// event::{Event, WindowEvent}, -// event_loop::ControlFlow, -//}; +//use winit_window::WinitWindow; mod renderer; -use renderer::Renderer; +//use renderer::Renderer; -//mod local_state; -//use local_state::LocalState; +//mod controller; +//use controller::Controller; + +//use crate::engine::{ +// EngineController, +// TestEngine, +//}; pub enum Command { NoCommand, @@ -56,24 +57,73 @@ pub enum Input { /// The main function of the library pub fn run() -> Result<(), &'static str> { - - let mut windows = vec![ - WinitWindow::new("IV", Rect {w: 1280, h: 720})?, - // WinitWindow::new("IV 2", Rect {w: 720, h: 480})?, - ]; + use std::{ + iter, + cell::RefCell, + }; - let mut renderer: Renderer = Renderer::new(&mut windows)?; + use crate::{ + winit_window::WinitWindow, + renderer::Renderer, + utils::Rect, + subengine::{SubengineController, TestSubengine}, + }; + + //creating windows + let window1 = RefCell::new(WinitWindow::new("IV", Rect {w: 1280, h: 720}).unwrap()); + //let window2 = RefCell::new(WinitWindow::new("IV 2", Rect {w: 720, h: 480}).unwrap()); + + //creating renderers + let renderer1 = Renderer::::new(&mut iter::once(&window1)).unwrap(); + //let renderer2 = Renderer::::new(&mut iter::once(&window2)).unwrap(); + + //creating subengines + let (test_subengine1, _test_rx1) = TestSubengine::new("run1"); + let test_controller1 = SubengineController::new(test_subengine1); + //let (test_subengine2, _test_rx2) = TestSubengine::new("run2"); + //let test_controller2 = SubengineController::new(test_subengine2); + + //preparing data + let inputs = vec![&window1]; + let subengines = vec![vec![test_controller1/*, test_controller2*/]]; + let renderers = vec![(renderer1, &window1)/*, (renderer2, &window2)*/]; + + //creating pipeline + let subengine_pipeline = SubenginePipeline::new(inputs, subengines, renderers); + + //running controller + let mut controller = Controller::new(vec![subengine_pipeline]); + loop { + controller.run(); + } + + //let engine_pipelines = vec![ + // EnginePipeline { + // Inputs: vec![0,1], + // Engines: vec![&color_engine], + // Renderers: vec![(1,0)], + // }, + // EnginePipeline { + // Inputs: vec![3], + // Engines: vec![&color_engine], + // Renderers: vec![(1,1),(1,2),(1,3)], + //}]; + + //let controller = Controller::new(renderers, &windows, &windows, engine_pipelines); + //controller.run(); + + Ok(()) //let local_state = LocalState::default(); - let color = [0.5, 0.0, 0.0, 1.0]; - - loop { - for window in &mut windows { - match renderer.draw_clear_frame(window, color) { - Err(err) => println!("{}", err), - _ => (), - }}} - +// let color = [0.5, 0.0, 0.0, 1.0]; +// +// loop { +// for window in &mut windows { +// match renderer.draw_clear_frame(window, color) { +// Err(err) => println!("{}", err), +// _ => (), +// }}} +// // Ok(()) } @@ -92,7 +142,7 @@ pub fn run() -> Result<(), &'static str> { // // let mut color = [0.0, 0.0, 0.0, 0.0]; // -// loop { +// loop // // //TODO manage errors // for window in windows { diff --git a/src/renderer.rs b/src/renderer.rs index dff28a5..2fc712e 100644 --- a/src/renderer.rs +++ b/src/renderer.rs @@ -4,6 +4,11 @@ use log::{debug, error, info, trace, warn}; use std::{ mem::ManuallyDrop, iter, + cell::RefCell, +}; + +use crate::{ + io::Output, }; mod gpu; @@ -12,18 +17,11 @@ use gpu::Gpu; mod swap_system; use swap_system::SwapSystem; -pub mod output; -use output::Output; - -//mod pipeline; -//use pipeline::Pipeline; - //--Renderer implementation------------------------------------------------------------------------- #[derive(Debug)] pub struct Renderer { instance: ManuallyDrop, gpu: ManuallyDrop>, - //pipelines: Vec>, swap_systems: Vec>, } @@ -62,12 +60,11 @@ impl Renderer where B: gfx_hal::Backend, { - pub fn new<'a, H, T: 'a, I>(outputs: I) -> Result, &'static str> + pub fn new<'a, W: 'a, O: 'a, I>(outputs: &mut I) -> Result, &'static str> where - H: raw_window_handle::HasRawWindowHandle, - T: Output, - I: IntoIterator, - + W: raw_window_handle::HasRawWindowHandle, + O: Output, + I: Iterator>, { use gfx_hal::Instance; @@ -91,11 +88,11 @@ where }) } - pub fn draw_clear_frame(&mut self, output: &mut O, color: [f32; 4]) + pub fn draw_clear_frame(&mut self, output: &RefCell, color: [f32; 4]) -> Result<(), &'static str> where - T: raw_window_handle::HasRawWindowHandle, - O: Output + W: raw_window_handle::HasRawWindowHandle, + O: Output, { use gfx_hal::{ window::AcquireError, @@ -103,7 +100,7 @@ where queue::Submission, }; - let swap_system = &mut self.swap_systems[output.get_id()]; + let swap_system = &mut self.swap_systems[output.borrow_mut().get_id()]; let mut frame = match swap_system.acquire_frame(&self.gpu) { Ok(frame) => frame, diff --git a/src/renderer/gpu.rs b/src/renderer/gpu.rs index e88b197..31fcc7f 100644 --- a/src/renderer/gpu.rs +++ b/src/renderer/gpu.rs @@ -4,6 +4,7 @@ use log::{debug, error, info, trace, warn}; use std::{ mem::ManuallyDrop, ptr::read, + cell::RefCell, }; use gfx_hal::{ @@ -13,9 +14,14 @@ use gfx_hal::{ use gfx_hal::adapter::Gpu as GfxGpu; -use super::output::Output; +use crate::io::Output; //--Gpu implementation------------------------------------------------------------------------------ +/// A struct managing all things related to a specific GPU +/// +/// The `GPU` struct manages the structs from the gfx_hal[gfx_hal] related to the physical device. +/// It implements constructor and destructors as well as acces functions. This is done to make the +/// usage of the HAL easier and make the higher level code less dependant on changes in it. #[derive(Debug)] pub struct Gpu { adapter: ManuallyDrop>, @@ -47,12 +53,13 @@ impl Gpu where B: gfx_hal::Backend, { - pub fn new<'a, H, T: 'a, I>(instance: &B::Instance, outputs: I) + /// Create a new `GPU` based on an `instance` of the gfx_hal[gfx_hal]. + pub fn new<'a, W, O: 'a, I>(instance: &B::Instance, outputs: &mut I) -> Result<(Gpu, Vec), &'static str> where - H: raw_window_handle::HasRawWindowHandle, - T: Output, - I: IntoIterator, + W: raw_window_handle::HasRawWindowHandle, + O: Output, + I: Iterator>, { use gfx_hal::{ queue::family::QueueFamily, @@ -65,13 +72,13 @@ where let mut id = 0; outputs - .into_iter() + .by_ref() .map(|output| unsafe { - output.set_id(id); + output.borrow_mut().set_id(id); id += 1; instance - .create_surface(output.window()) + .create_surface(output.borrow().window()) .map_err(|_| "Could not create surface") }) .collect::, &str>>()? diff --git a/src/renderer/output.rs b/src/renderer/output.rs deleted file mode 100644 index 49de5f2..0000000 --- a/src/renderer/output.rs +++ /dev/null @@ -1,43 +0,0 @@ -#[allow(unused_imports)] -use log::{debug, error, info, trace, warn}; - -use raw_window_handle::HasRawWindowHandle; - -use crate::utils::Rect; - -//--Output trait------------------------------------------------------------------------------------ -pub trait Output -where - T: HasRawWindowHandle, -{ - fn get_id(&self) -> usize; - fn set_id(&mut self, id: usize); - - fn size(&mut self) -> &mut Rect; - - fn window(&self) -> &T; -} - -//impl<'a, T, O> Output for &'a O -//where -// T: HasRawWindowHandle, -// O: Output { -// fn id(&mut self) -> &mut i32 { Output::id(*self) } -// -// fn size(&mut self) -> &mut Rect { Output::size(*self) } -// -// fn window(&self) -> &T { Output::window(*self) } -//} - -impl<'a, T, O> Output for &'a mut O -where - T: HasRawWindowHandle, - O: Output { - fn get_id(&self) -> usize { Output::get_id(*self) } - fn set_id(&mut self, id: usize) { Output::set_id(*self, id); } - - fn size(&mut self) -> &mut Rect { Output::size(*self) } - - fn window(&self) -> &T { Output::window(*self) } -} - diff --git a/src/subengine.rs b/src/subengine.rs new file mode 100644 index 0000000..12fc610 --- /dev/null +++ b/src/subengine.rs @@ -0,0 +1,22 @@ +#[allow(unused_imports)] +use log::{debug, error, info, trace, warn}; + +pub mod subengine_controller; +pub use self::subengine_controller::SubengineController; + +pub mod subengine_pipeline; +pub use self::subengine_pipeline::SubenginePipeline; + +pub mod test_subengine; +pub use self::test_subengine::TestSubengine; + + +//--SubEngine trait------------------------------------------------------------------------------------ +/// A trait that should be implemented by all subengines running it the game engine. +/// +/// Allow the [`Controller`] to run custom subengines. +pub trait Subengine { + /// Main function of the subengine. Called byt the [`Controller`] for each frame. + fn run(&self); +} + diff --git a/src/subengine/subengine_controller.rs b/src/subengine/subengine_controller.rs new file mode 100644 index 0000000..94cef97 --- /dev/null +++ b/src/subengine/subengine_controller.rs @@ -0,0 +1,140 @@ +#[allow(unused_imports)] +use log::{debug, error, info, trace, warn}; + +use std::{ + sync::mpsc::{Sender, Receiver}, + thread::JoinHandle, + mem::ManuallyDrop, + ptr::read, + time::Duration, +}; + +use crate::subengine::Subengine; + +//--SubengineController Implementation-------------------------------------------------------------- +/// Handle to manage an [`Subengine`]. +/// +/// The `SubengineController` runs the [`Engine`] in a separated thread with some control code to +/// allow control from the main thread. SubengineControllers are used by the [`Controller`] to +/// interact with Subengines. +#[derive(Debug)] +pub struct SubengineController { + tx: Sender, + rx: Receiver, + handle: ManuallyDrop>, +} + +impl Drop for SubengineController { + fn drop(&mut self) { + self.exec(SubengineCommand::Stop); + unsafe { let _ = ManuallyDrop::into_inner(read(&mut self.handle)).join(); } + debug!("SubengineController dropped !"); + } +} + +impl SubengineController { + /// Creates a new `SubengineController` from a given [`Engine`]. Since the latter will be moved + /// to a separated thread, it must implement the [`Send`] trait. + pub fn new(engine: E) -> SubengineController + where + E: Subengine + std::marker::Send, + { + use std::{ + thread, + sync::mpsc::channel, + }; + + debug!("Creating SubengineController..."); + let (tx, e_rx) = channel(); + let (e_tx, rx) = channel(); + + let handle = thread::spawn(move || { + trace!("Subengine thread started !"); + loop { + //TODO manage errors + match e_rx.recv().unwrap() { + SubengineCommand::Run => engine.run(), + SubengineCommand::Stop => return, + }; + e_tx.send(SubengineResponse::Done).unwrap(); + } + }); + + SubengineController { + tx, + rx, + handle: ManuallyDrop::new(handle), + } + } + + /// Sends a command to the [`Subengine`]. This is function is not blocking and WILL NOT check if + /// the command was received. + pub fn exec(&self, cmd: SubengineCommand) { + self.tx.send(cmd).unwrap(); + } + + /// Blocking function, waits for the [`Subengine`] to finish executing the last command given. + pub fn wait_for_exec(&self, timeout: Duration) -> Result<(),SubengineWaitError> { + match self.rx.recv_timeout(timeout) { + Err(_) => Err(SubengineWaitError::NoResponse), + Ok(val) => match val { + SubengineResponse::Done => Ok(()), + //_ => Err(SubengineWaitError::BadResponse), + }} + } +} + +//--SubengineCommand enum--------------------------------------------------------------------------- +/// Commands that can be sent to an [`Subengine`] via an `EngineController`. +#[derive(Debug)] +pub enum SubengineCommand { + Run, + Stop, +} + +//--SubengineWaitError enum------------------------------------------------------------------------- +/// Errors that can be returned by the wait_for_exec function. +#[derive(Debug)] +pub enum SubengineWaitError { + NoResponse, + BadResponse, +} + +//--SubengineResponse enum-------------------------------------------------------------------------- +#[derive(Debug)] +enum SubengineResponse { + Done, +} + +//--Tests------------------------------------------------------------------------------------------- +#[cfg(test)] +mod tests { + use super::*; + use crate::subengine::TestSubengine; + + #[test] + fn test_new_drop() { + let (test_subengine, _test_rx) = TestSubengine::new("run"); + let subengine_controller = SubengineController::new(test_subengine); + } + + #[test] + fn test_exec() { + let (test_subengine, test_rx) = TestSubengine::new("run"); + let subengine_controller = SubengineController::new(test_subengine); + + subengine_controller.exec(SubengineCommand::Run); + let response = test_rx.recv_timeout(Duration::from_millis(10)).unwrap(); + assert_eq!(response, "run"); + } + + #[test] + fn test_wait_for_exec() { + let (test_subengine, _test_rx) = TestSubengine::new("run"); + let subengine_controller = SubengineController::new(test_subengine); + + subengine_controller.exec(SubengineCommand::Run); + subengine_controller.wait_for_exec(Duration::from_millis(10)).unwrap(); + } + +} diff --git a/src/subengine/subengine_pipeline.rs b/src/subengine/subengine_pipeline.rs new file mode 100644 index 0000000..dc5ad08 --- /dev/null +++ b/src/subengine/subengine_pipeline.rs @@ -0,0 +1,72 @@ +#[allow(unused_imports)] +use log::{debug, error, info, trace, warn}; + +use std::{ + cell::RefCell, + marker::PhantomData, +}; + +use gfx_backend_vulkan as vk_back; + +use crate::{ + io::{Input, Output}, + subengine::SubengineController, + renderer::Renderer, +}; + +//--SubenginePipeline Implementation---------------------------------------------------------------- +#[derive(Debug)] +pub struct SubenginePipeline<'a, I, W, O> +where + I: Input, + W: raw_window_handle::HasRawWindowHandle, + O: Output, +{ + pub inputs: Vec<&'a RefCell>, + pub subengines: Vec>, + pub renderers: Vec<(Renderer, &'a RefCell)>, + pub phantom: PhantomData, //needed because of compiler limitations +} + +impl<'a, I, W, O> SubenginePipeline<'a, I, W, O> +where + I: Input, + W: raw_window_handle::HasRawWindowHandle, + O: Output, +{ + + pub fn new(inputs: Ii, subengines: Is, renderers: Ir) + -> SubenginePipeline<'a, I, W, O> + where + Ii: IntoIterator>, + Iss: IntoIterator, + Is: IntoIterator, + Ir: IntoIterator, &'a RefCell)>, + { + let inputs_vec = inputs + .into_iter() + .map(|input| input) + .collect(); + + let subengines_vecs = subengines + .into_iter() + .map(|subengines_vec| subengines_vec + .into_iter() + .map(|subengine| subengine) + .collect()) + .collect(); + + let renderers_vec = renderers + .into_iter() + .map(|renderer| renderer) + .collect(); + + SubenginePipeline{ + inputs: inputs_vec, + subengines: subengines_vecs, + renderers: renderers_vec, + phantom: PhantomData, + } + } +} + diff --git a/src/subengine/test_subengine.rs b/src/subengine/test_subengine.rs new file mode 100644 index 0000000..ac32da6 --- /dev/null +++ b/src/subengine/test_subengine.rs @@ -0,0 +1,36 @@ +#[allow(unused_imports)] +use log::{debug, error, info, trace, warn}; + +use std::sync::mpsc::{Sender, Receiver, channel}; + +use super::*; + +//--TestSubengine Implementation-------------------------------------------------------------------- +/// [`Subengine`] implementation used for tests. +/// +/// Simply sends back the given [`str`] depending on the command. +#[derive(Debug)] +pub struct TestSubengine { + tx: Sender<&'static str>, + run: &'static str, +} + +impl TestSubengine { + /// Creates a `TestSubengine` with specific [`str`]s to use. + pub fn new(run: &'static str) + -> (TestSubengine, Receiver<&'static str>) { + + let (tx, rx) = channel(); + ( + TestSubengine { tx, run }, + rx + ) + } +} + +impl Subengine for TestSubengine { + fn run(&self) { + self.tx.send(self.run).unwrap(); + } +} + diff --git a/src/winit_window.rs b/src/winit_window.rs index c08320a..ac8b605 100644 --- a/src/winit_window.rs +++ b/src/winit_window.rs @@ -1,6 +1,11 @@ #[allow(unused_imports)] use log::{debug, error, info, trace, warn}; +use std::{ + thread, + sync::mpsc, +}; + use winit::{ dpi::PhysicalSize, event_loop::{EventLoop}, @@ -8,8 +13,10 @@ use winit::{ }; //TODO fix that -use super::renderer::output::Output; -use crate::utils::Rect; +use crate::{ + io::{Output, Input, Key, ReadError}, + utils::Rect, +}; #[derive(Debug)] pub struct WinitWindow { @@ -17,27 +24,77 @@ pub struct WinitWindow { size: Rect, id: usize, - pub event_loop: EventLoop<()>, + handle: thread::JoinHandle<()>, + receiver: mpsc::Receiver, window: Window, } impl WinitWindow { pub fn new(title: &str, size: Rect) -> Result { + use winit::platform::unix::EventLoopExtUnix; + debug!("Creating window"); let name = title.to_string(); let id = 0; - let event_loop = EventLoop::new(); - let window = WindowBuilder::new() - .with_inner_size(PhysicalSize {width: size.w, height: size.h}) - .with_title(title) - .build(&event_loop) - .map_err(|_| "Could not create window")?; + + //Since we can't move the EventLoop from one thread to another, we need to create it in the + //right thread and then move the Window back to the main thread instead + let cloned_name = name.clone(); + let (tx, rx) = mpsc::channel(); + let (tmp_tx, tmp_rx) = mpsc::sync_channel(1); + let handle = thread::spawn(move || { + + trace!("Creating Window in EventLoop thread"); + //winit doesn't like use creating the EventLoop in another thread either so we have to + //drop crossplatform compatibility :/ + let event_loop = EventLoop::new_any_thread(); + let window = WindowBuilder::new() + .with_inner_size(PhysicalSize {width: size.w, height: size.h}) + .with_title(cloned_name) + .build(&event_loop).unwrap(); + + trace!("Sending Window back to main thread"); + tmp_tx.send(window).unwrap(); + + //TODO clean event type + event_loop.run(move |event: winit::event::Event<'_, ()>, _, control_flow| { + use winit::{ + event_loop::ControlFlow, + event::Event, + event, + }; + + *control_flow = ControlFlow::Wait; + + //TODO manage errors + match event { + Event::WindowEvent{window_id: _, event} => match event { + event::WindowEvent::CloseRequested => { + tx.send(Key::Close).unwrap(); + warn!("Stop input thread"); + *control_flow = ControlFlow::Exit; + }, + event::WindowEvent::CursorMoved{position, ..} => { + tx.send(Key::MouseMove{ + x: position.x, + y: position.y, + }).unwrap(); + }, + _ => (), + } + _ => (), + }}) + }); + + let window = tmp_rx.recv().unwrap(); + trace!("Received Window in main thread"); Ok(Self { name, size, id, - event_loop, + handle: handle, + receiver: rx, window, }) } @@ -52,3 +109,14 @@ impl Output for WinitWindow { fn window(&self) -> &Window { &self.window } } +impl Input for WinitWindow { + fn read(&self, timeout_ms: u32) -> Result { + use std::time::Duration; + + match self.receiver.recv_timeout(Duration::from_millis(timeout_ms.into())) { + Ok(key) => Ok(key), + Err(_) => Err(ReadError::Timeout), + } + } +} +