engine: add fps counter, fix flipping

ecs
q3k 2020-01-20 02:00:14 +01:00
parent ac4b0ca497
commit 8fc9fd6c9d
6 changed files with 78 additions and 8 deletions

View File

@ -11,6 +11,8 @@ rust_binary(
"src/render/vulkan/qfi.rs", "src/render/vulkan/qfi.rs",
"src/render/vulkan/shaders.rs", "src/render/vulkan/shaders.rs",
"src/render/vulkan/swapchains.rs", "src/render/vulkan/swapchains.rs",
"src/util/mod.rs",
"src/util/counter.rs",
], ],
deps = [ deps = [
"//third_party/cargo:winit", "//third_party/cargo:winit",

View File

@ -2,6 +2,7 @@ use log;
use env_logger; use env_logger;
mod render; mod render;
mod util;
fn main() { fn main() {
env_logger::init(); env_logger::init();

View File

@ -45,8 +45,7 @@ impl Renderer {
} }
fn draw_frame(&mut self) { fn draw_frame(&mut self) {
let future = self.instance.flip(); self.instance.flip();
future.wait(None).unwrap()
} }
pub fn main_loop(&mut self) { pub fn main_loop(&mut self) {

View File

@ -1,4 +1,5 @@
use std::sync::Arc; use std::sync::Arc;
use std::time;
use log; use log;
use vulkano::command_buffer as vc; use vulkano::command_buffer as vc;
@ -31,8 +32,14 @@ pub struct Instance<WT> {
render_pass: Option<Arc<dyn vf::RenderPassAbstract + Send + Sync>>, render_pass: Option<Arc<dyn vf::RenderPassAbstract + Send + Sync>>,
framebuffers: Vec<Arc<dyn vf::FramebufferAbstract + Send + Sync>>, framebuffers: Vec<Arc<dyn vf::FramebufferAbstract + Send + Sync>>,
command_buffers: Vec<Arc<vc::AutoCommandBuffer>>, command_buffers: Vec<Arc<vc::AutoCommandBuffer>>,
previous_frame_end: Option<Box<FlipFuture<WT>>>,
recreate_swap_chain: bool,
fps_counter: crate::util::counter::Counter,
} }
type FlipFuture<WT> = FenceSignalFuture<vs::PresentFuture<vc::CommandBufferExecFuture<vs::SwapchainAcquireFuture<WT>, Arc<vc::AutoCommandBuffer>>, WT>>;
impl<WT: 'static + Send + Sync> Instance<WT> { impl<WT: 'static + Send + Sync> Instance<WT> {
pub fn new(name: String) -> Self { pub fn new(name: String) -> Self {
let ai = vi::ApplicationInfo { let ai = vi::ApplicationInfo {
@ -58,6 +65,10 @@ impl<WT: 'static + Send + Sync> Instance<WT> {
render_pass: None, render_pass: None,
framebuffers: vec![], framebuffers: vec![],
command_buffers: 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<WT: 'static + Send + Sync> Instance<WT> {
pub fn use_surface(&mut self, surface: &Arc<vs::Surface<WT>>) { pub fn use_surface(&mut self, surface: &Arc<vs::Surface<WT>>) {
self.surface = Some(surface.clone()); 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()); log::info!("Bound to Vulkan Device: {}", self.binding.as_ref().unwrap().physical_device().name());
self.arm();
} }
fn arm(&mut self) { 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)); self.swapchains = Some(swapchains::Swapchains::new(self.binding.as_ref().unwrap(), None));
let device = self.binding.as_ref().unwrap().device.clone(); let device = self.binding.as_ref().unwrap().device.clone();
@ -87,11 +99,20 @@ impl<WT: 'static + Send + Sync> Instance<WT> {
self.create_framebuffers(); self.create_framebuffers();
let render_pass = self.render_pass.as_ref().unwrap().clone(); 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.create_command_buffers(pipeline);
self.previous_frame_end = None
} }
pub fn flip(&self) -> FenceSignalFuture<vs::PresentFuture<vc::CommandBufferExecFuture<vs::SwapchainAcquireFuture<WT>, Arc<vc::AutoCommandBuffer>>, WT>> {
// (╯°□°)╯︵ ┻━┻
pub fn flip(&mut self) {
match &self.previous_frame_end {
None => (),
Some(future) => future.wait(None).unwrap(),
}
let chain = self.get_swapchain(); let chain = self.get_swapchain();
let (image_index, acquire_future) = vs::acquire_next_image(chain.clone(), None).unwrap(); let (image_index, acquire_future) = vs::acquire_next_image(chain.clone(), None).unwrap();
let command_buffer = self.command_buffers[image_index].clone(); let command_buffer = self.command_buffers[image_index].clone();
@ -99,12 +120,19 @@ impl<WT: 'static + Send + Sync> Instance<WT> {
let gq = self.binding.as_ref().unwrap().graphics_queue.clone(); let gq = self.binding.as_ref().unwrap().graphics_queue.clone();
let pq = self.binding.as_ref().unwrap().present_queue.clone(); let pq = self.binding.as_ref().unwrap().present_queue.clone();
acquire_future let future = acquire_future
.then_execute(gq, command_buffer) .then_execute(gq, command_buffer)
.unwrap() .unwrap()
.then_swapchain_present(pq, chain, image_index) .then_swapchain_present(pq, chain, image_index)
.then_signal_fence_and_flush() .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) { fn create_render_pass(&mut self, color_format: vulkano::format::Format) {

View File

@ -0,0 +1,39 @@
use std::time;
pub struct Counter {
window: time::Duration,
start: Option<time::Instant>,
count: u64,
}
impl Counter {
pub fn new(window: time::Duration) -> Self {
Self {
window,
start: None,
count: 0,
}
}
pub fn tick(&mut self) -> Option<f64> {
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
}
}

1
engine/src/util/mod.rs Normal file
View File

@ -0,0 +1 @@
pub mod counter;