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/shaders.rs",
"src/render/vulkan/swapchains.rs",
"src/util/mod.rs",
"src/util/counter.rs",
],
deps = [
"//third_party/cargo:winit",

View File

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

View File

@ -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) {

View File

@ -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<WT> {
render_pass: Option<Arc<dyn vf::RenderPassAbstract + Send + Sync>>,
framebuffers: Vec<Arc<dyn vf::FramebufferAbstract + Send + Sync>>,
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> {
pub fn new(name: String) -> Self {
let ai = vi::ApplicationInfo {
@ -58,6 +65,10 @@ impl<WT: 'static + Send + Sync> Instance<WT> {
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<WT: 'static + Send + Sync> Instance<WT> {
pub fn use_surface(&mut self, surface: &Arc<vs::Surface<WT>>) {
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<WT: 'static + Send + Sync> Instance<WT> {
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<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 (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<WT: 'static + Send + Sync> Instance<WT> {
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) {

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;