refactor 2

This commit is contained in:
2019-07-30 15:17:52 +02:00
parent 5a67eb1042
commit 0f837ce65e
2 changed files with 142 additions and 125 deletions

View File

@@ -2,7 +2,7 @@ use winit::{Event};
use cgmath::{Matrix4, Rad, Vector3, Deg, Quaternion, Rotation3, One, Rotation, SquareMatrix}; use cgmath::{Matrix4, Rad, Vector3, Deg, Quaternion, Rotation3, One, Rotation, SquareMatrix};
mod vulkan; mod vulkan;
use crate::vulkan::{GameData, Game, LinePoint, GameObject, VulkanRenderer}; use crate::vulkan::{GameData, Game, LinePoint, GameObject, VulkanRenderer, RenderLoopResult};
mod input; mod input;
use crate::input::{InputState}; use crate::input::{InputState};
@@ -100,5 +100,13 @@ fn main() {
log_config.vulkan_validation_layers, log_config.vulkan_validation_layers,
); );
renderer.upload_mesh(mesh::load_mesh("models/cube.dae", true).into_iter().nth(0).unwrap()); renderer.upload_mesh(mesh::load_mesh("models/cube.dae", true).into_iter().nth(0).unwrap());
renderer.render_loop(&mut game);
let mut continue_rendering = true;
while continue_rendering {
match renderer.render_loop(&mut game) {
RenderLoopResult::Ok => {},
RenderLoopResult::Quit => continue_rendering = false,
}
}
} }

View File

@@ -34,6 +34,7 @@ use vs::ty::PushConstants;
use line_vs::ty::LinePushConstants; use line_vs::ty::LinePushConstants;
use crate::mesh::CPUMesh; use crate::mesh::CPUMesh;
use crate::vulkan::RenderLoopResult::Quit;
const VALIDATION_LAYERS: &[&str] = &[ const VALIDATION_LAYERS: &[&str] = &[
"VK_LAYER_LUNARG_standard_validation" "VK_LAYER_LUNARG_standard_validation"
@@ -97,7 +98,14 @@ pub struct VulkanRenderer {
pub render_pass: Arc<RenderPassAbstract + Send + Sync>, pub render_pass: Arc<RenderPassAbstract + Send + Sync>,
pub queue: Arc<Queue>, pub queue: Arc<Queue>,
pub events_loop: EventsLoop, pub events_loop: EventsLoop,
pub recreate_swapchain: bool,
pub debug_callback: Option<DebugCallback>, pub debug_callback: Option<DebugCallback>,
pub previous_frame_end: Option<Box<GpuFuture>>,
}
pub enum RenderLoopResult {
Ok,
Quit
} }
impl VulkanRenderer { impl VulkanRenderer {
@@ -273,42 +281,40 @@ impl VulkanRenderer {
// can draw we also need to create the actual framebuffers. // can draw we also need to create the actual framebuffers.
let framebuffers = window_size_dependent_setup(device.clone(), &images, render_pass.clone(), &mut dynamic_state); let framebuffers = window_size_dependent_setup(device.clone(), &images, render_pass.clone(), &mut dynamic_state);
VulkanRenderer { game_data: data, device, framebuffers, dynamic_state, pipeline, line_pipeline,
surface, swapchain, render_pass, queue, line_vertex_buffer, events_loop, debug_callback }
}
pub fn render_loop(self: &mut Self, game: &mut dyn Game) {
let mut recreate_swapchain = false;
// In the loop below we are going to submit commands to the GPU. Submitting a command produces // In the loop below we are going to submit commands to the GPU. Submitting a command produces
// an object that implements the `GpuFuture` trait, which holds the resources for as long as // an object that implements the `GpuFuture` trait, which holds the resources for as long as
// they are in use by the GPU. // they are in use by the GPU.
// //
// Destroying the `GpuFuture` blocks until the GPU is finished executing it. In order to avoid // Destroying the `GpuFuture` blocks until the GPU is finished executing it. In order to avoid
// that, we store the submission of the previous frame here. // that, we store the submission of the previous frame here.
let mut previous_frame_end = Box::new(sync::now(self.device.clone())) as Box<dyn GpuFuture>; let previous_frame_end = Some(Box::new(sync::now(device.clone())) as Box<dyn GpuFuture>);
loop { VulkanRenderer { game_data: data, device, framebuffers, dynamic_state, pipeline, line_pipeline,
surface, swapchain, render_pass, queue, line_vertex_buffer, events_loop,
recreate_swapchain: false, debug_callback, previous_frame_end }
}
pub fn render_loop(self: &mut Self, game: &mut dyn Game) -> RenderLoopResult {
// It is important to call this function from time to time, otherwise resources will keep // It is important to call this function from time to time, otherwise resources will keep
// accumulating and you will eventually reach an out of memory error. // accumulating and you will eventually reach an out of memory error.
// Calling this function polls various fences in order to determine what the GPU has // Calling this function polls various fences in order to determine what the GPU has
// already processed, and frees the resources that are no longer needed. // already processed, and frees the resources that are no longer needed.
previous_frame_end.cleanup_finished(); self.previous_frame_end.as_mut().unwrap().cleanup_finished();
if recreate_swapchain { if self.recreate_swapchain {
let window = self.surface.window(); let window = self.surface.window();
self.game_data.dimensions = if let Some(dimensions) = window.get_inner_size() { self.game_data.dimensions = if let Some(dimensions) = window.get_inner_size() {
let dimensions: (u32, u32) = dimensions.to_physical(window.get_hidpi_factor()).into(); let dimensions: (u32, u32) = dimensions.to_physical(window.get_hidpi_factor()).into();
[dimensions.0, dimensions.1] [dimensions.0, dimensions.1]
} else { } else {
return; return RenderLoopResult::Ok;
}; };
let (new_swapchain, new_images) = match self.swapchain.recreate_with_dimension(self.game_data.dimensions) { let (new_swapchain, new_images) = match self.swapchain.recreate_with_dimension(self.game_data.dimensions) {
Ok(r) => r, Ok(r) => r,
// This error tends to happen when the user is manually resizing the window. // This error tends to happen when the user is manually resizing the window.
// Simply restarting the loop is the easiest way to fix this issue. // Simply restarting the loop is the easiest way to fix this issue.
Err(SwapchainCreationError::UnsupportedDimensions) => continue, Err(SwapchainCreationError::UnsupportedDimensions) => return RenderLoopResult::Ok,
Err(err) => panic!("{:?}", err) Err(err) => panic!("{:?}", err)
}; };
@@ -317,7 +323,7 @@ impl VulkanRenderer {
// recreate framebuffers as well. // recreate framebuffers as well.
self.framebuffers = window_size_dependent_setup(self.device.clone(), &new_images, self.render_pass.clone(), &mut self.dynamic_state); self.framebuffers = window_size_dependent_setup(self.device.clone(), &new_images, self.render_pass.clone(), &mut self.dynamic_state);
recreate_swapchain = false; self.recreate_swapchain = false;
} }
if self.game_data.recreate_pipeline { if self.game_data.recreate_pipeline {
@@ -340,8 +346,8 @@ impl VulkanRenderer {
let (image_num, acquire_future) = match swapchain::acquire_next_image(self.swapchain.clone(), None) { let (image_num, acquire_future) = match swapchain::acquire_next_image(self.swapchain.clone(), None) {
Ok(r) => r, Ok(r) => r,
Err(AcquireError::OutOfDate) => { Err(AcquireError::OutOfDate) => {
recreate_swapchain = true; self.recreate_swapchain = true;
continue; return RenderLoopResult::Ok;
}, },
Err(err) => panic!("{:?}", err) Err(err) => panic!("{:?}", err)
}; };
@@ -375,24 +381,24 @@ impl VulkanRenderer {
let command_buffer = cbb.build().unwrap(); let command_buffer = cbb.build().unwrap();
let future = previous_frame_end.join(acquire_future) let future = self.previous_frame_end.take().unwrap().join(acquire_future)
.then_execute(self.queue.clone(), command_buffer).unwrap() .then_execute(self.queue.clone(), command_buffer).unwrap()
.then_swapchain_present(self.queue.clone(), self.swapchain.clone(), image_num) .then_swapchain_present(self.queue.clone(), self.swapchain.clone(), image_num)
.then_signal_fence_and_flush(); .then_signal_fence_and_flush();
match future { match future {
Ok(future) => { Ok(future) => {
previous_frame_end = Box::new(future) as Box<_>; self.previous_frame_end = Some(Box::new(future) as Box<_>);
} },
Err(FlushError::OutOfDate) => { Err(FlushError::OutOfDate) => {
recreate_swapchain = true; self.recreate_swapchain = true;
previous_frame_end = Box::new(sync::now(self.device.clone())) as Box<_>; self.previous_frame_end = Some(Box::new(sync::now(self.device.clone())) as Box<_>);
} }
Err(e) => { Err(e) => {
println!("{:?}", e); println!("{:?}", e);
previous_frame_end = Box::new(sync::now(self.device.clone())) as Box<_>; self.previous_frame_end = Some(Box::new(sync::now(self.device.clone())) as Box<_>);
}
} }
};
// Note that in more complex programs it is likely that one of `acquire_next_image`, // Note that in more complex programs it is likely that one of `acquire_next_image`,
// `command_buffer::submit`, or `present` will block for some time. This happens when the // `command_buffer::submit`, or `present` will block for some time. This happens when the
@@ -402,16 +408,19 @@ impl VulkanRenderer {
// wait would happen. Blocking may be the desired behavior, but if you don't want to // wait would happen. Blocking may be the desired behavior, but if you don't want to
// block you should spawn a separate thread dedicated to submissions. // block you should spawn a separate thread dedicated to submissions.
let mut window_closed = false; let mut window_closed = false;
let mut resized = false;
self.events_loop.poll_events(|ev| { self.events_loop.poll_events(|ev| {
game.on_window_event(&ev); game.on_window_event(&ev);
match ev { match ev {
Event::WindowEvent { event: WindowEvent::CloseRequested, .. } => window_closed = true, Event::WindowEvent { event: WindowEvent::CloseRequested, .. } => window_closed = true,
Event::WindowEvent { event: WindowEvent::Resized(_), .. } => recreate_swapchain = true, Event::WindowEvent { event: WindowEvent::Resized(_), .. } => resized = true,
_ => {} _ => {}
} }
}); });
if self.game_data.shutdown || window_closed { return; } if resized { self.recreate_swapchain = true }
} if self.game_data.shutdown || window_closed { return Quit; }
RenderLoopResult::Ok
} }
pub fn upload_mesh(self: &mut Self, mesh: CPUMesh) -> usize { pub fn upload_mesh(self: &mut Self, mesh: CPUMesh) -> usize {