Got input system to work

+ added changing color depending on mouse pos
+ started refactoring HalState
* Vsync may not be working
This commit is contained in:
Steins7 2020-07-28 11:18:13 +02:00
parent ebc9299f33
commit 7dc22f026e
5 changed files with 120 additions and 137 deletions

View File

@ -16,7 +16,7 @@ fn setup_logger() -> Result<(), fern::InitError> {
message message
)) ))
}) })
.level(log::LevelFilter::Warn) .level(log::LevelFilter::Debug)
.chain(std::io::stdout()) .chain(std::io::stdout())
.chain(fern::log_file("output.log")?) .chain(fern::log_file("output.log")?)
.apply()?; .apply()?;

View File

@ -10,7 +10,6 @@ use std::{
thread, thread,
collections::HashMap, collections::HashMap,
cell::RefCell, cell::RefCell,
time,
}; };
mod winit_state; mod winit_state;
@ -21,15 +20,29 @@ use winit::{
event_loop::ControlFlow, event_loop::ControlFlow,
}; };
mod hal; mod renderer;
use hal::HalState; use renderer::Renderer;
//mod local_state; //mod local_state;
//use local_state::LocalState; //use local_state::LocalState;
pub enum Command { pub enum Command {
Draw, NoCommand,
Stop, Stop,
Color{
r: f32,
g: f32,
b: f32,
a: f32,
},
}
pub enum Input {
Close,
Mouse{
x: f64,
y: f64,
},
} }
@ -39,7 +52,7 @@ pub enum Command {
/// The main function of the library /// The main function of the library
pub fn run() -> Result<(), &'static str> { pub fn run() -> Result<(), &'static str> {
let winit_state = WinitState::default(); let winit_state = WinitState::default();
let mut hal_state = HalState::new(&winit_state.window)?; let mut renderer = Renderer::new(&winit_state.window)?;
//let local_state = LocalState::default(); //let local_state = LocalState::default();
let (input_tx, input_rx) = mpsc::channel(); let (input_tx, input_rx) = mpsc::channel();
@ -55,39 +68,46 @@ pub fn run() -> Result<(), &'static str> {
#[allow(unused_imports)] #[allow(unused_imports)]
use log::{debug, error, info, trace, warn}; use log::{debug, error, info, trace, warn};
let mut color = [0.0, 0.0, 0.0, 0.0];
loop { loop {
match cmd_rx.try_recv().unwrap_or(None) {
None => (), //TODO manage errors
Some(Command::Draw) => { let _ = renderer.draw_clear_frame(color);
//TODO manage errors
let _ = hal_state.draw_clear_frame([0.0, 255.0, 0.0, 0.0]); match cmd_rx.try_recv().unwrap_or(Command::NoCommand) {
}, Command::NoCommand => (),
Some(Command::Stop) => { Command::Stop => {
warn!("Stop render thread"); warn!("Stop render thread");
return; return;
}, },
}; Command::Color{r, g, b, a} => {
color = [r, g, b, a];
},
}
} }
}); });
loop { loop {
match input_rx.try_recv().unwrap_or(false) { match input_rx.recv().unwrap() {
false => (), Input::Close => {
true => { cmd_tx.send(Command::Stop).unwrap();
cmd_tx.send(Some(Command::Stop)).unwrap();
//TODO stop event_loop //TODO stop event_loop
warn!("wait for render thread"); warn!("wait for render thread");
render_thread.join().unwrap(); render_thread.join().unwrap();
warn!("Stop control thread"); warn!("Stop control thread");
return; return;
}, },
}; Input::Mouse{x, y} => {
let pos = Command::Color{
cmd_tx.send(Some(Command::Draw)).unwrap(); r: (x/1280.0) as f32,
thread::sleep(time::Duration::from_millis(100)); g: (y/720.0) as f32,
b: ((x/1280.0 + y/720.0)/2.0) as f32,
a: 1.0,
};
cmd_tx.send(pos).unwrap();
},
}
} }
}))); })));
@ -102,13 +122,20 @@ pub fn run() -> Result<(), &'static str> {
match event { match event {
Event::WindowEvent{window_id: _, event} => match event { Event::WindowEvent{window_id: _, event} => match event {
WindowEvent::CloseRequested => { WindowEvent::CloseRequested => {
input_tx.send(true).unwrap(); input_tx.send(Input::Close).unwrap();
let handle = control_thread.replace(None).unwrap(); let handle = control_thread.replace(None).unwrap();
warn!("Wait for control thread"); warn!("Wait for control thread");
handle.join().unwrap(); handle.join().unwrap();
warn!("Stop input thread"); warn!("Stop input thread");
*control_flow = ControlFlow::Exit; *control_flow = ControlFlow::Exit;
}, },
WindowEvent::CursorMoved{position, ..} => {
input_tx
.send(Input::Mouse{
x: position.x,
y: position.y})
.unwrap();
},
_ => (), _ => (),
} }
_ => (), _ => (),

42
src/renderer.rs Normal file
View File

@ -0,0 +1,42 @@
use std::mem::ManuallyDrop;
use gfx_hal::{
queue::QueueGroup,
Backend,
pso::Rect,
};
use gfx_backend_vulkan as vk_back;
pub mod init;
pub mod render;
#[derive(Debug)]
pub struct Renderer {
//items need to communicate with the GPU
instance: ManuallyDrop<<vk_back::Backend as Backend>::Instance>,
surface: ManuallyDrop<<vk_back::Backend as Backend>::Surface>,
adapter: ManuallyDrop<gfx_hal::adapter::Adapter<vk_back::Backend>>,
device: vk_back::Device,
queue_group: ManuallyDrop<QueueGroup<vk_back::Backend>>,
render_pass: ManuallyDrop<<vk_back::Backend as Backend>::RenderPass>,
swapchain: ManuallyDrop<<vk_back::Backend as Backend>::Swapchain>,
extent: gfx_hal::window::Extent2D,
format: gfx_hal::format::Format,
render_area: Rect,
//items needed to render the images
sems_image_available: Vec<<vk_back::Backend as Backend>::Semaphore>,
sems_render_finished: Vec<<vk_back::Backend as Backend>::Semaphore>,
fences: Vec<<vk_back::Backend as Backend>::Fence>,
image_views: Vec<<vk_back::Backend as Backend>::ImageView>,
framebuffers: Vec<<vk_back::Backend as Backend>::Framebuffer>,
command_pool: ManuallyDrop<<vk_back::Backend as Backend>::CommandPool>,
command_buffers: Vec<<vk_back::Backend as Backend>::CommandBuffer>,
//items needed to keep track of the images
image_count: usize,
current_image: usize,
}

View File

@ -3,7 +3,6 @@ use log::{debug, error, info, trace, warn};
use std::{ use std::{
mem::ManuallyDrop, mem::ManuallyDrop,
iter,
}; };
use core::ptr::read; use core::ptr::read;
@ -11,7 +10,6 @@ use core::ptr::read;
use gfx_hal::{ use gfx_hal::{
Instance, Instance,
device::Device, device::Device,
queue::QueueGroup,
Backend, Backend,
pool::CommandPool, pool::CommandPool,
pso::Rect, pso::Rect,
@ -21,38 +19,9 @@ use gfx_backend_vulkan as vk_back;
use winit::window::Window; use winit::window::Window;
pub mod render; use crate::renderer::Renderer;
#[derive(Debug)] impl core::ops::Drop for Renderer {
pub struct HalState {
//items need to communicate with the GPU
instance: ManuallyDrop<<vk_back::Backend as Backend>::Instance>,
surface: ManuallyDrop<<vk_back::Backend as Backend>::Surface>,
adapter: ManuallyDrop<gfx_hal::adapter::Adapter<vk_back::Backend>>,
device: vk_back::Device,
queue_group: ManuallyDrop<QueueGroup<vk_back::Backend>>,
render_pass: ManuallyDrop<<vk_back::Backend as Backend>::RenderPass>,
swapchain: ManuallyDrop<<vk_back::Backend as Backend>::Swapchain>,
extent: gfx_hal::window::Extent2D,
format: gfx_hal::format::Format,
render_area: Rect,
//items needed to render the images
sems_image_available: Vec<<vk_back::Backend as Backend>::Semaphore>,
sems_render_finished: Vec<<vk_back::Backend as Backend>::Semaphore>,
fences: Vec<<vk_back::Backend as Backend>::Fence>,
image_views: Vec<<vk_back::Backend as Backend>::ImageView>,
framebuffers: Vec<<vk_back::Backend as Backend>::Framebuffer>,
command_pool: ManuallyDrop<<vk_back::Backend as Backend>::CommandPool>,
command_buffers: Vec<<vk_back::Backend as Backend>::CommandBuffer>,
//items needed to keep track of the images
image_count: usize,
current_image: usize,
}
impl core::ops::Drop for HalState {
//---------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------
fn drop(&mut self) { fn drop(&mut self) {
@ -60,7 +29,7 @@ impl core::ops::Drop for HalState {
let _ = self.device.wait_idle(); let _ = self.device.wait_idle();
//destroy all underlying ressources //destroy all underlying ressources
debug!("Destroying HAL ressources"); debug!("Destroying Renderer ressources");
unsafe { unsafe {
self.command_pool.free(self.command_buffers.drain(..)); self.command_pool.free(self.command_buffers.drain(..));
self.device.destroy_command_pool( self.device.destroy_command_pool(
@ -87,95 +56,43 @@ impl core::ops::Drop for HalState {
self.instance.destroy_surface(ManuallyDrop::into_inner(read(&mut self.surface))); self.instance.destroy_surface(ManuallyDrop::into_inner(read(&mut self.surface)));
ManuallyDrop::drop(&mut self.instance); ManuallyDrop::drop(&mut self.instance);
} }
info!("HAL ressources destroyed"); info!("Renderer ressources destroyed");
} }
} }
impl HalState { impl Renderer {
//---------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------
pub fn recreate_swapchain(&mut self) -> Result<(), &'static str> { pub fn update_swapchain(&mut self) -> Result<(), &'static str> {
use gfx_hal::window::{ use gfx_hal::window::{
SwapchainConfig, SwapchainConfig,
Surface, Surface,
PresentationSurface,
}; };
debug!("Recreating swapchain"); debug!("Updating swapchain");
//destroying previous swapchain //creating new swapchain config
unsafe {
for buffer in self.framebuffers.drain(..) {
self.device.destroy_framebuffer(buffer);
}
for view in self.image_views.drain(..) {
self.device.destroy_image_view(view);
}
self.device.destroy_swapchain(ManuallyDrop::into_inner(read(&mut self.swapchain)));
}
let capabilities = self.surface.capabilities(&self.adapter.physical_device); let capabilities = self.surface.capabilities(&self.adapter.physical_device);
info!("{:#?}", capabilities);
//creating new swapchain
let swapchain_config = SwapchainConfig::from_caps(&capabilities, self.format, self.extent); let swapchain_config = SwapchainConfig::from_caps(&capabilities, self.format, self.extent);
info!("{:?}", swapchain_config); info!("{:?}", swapchain_config);
let (swapchain, backbuffer) = unsafe { self.device
self.device .wait_idle()
.create_swapchain(&mut self.surface, swapchain_config, None) .map_err(|_| "Failed to to wait for device to be idle")?;
.map_err(|_| "Failed to create swapchain and backbuffer")?
};
let image_views : Vec<_> = { unsafe {
use gfx_hal::{ self.surface
image::{ViewKind, SubresourceRange}, .configure_swapchain(&self.device, swapchain_config)
format::{Swizzle, Aspects}, .map_err(|_| "Failed to updtate swapchain")?;
}; debug!("update succesfull !");
}
backbuffer
.iter()
.map(|img| unsafe {
self.device
.create_image_view(
&img,
ViewKind::D2,
self.format,
Swizzle::NO,
SubresourceRange {
aspects : Aspects::COLOR,
levels : 0..1,
layers : 0..1,
},
)
.map_err(|_| "Could not create ImageViews")
})
.collect::<Result<Vec<_>, &str>>()?
};
let framebuffers: Vec<_> = {
image_views
.iter()
.map(|image_view|
unsafe {
self.device
.create_framebuffer(&self.render_pass,
iter::once(image_view),
self.extent.to_extent())
.map_err(|_| "Could not create FrameBuffer")
},
)
.collect::<Result<Vec<_>, &str>>()?
};
self.swapchain = ManuallyDrop::new(swapchain);
self.image_views = image_views;
self.framebuffers = framebuffers;
Ok(()) Ok(())
} }
//---------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------
pub fn new(window: &Window) -> Result<HalState, &'static str> { pub fn new(window: &Window) -> Result<Renderer, &'static str> {
use gfx_hal::adapter::Gpu; use gfx_hal::adapter::Gpu;
// create top level // create top level
@ -469,7 +386,7 @@ impl HalState {
info!("HAL successfully initialized"); info!("HAL successfully initialized");
Ok( Ok(
HalState { Renderer {
instance: ManuallyDrop::new(instance), instance: ManuallyDrop::new(instance),
surface: ManuallyDrop::new(surface), surface: ManuallyDrop::new(surface),
adapter: ManuallyDrop::new(adapter), adapter: ManuallyDrop::new(adapter),

View File

@ -9,9 +9,9 @@ use gfx_hal::{
command::CommandBuffer, command::CommandBuffer,
}; };
use crate::hal::HalState; use crate::renderer::Renderer;
impl HalState { impl Renderer {
//---------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------
pub fn draw_clear_frame(&mut self, color: [f32; 4]) -> Result<(), &'static str> { pub fn draw_clear_frame(&mut self, color: [f32; 4]) -> Result<(), &'static str> {
@ -20,7 +20,7 @@ impl HalState {
queue::{Submission, CommandQueue}, queue::{Submission, CommandQueue},
pso::PipelineStage, pso::PipelineStage,
}; };
// get current frame fence // get current frame fence
let fence = &self.fences[self.current_image]; let fence = &self.fences[self.current_image];
@ -43,13 +43,13 @@ impl HalState {
match self.swapchain.acquire_image(core::u64::MAX, Some(sem_image_available), None) { match self.swapchain.acquire_image(core::u64::MAX, Some(sem_image_available), None) {
Ok((swp_image_id, suboptimal)) => match suboptimal { Ok((swp_image_id, suboptimal)) => match suboptimal {
Some(_) => { Some(_) => {
return self.recreate_swapchain() return self.update_swapchain()
.map_err(|_| "Could not recreate swpachain"); .map_err(|_| "Could not recreate swpachain");
}, },
None => swp_image_id, None => swp_image_id,
} }
Err(_) => { Err(_) => {
return self.recreate_swapchain() return self.update_swapchain()
.map_err(|_| "Could not recreate swpachain"); .map_err(|_| "Could not recreate swpachain");
}, },
} }
@ -73,7 +73,6 @@ impl HalState {
SubpassContents::Inline, SubpassContents::Inline,
); );
command_buffer.end_render_pass(); command_buffer.end_render_pass();
command_buffer.finish(); command_buffer.finish();
} }
@ -91,15 +90,13 @@ impl HalState {
unsafe { unsafe {
debug!("Submiting");
queue.submit(submission, Some(fence)); queue.submit(submission, Some(fence));
debug!("Presenting into swapchain");
let result = self.swapchain.present(&mut queue, swp_image_id, Some(sem_render_finished)) let result = self.swapchain.present(&mut queue, swp_image_id, Some(sem_render_finished))
.map_err(|_| "Failed to present into the swapchain")?; .map_err(|_| "Failed to present into the swapchain")?;
if result.is_some() { if result.is_some() {
self.recreate_swapchain() self.update_swapchain()
.map_err(|_| "Could not recreate swapchain")?; .map_err(|_| "Could not recreate swapchain")?;
} }
} }