forked from StrafesNET/strafe-client
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>,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum GraphicsInstruction{
|
||||
UpdateModel(ModelUpdate),
|
||||
Render,
|
||||
}
|
||||
|
||||
struct Entity {
|
||||
index_count: u32,
|
||||
index_buf: wgpu::Buffer,
|
||||
@ -878,31 +872,27 @@ impl GraphicsState{
|
||||
device:&wgpu::Device,
|
||||
queue:&wgpu::Queue,
|
||||
config:&wgpu::SurfaceConfiguration,
|
||||
user_settings:&crate::settings::UserSettings,
|
||||
) {
|
||||
self.depth_view = Self::create_depth_texture(config,device);
|
||||
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(
|
||||
&mut self,
|
||||
view: &wgpu::TextureView,
|
||||
device: &wgpu::Device,
|
||||
queue: &wgpu::Queue,
|
||||
view:&wgpu::TextureView,
|
||||
device:&wgpu::Device,
|
||||
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.
|
||||
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;
|
||||
//TODO: use scheduled frame times to create beautiful smoothing simulation physics extrapolation assuming no input
|
||||
|
||||
let mut encoder =
|
||||
device.create_command_encoder(&wgpu::CommandEncoderDescriptor { label: None });
|
||||
|
||||
// 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
|
||||
.write_buffer(
|
||||
&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 load_roblox;
|
||||
mod model_graphics;
|
||||
mod physics_context;
|
||||
mod graphics_context;
|
||||
mod physics_worker;
|
||||
mod graphics_worker;
|
||||
|
||||
fn load_file(path: std::path::PathBuf)->Option<model::IndexedModelInstances>{
|
||||
println!("Loading file: {:?}", &path);
|
||||
|
@ -533,8 +533,8 @@ pub struct PhysicsOutputState{
|
||||
body:Body,
|
||||
}
|
||||
impl PhysicsOutputState{
|
||||
pub fn adjust_mouse(&self,mouse:&MouseState)->(glam::Vec3,glam::Vec2){
|
||||
((self.body.extrapolated_position(mouse.time)+self.camera.offset).into(),self.camera.simulate_move_angles(mouse.pos))
|
||||
pub fn extrapolate(&self,mouse_pos:glam::IVec2,time:Time)->(glam::Vec3,glam::Vec2){
|
||||
((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.
|
||||
}
|
||||
|
||||
pub struct Context{
|
||||
//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();
|
||||
pub fn new(physics:crate::physics::PhysicsState,graphics_worker:crate::worker::INWorker<crate::graphics::GraphicsInstruction>)->crate::worker::QNWorker<TimedInstruction<InputInstruction>>{
|
||||
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();
|
||||
crate::worker::QNWorker::new(move |ins:TimedInstruction<InputInstruction>|{
|
||||
let mut render=false;
|
||||
@ -60,7 +40,7 @@ impl Context{
|
||||
timeline.push_front(TimedInstruction{
|
||||
time:last_mouse_time,
|
||||
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}
|
||||
),
|
||||
});
|
||||
@ -92,11 +72,11 @@ impl Context{
|
||||
//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,
|
||||
//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
|
||||
timeline.push_front(TimedInstruction{
|
||||
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;
|
||||
//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
|
||||
while let Some(instruction)=timeline.pop_front(){
|
||||
self.physics.run(instruction.time);
|
||||
self.physics.process_instruction(TimedInstruction{
|
||||
physics.run(instruction.time);
|
||||
physics.process_instruction(TimedInstruction{
|
||||
time:instruction.time,
|
||||
instruction:crate::physics::PhysicsInstruction::Input(instruction.instruction),
|
||||
});
|
||||
}
|
||||
}
|
||||
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});
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
128
src/run.rs
128
src/run.rs
@ -12,55 +12,26 @@ pub enum RunInstruction{
|
||||
|
||||
//holds thread handles to dispatch to
|
||||
struct RunContext{
|
||||
physics_thread:crate::worker::QNWorker<TimedInstruction<InputInstruction>>,
|
||||
}
|
||||
|
||||
pub struct RunContextSetup{
|
||||
manual_mouse_lock:bool,
|
||||
mouse:crate::physics::MouseState,//std::sync::Arc<std::sync::Mutex<>>
|
||||
screen_size:glam::UVec2,
|
||||
user_settings:crate::settings::UserSettings,
|
||||
window:winit::window::Window,
|
||||
physics:crate::physics::PhysicsState,
|
||||
graphics:crate::graphics::GraphicsState,
|
||||
//physics_thread:crate::worker::QNWorker<TimedInstruction<InputInstruction>>,
|
||||
}
|
||||
|
||||
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{
|
||||
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) {
|
||||
impl RunContext{
|
||||
fn window_event(&mut self,time:crate::integer::Time,event: winit::event::WindowEvent) {
|
||||
match event {
|
||||
winit::event::WindowEvent::DroppedFile(path)=>{
|
||||
let sender=self.sender.clone();//mpsc
|
||||
std::thread::spawn(move ||{
|
||||
let indexed_model_instances=crate::load_file(path);
|
||||
sender.send(Instruction::Die(indexed_model_instances));
|
||||
});
|
||||
// let sender=self.sender.clone();//mpsc
|
||||
// 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);
|
||||
//self.physics=
|
||||
println!("unimplemented");
|
||||
},
|
||||
winit::event::WindowEvent::Focused(state)=>{
|
||||
//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();
|
||||
crate::worker::QNWorker::new(move |ins:TimedInstruction<RunInstruction>|{
|
||||
match ins.instruction{
|
||||
RunInstruction::RequestRedraw=>{
|
||||
self.window.request_redraw();
|
||||
run_context.window.request_redraw();
|
||||
}
|
||||
RunInstruction::WindowEvent(window_event)=>{
|
||||
self.window_event(ins.time,window_event);
|
||||
run_context.window_event(ins.time,window_event);
|
||||
},
|
||||
RunInstruction::DeviceEvent(device_event)=>{
|
||||
self.device_event(ins.time,device_event);
|
||||
run_context.device_event(ins.time,device_event);
|
||||
},
|
||||
RunInstruction::Resize(size)=>{
|
||||
setup_context.config.width=size.width.max(1);
|
||||
setup_context.config.height=size.height.max(1);
|
||||
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=>{
|
||||
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