Reuse command and uniform buffers
This commit is contained in:
parent
f3387f03ae
commit
109ecf929c
@ -2,7 +2,7 @@ use std::fmt::{Display, Formatter};
|
||||
|
||||
use vulkano::{
|
||||
device::{physical::SurfacePropertiesError, DeviceCreationError},
|
||||
image::view::ImageViewCreationError,
|
||||
image::{view::ImageViewCreationError, ImageCreationError},
|
||||
instance::InstanceCreationError,
|
||||
render_pass::FramebufferCreationError,
|
||||
swapchain::SwapchainCreationError,
|
||||
@ -18,6 +18,7 @@ pub enum EngineError {
|
||||
VulkanSwapchainError(SwapchainCreationError),
|
||||
VulkanSurfacePropertiesError(SurfacePropertiesError),
|
||||
VulkanImageViewError(ImageViewCreationError),
|
||||
VulkanImageError(ImageCreationError),
|
||||
VulkanFramebufferError(FramebufferCreationError),
|
||||
}
|
||||
|
||||
@ -52,5 +53,6 @@ wrap!(
|
||||
FramebufferCreationError,
|
||||
VulkanFramebufferError
|
||||
);
|
||||
wrap!(EngineError, ImageCreationError, VulkanImageError);
|
||||
|
||||
impl std::error::Error for EngineError {}
|
||||
|
275
src/main.rs
275
src/main.rs
@ -1,25 +1,28 @@
|
||||
extern crate nalgebra_glm as glm;
|
||||
|
||||
use std::time::Instant;
|
||||
use std::{sync::Arc, time::Instant};
|
||||
|
||||
use log::LevelFilter;
|
||||
use render::event::RenderEvent;
|
||||
use simplelog::{ColorChoice, CombinedLogger, SharedLogger, TermLogger, TerminalMode};
|
||||
use vulkano::{
|
||||
buffer::{BufferUsage, CpuAccessibleBuffer, CpuBufferPool, TypedBufferAccess},
|
||||
command_buffer::{AutoCommandBufferBuilder, CommandBufferUsage, SubpassContents},
|
||||
buffer::{BufferUsage, CpuAccessibleBuffer, TypedBufferAccess},
|
||||
command_buffer::{
|
||||
AutoCommandBufferBuilder, CommandBufferUsage, PrimaryAutoCommandBuffer, SubpassContents,
|
||||
},
|
||||
descriptor_set::{PersistentDescriptorSet, WriteDescriptorSet},
|
||||
pipeline::{
|
||||
graphics::{
|
||||
input_assembly::InputAssemblyState, vertex_input::BuffersDefinition,
|
||||
viewport::ViewportState,
|
||||
viewport::ViewportState, depth_stencil::DepthStencilState,
|
||||
},
|
||||
GraphicsPipeline, Pipeline, PipelineBindPoint,
|
||||
},
|
||||
render_pass::Subpass,
|
||||
swapchain::{self, AcquireError},
|
||||
sync::GpuFuture,
|
||||
};
|
||||
use winit::{
|
||||
event::{Event, WindowEvent},
|
||||
event_loop::{ControlFlow, EventLoop},
|
||||
window::WindowBuilder,
|
||||
};
|
||||
@ -29,10 +32,57 @@ pub mod render;
|
||||
|
||||
use crate::render::{
|
||||
context::VulkanContext,
|
||||
data::{ModelViewProjection, Vertex},
|
||||
shaders,
|
||||
data::{ModelViewProjection, Vertex, CUBE_VERTEX_DATA},
|
||||
shaders, FrameTimer, FrameTracer,
|
||||
};
|
||||
|
||||
fn create_command_buffers(
|
||||
vk: &VulkanContext,
|
||||
pipeline: Arc<GraphicsPipeline>,
|
||||
uniform_buffers: &[Arc<CpuAccessibleBuffer<shaders::vs::ty::MVP_Data>>],
|
||||
vertex_buffer: Arc<CpuAccessibleBuffer<[Vertex]>>,
|
||||
) -> Vec<Arc<PrimaryAutoCommandBuffer>> {
|
||||
vk.framebuffers()
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(i, framebuffer)| {
|
||||
let clear_values = vec![[0.0, 0.68, 1.0, 1.0].into(), 1f32.into()];
|
||||
|
||||
let layout = pipeline.layout().set_layouts().get(0).unwrap();
|
||||
let set = PersistentDescriptorSet::new(
|
||||
layout.clone(),
|
||||
[WriteDescriptorSet::buffer(0, uniform_buffers[i].clone())],
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let mut cmd_buffer_builder = AutoCommandBufferBuilder::primary(
|
||||
vk.device().clone(),
|
||||
vk.queue_family(),
|
||||
CommandBufferUsage::MultipleSubmit,
|
||||
)
|
||||
.unwrap();
|
||||
cmd_buffer_builder
|
||||
.begin_render_pass(framebuffer.clone(), 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();
|
||||
|
||||
Arc::new(cmd_buffer_builder.build().unwrap())
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let loggers: Vec<Box<dyn SharedLogger>> = vec![TermLogger::new(
|
||||
LevelFilter::Debug,
|
||||
@ -51,7 +101,7 @@ fn main() {
|
||||
};
|
||||
|
||||
let event_loop = EventLoop::new();
|
||||
let vk = VulkanContext::new_windowed(
|
||||
let mut vk = VulkanContext::new_windowed(
|
||||
&event_loop,
|
||||
WindowBuilder::new()
|
||||
.with_title("yray engine")
|
||||
@ -64,15 +114,13 @@ fn main() {
|
||||
let vs = shaders::vs::load(vk.device().clone()).unwrap();
|
||||
let fs = shaders::fs::load(vk.device().clone()).unwrap();
|
||||
|
||||
let uniform_buffer: CpuBufferPool<shaders::vs::ty::MVP_Data> =
|
||||
CpuBufferPool::uniform_buffer(vk.device().clone());
|
||||
|
||||
let pipeline = GraphicsPipeline::start()
|
||||
.vertex_input_state(BuffersDefinition::new().vertex::<Vertex>())
|
||||
.vertex_shader(vs.entry_point("main").unwrap(), ())
|
||||
.input_assembly_state(InputAssemblyState::new())
|
||||
.viewport_state(ViewportState::viewport_dynamic_scissor_irrelevant())
|
||||
.fragment_shader(fs.entry_point("main").unwrap(), ())
|
||||
.depth_stencil_state(DepthStencilState::simple_depth_test())
|
||||
.render_pass(Subpass::from(vk.render_pass().clone(), 0).unwrap())
|
||||
.build(vk.device().clone())
|
||||
.unwrap();
|
||||
@ -81,134 +129,123 @@ fn main() {
|
||||
vk.device().clone(),
|
||||
BufferUsage::vertex_buffer(),
|
||||
false,
|
||||
[
|
||||
// Front
|
||||
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],
|
||||
},
|
||||
// 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()
|
||||
.cloned(),
|
||||
CUBE_VERTEX_DATA.iter().cloned(),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let rotation_start = Instant::now();
|
||||
|
||||
let viewport = vk.viewport();
|
||||
mvp.projection = glm::perspective(
|
||||
viewport.dimensions[0] / viewport.dimensions[1],
|
||||
45.0,
|
||||
0.01,
|
||||
100.0,
|
||||
let dim = vk.inner_size();
|
||||
mvp.projection = glm::perspective(dim.0 / dim.1, 45.0, 0.01, 100.0);
|
||||
|
||||
let uniform_buffers: Vec<_> = (0..vk.swapchain().image_count())
|
||||
.map(|_| {
|
||||
CpuAccessibleBuffer::from_data(
|
||||
vk.device().clone(),
|
||||
BufferUsage::uniform_buffer_transfer_destination(),
|
||||
false,
|
||||
shaders::vs::ty::MVP_Data::from(mvp),
|
||||
)
|
||||
.unwrap()
|
||||
})
|
||||
.collect();
|
||||
|
||||
let mut command_buffers = create_command_buffers(
|
||||
&vk,
|
||||
pipeline.clone(),
|
||||
&uniform_buffers,
|
||||
vertex_buffer.clone(),
|
||||
);
|
||||
|
||||
log::info!("Entering event loop");
|
||||
|
||||
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);
|
||||
let mut recreate_swapchain = false;
|
||||
|
||||
let mut frame_timer = FrameTimer::new();
|
||||
let mut frame_tracer = FrameTracer::new();
|
||||
|
||||
event_loop.run(move |event, _, ctl| match event {
|
||||
Event::WindowEvent {
|
||||
event: WindowEvent::CloseRequested,
|
||||
..
|
||||
} => {
|
||||
*ctl = ControlFlow::Exit;
|
||||
}
|
||||
Event::WindowEvent {
|
||||
event: WindowEvent::Resized(_),
|
||||
..
|
||||
} => {
|
||||
recreate_swapchain = true;
|
||||
}
|
||||
Event::RedrawEventsCleared => {
|
||||
frame_tracer.reset();
|
||||
frame_tracer.trace("Frame begin");
|
||||
|
||||
if recreate_swapchain {
|
||||
let size = vk.recreate_swapchain().unwrap();
|
||||
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()];
|
||||
recreate_swapchain = false;
|
||||
|
||||
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;
|
||||
|
||||
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),
|
||||
command_buffers = create_command_buffers(
|
||||
&vk,
|
||||
pipeline.clone(),
|
||||
&uniform_buffers,
|
||||
vertex_buffer.clone(),
|
||||
);
|
||||
frame_tracer.trace("Recreate swapchain/command buffers");
|
||||
}
|
||||
|
||||
let uniform_data = shaders::vs::ty::MVP_Data {
|
||||
model: mvp.model.into(),
|
||||
view: mvp.view.into(),
|
||||
projection: mvp.projection.into(),
|
||||
let (image_index, suboptimal, acquire_future) =
|
||||
match swapchain::acquire_next_image(vk.swapchain().clone(), None) {
|
||||
Ok(r) => r,
|
||||
Err(AcquireError::OutOfDate) => {
|
||||
recreate_swapchain = true;
|
||||
return;
|
||||
}
|
||||
Err(e) => panic!("Failed to acquire next image: {:?}", e),
|
||||
};
|
||||
|
||||
uniform_buffer.next(uniform_data).unwrap()
|
||||
};
|
||||
if suboptimal {
|
||||
recreate_swapchain = true;
|
||||
}
|
||||
|
||||
let layout = pipeline.layout().set_layouts().get(0).unwrap();
|
||||
let set = PersistentDescriptorSet::new(
|
||||
layout.clone(),
|
||||
[WriteDescriptorSet::buffer(0, uniform_buffer_subbuffer)],
|
||||
)
|
||||
.unwrap();
|
||||
frame_tracer.trace("Acquire next image");
|
||||
|
||||
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();
|
||||
let elapsed = rotation_start.elapsed().as_secs() as f64
|
||||
+ rotation_start.elapsed().subsec_nanos() as f64 / 1_000_000_000.0;
|
||||
|
||||
let res = future
|
||||
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 buffer = uniform_buffers[image_index].clone();
|
||||
let mut data = buffer.write().unwrap();
|
||||
*data = mvp.into();
|
||||
}
|
||||
|
||||
frame_tracer.trace("Submit new uniforms");
|
||||
|
||||
let command_buffer = command_buffers[image_index].clone();
|
||||
let future = acquire_future
|
||||
.then_execute(vk.queue().clone(), command_buffer)
|
||||
.unwrap()
|
||||
.then_swapchain_present(vk.queue().clone(), vk.swapchain().clone(), image_index)
|
||||
.then_signal_fence_and_flush()
|
||||
.unwrap();
|
||||
|
||||
vk.frame_tracer().trace("Render pass 1 command send");
|
||||
future.wait(None).unwrap();
|
||||
|
||||
res
|
||||
},
|
||||
);
|
||||
frame_tracer.trace("Submit commands and wait");
|
||||
|
||||
frame_timer.frame_done();
|
||||
if frame_timer.update() {
|
||||
log::debug!("{} frames/s", frame_timer.fps());
|
||||
log::debug!("{:?}", frame_tracer.timings());
|
||||
}
|
||||
}
|
||||
_ => (),
|
||||
});
|
||||
}
|
||||
|
@ -5,29 +5,22 @@ use vulkano::{
|
||||
physical::{PhysicalDevice, PhysicalDeviceType, QueueFamily},
|
||||
Device, DeviceCreateInfo, DeviceExtensions, Queue, QueueCreateInfo,
|
||||
},
|
||||
image::{view::ImageView, SwapchainImage},
|
||||
format::Format,
|
||||
image::{view::ImageView, AttachmentImage, ImageAccess, SwapchainImage},
|
||||
instance::{Instance, InstanceCreateInfo},
|
||||
pipeline::graphics::viewport::Viewport,
|
||||
render_pass::{Framebuffer, FramebufferCreateInfo, RenderPass},
|
||||
swapchain::{
|
||||
self, AcquireError, Surface, Swapchain, SwapchainAcquireFuture, SwapchainCreateInfo,
|
||||
SwapchainCreationError,
|
||||
},
|
||||
sync::{self, FlushError},
|
||||
sync::{GpuFuture, JoinFuture},
|
||||
swapchain::{Surface, Swapchain, SwapchainCreateInfo, SwapchainCreationError},
|
||||
Version,
|
||||
};
|
||||
use vulkano_win::VkSurfaceBuild;
|
||||
use winit::{
|
||||
event::{Event, WindowEvent},
|
||||
event_loop::{ControlFlow, EventLoop},
|
||||
event_loop::EventLoop,
|
||||
window::{Window, WindowBuilder},
|
||||
};
|
||||
|
||||
use crate::error::EngineError;
|
||||
|
||||
use super::{event::RenderEvent, FrameTimer, FrameTracer};
|
||||
|
||||
pub struct VulkanContext {
|
||||
#[allow(dead_code)]
|
||||
instance: Arc<Instance>,
|
||||
@ -41,8 +34,6 @@ pub struct VulkanContext {
|
||||
|
||||
surface: Arc<Surface<Window>>,
|
||||
viewport: Viewport,
|
||||
|
||||
frame_tracer: FrameTracer,
|
||||
}
|
||||
|
||||
impl VulkanContext {
|
||||
@ -53,7 +44,7 @@ impl VulkanContext {
|
||||
let required_extensions = vulkano_win::required_extensions();
|
||||
let device_extensions = DeviceExtensions {
|
||||
khr_swapchain: true,
|
||||
khr_maintenance1: true, // Required for flipping Y-axis on viewport
|
||||
khr_maintenance1: true, // Required for flipping Y-axis on viewport
|
||||
..DeviceExtensions::none()
|
||||
};
|
||||
|
||||
@ -110,16 +101,23 @@ impl VulkanContext {
|
||||
store: Store,
|
||||
format: swapchain.image_format(),
|
||||
samples: 1,
|
||||
},
|
||||
depth: {
|
||||
load: Clear,
|
||||
store: DontCare,
|
||||
format: Format::D16_UNORM,
|
||||
samples: 1,
|
||||
}
|
||||
},
|
||||
pass: {
|
||||
color: [color],
|
||||
depth_stencil: {}
|
||||
depth_stencil: {depth}
|
||||
}
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let framebuffers = Self::create_framebuffers(&swapchain_images, render_pass.clone())?;
|
||||
let framebuffers =
|
||||
Self::create_framebuffers(device.clone(), &swapchain_images, render_pass.clone())?;
|
||||
|
||||
let viewport = Viewport {
|
||||
origin: [0.0, dim.height as f32],
|
||||
@ -137,120 +135,10 @@ impl VulkanContext {
|
||||
render_pass,
|
||||
framebuffers,
|
||||
viewport,
|
||||
|
||||
frame_tracer: FrameTracer::new()
|
||||
})
|
||||
}
|
||||
|
||||
pub fn frame_tracer(&mut self) -> &mut FrameTracer {
|
||||
&mut self.frame_tracer
|
||||
}
|
||||
|
||||
pub fn run<
|
||||
T: GpuFuture + 'static,
|
||||
EventHandler: 'static + FnMut(RenderEvent, &mut ControlFlow),
|
||||
RenderHandler: 'static
|
||||
+ FnMut(
|
||||
&mut VulkanContext,
|
||||
JoinFuture<Box<dyn GpuFuture>, SwapchainAcquireFuture<Window>>,
|
||||
Arc<Framebuffer>,
|
||||
) -> T,
|
||||
>(
|
||||
mut self,
|
||||
event_loop: EventLoop<()>,
|
||||
mut event_handler: EventHandler,
|
||||
mut render_handler: RenderHandler,
|
||||
) -> ! {
|
||||
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 {
|
||||
Event::WindowEvent {
|
||||
event: WindowEvent::CloseRequested,
|
||||
..
|
||||
} => {
|
||||
event_handler(RenderEvent::CloseRequested, ctl);
|
||||
}
|
||||
Event::WindowEvent {
|
||||
event: WindowEvent::Resized(_),
|
||||
..
|
||||
} => {
|
||||
recreate_swapchain = true;
|
||||
}
|
||||
Event::RedrawEventsCleared => {
|
||||
self.frame_tracer.reset();
|
||||
previous_frame_end
|
||||
.as_mut()
|
||||
.take()
|
||||
.unwrap()
|
||||
.cleanup_finished();
|
||||
self.frame_tracer.trace("Previous frame cleanup");
|
||||
|
||||
if recreate_swapchain {
|
||||
let size = self.recreate_swapchain().unwrap();
|
||||
event_handler(RenderEvent::ViewportResized(size), ctl);
|
||||
recreate_swapchain = false;
|
||||
}
|
||||
|
||||
let (image_num, suboptimal, acquire_future) =
|
||||
match swapchain::acquire_next_image(self.swapchain.clone(), None) {
|
||||
Ok(r) => r,
|
||||
Err(AcquireError::OutOfDate) => {
|
||||
recreate_swapchain = true;
|
||||
return;
|
||||
}
|
||||
Err(e) => panic!("Failed to acquire next image: {:?}", e),
|
||||
};
|
||||
|
||||
if suboptimal {
|
||||
recreate_swapchain = true;
|
||||
}
|
||||
|
||||
self.frame_tracer.trace("Acquire next frame");
|
||||
|
||||
let future = previous_frame_end.take().unwrap().join(acquire_future);
|
||||
let framebuffer = self.framebuffers[image_num].clone();
|
||||
let future = render_handler(&mut self, future, framebuffer)
|
||||
.then_swapchain_present(
|
||||
self.queue.clone(),
|
||||
self.swapchain.clone(),
|
||||
image_num,
|
||||
)
|
||||
.then_signal_semaphore_and_flush();
|
||||
|
||||
match future {
|
||||
Ok(future) => {
|
||||
previous_frame_end = Some(Box::new(future) as Box<_>);
|
||||
}
|
||||
Err(FlushError::OutOfDate) => {
|
||||
recreate_swapchain = true;
|
||||
previous_frame_end =
|
||||
Some(Box::new(sync::now(self.device.clone())) as Box<_>);
|
||||
}
|
||||
Err(e) => {
|
||||
log::error!("Failed to flush future: {:?}", e);
|
||||
previous_frame_end =
|
||||
Some(Box::new(sync::now(self.device.clone())) as Box<_>);
|
||||
}
|
||||
}
|
||||
|
||||
self.frame_tracer.trace("Frame finish");
|
||||
|
||||
frame_timer.frame_done();
|
||||
if frame_timer.update() {
|
||||
log::debug!("{} frames/s", frame_timer.fps());
|
||||
log::debug!("{:?}", self.frame_tracer.timings());
|
||||
}
|
||||
}
|
||||
_ => (),
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
fn recreate_swapchain(&mut self) -> Result<(f32, f32), EngineError> {
|
||||
pub fn recreate_swapchain(&mut self) -> Result<(f32, f32), EngineError> {
|
||||
let dim = self.surface.window().inner_size();
|
||||
|
||||
self.viewport.origin[1] = dim.height as f32;
|
||||
@ -269,12 +157,17 @@ impl VulkanContext {
|
||||
};
|
||||
|
||||
self.swapchain = new_swapchain;
|
||||
self.framebuffers = Self::create_framebuffers(&new_images, self.render_pass.clone())?;
|
||||
self.framebuffers =
|
||||
Self::create_framebuffers(self.device.clone(), &new_images, self.render_pass.clone())?;
|
||||
self.swapchain_images = new_images;
|
||||
|
||||
Ok(dim.into())
|
||||
}
|
||||
|
||||
pub fn inner_size(&self) -> (f32, f32) {
|
||||
self.surface.window().inner_size().into()
|
||||
}
|
||||
|
||||
pub fn device(&self) -> &Arc<Device> {
|
||||
&self.device
|
||||
}
|
||||
@ -327,14 +220,22 @@ impl VulkanContext {
|
||||
}
|
||||
|
||||
fn create_single_framebuffer(
|
||||
device: Arc<Device>,
|
||||
image: Arc<SwapchainImage<Window>>,
|
||||
render_pass: Arc<RenderPass>,
|
||||
) -> Result<Arc<Framebuffer>, EngineError> {
|
||||
let dimensions = image.dimensions().width_height();
|
||||
let view = ImageView::new_default(image)?;
|
||||
let depth_buffer = ImageView::new_default(AttachmentImage::transient(
|
||||
device,
|
||||
dimensions,
|
||||
Format::D16_UNORM,
|
||||
)?)?;
|
||||
|
||||
let res = Framebuffer::new(
|
||||
render_pass,
|
||||
FramebufferCreateInfo {
|
||||
attachments: vec![view],
|
||||
attachments: vec![view, depth_buffer],
|
||||
..Default::default()
|
||||
},
|
||||
)?;
|
||||
@ -342,12 +243,15 @@ impl VulkanContext {
|
||||
}
|
||||
|
||||
fn create_framebuffers(
|
||||
device: Arc<Device>,
|
||||
images: &[Arc<SwapchainImage<Window>>],
|
||||
render_pass: Arc<RenderPass>,
|
||||
) -> Result<Vec<Arc<Framebuffer>>, EngineError> {
|
||||
images
|
||||
.iter()
|
||||
.map(|image| Self::create_single_framebuffer(image.clone(), render_pass.clone()))
|
||||
.map(|image| {
|
||||
Self::create_single_framebuffer(device.clone(), image.clone(), render_pass.clone())
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,8 @@
|
||||
use bytemuck_derive::{Pod, Zeroable};
|
||||
use glm::TMat4;
|
||||
|
||||
use super::shaders;
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Debug, Default, Zeroable, Pod)]
|
||||
pub struct Vertex {
|
||||
@ -15,3 +17,130 @@ pub struct ModelViewProjection {
|
||||
pub view: TMat4<f32>,
|
||||
pub projection: TMat4<f32>,
|
||||
}
|
||||
|
||||
pub const CUBE_VERTEX_DATA: &[Vertex] = &[
|
||||
// Front
|
||||
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],
|
||||
},
|
||||
// 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],
|
||||
},
|
||||
// Back
|
||||
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],
|
||||
},
|
||||
// Left
|
||||
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],
|
||||
},
|
||||
// Top
|
||||
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],
|
||||
},
|
||||
// Bottom
|
||||
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],
|
||||
},
|
||||
];
|
||||
|
||||
impl From<ModelViewProjection> for shaders::vs::ty::MVP_Data {
|
||||
fn from(mvp: ModelViewProjection) -> Self {
|
||||
Self {
|
||||
model: mvp.model.into(),
|
||||
view: mvp.view.into(),
|
||||
projection: mvp.projection.into()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +0,0 @@
|
||||
|
||||
pub enum RenderEvent {
|
||||
ViewportResized((f32, f32)),
|
||||
CloseRequested,
|
||||
}
|
@ -1,18 +1,16 @@
|
||||
use std::time::{Instant, Duration};
|
||||
use std::time::{Duration, Instant};
|
||||
|
||||
pub mod context;
|
||||
pub mod shaders;
|
||||
pub mod event;
|
||||
pub mod data;
|
||||
pub mod shaders;
|
||||
|
||||
pub struct FrameTimer {
|
||||
last_time: Instant,
|
||||
frames_per_second: u64,
|
||||
counter: u64
|
||||
counter: u64,
|
||||
}
|
||||
|
||||
pub struct FrameTracer {
|
||||
frame_start: Option<Instant>,
|
||||
trace_points: Vec<(String, Instant)>,
|
||||
}
|
||||
|
||||
@ -21,7 +19,7 @@ impl FrameTimer {
|
||||
Self {
|
||||
last_time: Instant::now(),
|
||||
frames_per_second: 0,
|
||||
counter: 0
|
||||
counter: 0,
|
||||
}
|
||||
}
|
||||
|
||||
@ -49,16 +47,20 @@ impl FrameTimer {
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for FrameTimer {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl FrameTracer {
|
||||
pub const fn new() -> Self {
|
||||
Self {
|
||||
frame_start: None,
|
||||
trace_points: vec![]
|
||||
trace_points: vec![],
|
||||
}
|
||||
}
|
||||
|
||||
pub fn reset(&mut self) {
|
||||
self.frame_start = Some(Instant::now());
|
||||
self.trace_points.clear();
|
||||
}
|
||||
|
||||
@ -67,10 +69,9 @@ impl FrameTracer {
|
||||
}
|
||||
|
||||
pub fn timings(&self) -> Vec<(String, Duration)> {
|
||||
if let Some(start) = self.frame_start {
|
||||
self.trace_points.iter().map(|point| (point.0.clone(), point.1 - start)).collect()
|
||||
} else {
|
||||
vec![]
|
||||
}
|
||||
self.trace_points
|
||||
.windows(2)
|
||||
.map(|pair| (pair[1].0.to_owned(), pair[1].1 - pair[0].1))
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
@ -14,9 +14,13 @@ layout(set = 0, binding = 0) uniform MVP_Data {
|
||||
mat4 projection;
|
||||
} uniforms;
|
||||
|
||||
layout(location = 0) out vec3 m_position;
|
||||
|
||||
void main() {
|
||||
mat4 worldview = uniforms.view * uniforms.model;
|
||||
gl_Position = uniforms.projection * worldview * vec4(position, 1.0);
|
||||
|
||||
m_position = position;
|
||||
}",
|
||||
types_meta: {
|
||||
use bytemuck::{Pod, Zeroable};
|
||||
@ -32,10 +36,12 @@ pub mod fs {
|
||||
src: "
|
||||
#version 450
|
||||
|
||||
layout(location = 0) in vec3 m_position;
|
||||
|
||||
layout(location = 0) out vec4 f_color;
|
||||
|
||||
void main() {
|
||||
f_color = vec4(1.0, 0.0, 0.0, 1.0);
|
||||
f_color = vec4(m_position, 1.0);
|
||||
}"
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user