diff --git a/engine/BUILD b/engine/BUILD index 789fbe2..a3754c9 100644 --- a/engine/BUILD +++ b/engine/BUILD @@ -11,6 +11,8 @@ rust_binary( "src/render/vulkan/qfi.rs", "src/render/vulkan/shaders.rs", "src/render/vulkan/swapchains.rs", + "src/util/mod.rs", + "src/util/counter.rs", ], deps = [ "//third_party/cargo:winit", diff --git a/engine/src/main.rs b/engine/src/main.rs index 5349ec0..e3c030c 100644 --- a/engine/src/main.rs +++ b/engine/src/main.rs @@ -2,6 +2,7 @@ use log; use env_logger; mod render; +mod util; fn main() { env_logger::init(); diff --git a/engine/src/render/mod.rs b/engine/src/render/mod.rs index c66ee26..5c3948a 100644 --- a/engine/src/render/mod.rs +++ b/engine/src/render/mod.rs @@ -45,8 +45,7 @@ impl Renderer { } fn draw_frame(&mut self) { - let future = self.instance.flip(); - future.wait(None).unwrap() + self.instance.flip(); } pub fn main_loop(&mut self) { diff --git a/engine/src/render/vulkan/mod.rs b/engine/src/render/vulkan/mod.rs index 9224919..a9927fd 100644 --- a/engine/src/render/vulkan/mod.rs +++ b/engine/src/render/vulkan/mod.rs @@ -1,4 +1,5 @@ use std::sync::Arc; +use std::time; use log; use vulkano::command_buffer as vc; @@ -31,8 +32,14 @@ pub struct Instance { render_pass: Option>, framebuffers: Vec>, command_buffers: Vec>, + + previous_frame_end: Option>>, + recreate_swap_chain: bool, + fps_counter: crate::util::counter::Counter, } +type FlipFuture = FenceSignalFuture, Arc>, WT>>; + impl Instance { pub fn new(name: String) -> Self { let ai = vi::ApplicationInfo { @@ -58,6 +65,10 @@ impl Instance { render_pass: None, framebuffers: vec![], command_buffers: vec![], + + previous_frame_end: None, + recreate_swap_chain: false, + fps_counter: crate::util::counter::Counter::new(time::Duration::from_millis(100)), } } @@ -71,13 +82,14 @@ impl Instance { pub fn use_surface(&mut self, surface: &Arc>) { self.surface = Some(surface.clone()); - self.arm(); + self.binding = Some(binding::Binding::new(&self.vulkan, self.surface.as_ref().unwrap().clone())); log::info!("Bound to Vulkan Device: {}", self.binding.as_ref().unwrap().physical_device().name()); + + self.arm(); } fn arm(&mut self) { - self.binding = Some(binding::Binding::new(&self.vulkan, self.surface.as_ref().unwrap().clone())); self.swapchains = Some(swapchains::Swapchains::new(self.binding.as_ref().unwrap(), None)); let device = self.binding.as_ref().unwrap().device.clone(); @@ -87,11 +99,20 @@ impl Instance { self.create_framebuffers(); let render_pass = self.render_pass.as_ref().unwrap().clone(); - let pipeline = shaders::pipeline_triangle(device, chain.dimensions(), render_pass); + let pipeline = shaders::pipeline_triangle(device.clone(), chain.dimensions(), render_pass); self.create_command_buffers(pipeline); + + self.previous_frame_end = None } - pub fn flip(&self) -> FenceSignalFuture, Arc>, WT>> { + + // (╯°□°)╯︵ ┻━┻ + pub fn flip(&mut self) { + match &self.previous_frame_end { + None => (), + Some(future) => future.wait(None).unwrap(), + } + let chain = self.get_swapchain(); let (image_index, acquire_future) = vs::acquire_next_image(chain.clone(), None).unwrap(); let command_buffer = self.command_buffers[image_index].clone(); @@ -99,12 +120,19 @@ impl Instance { let gq = self.binding.as_ref().unwrap().graphics_queue.clone(); let pq = self.binding.as_ref().unwrap().present_queue.clone(); - acquire_future + let future = acquire_future .then_execute(gq, command_buffer) .unwrap() .then_swapchain_present(pq, chain, image_index) .then_signal_fence_and_flush() - .unwrap() + .unwrap(); + + self.previous_frame_end = Some(Box::new(future)); + + match self.fps_counter.tick() { + Some(rate) => log::info!("FPS: {}", rate), + None => () + } } fn create_render_pass(&mut self, color_format: vulkano::format::Format) { diff --git a/engine/src/util/counter.rs b/engine/src/util/counter.rs new file mode 100644 index 0000000..db4fc5f --- /dev/null +++ b/engine/src/util/counter.rs @@ -0,0 +1,39 @@ +use std::time; + +pub struct Counter { + window: time::Duration, + start: Option, + count: u64, +} + +impl Counter { + pub fn new(window: time::Duration) -> Self { + Self { + window, + start: None, + count: 0, + } + } + + pub fn tick(&mut self) -> Option { + if self.start.is_none() { + self.start = Some(time::Instant::now()); + return None + } + + self.count += 1; + + let start = self.start.unwrap(); + let now = time::Instant::now(); + let delta = now.duration_since(start); + + + if now.duration_since(start) > self.window { + let res = (self.count as f64) / (delta.as_secs_f64()); + self.start = Some(now); + self.count = 0; + return Some(res) + } + None + } +} diff --git a/engine/src/util/mod.rs b/engine/src/util/mod.rs new file mode 100644 index 0000000..a33a516 --- /dev/null +++ b/engine/src/util/mod.rs @@ -0,0 +1 @@ +pub mod counter;