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:
parent
ebc9299f33
commit
7dc22f026e
@ -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()?;
|
||||||
|
|||||||
71
src/lib.rs
71
src/lib.rs
@ -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 => (),
|
|
||||||
Some(Command::Draw) => {
|
|
||||||
//TODO manage errors
|
//TODO manage errors
|
||||||
let _ = hal_state.draw_clear_frame([0.0, 255.0, 0.0, 0.0]);
|
let _ = renderer.draw_clear_frame(color);
|
||||||
},
|
|
||||||
Some(Command::Stop) => {
|
match cmd_rx.try_recv().unwrap_or(Command::NoCommand) {
|
||||||
|
Command::NoCommand => (),
|
||||||
|
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{
|
||||||
|
r: (x/1280.0) as f32,
|
||||||
|
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();
|
||||||
cmd_tx.send(Some(Command::Draw)).unwrap();
|
},
|
||||||
thread::sleep(time::Duration::from_millis(100));
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
})));
|
})));
|
||||||
|
|
||||||
@ -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
42
src/renderer.rs
Normal 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,
|
||||||
|
}
|
||||||
|
|
||||||
@ -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
|
||||||
.create_swapchain(&mut self.surface, swapchain_config, None)
|
.wait_idle()
|
||||||
.map_err(|_| "Failed to create swapchain and backbuffer")?
|
.map_err(|_| "Failed to to wait for device to be idle")?;
|
||||||
};
|
|
||||||
|
|
||||||
let image_views : Vec<_> = {
|
|
||||||
use gfx_hal::{
|
|
||||||
image::{ViewKind, SubresourceRange},
|
|
||||||
format::{Swizzle, Aspects},
|
|
||||||
};
|
|
||||||
|
|
||||||
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 {
|
unsafe {
|
||||||
self.device
|
self.surface
|
||||||
.create_framebuffer(&self.render_pass,
|
.configure_swapchain(&self.device, swapchain_config)
|
||||||
iter::once(image_view),
|
.map_err(|_| "Failed to updtate swapchain")?;
|
||||||
self.extent.to_extent())
|
debug!("update succesfull !");
|
||||||
.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),
|
||||||
@ -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> {
|
||||||
@ -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")?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue
Block a user