Add frame timer
This commit is contained in:
parent
f8a1c65b8c
commit
12731f507c
7
Cargo.lock
generated
7
Cargo.lock
generated
@ -11,12 +11,6 @@ dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anyhow"
|
||||
version = "1.0.58"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bb07d2053ccdbe10e2af2995a2f116c1330396493dc1269f6a91d0ae82e19704"
|
||||
|
||||
[[package]]
|
||||
name = "approx"
|
||||
version = "0.5.1"
|
||||
@ -1435,7 +1429,6 @@ checksum = "d2d7d3948613f75c98fd9328cfdcc45acc4d360655289d0a7d4ec931392200a3"
|
||||
name = "yray"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bytemuck",
|
||||
"bytemuck_derive",
|
||||
"log",
|
||||
|
@ -6,7 +6,6 @@ edition = "2021"
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1.0.58"
|
||||
bytemuck = "1.10.0"
|
||||
bytemuck_derive = "1.1.0"
|
||||
log = "0.4.17"
|
||||
|
209
src/main.rs
209
src/main.rs
@ -2,11 +2,11 @@ extern crate nalgebra_glm as glm;
|
||||
|
||||
use std::time::Instant;
|
||||
|
||||
use bytemuck_derive::{Pod, Zeroable};
|
||||
use glm::TMat4;
|
||||
use log::LevelFilter;
|
||||
use render::event::RenderEvent;
|
||||
use simplelog::{ColorChoice, CombinedLogger, SharedLogger, TermLogger, TerminalMode};
|
||||
use vulkano::{
|
||||
buffer::{BufferUsage, CpuAccessibleBuffer, CpuBufferPool},
|
||||
buffer::{BufferUsage, CpuAccessibleBuffer, CpuBufferPool, TypedBufferAccess},
|
||||
command_buffer::{AutoCommandBufferBuilder, CommandBufferUsage, SubpassContents},
|
||||
descriptor_set::{PersistentDescriptorSet, WriteDescriptorSet},
|
||||
pipeline::{
|
||||
@ -24,35 +24,42 @@ use winit::{
|
||||
window::WindowBuilder,
|
||||
};
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Debug, Default, Zeroable, Pod)]
|
||||
struct Vertex {
|
||||
position: [f32; 3],
|
||||
color: [f32; 3],
|
||||
}
|
||||
vulkano::impl_vertex!(Vertex, position, color);
|
||||
|
||||
pub mod error;
|
||||
pub mod render;
|
||||
|
||||
use crate::render::{context::VulkanContext, shaders};
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Default, Clone, Copy)]
|
||||
struct ModelViewProjection {
|
||||
model: TMat4<f32>,
|
||||
view: TMat4<f32>,
|
||||
projection: TMat4<f32>,
|
||||
}
|
||||
use crate::render::{
|
||||
context::VulkanContext,
|
||||
data::{ModelViewProjection, Vertex},
|
||||
shaders,
|
||||
};
|
||||
|
||||
fn main() {
|
||||
let loggers: Vec<Box<dyn SharedLogger>> = vec![TermLogger::new(
|
||||
LevelFilter::Debug,
|
||||
simplelog::ConfigBuilder::new().build(),
|
||||
TerminalMode::Mixed,
|
||||
ColorChoice::Auto,
|
||||
)];
|
||||
|
||||
let _ = CombinedLogger::init(loggers);
|
||||
|
||||
log::info!("yray starting");
|
||||
|
||||
let mut mvp = ModelViewProjection {
|
||||
model: glm::identity(),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let event_loop = EventLoop::new();
|
||||
let vk = VulkanContext::new_windowed(&event_loop, WindowBuilder::new()).unwrap();
|
||||
let vk = VulkanContext::new_windowed(
|
||||
&event_loop,
|
||||
WindowBuilder::new()
|
||||
.with_title("yray engine")
|
||||
.with_resizable(false),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
log::info!("Vulkan initialized");
|
||||
|
||||
let vs = shaders::vs::load(vk.device().clone()).unwrap();
|
||||
let fs = shaders::fs::load(vk.device().clone()).unwrap();
|
||||
@ -75,17 +82,43 @@ fn main() {
|
||||
BufferUsage::vertex_buffer(),
|
||||
false,
|
||||
[
|
||||
// Front
|
||||
Vertex {
|
||||
position: [-1.0, -1.0, 0.0],
|
||||
color: [1.0, 0.0, 0.0],
|
||||
position: [-0.5, -0.5, -0.5],
|
||||
},
|
||||
Vertex {
|
||||
position: [0.0, 1.0, 0.0],
|
||||
color: [0.0, 1.0, 0.0],
|
||||
position: [ 0.5, -0.5, -0.5],
|
||||
},
|
||||
Vertex {
|
||||
position: [1.0, -1.0, 0.0],
|
||||
color: [0.0, 0.0, 1.0],
|
||||
position: [ 0.5, 0.5, -0.5],
|
||||
},
|
||||
Vertex {
|
||||
position: [ 0.5, 0.5, -0.5],
|
||||
},
|
||||
Vertex {
|
||||
position: [-0.5, 0.5, -0.5],
|
||||
},
|
||||
Vertex {
|
||||
position: [-0.5, -0.5, -0.5],
|
||||
},
|
||||
// Right
|
||||
Vertex {
|
||||
position: [ 0.5, -0.5, -0.5],
|
||||
},
|
||||
Vertex {
|
||||
position: [ 0.5, -0.5, 0.5],
|
||||
},
|
||||
Vertex {
|
||||
position: [ 0.5, 0.5, 0.5],
|
||||
},
|
||||
Vertex {
|
||||
position: [ 0.5, 0.5, 0.5],
|
||||
},
|
||||
Vertex {
|
||||
position: [ 0.5, 0.5, -0.5],
|
||||
},
|
||||
Vertex {
|
||||
position: [ 0.5, -0.5, -0.5],
|
||||
},
|
||||
]
|
||||
.iter()
|
||||
@ -103,71 +136,75 @@ fn main() {
|
||||
100.0,
|
||||
);
|
||||
|
||||
vk.run(event_loop, move |event, ctl| match event {
|
||||
RenderEvent::CloseRequested => {
|
||||
*ctl = ControlFlow::Exit;
|
||||
}
|
||||
RenderEvent::ViewportResized(size) => {
|
||||
mvp.projection = glm::perspective(
|
||||
size.0 / size.1,
|
||||
45.0,
|
||||
0.01,
|
||||
100.0,
|
||||
);
|
||||
}
|
||||
}, move |vk, future, framebuffer| {
|
||||
let clear_values = vec![[0.0, 0.68, 1.0, 1.0].into()];
|
||||
log::info!("Entering event loop");
|
||||
|
||||
let uniform_buffer_subbuffer = {
|
||||
let elapsed = rotation_start.elapsed().as_secs() as f64
|
||||
+ rotation_start.elapsed().subsec_nanos() as f64 / 1_000_000_000.0;
|
||||
vk.run(
|
||||
event_loop,
|
||||
move |event, ctl| match event {
|
||||
RenderEvent::CloseRequested => {
|
||||
*ctl = ControlFlow::Exit;
|
||||
}
|
||||
RenderEvent::ViewportResized(size) => {
|
||||
log::debug!("Window resized, new size: {}x{}", size.0, size.1);
|
||||
mvp.projection = glm::perspective(size.0 / size.1, 45.0, 0.01, 100.0);
|
||||
}
|
||||
},
|
||||
move |vk, future, framebuffer| {
|
||||
let clear_values = vec![[0.0, 0.68, 1.0, 1.0].into()];
|
||||
|
||||
mvp.view = glm::look_at(
|
||||
&glm::vec3(elapsed.cos() as f32 * 5.0, 5.0, elapsed.sin() as f32 * 5.0),
|
||||
&glm::vec3(0.0, 0.0, 0.0),
|
||||
&glm::vec3(0.0, 1.0, 0.0),
|
||||
);
|
||||
let uniform_buffer_subbuffer = {
|
||||
let elapsed = rotation_start.elapsed().as_secs() as f64
|
||||
+ rotation_start.elapsed().subsec_nanos() as f64 / 1_000_000_000.0;
|
||||
|
||||
let uniform_data = shaders::vs::ty::MVP_Data {
|
||||
model: mvp.model.into(),
|
||||
view: mvp.view.into(),
|
||||
projection: mvp.projection.into(),
|
||||
mvp.view = glm::look_at(
|
||||
&glm::vec3(elapsed.cos() as f32 * 5.0, 5.0, elapsed.sin() as f32 * 5.0),
|
||||
&glm::vec3(0.0, 0.0, 0.0),
|
||||
&glm::vec3(0.0, 1.0, 0.0),
|
||||
);
|
||||
|
||||
let uniform_data = shaders::vs::ty::MVP_Data {
|
||||
model: mvp.model.into(),
|
||||
view: mvp.view.into(),
|
||||
projection: mvp.projection.into(),
|
||||
};
|
||||
|
||||
uniform_buffer.next(uniform_data).unwrap()
|
||||
};
|
||||
|
||||
uniform_buffer.next(uniform_data).unwrap()
|
||||
};
|
||||
|
||||
let layout = pipeline.layout().set_layouts().get(0).unwrap();
|
||||
let set = PersistentDescriptorSet::new(
|
||||
layout.clone(),
|
||||
[WriteDescriptorSet::buffer(0, uniform_buffer_subbuffer)],
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let mut cmd_buffer_builder = AutoCommandBufferBuilder::primary(vk.device().clone(), vk.queue_family(), CommandBufferUsage::OneTimeSubmit)
|
||||
.unwrap();
|
||||
cmd_buffer_builder
|
||||
.begin_render_pass(
|
||||
framebuffer,
|
||||
SubpassContents::Inline,
|
||||
clear_values,
|
||||
let layout = pipeline.layout().set_layouts().get(0).unwrap();
|
||||
let set = PersistentDescriptorSet::new(
|
||||
layout.clone(),
|
||||
[WriteDescriptorSet::buffer(0, uniform_buffer_subbuffer)],
|
||||
)
|
||||
.unwrap()
|
||||
.set_viewport(0, [vk.viewport().clone()])
|
||||
.bind_pipeline_graphics(pipeline.clone())
|
||||
.bind_descriptor_sets(
|
||||
PipelineBindPoint::Graphics,
|
||||
pipeline.layout().clone(),
|
||||
0,
|
||||
set,
|
||||
)
|
||||
.bind_vertex_buffers(0, vertex_buffer.clone())
|
||||
.draw(3, 1, 0, 0)
|
||||
.unwrap()
|
||||
.end_render_pass()
|
||||
.unwrap();
|
||||
let command_buffer = cmd_buffer_builder.build().unwrap();
|
||||
|
||||
future.then_execute(vk.queue().clone(), command_buffer).unwrap()
|
||||
});
|
||||
let mut cmd_buffer_builder = AutoCommandBufferBuilder::primary(
|
||||
vk.device().clone(),
|
||||
vk.queue_family(),
|
||||
CommandBufferUsage::OneTimeSubmit,
|
||||
)
|
||||
.unwrap();
|
||||
cmd_buffer_builder
|
||||
.begin_render_pass(framebuffer, SubpassContents::Inline, clear_values)
|
||||
.unwrap()
|
||||
.set_viewport(0, [vk.viewport().clone()])
|
||||
.bind_pipeline_graphics(pipeline.clone())
|
||||
.bind_descriptor_sets(
|
||||
PipelineBindPoint::Graphics,
|
||||
pipeline.layout().clone(),
|
||||
0,
|
||||
set,
|
||||
)
|
||||
.bind_vertex_buffers(0, vertex_buffer.clone())
|
||||
.draw(vertex_buffer.len() as u32, 1, 0, 0)
|
||||
.unwrap()
|
||||
.end_render_pass()
|
||||
.unwrap();
|
||||
let command_buffer = cmd_buffer_builder.build().unwrap();
|
||||
|
||||
future
|
||||
.then_execute(vk.queue().clone(), command_buffer)
|
||||
.unwrap()
|
||||
},
|
||||
);
|
||||
}
|
||||
|
@ -26,7 +26,7 @@ use winit::{
|
||||
|
||||
use crate::error::EngineError;
|
||||
|
||||
use super::event::RenderEvent;
|
||||
use super::{event::RenderEvent, FrameTimer};
|
||||
|
||||
pub struct VulkanContext {
|
||||
#[allow(dead_code)]
|
||||
@ -155,6 +155,7 @@ impl VulkanContext {
|
||||
let mut recreate_swapchain = false;
|
||||
let mut previous_frame_end =
|
||||
Some(Box::new(sync::now(self.device().clone())) as Box<dyn GpuFuture>);
|
||||
let mut frame_timer = FrameTimer::new();
|
||||
|
||||
event_loop.run(move |event, _, ctl| {
|
||||
match event {
|
||||
@ -217,11 +218,16 @@ impl VulkanContext {
|
||||
Some(Box::new(sync::now(self.device.clone())) as Box<_>);
|
||||
}
|
||||
Err(e) => {
|
||||
println!("Failed to flush future: {:?}", e);
|
||||
log::error!("Failed to flush future: {:?}", e);
|
||||
previous_frame_end =
|
||||
Some(Box::new(sync::now(self.device.clone())) as Box<_>);
|
||||
}
|
||||
}
|
||||
|
||||
frame_timer.frame_done();
|
||||
if frame_timer.update() {
|
||||
log::debug!("{} frames/s", frame_timer.fps());
|
||||
}
|
||||
}
|
||||
_ => (),
|
||||
};
|
||||
|
17
src/render/data.rs
Normal file
17
src/render/data.rs
Normal file
@ -0,0 +1,17 @@
|
||||
use bytemuck_derive::{Pod, Zeroable};
|
||||
use glm::TMat4;
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Debug, Default, Zeroable, Pod)]
|
||||
pub struct Vertex {
|
||||
pub position: [f32; 3],
|
||||
}
|
||||
vulkano::impl_vertex!(Vertex, position);
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Default, Clone, Copy)]
|
||||
pub struct ModelViewProjection {
|
||||
pub model: TMat4<f32>,
|
||||
pub view: TMat4<f32>,
|
||||
pub projection: TMat4<f32>,
|
||||
}
|
@ -1,3 +1,45 @@
|
||||
use std::time::Instant;
|
||||
|
||||
pub mod context;
|
||||
pub mod shaders;
|
||||
pub mod event;
|
||||
pub mod data;
|
||||
|
||||
pub struct FrameTimer {
|
||||
last_time: Instant,
|
||||
frames_per_second: u64,
|
||||
counter: u64
|
||||
}
|
||||
|
||||
impl FrameTimer {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
last_time: Instant::now(),
|
||||
frames_per_second: 0,
|
||||
counter: 0
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update(&mut self) -> bool {
|
||||
let now = Instant::now();
|
||||
let delta = now - self.last_time;
|
||||
|
||||
if delta.as_secs() >= 1 {
|
||||
self.frames_per_second = self.counter / delta.as_secs();
|
||||
self.counter = 0;
|
||||
self.last_time = now;
|
||||
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
pub fn frame_done(&mut self) {
|
||||
self.counter += 1;
|
||||
}
|
||||
|
||||
pub const fn fps(&self) -> u64 {
|
||||
self.frames_per_second
|
||||
}
|
||||
}
|
||||
|
@ -7,8 +7,6 @@ pub mod vs {
|
||||
#version 450
|
||||
|
||||
layout(location = 0) in vec3 position;
|
||||
layout(location = 1) in vec3 color;
|
||||
layout(location = 0) out vec3 out_color;
|
||||
|
||||
layout(set = 0, binding = 0) uniform MVP_Data {
|
||||
mat4 model;
|
||||
@ -19,7 +17,6 @@ layout(set = 0, binding = 0) uniform MVP_Data {
|
||||
void main() {
|
||||
mat4 worldview = uniforms.view * uniforms.model;
|
||||
gl_Position = uniforms.projection * worldview * vec4(position, 1.0);
|
||||
out_color = color;
|
||||
}",
|
||||
types_meta: {
|
||||
use bytemuck::{Pod, Zeroable};
|
||||
@ -35,11 +32,10 @@ pub mod fs {
|
||||
src: "
|
||||
#version 450
|
||||
|
||||
layout(location = 0) in vec3 in_color;
|
||||
layout(location = 0) out vec4 f_color;
|
||||
|
||||
void main() {
|
||||
f_color = vec4(in_color, 1.0);
|
||||
f_color = vec4(1.0, 0.0, 0.0, 1.0);
|
||||
}"
|
||||
}
|
||||
}
|
||||
|
27
yray.cap
Normal file
27
yray.cap
Normal file
@ -0,0 +1,27 @@
|
||||
{
|
||||
"rdocCaptureSettings": 1,
|
||||
"settings": {
|
||||
"autoStart": false,
|
||||
"commandLine": "",
|
||||
"environment": [
|
||||
],
|
||||
"executable": "/home/alnyan/build/sandbox/yray/target/debug/yray",
|
||||
"inject": false,
|
||||
"numQueuedFrames": 2,
|
||||
"options": {
|
||||
"allowFullscreen": true,
|
||||
"allowVSync": true,
|
||||
"apiValidation": false,
|
||||
"captureAllCmdLists": false,
|
||||
"captureCallstacks": false,
|
||||
"captureCallstacksOnlyDraws": false,
|
||||
"debugOutputMute": true,
|
||||
"delayForDebugger": 0,
|
||||
"hookIntoChildren": false,
|
||||
"refAllResources": false,
|
||||
"verifyBufferAccess": false
|
||||
},
|
||||
"queuedFrameCap": 0,
|
||||
"workingDir": "/home/alnyan/build/sandbox/yray"
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user