engine: add fps counter, fix flipping
parent
ac4b0ca497
commit
8fc9fd6c9d
|
@ -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",
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
pub mod counter;
|
Loading…
Reference in New Issue