what I got done before giving up on thread chaining
This commit is contained in:
parent
de063f4d74
commit
4cf10dad78
@ -8,12 +8,6 @@ pub struct ModelUpdate{
|
|||||||
color:Option<glam::Vec4>,
|
color:Option<glam::Vec4>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
pub enum GraphicsInstruction{
|
|
||||||
UpdateModel(ModelUpdate),
|
|
||||||
Render,
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Entity {
|
struct Entity {
|
||||||
index_count: u32,
|
index_count: u32,
|
||||||
index_buf: wgpu::Buffer,
|
index_buf: wgpu::Buffer,
|
||||||
@ -878,31 +872,27 @@ impl GraphicsState{
|
|||||||
device:&wgpu::Device,
|
device:&wgpu::Device,
|
||||||
queue:&wgpu::Queue,
|
queue:&wgpu::Queue,
|
||||||
config:&wgpu::SurfaceConfiguration,
|
config:&wgpu::SurfaceConfiguration,
|
||||||
|
user_settings:&crate::settings::UserSettings,
|
||||||
) {
|
) {
|
||||||
self.depth_view = Self::create_depth_texture(config,device);
|
self.depth_view = Self::create_depth_texture(config,device);
|
||||||
self.camera.screen_size=glam::uvec2(config.width, config.height);
|
self.camera.screen_size=glam::uvec2(config.width, config.height);
|
||||||
self.load_user_settings(&self.user_settings);
|
self.load_user_settings(user_settings);
|
||||||
}
|
}
|
||||||
pub fn render(
|
pub fn render(
|
||||||
&mut self,
|
&mut self,
|
||||||
view:&wgpu::TextureView,
|
view:&wgpu::TextureView,
|
||||||
device:&wgpu::Device,
|
device:&wgpu::Device,
|
||||||
queue:&wgpu::Queue,
|
queue:&wgpu::Queue,
|
||||||
|
predicted_time:crate::integer::Time,
|
||||||
|
physics_output:crate::physics::PhysicsOutputState,
|
||||||
) {
|
) {
|
||||||
//ideally this would be scheduled to execute and finish right before the render.
|
//TODO: use scheduled frame times to create beautiful smoothing simulation physics extrapolation assuming no input
|
||||||
let time=crate::integer::Time::from_nanos(self.start_time.elapsed().as_nanos() as i64);
|
|
||||||
self.physics_thread.send(crate::instruction::TimedInstruction{
|
|
||||||
time,
|
|
||||||
instruction:crate::render_thread::InputInstruction::Idle,
|
|
||||||
}).unwrap();
|
|
||||||
//update time lol
|
|
||||||
self.mouse.time=time;
|
|
||||||
|
|
||||||
let mut encoder =
|
let mut encoder =
|
||||||
device.create_command_encoder(&wgpu::CommandEncoderDescriptor { label: None });
|
device.create_command_encoder(&wgpu::CommandEncoderDescriptor { label: None });
|
||||||
|
|
||||||
// update rotation
|
// update rotation
|
||||||
let camera_uniforms = self.camera.to_uniform_data(self.physics_thread.grab_clone().adjust_mouse(&self.mouse));
|
let camera_uniforms = self.camera.to_uniform_data(physics_output.extrapolate(self.global_mouse.lock().clone(),predicted_time));
|
||||||
self.staging_belt
|
self.staging_belt
|
||||||
.write_buffer(
|
.write_buffer(
|
||||||
&mut encoder,
|
&mut encoder,
|
||||||
|
@ -1,13 +0,0 @@
|
|||||||
struct Context<'a>{
|
|
||||||
device:&'a wgpu::Device,
|
|
||||||
queue:&'a wgpu::Queue,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Context{
|
|
||||||
pub fn new(user_settings:&crate::settings::UserSettings,indexed_model_instances:&crate::model::IndexedModelInstances){
|
|
||||||
let mut graphics=crate::graphics::GraphicsState::new();
|
|
||||||
graphics.load_user_settings(user_settings);
|
|
||||||
graphics.generate_models(indexed_model_instances);
|
|
||||||
}
|
|
||||||
//into_worker
|
|
||||||
}
|
|
46
src/graphics_worker.rs
Normal file
46
src/graphics_worker.rs
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
#[derive(Clone)]
|
||||||
|
pub enum GraphicsInstruction{
|
||||||
|
Render(crate::physics::PhysicsOutputState,crate::integer::Time),
|
||||||
|
//UpdateModel(crate::graphics::ModelUpdate),
|
||||||
|
}
|
||||||
|
|
||||||
|
//Ideally the graphics thread worker description is:
|
||||||
|
/*
|
||||||
|
WorkerDescription{
|
||||||
|
input:Immediate,
|
||||||
|
output:Realtime(PoolOrdering::Ordered(3)),
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
//up to three frames in flight, dropping new frame requests when all three are busy, and dropping output frames when one renders out of order
|
||||||
|
|
||||||
|
pub fn new(
|
||||||
|
graphics:crate::graphics::GraphicsState,
|
||||||
|
surface:&wgpu::Surface,
|
||||||
|
device:&wgpu::Device,
|
||||||
|
queue:&wgpu::Queue,
|
||||||
|
)->crate::worker::INWorker<GraphicsInstruction>{
|
||||||
|
crate::worker::INWorker::new(a,move |ins:GraphicsInstruction|{
|
||||||
|
match ins{
|
||||||
|
GraphicsInstruction::Render(physics_output,predicted_time)=>{
|
||||||
|
//this has to go deeper somehow
|
||||||
|
let frame=match surface.get_current_texture(){
|
||||||
|
Ok(frame)=>frame,
|
||||||
|
Err(_)=>{
|
||||||
|
surface.configure(device,config);
|
||||||
|
surface
|
||||||
|
.get_current_texture()
|
||||||
|
.expect("Failed to acquire next surface texture!")
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let view=frame.texture.create_view(&wgpu::TextureViewDescriptor{
|
||||||
|
format:Some(config.view_formats[0]),
|
||||||
|
..wgpu::TextureViewDescriptor::default()
|
||||||
|
});
|
||||||
|
|
||||||
|
graphics.render(&view,device,queue,physics_output,predicted_time);
|
||||||
|
|
||||||
|
frame.present();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
@ -13,8 +13,8 @@ mod primitives;
|
|||||||
mod instruction;
|
mod instruction;
|
||||||
mod load_roblox;
|
mod load_roblox;
|
||||||
mod model_graphics;
|
mod model_graphics;
|
||||||
mod physics_context;
|
mod physics_worker;
|
||||||
mod graphics_context;
|
mod graphics_worker;
|
||||||
|
|
||||||
fn load_file(path: std::path::PathBuf)->Option<model::IndexedModelInstances>{
|
fn load_file(path: std::path::PathBuf)->Option<model::IndexedModelInstances>{
|
||||||
println!("Loading file: {:?}", &path);
|
println!("Loading file: {:?}", &path);
|
||||||
|
@ -533,8 +533,8 @@ pub struct PhysicsOutputState{
|
|||||||
body:Body,
|
body:Body,
|
||||||
}
|
}
|
||||||
impl PhysicsOutputState{
|
impl PhysicsOutputState{
|
||||||
pub fn adjust_mouse(&self,mouse:&MouseState)->(glam::Vec3,glam::Vec2){
|
pub fn extrapolate(&self,mouse_pos:glam::IVec2,time:Time)->(glam::Vec3,glam::Vec2){
|
||||||
((self.body.extrapolated_position(mouse.time)+self.camera.offset).into(),self.camera.simulate_move_angles(mouse.pos))
|
((self.body.extrapolated_position(time)+self.camera.offset).into(),self.camera.simulate_move_angles(mouse_pos))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,29 +20,9 @@ pub enum InputInstruction {
|
|||||||
//to be 1 instruction ahead to generate the next state for interpolation.
|
//to be 1 instruction ahead to generate the next state for interpolation.
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Context{
|
pub fn new(physics:crate::physics::PhysicsState,graphics_worker:crate::worker::INWorker<crate::graphics::GraphicsInstruction>)->crate::worker::QNWorker<TimedInstruction<InputInstruction>>{
|
||||||
//Ideally the graphics thread worker description is:
|
|
||||||
/*
|
|
||||||
WorkerDescription{
|
|
||||||
input:Immediate,
|
|
||||||
output:Realtime(PoolOrdering::Ordered(3)),
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
//up to three frames in flight, dropping new frame requests when all three are busy, and dropping output frames when one renders out of order
|
|
||||||
graphics_thread:crate::worker::INWorker<crate::graphics::GraphicsInstruction>,
|
|
||||||
}
|
|
||||||
impl Context{
|
|
||||||
pub fn new(user_settings:&crate::settings::UserSettings,indexed_model_instances:&crate::model::IndexedModelInstances){
|
|
||||||
let mut physics=crate::physics::PhysicsState::default();
|
|
||||||
physics.spawn(indexed_model_instances.spawn_point);
|
|
||||||
physics.load_user_settings(user_settings);
|
|
||||||
physics.generate_models(&indexed_model_instances);
|
|
||||||
}
|
|
||||||
pub fn into_worker(mut self)->crate::worker::QNWorker<TimedInstruction<InputInstruction>>{
|
|
||||||
let graphics_context=crate::graphics_context::Context::new();
|
|
||||||
let graphics_thread=graphics_context.into_worker();
|
|
||||||
let mut mouse_blocking=true;
|
let mut mouse_blocking=true;
|
||||||
let mut last_mouse_time=self.physics.next_mouse.time;
|
let mut last_mouse_time=physics.next_mouse.time;
|
||||||
let mut timeline=std::collections::VecDeque::new();
|
let mut timeline=std::collections::VecDeque::new();
|
||||||
crate::worker::QNWorker::new(move |ins:TimedInstruction<InputInstruction>|{
|
crate::worker::QNWorker::new(move |ins:TimedInstruction<InputInstruction>|{
|
||||||
let mut render=false;
|
let mut render=false;
|
||||||
@ -60,7 +40,7 @@ impl Context{
|
|||||||
timeline.push_front(TimedInstruction{
|
timeline.push_front(TimedInstruction{
|
||||||
time:last_mouse_time,
|
time:last_mouse_time,
|
||||||
instruction:PhysicsInputInstruction::ReplaceMouse(
|
instruction:PhysicsInputInstruction::ReplaceMouse(
|
||||||
MouseState{time:last_mouse_time,pos:self.physics.next_mouse.pos},
|
MouseState{time:last_mouse_time,pos:physics.next_mouse.pos},
|
||||||
MouseState{time:ins.time,pos:m}
|
MouseState{time:ins.time,pos:m}
|
||||||
),
|
),
|
||||||
});
|
});
|
||||||
@ -92,11 +72,11 @@ impl Context{
|
|||||||
//shitty mice are 125Hz which is 8ms so this should cover that.
|
//shitty mice are 125Hz which is 8ms so this should cover that.
|
||||||
//setting this to 100us still doesn't print even though it's 10x lower than the polling rate,
|
//setting this to 100us still doesn't print even though it's 10x lower than the polling rate,
|
||||||
//so mouse events are probably not handled separately from drawing and fire right before it :(
|
//so mouse events are probably not handled separately from drawing and fire right before it :(
|
||||||
if Time::from_millis(10)<ins.time-self.physics.next_mouse.time{
|
if Time::from_millis(10)<ins.time-physics.next_mouse.time{
|
||||||
//push an event to extrapolate no movement from
|
//push an event to extrapolate no movement from
|
||||||
timeline.push_front(TimedInstruction{
|
timeline.push_front(TimedInstruction{
|
||||||
time:last_mouse_time,
|
time:last_mouse_time,
|
||||||
instruction:PhysicsInputInstruction::SetNextMouse(MouseState{time:ins.time,pos:self.physics.next_mouse.pos}),
|
instruction:PhysicsInputInstruction::SetNextMouse(MouseState{time:ins.time,pos:physics.next_mouse.pos}),
|
||||||
});
|
});
|
||||||
last_mouse_time=ins.time;
|
last_mouse_time=ins.time;
|
||||||
//stop blocking. the mouse is not moving so the physics does not need to live in the past and wait for interpolation targets.
|
//stop blocking. the mouse is not moving so the physics does not need to live in the past and wait for interpolation targets.
|
||||||
@ -117,16 +97,15 @@ impl Context{
|
|||||||
}{
|
}{
|
||||||
//empty queue
|
//empty queue
|
||||||
while let Some(instruction)=timeline.pop_front(){
|
while let Some(instruction)=timeline.pop_front(){
|
||||||
self.physics.run(instruction.time);
|
physics.run(instruction.time);
|
||||||
self.physics.process_instruction(TimedInstruction{
|
physics.process_instruction(TimedInstruction{
|
||||||
time:instruction.time,
|
time:instruction.time,
|
||||||
instruction:crate::physics::PhysicsInstruction::Input(instruction.instruction),
|
instruction:crate::physics::PhysicsInstruction::Input(instruction.instruction),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if render{
|
if render{
|
||||||
graphics_thread.send(TimedInstruction{time:ins.time,instruction:crate::graphics_context::GraphicsInstruction::Render});
|
graphics_worker.send(TimedInstruction{time:ins.time,instruction:crate::graphics_worker::GraphicsInstruction::Render});
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
|
126
src/run.rs
126
src/run.rs
@ -12,55 +12,26 @@ pub enum RunInstruction{
|
|||||||
|
|
||||||
//holds thread handles to dispatch to
|
//holds thread handles to dispatch to
|
||||||
struct RunContext{
|
struct RunContext{
|
||||||
physics_thread:crate::worker::QNWorker<TimedInstruction<InputInstruction>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct RunContextSetup{
|
|
||||||
manual_mouse_lock:bool,
|
manual_mouse_lock:bool,
|
||||||
mouse:crate::physics::MouseState,//std::sync::Arc<std::sync::Mutex<>>
|
mouse:crate::physics::MouseState,//std::sync::Arc<std::sync::Mutex<>>
|
||||||
|
screen_size:glam::UVec2,
|
||||||
user_settings:crate::settings::UserSettings,
|
user_settings:crate::settings::UserSettings,
|
||||||
window:winit::window::Window,
|
window:winit::window::Window,
|
||||||
physics:crate::physics::PhysicsState,
|
//physics_thread:crate::worker::QNWorker<TimedInstruction<InputInstruction>>,
|
||||||
graphics:crate::graphics::GraphicsState,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RunContextSetup {
|
impl RunContext{
|
||||||
pub fn new(context:&crate::setup::SetupContext,window:winit::window::Window)->Self{
|
fn window_event(&mut self,time:crate::integer::Time,event: winit::event::WindowEvent) {
|
||||||
//wee
|
|
||||||
let user_settings=crate::settings::read_user_settings();
|
|
||||||
|
|
||||||
let args:Vec<String>=std::env::args().collect();
|
|
||||||
let indexed_model_instances=if args.len()==2{
|
|
||||||
crate::load_file(std::path::PathBuf::from(&args[1]))
|
|
||||||
}else{
|
|
||||||
None
|
|
||||||
}.unwrap_or(crate::default_models());
|
|
||||||
|
|
||||||
let mut graphics=crate::graphics::GraphicsState::new(&context.device,&context.queue);
|
|
||||||
graphics.load_user_settings(&user_settings);
|
|
||||||
graphics.generate_models(&context.device,&context.queue,indexed_model_instances);
|
|
||||||
|
|
||||||
let mut physics=crate::physics::PhysicsState::default();
|
|
||||||
physics.load_user_settings(&user_settings);
|
|
||||||
physics.generate_models(&indexed_model_instances);
|
|
||||||
|
|
||||||
Self{
|
|
||||||
manual_mouse_lock:false,
|
|
||||||
mouse:crate::physics::MouseState::default(),
|
|
||||||
user_settings,
|
|
||||||
window,
|
|
||||||
graphics,
|
|
||||||
physics,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn window_event(&self,time:crate::integer::Time,event: winit::event::WindowEvent) {
|
|
||||||
match event {
|
match event {
|
||||||
winit::event::WindowEvent::DroppedFile(path)=>{
|
winit::event::WindowEvent::DroppedFile(path)=>{
|
||||||
let sender=self.sender.clone();//mpsc
|
// let sender=self.sender.clone();//mpsc
|
||||||
std::thread::spawn(move ||{
|
// std::thread::spawn(move ||{
|
||||||
|
// let indexed_model_instances=crate::load_file(path);
|
||||||
|
// sender.send(Instruction::Die(indexed_model_instances));
|
||||||
|
// });
|
||||||
let indexed_model_instances=crate::load_file(path);
|
let indexed_model_instances=crate::load_file(path);
|
||||||
sender.send(Instruction::Die(indexed_model_instances));
|
//self.physics=
|
||||||
});
|
println!("unimplemented");
|
||||||
},
|
},
|
||||||
winit::event::WindowEvent::Focused(state)=>{
|
winit::event::WindowEvent::Focused(state)=>{
|
||||||
//pause unpause
|
//pause unpause
|
||||||
@ -187,44 +158,75 @@ impl RunContextSetup {
|
|||||||
_=>(),
|
_=>(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn into_worker(self)->crate::worker::QNWorker<TimedInstruction<RunInstruction>>{
|
pub struct RunContextSetup{
|
||||||
|
user_settings:crate::settings::UserSettings,
|
||||||
|
window:winit::window::Window,
|
||||||
|
physics:crate::physics::PhysicsState,
|
||||||
|
graphics:crate::graphics::GraphicsState,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RunContextSetup{
|
||||||
|
pub fn new(context:&crate::setup::SetupContext,window:winit::window::Window)->Self{
|
||||||
|
//wee
|
||||||
|
let user_settings=crate::settings::read_user_settings();
|
||||||
|
|
||||||
|
let args:Vec<String>=std::env::args().collect();
|
||||||
|
let indexed_model_instances=if args.len()==2{
|
||||||
|
crate::load_file(std::path::PathBuf::from(&args[1]))
|
||||||
|
}else{
|
||||||
|
None
|
||||||
|
}.unwrap_or(crate::default_models());
|
||||||
|
|
||||||
|
let mut graphics=crate::graphics::GraphicsState::new(&context.device,&context.queue);
|
||||||
|
graphics.load_user_settings(&user_settings);
|
||||||
|
graphics.generate_models(&context.device,&context.queue,indexed_model_instances);
|
||||||
|
|
||||||
|
let mut physics=crate::physics::PhysicsState::default();
|
||||||
|
physics.load_user_settings(&user_settings);
|
||||||
|
physics.generate_models(&indexed_model_instances);
|
||||||
|
|
||||||
|
Self{
|
||||||
|
user_settings,
|
||||||
|
window,
|
||||||
|
graphics,
|
||||||
|
physics,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn into_context(self)->RunContext{
|
||||||
|
RunContext{
|
||||||
|
manual_mouse_lock:false,
|
||||||
|
mouse:crate::physics::MouseState::default(),
|
||||||
|
user_settings:self.user_settings,
|
||||||
|
window:self.window,
|
||||||
|
physics:self.physics,
|
||||||
|
graphics:self.graphics,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn into_worker(self,setup_context:crate::setup::SetupContext)->crate::worker::QNWorker<TimedInstruction<RunInstruction>>{
|
||||||
let run_context=self.into_context();
|
let run_context=self.into_context();
|
||||||
crate::worker::QNWorker::new(move |ins:TimedInstruction<RunInstruction>|{
|
crate::worker::QNWorker::new(move |ins:TimedInstruction<RunInstruction>|{
|
||||||
match ins.instruction{
|
match ins.instruction{
|
||||||
RunInstruction::RequestRedraw=>{
|
RunInstruction::RequestRedraw=>{
|
||||||
self.window.request_redraw();
|
run_context.window.request_redraw();
|
||||||
}
|
}
|
||||||
RunInstruction::WindowEvent(window_event)=>{
|
RunInstruction::WindowEvent(window_event)=>{
|
||||||
self.window_event(ins.time,window_event);
|
run_context.window_event(ins.time,window_event);
|
||||||
},
|
},
|
||||||
RunInstruction::DeviceEvent(device_event)=>{
|
RunInstruction::DeviceEvent(device_event)=>{
|
||||||
self.device_event(ins.time,device_event);
|
run_context.device_event(ins.time,device_event);
|
||||||
},
|
},
|
||||||
RunInstruction::Resize(size)=>{
|
RunInstruction::Resize(size)=>{
|
||||||
setup_context.config.width=size.width.max(1);
|
setup_context.config.width=size.width.max(1);
|
||||||
setup_context.config.height=size.height.max(1);
|
setup_context.config.height=size.height.max(1);
|
||||||
setup_context.surface.configure(&setup_context.device,&setup_context.config);
|
setup_context.surface.configure(&setup_context.device,&setup_context.config);
|
||||||
physics_thread.send(TimedInstruction{time:ins.time,instruction:PhysicsInstruction::Resize(size)});
|
run_context.physics_thread.send(TimedInstruction{time:ins.time,instruction:PhysicsInstruction::Resize(size)});
|
||||||
}
|
}
|
||||||
RunInstruction::Render=>{
|
RunInstruction::Render=>{
|
||||||
let frame=match setup_context.surface.get_current_texture(){
|
//
|
||||||
Ok(frame)=>frame,
|
|
||||||
Err(_)=>{
|
|
||||||
setup_context.surface.configure(&setup_context.device,&setup_context.config);
|
|
||||||
setup_context.surface
|
|
||||||
.get_current_texture()
|
|
||||||
.expect("Failed to acquire next surface texture!")
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let view=frame.texture.create_view(&wgpu::TextureViewDescriptor{
|
|
||||||
format:Some(setup_context.config.view_formats[0]),
|
|
||||||
..wgpu::TextureViewDescriptor::default()
|
|
||||||
});
|
|
||||||
|
|
||||||
physics_thread.send(TimedInstruction{time:ins.time,instruction:PhysicsInstruction::Render(view)});
|
|
||||||
|
|
||||||
frame.present();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
Loading…
Reference in New Issue
Block a user