diff --git a/Cargo.lock b/Cargo.lock
index 87b4b99..3b72c66 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -44,6 +44,17 @@ dependencies = [
"libloading",
]
+[[package]]
+name = "atty"
+version = "0.2.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
+dependencies = [
+ "hermit-abi",
+ "libc",
+ "winapi 0.3.8",
+]
+
[[package]]
name = "autocfg"
version = "1.0.0"
@@ -126,6 +137,17 @@ dependencies = [
"objc",
]
+[[package]]
+name = "colored"
+version = "1.9.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f4ffc801dacf156c5854b9df4f425a626539c3a6ef7893cc0c5084a23f0b6c59"
+dependencies = [
+ "atty",
+ "lazy_static",
+ "winapi 0.3.8",
+]
+
[[package]]
name = "core-foundation"
version = "0.7.0"
@@ -205,6 +227,7 @@ version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8c9a4820f0ccc8a7afd67c39a0f1a0f4b07ca1725164271a64939d7aeb9af065"
dependencies = [
+ "colored",
"log",
]
@@ -269,6 +292,15 @@ dependencies = [
"raw-window-handle",
]
+[[package]]
+name = "hermit-abi"
+version = "0.1.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b9586eedd4ce6b3c498bc3b4dd92fc9f11166aa908a914071953768066c67909"
+dependencies = [
+ "libc",
+]
+
[[package]]
name = "instant"
version = "0.1.2"
@@ -293,6 +325,8 @@ dependencies = [
"gfx-backend-vulkan",
"gfx-hal",
"log",
+ "num-traits",
+ "raw-window-handle",
"winit",
]
@@ -502,9 +536,9 @@ dependencies = [
[[package]]
name = "num-traits"
-version = "0.2.11"
+version = "0.2.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c62be47e61d1842b9170f0fdeec8eba98e60e90e5446449a0545e5152acd7096"
+checksum = "ac267bcc07f48ee5f8935ab0d24f316fb722d7a1292e2913f0cc196b29ffd611"
dependencies = [
"autocfg",
]
diff --git a/Cargo.toml b/Cargo.toml
index 31ed5e5..e490da6 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -9,9 +9,11 @@ edition = "2018"
[dependencies]
log = "0.4.8"
chrono = "0.4.11"
-fern = "0.6.0"
+fern = { version = "0.6.0", features = ["colored"] }
gfx-hal = "0.5.0"
winit = "0.22.0"
+raw-window-handle = "0.3.3"
+num-traits = "0.2.12"
[dependencies.gfx-backend-vulkan]
version = "0.5"
@@ -23,5 +25,5 @@ path = "src/lib.rs"
[[bin]]
name = "iv"
-path = "src/bin/main.rs"
+path = "main.rs"
diff --git a/doc/architecture b/doc/architecture
new file mode 100644
index 0000000..e5a3284
--- /dev/null
+++ b/doc/architecture
@@ -0,0 +1 @@
+7Vxtc5u4Fv41nuneGXsMGAIfYztu9266m607t+l+8Sgg22oBsSDHcX/9lYTEq+zgGpLNvXQyrjlIB0nn6NGjc4QHxix4eh+DaPsRe9Af6GPvaWDMB7quG8YV/Y9JDqnEMoxUsImRl4q0XLBEP6AQjoV0hzyYlAoSjH2CorLQxWEIXVKSgTjG+3KxNfbLT43ABtYESxf4dekX5JGtkGqWk9/4ANFmKx5t66LDAZCFRU+SLfDwviAybgbGLMaYpN+Cpxn02eDJcUnrLY7czRoWw5A0qfDv334Lr//z9dt85d7D7zrx1tvNUGh5BP5OdPh9tBPtJQc5CMkeBT4I6dV0jUOyFHc0eg18tAnpd5e2AsZU8Ahjguj4XYsbBEdU6m6R792CA96xtiYEuN/l1XSLY/SDqgW+0Elvx0S4gm6VSixZTSoeU2kME1rmTg6AVhF9BE+lgrcgIULgYt8HUYIesm4EIN6gcIoJwYEoVB9fOVi0h/CpIBLj/R7iAJL4QIuIu0N9IowvvN+0xPU+96WJLWTbghtpjhAC4b+bTHluYvpFWPkMi+s1iw/ZYzwQMftRHzKu6ee1vLYGuqGx4WClPPiIXJgVmovLUpm/d3AHV5sY76Ks4J9M9p6LzKk2Gv1rYM4r1VwcBCD0VhGd3Fm9WSq847KKT1ITEO4rMf4OZ9jH1PnmIU6dFPl+RST91IdrctRLkwi4KNzc8jLzSS75JCzDRJjWXft8Jm+R58GQeRgmgIDUnViPIoxCwi1nTukfteVsPDJ5r2dsCPJr+seKx2SGQ9oXgLizQeqre8j8VeGGJyfy874pXJENfxNPtCYdOaJRc8SajX3EbZfaWMKv9lMGDqipfJhb9DMz+Hyo1axu1K1uKCzsgwfo3+EEEYSZ/jgtW7H8axnXaQgzdke2nShsSzs7DuGefr6jcx8EbML9SocFhAxDZoOZPrgeZ3f+2JGIrg4ZXPySgcInmOx8Qgv6bATf8fWKtnK83MVr4FKuUKwze0c/rE061hngpI3xYhyVWhPQB+pjqjB/GK+eV6toEKiZayjVzaR1MBUN4Pj5XO0ayqaVi4C5oi1/Tk3auR5RO5x0drNJ5+iXzzqb/PHtYYG//vkZ/2564FfX+euvoVZf2xcxCGDP51ric5OJMdJLhO5KgbSmZo3sutkzLti+3etLKaNUe4DIKoEB3ZdhOmQZJCyliEnobDIWdTqWUGMD9uCfrL+GoVuosoChe6o4Cug2avWI+PLASlS0MS9+2K3XBYa6KMrKVDLwVpXCAvam1eI9BmaT4TSiXEIrj8wHpwViqW60in30zLIlA2t6Y8RrgV2qG202pJcZoUsZYk47GdxUZAscB4BUhJ9g6MH4DiRJ5cbNE6EDqx+lpWLd/Qn6KWvWudsZxDQ5hO5qw/pd0L+oKz6lcso7xfrPtRiLAqksIXRa9C6GzNvKT2R9yastdw8BShLm1tXa/BapV1YOBA8nSNIvVR7dIFR3AT3itw0Idd57BBA0qb19SLBqkLDcg2h5SAgMev7bVTxTRX+Ve54snt++5a+U5DdJowEF7BHXJaoYc3xb0TEBEjtcUqXC1I/cLZ1Qua5cUi7JBjdn3CrCrHp6xJYX8fR8uelh6iRMWY1998x4p90ZLbV7WtqdeTXt5UKe6iY7F5JSgVDHeExxOZtJtnYWs6xqUEZhz2KdUw5iLkVPAs954PmBVvfvHaLYuk454Ykn5RoFf6xoiujiSX2vgaa0zc+w0J51vtp8f+1oa5bXz60KvQ2UZJIOyhZvcAj8m1xKh3pHl3hPDHRe5hZzeGbo/A0SchBsEewIZnyRBJJLwidE7gvfvzJV1Bjp1VxSRH5xkBch7e998SKtNbFsKcgr8qtSzTsYIzpkjA2fJpIJ3sUubMDVKB/ewJP+ICKabEBPekMMfUDQY/mwhsrUouodc+2c0Gpmmc/aZoWmpi0VtXKHuY5jcCgUEzPm6HOqvNk27KK6WnlDv7C8VToLQr+kLc69PRvDCyZA/fBIFqw9SmALrvzsViujMHzDcxSg5pKdTOleasNnmIRPiv1r/q85FMmRrEFRdsZINGRQPMaj2i2NR44+ER5/oZ8OJ8ZIhjWFiYfOyHHKevB6nUAyqAJbG6auZ5bo0KdRe5cOOOGLQ29xanFplENJ0aX2N43RVTnzpGmjsf5i9q9vsu9QBPl2pQ+udBRc0caT+p5GH6tOi427iq7o9U0rw/gwJc88Dtwz25PgctXYD44HKpRG17sKVOiqnWwfqGjJvGbDOd1VnMIYK6xbiFPkO9oc4ZvFF2T58qa+h4eW/ae+71X6z6Srfa9RT6+ncWuWKOy5QDtcwG5wcNywVFSgs1NGRj3rzo/uZMFDMenzaGI/9U9N/WweXcIMlD4gy7XvAvUsa88MWjOvqTczb2fMoL7JU2cwvqCQvclUeJVDER4/dYBbrhbNeIUs3zRZ4MVgv3J9COI8ys8dr3GwXqWQxAiEG59r+yy+99H/V5oqTVdDu7PF0K4Z9Y0F/83B6dA/51LX7A3K3BG5bIHYUIkanizh+iBJkJsKRRHtFBl6Nlkg+UYxWXDqjbb2cgUXecZEHRXfKF6rfCsBUunsbQRIrYlc5mQcW6R6LoyQmmWlWoUCdRcalfuscmhce8sB8TbtfWWaTsU0l9lbrgAvZV/D6ZH+FZD+ZP74nwL16vdu2IHBVcLPkLzdNKh0+zYwwLZ0o1UMyDImVkVtJSTeIeor3jEp7Id6o49sU6YnL7TyVcnGVy9m4Td/vOd/B/dlyOOfgvvqSGgk8h9vF/QnLZ6EsC2njM6TVtCgsnl4sRMwE0Xo8+0DfpsGdzSnssq3s7Mbls89dbHEL27vHde6/zL8sb0Jx7//SJyPmuKnkdKXQ/oUl3QvhdfUloHjKa7stK7MbihOu2iqoJ7VQgBcaXHFTp7Hf0WDWJwXGXotPCzblt3/v472PuMUx6faOWkvpV8YLRyIUTav/6Wi7oyriOQrjdvVnK9TOZG46nG+JZy3G+C8MnnTxk/gKW2uynP287npfDbPBeuuktjK1qlespzyStW0cjrPf1H+TJZqmWfz5xwd4lVinhBO9amzy3ueTc81H1WbKQsiNgwfQPIJ7NNc/AcQMh/r883dOLVkFs85tXn+wRt6mf8EbLp1yX9I17j5Lw==
\ No newline at end of file
diff --git a/src/bin/main.rs b/main.rs
similarity index 72%
rename from src/bin/main.rs
rename to main.rs
index ebf4501..bda4db0 100644
--- a/src/bin/main.rs
+++ b/main.rs
@@ -1,17 +1,26 @@
#[allow(unused_imports)]
use log::{debug, error, info, trace, warn};
+
use chrono;
use ::iv::run;
fn setup_logger() -> Result<(), fern::InitError> {
+ use fern::colors::{Color, ColoredLevelConfig};
+
+ let colors = ColoredLevelConfig::new()
+ .info(Color::Green)
+ .debug(Color::Magenta)
+ .warn(Color::Yellow)
+ .error(Color::Red);
+
fern::Dispatch::new()
- .format(|out, message, record| {
+ .format(move |out, message, record| {
out.finish(format_args!(
"{}[{}][{}] {}",
chrono::Local::now().format("[%H:%M:%S]"),
- record.level(),
+ colors.color(record.level()),
record.target(),
message
))
diff --git a/src/lib.rs b/src/lib.rs
index 4086d54..81951ff 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -5,20 +5,25 @@
#[allow(unused_imports)]
use log::{debug, error, info, trace, warn};
-use std::{
- sync::mpsc,
- thread,
- collections::HashMap,
- cell::RefCell,
-};
+//use std::{
+// sync::mpsc,
+// thread,
+// collections::HashMap,
+// cell::RefCell,
+//};
-mod winit_state;
-use winit_state::WinitState;
+use gfx_backend_vulkan as vk_back;
-use winit::{
- event::{Event, WindowEvent},
- event_loop::ControlFlow,
-};
+pub mod utils;
+use crate::utils::Rect;
+
+mod winit_window;
+use winit_window::WinitWindow;
+
+//use winit::{
+// event::{Event, WindowEvent},
+// event_loop::ControlFlow,
+//};
mod renderer;
use renderer::Renderer;
@@ -51,101 +56,117 @@ pub enum Input {
/// The main function of the library
pub fn run() -> Result<(), &'static str> {
- let winit_state = WinitState::default();
- let mut renderer = Renderer::new(&winit_state.window)?;
+
+ let mut windows = vec![
+ WinitWindow::new("IV", Rect {w: 1280, h: 720})?,
+ WinitWindow::new("IV 2", Rect {w: 720, h: 480})?,
+ ];
+
+ let mut renderer: Renderer = Renderer::new(&mut windows)?;
//let local_state = LocalState::default();
-
- let (input_tx, input_rx) = mpsc::channel();
- let mut window_senders = HashMap::with_capacity(1);
- window_senders.insert(1, input_tx);
-
- let control_thread = RefCell::new(Some(thread::spawn(move || {
- #[allow(unused_imports)]
- use log::{debug, error, info, trace, warn};
-
- let (cmd_tx, cmd_rx) = mpsc::channel();
- let render_thread = thread::spawn(move || {
- #[allow(unused_imports)]
- use log::{debug, error, info, trace, warn};
-
- let mut color = [0.0, 0.0, 0.0, 0.0];
-
- loop {
-
- //TODO manage errors
- let _ = renderer.draw_clear_frame(color);
-
- match cmd_rx.try_recv().unwrap_or(Command::NoCommand) {
- Command::NoCommand => (),
- Command::Stop => {
- warn!("Stop render thread");
- return;
- },
- Command::Color{r, g, b, a} => {
- color = [r, g, b, a];
- },
- }
- }
- });
-
- loop {
- match input_rx.recv().unwrap() {
- Input::Close => {
- cmd_tx.send(Command::Stop).unwrap();
- //TODO stop event_loop
- warn!("wait for render thread");
- render_thread.join().unwrap();
- warn!("Stop control thread");
- return;
- },
- Input::Mouse{x, y} => {
- let pos = Command::Color{
- r: (x/1280.0) as f32,
- g: (y/720.0) as f32,
- b: ((x/1280.0 + y/720.0)/2.0) as f32,
- a: 1.0,
- };
- cmd_tx.send(pos).unwrap();
- },
- }
+
+ let color = [0.5, 0.0, 0.0, 0.1];
+
+ loop {
+ for mut window in &mut windows {
+ let _ = renderer.draw_clear_frame(&mut window, color);
}
- })));
-
- winit_state.event_loop.run(move |event, _, control_flow| {
- #[allow(unused_imports)]
- use log::{debug, error, info, trace, warn};
-
- *control_flow = ControlFlow::Wait;
-
- //TODO manage errors
- let input_tx = window_senders.get(&1).unwrap();
- match event {
- Event::WindowEvent{window_id: _, event} => match event {
- WindowEvent::CloseRequested => {
- input_tx.send(Input::Close).unwrap();
- let handle = control_thread.replace(None).unwrap();
- warn!("Wait for control thread");
- handle.join().unwrap();
- warn!("Stop input thread");
- *control_flow = ControlFlow::Exit;
- },
- WindowEvent::CursorMoved{position, ..} => {
- input_tx
- .send(Input::Mouse{
- x: position.x,
- y: position.y})
- .unwrap();
- },
- _ => (),
- }
- _ => (),
- }
- });
+ }
}
-mod tests {
- #[test]
- fn it_works() {
- assert_eq!(2 + 2, 4);
- }
-}
+// let (input_tx, input_rx) = mpsc::channel();
+// let mut window_senders = HashMap::with_capacity(1);
+// window_senders.insert(1, input_tx);
+//
+// let control_thread = RefCell::new(Some(thread::spawn(move || {
+// #[allow(unused_imports)]
+// use log::{debug, error, info, trace, warn};
+//
+// let (cmd_tx, cmd_rx) = mpsc::channel();
+// let render_thread = thread::spawn(move || {
+// #[allow(unused_imports)]
+// use log::{debug, error, info, trace, warn};
+//
+// let mut color = [0.0, 0.0, 0.0, 0.0];
+//
+// loop {
+//
+// //TODO manage errors
+// for window in windows {
+// let _ = renderer.draw_clear_frame(&mut window, color);
+// }
+//
+// match cmd_rx.try_recv().unwrap_or(Command::NoCommand) {
+// Command::NoCommand => (),
+// Command::Stop => {
+// warn!("Stop render thread");
+// return;
+// },
+// Command::Color{r, g, b, a} => {
+// color = [r, g, b, a];
+// },
+// }
+// }
+// });
+//
+// loop {
+// match input_rx.recv().unwrap() {
+// Input::Close => {
+// cmd_tx.send(Command::Stop).unwrap();
+// //TODO stop event_loop
+// warn!("wait for render thread");
+// render_thread.join().unwrap();
+// warn!("Stop control thread");
+// return;
+// },
+// Input::Mouse{x, y} => {
+// let pos = Command::Color{
+// r: (x/1280.0) as f32,
+// g: (y/720.0) as f32,
+// b: ((x/1280.0 + y/720.0)/2.0) as f32,
+// a: 1.0,
+// };
+// cmd_tx.send(pos).unwrap();
+// },
+// }
+// }
+// })));
+//
+// windows[0].event_loop.run(move |event, _, control_flow| {
+// #[allow(unused_imports)]
+// use log::{debug, error, info, trace, warn};
+//
+// *control_flow = ControlFlow::Wait;
+//
+// //TODO manage errors
+// let input_tx = window_senders.get(&1).unwrap();
+// match event {
+// Event::WindowEvent{window_id: _, event} => match event {
+// WindowEvent::CloseRequested => {
+// input_tx.send(Input::Close).unwrap();
+// let handle = control_thread.replace(None).unwrap();
+// warn!("Wait for control thread");
+// handle.join().unwrap();
+// warn!("Stop input thread");
+// *control_flow = ControlFlow::Exit;
+// },
+// WindowEvent::CursorMoved{position, ..} => {
+// input_tx
+// .send(Input::Mouse{
+// x: position.x,
+// y: position.y})
+// .unwrap();
+// },
+// _ => (),
+// }
+// _ => (),
+// }
+// });
+//}
+//
+//mod tests {
+// #[test]
+// fn it_works() {
+// assert_eq!(2 + 2, 4);
+// }
+//}
diff --git a/src/renderer.rs b/src/renderer.rs
index a734acb..73e3b68 100644
--- a/src/renderer.rs
+++ b/src/renderer.rs
@@ -1,42 +1,103 @@
-use std::mem::ManuallyDrop;
+#[allow(unused_imports)]
+use log::{debug, error, info, trace, warn};
-use gfx_hal::{
- queue::QueueGroup,
- Backend,
- pso::Rect,
+use std::{
+ mem::ManuallyDrop,
};
-use gfx_backend_vulkan as vk_back;
+mod gpu;
+use gpu::Gpu;
-pub mod init;
-pub mod render;
+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 {
- //items need to communicate with the GPU
- instance: ManuallyDrop<::Instance>,
- surface: ManuallyDrop<::Surface>,
- adapter: ManuallyDrop>,
- device: vk_back::Device,
- queue_group: ManuallyDrop>,
- render_pass: ManuallyDrop<::RenderPass>,
- swapchain: ManuallyDrop<::Swapchain>,
- extent: gfx_hal::window::Extent2D,
- format: gfx_hal::format::Format,
- render_area: Rect,
-
- //items needed to render the images
- sems_image_available: Vec<::Semaphore>,
- sems_render_finished: Vec<::Semaphore>,
- fences: Vec<::Fence>,
- image_views: Vec<::ImageView>,
- framebuffers: Vec<::Framebuffer>,
-
- command_pool: ManuallyDrop<::CommandPool>,
- command_buffers: Vec<::CommandBuffer>,
-
- //items needed to keep track of the images
- image_count: usize,
- current_image: usize,
+pub struct Renderer {
+ instance: ManuallyDrop,
+ gpu: ManuallyDrop>,
+ //pipelines: Vec>,
+ swap_systems: Vec>,
}
+impl Drop for Renderer
+where
+ B: gfx_hal::Backend,
+{
+ fn drop(&mut self) {
+ use gfx_hal::device::Device;
+
+ debug!("Waiting for device to idle...");
+ let _ = self.gpu
+ .device()
+ .wait_idle();
+
+ info!("Dropping Renderer...");
+ for mut swap_system in self.swap_systems.drain(..) {
+ swap_system.drop(&mut self.gpu, &self.instance);
+ }
+// for mut pipeline in self.pipelines.drain(..) {
+//
+// }
+ unsafe {
+ ManuallyDrop::drop(&mut self.gpu);
+ ManuallyDrop::drop(&mut self.instance);
+ }
+ trace!("Renderer dropped !");
+ }
+}
+
+impl Renderer
+where
+ B: gfx_hal::Backend,
+{
+ pub fn new<'a, H, T: 'a, I>(outputs: I) -> Result, &'static str>
+ where
+ H: raw_window_handle::HasRawWindowHandle,
+ T: Output,
+ I: IntoIterator- ,
+
+ {
+ use gfx_hal::Instance;
+
+ info!("Creating renderer...");
+ let instance = B::Instance::create("IV", 1)
+ .map_err(|_| "Could not create instance")?;
+ let (mut gpu, mut surfaces) = Gpu::new(&instance, outputs)
+ .map_err(|err| err)?;
+ let swap_systems = {
+ surfaces
+ .drain(..)
+ .map(|surface| SwapSystem::new(&mut gpu, surface))
+ .collect::, &str>>()?
+ };
+
+ debug!("Renderer created !");
+ Ok( Renderer {
+ instance: ManuallyDrop::new(instance),
+ gpu: ManuallyDrop::new(gpu),
+ swap_systems,
+ })
+ }
+
+ pub fn draw_clear_frame(&mut self, output: &mut O, _color: [f32; 4])
+ -> Result<(), &'static str>
+ where
+ T: raw_window_handle::HasRawWindowHandle,
+ O: Output
+ {
+ let swap_index = output.get_id();
+ let frame = self.swap_systems[swap_index].acquire_frame();
+
+ frame.sync_gpu(&self.gpu);
+
+ Ok(())
+ }
+}
+
diff --git a/src/renderer/gpu.rs b/src/renderer/gpu.rs
new file mode 100644
index 0000000..eefb2ed
--- /dev/null
+++ b/src/renderer/gpu.rs
@@ -0,0 +1,193 @@
+#[allow(unused_imports)]
+use log::{debug, error, info, trace, warn};
+
+use std::{
+ mem::ManuallyDrop,
+ ptr::read,
+};
+
+use gfx_hal::{
+ adapter::Adapter,
+ queue::QueueGroup,
+};
+
+use gfx_hal::adapter::Gpu as GfxGpu;
+
+use super::output::Output;
+
+//--Gpu implementation------------------------------------------------------------------------------
+#[derive(Debug)]
+pub struct Gpu {
+ adapter: ManuallyDrop>,
+ device: ManuallyDrop,
+ queue_group: ManuallyDrop>,
+ command_pool: ManuallyDrop,
+}
+
+impl Drop for Gpu
+where
+ B: gfx_hal::Backend,
+{
+ fn drop(&mut self) {
+ use gfx_hal::device::Device;
+
+ debug!("Dropping Gpu...");
+ unsafe {
+ self.device.destroy_command_pool(
+ ManuallyDrop::into_inner(read(&mut self.command_pool)));
+ ManuallyDrop::drop(&mut self.queue_group);
+ ManuallyDrop::drop(&mut self.device);
+ ManuallyDrop::drop(&mut self.adapter);
+ }
+ trace!("Gpu dropped !");
+ }
+}
+
+impl Gpu
+where
+ B: gfx_hal::Backend,
+{
+ pub fn new<'a, H, T: 'a, I>(instance: &B::Instance, outputs: I)
+ -> Result<(Gpu, Vec), &'static str>
+ where
+ H: raw_window_handle::HasRawWindowHandle,
+ T: Output,
+ I: IntoIterator
- ,
+ {
+ use gfx_hal::{
+ queue::family::QueueFamily,
+ };
+
+ debug!("Creating Gpu...");
+ trace!("Creating Surfaces...");
+ let surfaces: Vec<_> = {
+ use gfx_hal::Instance;
+
+ let mut id = 0;
+ outputs
+ .into_iter()
+ .map(|output| unsafe {
+ output.set_id(id);
+ id += 1;
+
+ instance
+ .create_surface(output.window())
+ .map_err(|_| "Could not create surface")
+ })
+ .collect::, &str>>()?
+ };
+
+ let adapter = {
+ use gfx_hal::{
+ Instance,
+ window::Surface,
+ };
+
+ // dry run to print all adapters for debug purposes
+ trace!("Listing Adapters...");
+ let adapters = instance
+ .enumerate_adapters()
+ .into_iter();
+ debug!("Adapters : {:#?}", adapters);
+
+ // selecting an adapter suitabe for all surfaces used
+ //TODO improve selection
+ trace!("Selecting Adapter...");
+ let adapter = instance
+ .enumerate_adapters()
+ .into_iter()
+ .find(|a| {
+ a.queue_families
+ .iter()
+ .any(|qf|
+ QueueFamily::queue_type(qf).supports_graphics()
+ && surfaces
+ .iter()
+ .all(|surface|
+ surface.supports_queue_family(&qf)
+ ))})
+ .ok_or("Could not find a graphical adapter")?;
+ info!("Selected adapter : {}", adapter.info.name);
+
+ adapter
+ };
+
+ let (device, queue_group) = {
+ // get the previously found QueueFamily index
+ trace!("Getting QueueFamily index...");
+ let queue_family = adapter
+ .queue_families
+ .iter()
+ .find(|qf|
+ QueueFamily::queue_type(*qf).supports_graphics())
+ //&& Surface::supports_queue_family(&surface, &qf))
+ .ok_or("Could not find suitable queue_family")?;
+
+ // get the related PhysicalDevice and QueueFamily list
+ trace!("Get Device and QueueGroups...");
+ let GfxGpu {device, queue_groups} = unsafe {
+ use gfx_hal::{
+ adapter::PhysicalDevice,
+ Features,
+ };
+
+ adapter
+ .physical_device
+ .open(&[(&queue_family, &[1.0; 1])], Features::empty())
+ .map_err(|_| "Could not open physical device")?
+ };
+
+ // retrieve the selected QueueFamily
+ trace!("Selecting QueueGroup...");
+ let queue_group = queue_groups
+ .into_iter()
+ .find(|qg| qg.family == queue_family.id())
+ .ok_or("Could not take ownership of the queue")?;
+
+ // check the QueueGroup
+ trace!("Checking selected QueueGroup...");
+ if queue_group.queues.len() <= 0 {
+ return Err("The QueueGroup does not have any CommandQueues available");
+ };
+
+ (device, queue_group)
+ };
+
+ let command_pool = unsafe {
+ use gfx_hal::{
+ pool::CommandPoolCreateFlags,
+ device::Device,
+ };
+
+ trace!("Creating CommandPool...");
+ device
+ .create_command_pool(queue_group.family,
+ CommandPoolCreateFlags::RESET_INDIVIDUAL)
+ .map_err(|_| "Could not create CommandPool")?
+ };
+
+ debug!("Gpu created !");
+ Ok((
+ Gpu {
+ adapter: ManuallyDrop::new(adapter),
+ device: ManuallyDrop::new(device),
+ queue_group: ManuallyDrop::new(queue_group),
+ command_pool: ManuallyDrop::new(command_pool),
+ },
+ surfaces
+ ))
+ }
+
+ pub fn adapter(&self) -> &Adapter {
+ &self.adapter
+ }
+
+ pub fn device(&self) -> &B::Device {
+ &self.device
+ }
+
+ pub fn command_pool_mut(&mut self) -> &mut B::CommandPool {
+ &mut self.command_pool
+ }
+}
+
diff --git a/src/renderer/init.rs b/src/renderer/init.rs
deleted file mode 100644
index 9e5e85c..0000000
--- a/src/renderer/init.rs
+++ /dev/null
@@ -1,415 +0,0 @@
-#[allow(unused_imports)]
-use log::{debug, error, info, trace, warn};
-
-use std::{
- mem::ManuallyDrop,
-};
-
-use core::ptr::read;
-
-use gfx_hal::{
- Instance,
- device::Device,
- Backend,
- pool::CommandPool,
- pso::Rect,
-};
-
-use gfx_backend_vulkan as vk_back;
-
-use winit::window::Window;
-
-use crate::renderer::Renderer;
-
-impl core::ops::Drop for Renderer {
-
- //----------------------------------------------------------------------------------------------
- fn drop(&mut self) {
-
- let _ = self.device.wait_idle();
-
- //destroy all underlying ressources
- debug!("Destroying Renderer ressources");
- unsafe {
- self.command_pool.free(self.command_buffers.drain(..));
- self.device.destroy_command_pool(
- ManuallyDrop::into_inner(read(&mut self.command_pool)));
- for buffer in self.framebuffers.drain(..) {
- self.device.destroy_framebuffer(buffer);
- }
- for view in self.image_views.drain(..) {
- self.device.destroy_image_view(view);
- }
- for fence in self.fences.drain(..) {
- self.device.destroy_fence(fence);
- }
- for sem in self.sems_image_available.drain(..) {
- self.device.destroy_semaphore(sem);
- }
- for sem in self.sems_render_finished.drain(..) {
- self.device.destroy_semaphore(sem);
- }
- self.device.destroy_swapchain(ManuallyDrop::into_inner(read(&mut self.swapchain)));
- self.device.destroy_render_pass(ManuallyDrop::into_inner(read(&mut self.render_pass)));
- ManuallyDrop::drop(&mut self.queue_group);
- ManuallyDrop::drop(&mut self.adapter);
- self.instance.destroy_surface(ManuallyDrop::into_inner(read(&mut self.surface)));
- ManuallyDrop::drop(&mut self.instance);
- }
- info!("Renderer ressources destroyed");
- }
-}
-
-impl Renderer {
-
- //----------------------------------------------------------------------------------------------
- pub fn update_swapchain(&mut self) -> Result<(), &'static str> {
- use gfx_hal::window::{
- SwapchainConfig,
- Surface,
- PresentationSurface,
- };
-
- debug!("Updating swapchain");
-
- //creating new swapchain config
- let capabilities = self.surface.capabilities(&self.adapter.physical_device);
- let swapchain_config = SwapchainConfig::from_caps(&capabilities, self.format, self.extent);
- info!("{:?}", swapchain_config);
-
- self.device
- .wait_idle()
- .map_err(|_| "Failed to to wait for device to be idle")?;
-
- unsafe {
- self.surface
- .configure_swapchain(&self.device, swapchain_config)
- .map_err(|_| "Failed to updtate swapchain")?;
- debug!("update succesfull !");
- }
-
- Ok(())
- }
-
- //----------------------------------------------------------------------------------------------
- pub fn new(window: &Window) -> Result {
- use gfx_hal::adapter::Gpu;
-
- // create top level
- let instance = vk_back::Instance::create("IV", 1)
- .map_err(|_| "Could not create instance")?;
-
- let mut surface = unsafe {
- instance
- .create_surface(window)
- .map_err(|_| "Could not create Surface")?
- };
-
- let (adapter, device, queue_group) = {
- use gfx_hal::{
- window::Surface,
- queue::family::QueueFamily,
- };
-
- // find a adapter with a suitable queue family
- // TODO add weight for adapters
- let adapter =
- Instance::enumerate_adapters(&instance)
- .into_iter();
-// .find(|a| {
-// a.queue_families
-// .iter()
-// .any(|qf|
-// QueueFamily::queue_type(qf).supports_graphics()
-// && Surface::supports_queue_family(&surface, &qf)
-// )})
-// .ok_or("Could not find a graphical adapter")?;
-
- debug!("Adapters : {:#?}", adapter);
-
- let adapter =
- Instance::enumerate_adapters(&instance)
- .into_iter()
- .find(|a| {
- a.queue_families
- .iter()
- .any(|qf|
- QueueFamily::queue_type(qf).supports_graphics()
- && Surface::supports_queue_family(&surface, &qf)
- )})
- .ok_or("Could not find a graphical adapter")?;
-
- info!("Selected adapter : {}", adapter.info.name);
-
- // get the suitable queue family index
- let queue_family = adapter
- .queue_families
- .iter()
- .find(|qf|
- QueueFamily::queue_type(*qf).supports_graphics()
- && Surface::supports_queue_family(&surface, &qf))
- .ok_or("Could not find suitable queue_family")?;
-
- // get the related physical device and queue family list
- let Gpu {device, queue_groups} = unsafe {
- use gfx_hal::{
- adapter::PhysicalDevice,
- Features,
- };
-
- adapter
- .physical_device
- .open(&[(&queue_family, &[1.0; 1])], Features::empty())
- .map_err(|_| "Could not open physical device")?
- };
-
- // retrieve the selected queue family
- let queue_group = queue_groups
- .into_iter()
- .find(|qg| qg.family == queue_family.id())
- .ok_or("Could not take ownership of the queue")?;
-
- // check our harvest
- if queue_group.queues.len() <= 0 {
- return Err("The QueueGroup does not have any CommandQueues available");
- };
-
- (adapter, device, queue_group)
- };
-
- let (swapchain, extent, backbuffer, format, image_count) = {
- use gfx_hal::window::{
- SwapchainConfig,
- Surface,
- };
-
- let capabilities = surface.capabilities(&adapter.physical_device);
- debug!("{:#?}", capabilities);
-
- // select optimal presentation mode (vsync, triple buffuring, ...)
- let present_mode = {
- use gfx_hal::window::PresentMode;
-
- [PresentMode::MAILBOX, PresentMode::FIFO,
- PresentMode::RELAXED, PresentMode::IMMEDIATE]
- .iter()
- .cloned()
- .find(|pm| capabilities.present_modes.contains(*pm))
- .ok_or("No PresentMode found")?
- };
-
- // select optimal alpha composition
-// let composite_alpha_mode = {
-// use gfx_hal::window::CompositeAlphaMode;
-//
-// [CompositeAlphaMode::OPAQUE, CompositeAlphaMode::INHERIT,
-// CompositeAlphaMode::PREMULTIPLIED, CompositeAlphaMode::POSTMULTIPLIED]
-// .iter()
-// .cloned()
-// .find(|cam| capabilities.composite_alpha_modes.contains(*cam))
-// .ok_or("No CompositeAlphaMode found")?
-// };
-
- // select optimal format (sRGB)
- let format = {
- use gfx_hal::format::{Format, ChannelType};
-
- match surface.supported_formats(&adapter.physical_device) {
- None => Format::Rgba8Srgb,
- Some(formats) => formats
- .iter()
- .find(|f| f.base_format().1 == ChannelType::Srgb)
- .cloned()
- .ok_or("Could no find suitabe format")?
- }};
-
- let extent = capabilities.extents.end().clone();
-
- // verify swapchain size
- let image_count = {
- use gfx_hal::window::PresentMode;
-
- capabilities.image_count.end()
- .min(capabilities.image_count.start()
- .max(match present_mode {
- PresentMode::MAILBOX => &3,
- PresentMode::FIFO => &2,
- _ => &1,
- })).clone()
- };
- debug!("image count : {}", image_count);
-
-// // a surface support at least one layer
-// let image_layers = 1;
-//
-// // verify surface compatibility
-// let image_usage = {
-// use gfx_hal::image::Usage;
-//
-// if capabilities.usage.contains(Usage::COLOR_ATTACHMENT) {
-// Ok(Usage::COLOR_ATTACHMENT)
-// } else {
-// Err("This surface does not support color")
-// }
-// }?;
-
- let swapchain_config = SwapchainConfig::from_caps(&capabilities, format, extent);
- debug!("{:?}", swapchain_config);
-
- let (swapchain, backbuffer) = unsafe {
- device
- .create_swapchain(&mut surface, swapchain_config, None)
- .map_err(|_| "Failed to create swapchain and backbuffer")?
- };
-
- (swapchain, extent, backbuffer, format, image_count as usize)
- };
-
- // creating semaphores and fences
- let (sems_image_available, sems_render_finished, fences) = {
-
- let mut sems_image_available : Vec<::Semaphore> = vec![];
- let mut sems_render_finished : Vec<::Semaphore> = vec![];
- let mut fences :Vec<::Fence> = vec![];
-
- for _ in 0..image_count {
- sems_image_available
- .push(device
- .create_semaphore()
- .map_err(|_| "Could not create sempahore")?
- );
- sems_render_finished
- .push(device
- .create_semaphore()
- .map_err(|_| "Could not create sempahore")?
- );
- fences
- .push(device
- .create_fence(true)
- .map_err(|_| "Could not create fence")?
- );
- }
-
- (sems_image_available, sems_render_finished, fences)
- };
-
- // creating RenderPass
- let render_pass = {
- use gfx_hal::{
- pass::{Attachment, AttachmentOps, AttachmentLoadOp, AttachmentStoreOp, SubpassDesc},
- image::Layout,
- };
-
- let color_attachment = Attachment {
- format : Some(format),
- samples : 1,
- ops : AttachmentOps {
- load : AttachmentLoadOp::Clear,
- store : AttachmentStoreOp::Store,
- },
- stencil_ops : AttachmentOps::DONT_CARE,
- layouts : (Layout::Undefined..Layout::Present),
- };
-
- let subpass = SubpassDesc {
- colors : &[(0, Layout::ColorAttachmentOptimal)],
- depth_stencil : None,
- inputs : &[],
- resolves : &[],
- preserves : &[],
- };
-
- unsafe {
- device.create_render_pass(&[color_attachment], &[subpass], &[])
- .map_err(|_| "Could not create render pass")?
- }
- };
-
- // add ImageView "headers" to images in BackBuffer
- let image_views : Vec<_> = {
- use gfx_hal::{
- image::{ViewKind, SubresourceRange},
- format::{Swizzle, Aspects},
- };
-
- backbuffer
- .iter()
- .map(|img| unsafe {
- device
- .create_image_view(
- &img,
- ViewKind::D2,
- format,
- Swizzle::NO,
- SubresourceRange {
- aspects : Aspects::COLOR,
- levels : 0..1,
- layers : 0..1,
- },
- )
- .map_err(|_| "Could not create ImageViews")
- })
- .collect::, &str>>()?
- };
-
- let framebuffers: Vec<_> = {
-
- image_views
- .iter()
- .map(|image_view|
- unsafe {
- device
- .create_framebuffer(&render_pass, vec![image_view], extent.to_extent())
- .map_err(|_| "Could not create FrameBuffer")
- },
- )
- .collect::, &str>>()?
- };
-
- let mut command_pool = unsafe {
- use gfx_hal::pool::CommandPoolCreateFlags;
-
- device
- .create_command_pool(queue_group.family, CommandPoolCreateFlags::RESET_INDIVIDUAL)
- .map_err(|_| "Could not create CommandPool")?
- };
-
- let command_buffers: Vec<_> = unsafe {
- use gfx_hal::command::Level;
-
- framebuffers
- .iter()
- .map(|_| command_pool.allocate_one(Level::Primary))
- .collect()
- };
-
- info!("HAL successfully initialized");
-
- Ok(
- Renderer {
- instance: ManuallyDrop::new(instance),
- surface: ManuallyDrop::new(surface),
- adapter: ManuallyDrop::new(adapter),
- device: device,
- queue_group: ManuallyDrop::new(queue_group),
- render_pass: ManuallyDrop::new(render_pass),
- swapchain: ManuallyDrop::new(swapchain),
- extent: extent,
- format: format,
- render_area: Rect{x: 0, y: 0, w: 1280, h: 720},
- sems_image_available,
- sems_render_finished,
- fences,
- image_views,
- framebuffers,
-
- command_pool: ManuallyDrop::new(command_pool),
- command_buffers,
-
- image_count,
- current_image: 0,
- }
- )
- }
-}
-
diff --git a/src/renderer/output.rs b/src/renderer/output.rs
new file mode 100644
index 0000000..49de5f2
--- /dev/null
+++ b/src/renderer/output.rs
@@ -0,0 +1,43 @@
+#[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/renderer/pipeline.rs b/src/renderer/pipeline.rs
new file mode 100644
index 0000000..45217a1
--- /dev/null
+++ b/src/renderer/pipeline.rs
@@ -0,0 +1,20 @@
+#[allow(unused_imports)]
+use log::{debug, error, info, trace, warn};
+
+use std::{
+ mem::ManuallyDrop,
+};
+
+//--Pipeline implementation-------------------------------------------------------------------------
+#[derive(Debug)]
+pub struct Pipeline {
+ render_pass: ManuallyDrop,
+}
+
+impl Pipeline
+where
+ B: gfx_hal::Backend,
+{
+
+}
+
diff --git a/src/renderer/render.rs b/src/renderer/render.rs
deleted file mode 100644
index 86b244c..0000000
--- a/src/renderer/render.rs
+++ /dev/null
@@ -1,113 +0,0 @@
-#[allow(unused_imports)]
-use log::{debug, error, info, trace, warn};
-
-use std::iter;
-
-use gfx_hal::{
- device::Device,
- window::Swapchain,
- command::CommandBuffer,
-};
-
-use crate::renderer::Renderer;
-
-impl Renderer {
-
- //----------------------------------------------------------------------------------------------
- pub fn draw_clear_frame(&mut self, color: [f32; 4]) -> Result<(), &'static str> {
- use gfx_hal::{
- command::{SubpassContents, ClearValue, ClearColor, CommandBufferFlags},
- queue::{Submission, CommandQueue},
- pso::PipelineStage,
- };
-
- // get current frame fence
- let fence = &self.fences[self.current_image];
-
- //wait for current fence in case we are submiting too fast
- unsafe {
- self.device
- .wait_for_fence(fence, !0)
- .map_err(|_| "Failed to wait for fence")?;
- self.device
- .reset_fence(fence)
- .map_err(|_| "Failed to reset fence")?;
- }
-
- // get current frame semaphores
- let sem_image_available = &self.sems_image_available[self.current_image];
- let sem_render_finished = &self.sems_render_finished[self.current_image];
-
- // acquire image id in swapchain
- let swp_image_id = unsafe {
- match self.swapchain.acquire_image(core::u64::MAX, Some(sem_image_available), None) {
- Ok((swp_image_id, suboptimal)) => match suboptimal {
- Some(_) => {
- return self.update_swapchain()
- .map_err(|_| "Could not recreate swpachain");
- },
- None => swp_image_id,
- }
- Err(_) => {
- return self.update_swapchain()
- .map_err(|_| "Could not recreate swpachain");
- },
- }
- };
-
-// debug!("current image : {}", self.current_image);
-// debug!("swapchain index : {}", swp_image_id);
-
- unsafe {
-
- let command_buffer = &mut self.command_buffers[self.current_image];
- command_buffer.begin_primary(CommandBufferFlags::ONE_TIME_SUBMIT);
-
- let clear_value = ClearValue {color: ClearColor{float32: color}};
-
- command_buffer.begin_render_pass(
- &self.render_pass,
- &self.framebuffers[swp_image_id as usize],
- self.render_area,
- iter::once(clear_value),
- SubpassContents::Inline,
- );
- command_buffer.end_render_pass();
- command_buffer.finish();
- }
-
- let command_buffer = &self.command_buffers[self.current_image];
-
- // prepare the submission
- let submission = Submission {
- command_buffers: iter::once(command_buffer),
- wait_semaphores: iter::once((sem_image_available,
- PipelineStage::COLOR_ATTACHMENT_OUTPUT)),
- signal_semaphores: iter::once(sem_render_finished),
- };
-
- let mut queue = &mut self.queue_group.queues[0];
-
- unsafe {
-
- queue.submit(submission, Some(fence));
-
- let result = self.swapchain.present(&mut queue, swp_image_id, Some(sem_render_finished))
- .map_err(|_| "Failed to present into the swapchain")?;
-
- if result.is_some() {
- self.update_swapchain()
- .map_err(|_| "Could not recreate swapchain")?;
- }
- }
-
- self.current_image = (self.current_image + 1) % self.image_count;
-
-// if self.current_image == 0 {
-// panic!("Abort");
-// }
-
- Ok(())
- }
-}
-
diff --git a/src/renderer/swap_system.rs b/src/renderer/swap_system.rs
new file mode 100644
index 0000000..1fb820f
--- /dev/null
+++ b/src/renderer/swap_system.rs
@@ -0,0 +1,187 @@
+#[allow(unused_imports)]
+use log::{debug, error, info, trace, warn};
+
+use std::{
+ mem::ManuallyDrop,
+ ptr::read,
+};
+
+use gfx_hal::{
+ window::Extent2D,
+ pso::Rect as GfxRect,
+ format::Format,
+};
+
+mod frame;
+use frame::Frame;
+
+use super::gpu::Gpu;
+
+//--SwapSystem implementation-----------------------------------------------------------------------
+#[derive(Debug)]
+pub struct SwapSystem {
+ surface: ManuallyDrop,
+ render_area: GfxRect,
+ format: Format,
+ extent: Extent2D,
+ swapchain: ManuallyDrop,
+ spare_semaphore: ManuallyDrop,
+ render_pass: ManuallyDrop,
+ frames: Vec>,
+}
+
+impl SwapSystem
+where
+ B: gfx_hal::Backend,
+{
+ pub fn drop(&mut self, gpu: &mut Gpu, instance: &B::Instance) {
+ use gfx_hal::{
+ device::Device,
+ Instance,
+ };
+
+ debug!("Dropping SwapSystem...");
+ for mut frame in self.frames.drain(..) {
+ frame.drop(gpu);
+ }
+ unsafe {
+ gpu.device().destroy_render_pass(
+ ManuallyDrop::into_inner(read(&mut self.render_pass)));
+ gpu.device().destroy_semaphore(
+ ManuallyDrop::into_inner(read(&mut self.spare_semaphore)));
+ gpu.device().destroy_swapchain(
+ ManuallyDrop::into_inner(read(&mut self.swapchain)));
+ //render area can be dropped automatically
+ instance.destroy_surface(
+ ManuallyDrop::into_inner(read(&mut self.surface)));
+ }
+ trace!("SwapSystem dropped !");
+ }
+
+ pub fn new(gpu: &mut Gpu, mut surface: B::Surface)
+ -> Result, &'static str>
+ {
+ use gfx_hal::{
+ window::SwapchainConfig,
+ pso::Rect,
+ };
+
+ debug!("Creating SwapSystem...");
+ //TODO handle render_area properly
+ warn!("Hard-coding render area size !");
+ let render_area = Rect{x: 0, y: 0, w: 1280, h: 720};
+
+ trace!("Obtaining surface capabilities...");
+ let capabilities = {
+ use gfx_hal::window::Surface;
+
+ surface.capabilities(&gpu.adapter().physical_device)
+ };
+ debug!("Surface capabitlities : {:#?}", capabilities);
+
+ trace!("Selecting image format...");
+ let format = {
+ use gfx_hal::{
+ format::ChannelType,
+ window::Surface,
+ };
+
+ match surface.supported_formats(&gpu.adapter().physical_device) {
+ None => Format::Rgba8Srgb,
+ Some(formats) => formats
+ .iter()
+ .find(|f| f.base_format().1 == ChannelType::Srgb)
+ .cloned()
+ .ok_or("Could no find suitabe format")?
+ }};
+
+ trace!("Getting surface capabilities extend...");
+ let extent = capabilities.current_extent
+ .unwrap_or(*capabilities.extents.end())
+ .clone();
+
+ trace!("Generating Swapchain configuration...");
+ //TODO improve swapchain configuration
+ let swapchain_config = SwapchainConfig::from_caps(&capabilities, format, extent);
+ let swapchain_config = swapchain_config.with_image_count(3);
+ debug!("Swapchain configuration : {:?}", swapchain_config);
+
+ trace!("Creating Swapchain...");
+ let (swapchain, backbuffer) = unsafe {
+ use gfx_hal::device::Device;
+
+ gpu.device()
+ .create_swapchain(&mut surface, swapchain_config, None)
+ .map_err(|_| "Failed to create swapchain and backbuffer")?
+ };
+
+ trace!("Creating spare Semaphore...");
+ let spare_semaphore = {
+ use gfx_hal::device::Device;
+
+ gpu.device()
+ .create_semaphore()
+ .map_err(|_| "Could not create sempahore")?
+ };
+
+ trace!("Creating RenderPass...");
+ let render_pass = {
+ use gfx_hal::{
+ pass::{Attachment, AttachmentOps, AttachmentLoadOp, AttachmentStoreOp, SubpassDesc},
+ image::Layout,
+ device::Device,
+ };
+
+ let color_attachment = Attachment {
+ format : Some(format),
+ samples : 1,
+ ops : AttachmentOps {
+ load : AttachmentLoadOp::Clear,
+ store : AttachmentStoreOp::Store,
+ },
+ stencil_ops : AttachmentOps::DONT_CARE,
+ layouts : (Layout::Undefined..Layout::Present),
+ };
+
+ let subpass = SubpassDesc {
+ colors : &[(0, Layout::ColorAttachmentOptimal)],
+ depth_stencil : None,
+ inputs : &[],
+ resolves : &[],
+ preserves : &[],
+ };
+
+ unsafe {
+ gpu.device().create_render_pass(&[color_attachment], &[subpass], &[])
+ .map_err(|_| "Could not create render pass")?
+ }
+ };
+
+ //TODO adapt to improved swapchain configuration
+ warn!("Generating hard-coded number of frames !");
+ let frames = {
+ backbuffer
+ .iter()
+ .map(|img|
+ Frame::new(gpu, &img, &format, &render_pass, &extent))
+ .collect::, &str>>()?
+ };
+
+ trace!("Created SwapSystem !");
+ Ok( SwapSystem {
+ surface: ManuallyDrop::new(surface),
+ render_area,
+ format,
+ extent,
+ swapchain: ManuallyDrop::new(swapchain),
+ spare_semaphore: ManuallyDrop::new(spare_semaphore),
+ render_pass: ManuallyDrop::new(render_pass),
+ frames,
+ })
+ }
+
+ pub fn acquire_frame(&mut self) -> Frame {
+ unimplemented!();
+ }
+}
+
diff --git a/src/renderer/swap_system/frame.rs b/src/renderer/swap_system/frame.rs
new file mode 100644
index 0000000..a2d99d4
--- /dev/null
+++ b/src/renderer/swap_system/frame.rs
@@ -0,0 +1,207 @@
+#[allow(unused_imports)]
+use log::{debug, error, info, trace, warn};
+
+use std::{
+ mem::ManuallyDrop,
+ ptr::read,
+ iter,
+ borrow::Borrow,
+};
+
+use gfx_hal::{
+ window::Extent2D,
+ format::Format,
+ queue::Submission,
+ pso::Rect as GfxRect,
+};
+
+use super::super::gpu::Gpu;
+
+//--Frame implementation----------------------------------------------------------------------------
+#[derive(Debug)]
+pub struct Frame {
+ wait_semaphores: Vec,
+ signal_semaphores: Vec,
+ fences: Vec,
+ image_view: ManuallyDrop,
+ framebuffer: ManuallyDrop,
+ command_buffer: ManuallyDrop,
+}
+
+impl Frame
+where
+ B: gfx_hal::Backend,
+{
+ pub fn drop(&mut self, gpu: &mut Gpu) {
+ use gfx_hal::{
+ device::Device,
+ pool::CommandPool,
+ };
+
+ trace!("Dropping Frame...");
+ unsafe {
+ //TODO check that
+ gpu.command_pool_mut().free(
+ iter::once(ManuallyDrop::into_inner(read(&mut self.command_buffer))));
+ gpu.device().destroy_framebuffer(
+ ManuallyDrop::into_inner(read(&mut self.framebuffer)));
+ gpu.device().destroy_image_view(
+ ManuallyDrop::into_inner(read(&mut self.image_view)));
+ for fence in self.fences.drain(..) {
+ gpu.device().destroy_fence(fence);
+ }
+ for semaphore in self.signal_semaphores.drain(..) {
+ gpu.device().destroy_semaphore(semaphore);
+ }
+ for semaphore in self.wait_semaphores.drain(..) {
+ gpu.device().destroy_semaphore(semaphore);
+ }
+ trace!("Frame Dropped !");
+ }
+ }
+
+ pub fn new(gpu: &mut Gpu,
+ image: &B::Image,
+ format: &Format,
+ render_pass: &B::RenderPass,
+ extent: &Extent2D)
+ -> Result, &'static str>
+ {
+
+ debug!("Creating Frame...");
+ trace!("Creating Semaphore and Fences...");
+ let (wait_semaphores, signal_semaphores, fences) = {
+ use gfx_hal::device::Device;
+
+ let wait_semaphores = vec!(
+ gpu.device()
+ .create_semaphore()
+ .map_err(|_| "Could not create Semaphore")?);
+ let signal_semaphores = vec!(
+ gpu.device()
+ .create_semaphore()
+ .map_err(|_| "Could not create Semaphore")?);
+ let fences = vec!(
+ gpu.device()
+ .create_fence(true)
+ .map_err(|_| "Could not create Semaphore")?);
+
+ (wait_semaphores, signal_semaphores, fences)
+ };
+
+ trace!("Creating ImageView...");
+ let image_view = unsafe {
+ use gfx_hal::{
+ image::{ViewKind, SubresourceRange},
+ format::{Swizzle, Aspects},
+ device::Device,
+ };
+
+ gpu.device()
+ .create_image_view(
+ image,
+ ViewKind::D2,
+ format.clone(),
+ Swizzle::NO,
+ SubresourceRange {
+ aspects : Aspects::COLOR,
+ levels : 0..1,
+ layers : 0..1,
+ },
+ )
+ .map_err(|_| "Could not create ImageViews")?
+ };
+
+ trace!("Creating Framebuffer...");
+ let framebuffer = unsafe {
+ use gfx_hal::device::Device;
+
+ gpu.device()
+ .create_framebuffer(render_pass,
+ vec![&image_view],
+ extent.clone().to_extent())
+ .map_err(|_| "Could not create FrameBuffer")?
+ };
+
+ trace!("Allocating CommandBuffer...");
+ let command_buffer = unsafe {
+ use gfx_hal::{
+ command::Level,
+ pool::CommandPool,
+ };
+
+ gpu.command_pool_mut().allocate_one(Level::Primary)
+ };
+
+ trace!("Created Frame !");
+ Ok( Frame {
+ wait_semaphores,
+ signal_semaphores,
+ fences,
+ image_view: ManuallyDrop::new(image_view),
+ framebuffer: ManuallyDrop::new(framebuffer),
+ command_buffer: ManuallyDrop::new(command_buffer),
+ })
+ }
+
+ pub fn sync_gpu(&self, gpu: &Gpu) -> Result<(), &'static str>{
+ use gfx_hal::device::Device;
+
+ unsafe {
+ gpu.device()
+ .wait_for_fence(&self.fences[0], !0)
+ .map_err(|_| "Failed to wait for Fence");
+ gpu.device()
+ .reset_fence(&self.fences[0])
+ .map_err(|_| "Failed to reset fence");
+ }
+
+ Ok(())
+ }
+
+// pub fn construct_pipeline<'a, T, Ic, S, Iw, Is>(&self,
+// render_pass: &B::RenderPass,
+// render_area: GfxRect,
+// color: [f32; 4])
+// -> Result, &'static str>
+// where
+// T: 'a + Borrow,
+// Ic: IntoIterator
- ,
+// S: 'a + Borrow,
+// Iw: IntoIterator
- ,
+// Is: IntoIterator
- ,
+// {
+// use gfx_hal::pso::PipelineStage;
+//
+// unsafe {
+// use gfx_hal::command::{
+// CommandBufferFlags,
+// SubpassContents,
+// ClearValue,
+// ClearColor,
+// CommandBuffer,
+// };
+//
+// self.command_buffer.begin_primary(CommandBufferFlags::ONE_TIME_SUBMIT);
+//
+// let clear_value = ClearValue {color: ClearColor{float32: color}};
+//
+// self.command_buffer.begin_render_pass(
+// render_pass,
+// &self.framebuffer,
+// render_area,
+// iter::once(clear_value),
+// SubpassContents::Inline,
+// );
+// self.command_buffer.end_render_pass();
+// self.command_buffer.finish();
+// }
+//
+// Ok( Submission {
+// command_buffers: iter::once(&self.command_buffer),
+// wait_semaphores: iter::once((&self.wait_semaphores[0],
+// PipelineStage::COLOR_ATTACHMENT_OUTPUT)),
+// signal_semaphores: iter::once(&self.signal_semaphores[0]),
+// })
+// }
+}
diff --git a/src/utils.rs b/src/utils.rs
new file mode 100644
index 0000000..b51888b
--- /dev/null
+++ b/src/utils.rs
@@ -0,0 +1,11 @@
+#[allow(unused_imports)]
+use log::{debug, error, info, trace, warn};
+
+use num_traits::Num;
+
+#[derive(Debug, Copy, Clone)]
+pub struct Rect {
+ pub w: I,
+ pub h: I,
+}
+
diff --git a/src/winit_state.rs b/src/winit_state.rs
deleted file mode 100644
index b8faa77..0000000
--- a/src/winit_state.rs
+++ /dev/null
@@ -1,49 +0,0 @@
-#[allow(unused_imports)]
-use log::{debug, error, info, trace, warn};
-
-use winit::{
- dpi::PhysicalSize,
- event_loop::{EventLoop},
- window::{WindowBuilder, Window},
- error::OsError,
-};
-
-#[derive(Debug)]
-pub struct WinitState {
- pub event_loop: EventLoop<()>,
- pub window: Window,
-}
-
-impl WinitState {
-
- pub fn new (title: &str, size: PhysicalSize) -> Result {
-
- let event_loop = EventLoop::new();
-
- let window = WindowBuilder::new()
- .with_inner_size(size)
- .with_title(title)
- .build(&event_loop)
- .unwrap();
-
- Ok(Self {
- event_loop,
- window,
- })
- }
-}
-
-impl Default for WinitState {
-
- fn default() -> WinitState {
-
- WinitState::new(
- "IV",
- PhysicalSize {
- width : 1280,
- height : 720
- }
- ).unwrap()
- }
-}
-
diff --git a/src/winit_window.rs b/src/winit_window.rs
new file mode 100644
index 0000000..c08320a
--- /dev/null
+++ b/src/winit_window.rs
@@ -0,0 +1,54 @@
+#[allow(unused_imports)]
+use log::{debug, error, info, trace, warn};
+
+use winit::{
+ dpi::PhysicalSize,
+ event_loop::{EventLoop},
+ window::{WindowBuilder, Window},
+};
+
+//TODO fix that
+use super::renderer::output::Output;
+use crate::utils::Rect;
+
+#[derive(Debug)]
+pub struct WinitWindow {
+ pub name: String,
+ size: Rect,
+ id: usize,
+
+ pub event_loop: EventLoop<()>,
+ window: Window,
+}
+
+impl WinitWindow {
+ pub fn new(title: &str, size: Rect) -> Result {
+
+ 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")?;
+
+ Ok(Self {
+ name,
+ size,
+ id,
+ event_loop,
+ window,
+ })
+ }
+}
+
+impl Output for WinitWindow {
+ fn get_id(&self) -> usize { self.id }
+ fn set_id(&mut self, id: usize) { self.id = id; }
+
+ fn size(&mut self) -> &mut Rect { &mut self.size }
+
+ fn window(&self) -> &Window { &self.window }
+}
+