This commit is contained in:
Quaternions 2023-10-24 20:22:30 -07:00
parent 657e5dff7f
commit b5a0cf7045
8 changed files with 149 additions and 93 deletions

View File

@ -85,6 +85,14 @@ impl GraphicsCamera{
raw raw
} }
} }
impl std::default::Default for GraphicsCamera{
fn default()->Self{
Self{
screen_size:glam::UVec2::ONE,
fov:glam::Vec2::ONE,
}
}
}
pub struct GraphicsState{ pub struct GraphicsState{
pipelines: GraphicsPipelines, pipelines: GraphicsPipelines,
@ -128,7 +136,7 @@ impl GraphicsState{
pub fn load_user_settings(&mut self,user_settings:&crate::settings::UserSettings){ pub fn load_user_settings(&mut self,user_settings:&crate::settings::UserSettings){
self.camera.fov=user_settings.calculate_fov(1.0,&self.camera.screen_size).as_vec2(); self.camera.fov=user_settings.calculate_fov(1.0,&self.camera.screen_size).as_vec2();
} }
fn generate_model_graphics(&mut self,device:&wgpu::Device,queue:&wgpu::Queue,indexed_models:crate::model::IndexedModelInstances){ pub fn generate_models(&mut self,device:&wgpu::Device,queue:&wgpu::Queue,indexed_models:crate::model::IndexedModelInstances){
//generate texture view per texture //generate texture view per texture
//idk how to do this gooder lol //idk how to do this gooder lol
@ -448,7 +456,7 @@ impl GraphicsState{
//.into_iter() the modeldata vec so entities can be /moved/ to models.entities //.into_iter() the modeldata vec so entities can be /moved/ to models.entities
let mut model_count=0; let mut model_count=0;
let mut instance_count=0; let mut instance_count=0;
let uniform_buffer_binding_size=crate::graphics_context::required_limits().max_uniform_buffer_binding_size as usize; let uniform_buffer_binding_size=crate::setup::required_limits().max_uniform_buffer_binding_size as usize;
let chunk_size=uniform_buffer_binding_size/MODEL_BUFFER_SIZE_BYTES; let chunk_size=uniform_buffer_binding_size/MODEL_BUFFER_SIZE_BYTES;
self.models.reserve(models.len()); self.models.reserve(models.len());
for model in models.into_iter() { for model in models.into_iter() {
@ -521,7 +529,7 @@ impl GraphicsState{
println!("Graphics Instances: {}",instance_count); println!("Graphics Instances: {}",instance_count);
} }
pub fn init( pub fn new(
device:&wgpu::Device, device:&wgpu::Device,
queue:&wgpu::Queue, queue:&wgpu::Queue,
config:&wgpu::SurfaceConfiguration, config:&wgpu::SurfaceConfiguration,
@ -807,14 +815,8 @@ impl GraphicsState{
multiview: None, multiview: None,
}); });
let mut physics = crate::physics::PhysicsState::default(); let camera=GraphicsCamera::default();
let camera_uniforms = camera.to_uniform_data(crate::physics::PhysicsOutputState::default().extrapolate(glam::IVec2::ZERO,crate::integer::Time::ZERO));
physics.load_user_settings(&user_settings);
let screen_size=glam::uvec2(config.width,config.height);
let camera=GraphicsCamera::new(screen_size,user_settings.calculate_fov(1.0,&screen_size).as_vec2());
let camera_uniforms = camera.to_uniform_data(physics.output().adjust_mouse(&crate::physics::MouseState::default()));
let camera_buf = device.create_buffer_init(&wgpu::util::BufferInitDescriptor { let camera_buf = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some("Camera"), label: Some("Camera"),
contents: bytemuck::cast_slice(&camera_uniforms), contents: bytemuck::cast_slice(&camera_uniforms),
@ -883,8 +885,9 @@ impl GraphicsState{
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, physics_output:crate::physics::PhysicsOutputState,
predicted_time:crate::integer::Time,
mouse_pos:glam::IVec2,
) { ) {
//TODO: use scheduled frame times to create beautiful smoothing simulation physics extrapolation assuming no input //TODO: use scheduled frame times to create beautiful smoothing simulation physics extrapolation assuming no input
@ -892,7 +895,7 @@ impl GraphicsState{
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(physics_output.extrapolate(self.global_mouse.lock().clone(),predicted_time)); let camera_uniforms = self.camera.to_uniform_data(physics_output.extrapolate(mouse_pos,predicted_time));
self.staging_belt self.staging_belt
.write_buffer( .write_buffer(
&mut encoder, &mut encoder,

View File

@ -1,7 +1,8 @@
#[derive(Clone)] #[derive(Clone)]
pub enum GraphicsInstruction{ pub enum Instruction{
Render(crate::physics::PhysicsOutputState,crate::integer::Time), Render(crate::physics::PhysicsOutputState,crate::integer::Time,glam::IVec2),
//UpdateModel(crate::graphics::ModelUpdate), //UpdateModel(crate::graphics::ModelUpdate),
Resize(winit::dpi::PhysicalSize<u32>),
} }
//Ideally the graphics thread worker description is: //Ideally the graphics thread worker description is:
@ -14,19 +15,25 @@ WorkerDescription{
//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 //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( pub fn new(
graphics:crate::graphics::GraphicsState, mut graphics:crate::graphics::GraphicsState,
surface:&wgpu::Surface, mut config:wgpu::SurfaceConfiguration,
surface:wgpu::Surface,
device:&wgpu::Device, device:&wgpu::Device,
queue:&wgpu::Queue, queue:&wgpu::Queue,
)->crate::worker::INWorker<GraphicsInstruction>{ )->crate::compat_worker::INWorker<Instruction>{
crate::worker::INWorker::new(a,move |ins:GraphicsInstruction|{ crate::compat_worker::INWorker::new(move |ins:Instruction|{
match ins{ match ins{
GraphicsInstruction::Render(physics_output,predicted_time)=>{ Instruction::Resize(size)=>{
config.width=size.width.max(1);
config.height=size.height.max(1);
surface.configure(device,&config);
}
Instruction::Render(physics_output,predicted_time,mouse_pos)=>{
//this has to go deeper somehow //this has to go deeper somehow
let frame=match surface.get_current_texture(){ let frame=match surface.get_current_texture(){
Ok(frame)=>frame, Ok(frame)=>frame,
Err(_)=>{ Err(_)=>{
surface.configure(device,config); surface.configure(device,&config);
surface surface
.get_current_texture() .get_current_texture()
.expect("Failed to acquire next surface texture!") .expect("Failed to acquire next surface texture!")
@ -37,7 +44,7 @@ pub fn new(
..wgpu::TextureViewDescriptor::default() ..wgpu::TextureViewDescriptor::default()
}); });
graphics.render(&view,device,queue,physics_output,predicted_time); graphics.render(&view,device,queue,physics_output,predicted_time,mouse_pos);
frame.present(); frame.present();
} }

View File

@ -41,6 +41,11 @@ impl std::fmt::Display for Time{
write!(f,"{}s+{:09}ns",self.0/Self::ONE_SECOND.0,self.0%Self::ONE_SECOND.0) write!(f,"{}s+{:09}ns",self.0/Self::ONE_SECOND.0,self.0%Self::ONE_SECOND.0)
} }
} }
impl std::default::Default for Time{
fn default()->Self{
Self(0)
}
}
impl std::ops::Neg for Time{ impl std::ops::Neg for Time{
type Output=Time; type Output=Time;
#[inline] #[inline]

View File

@ -119,7 +119,6 @@ pub fn default_models()->model::IndexedModelInstances{
} }
fn main(){ fn main(){
let title=format!("Strafe Client v{}",env!("CARGO_PKG_VERSION")).as_str(); let context=setup::setup(format!("Strafe Client v{}",env!("CARGO_PKG_VERSION")).as_str());
let context=setup::setup(title);
context.start();//creates and runs a run context context.start();//creates and runs a run context
} }

View File

@ -31,9 +31,12 @@ pub enum PhysicsInputInstruction {
SetZoom(bool), SetZoom(bool),
Reset, Reset,
Idle, Idle,
//Idle: there were no input events, but the simulation is safe to advance to this timestep
//for interpolation / networking / playback reasons, most playback heads will always want
//to be 1 instruction ahead to generate the next state for interpolation.
} }
#[derive(Clone,Hash)] #[derive(Clone,Hash,Default)]
pub struct Body { pub struct Body {
position: Planar64Vec3,//I64 where 2^32 = 1 u position: Planar64Vec3,//I64 where 2^32 = 1 u
velocity: Planar64Vec3,//I64 where 2^32 = 1 u/s velocity: Planar64Vec3,//I64 where 2^32 = 1 u/s
@ -241,6 +244,19 @@ impl PhysicsCamera {
} }
} }
impl std::default::Default for PhysicsCamera{
fn default()->Self{
Self{
offset:Planar64Vec3::ZERO,//TODO: delete this from PhysicsCamera, it should be GraphicsCamera only
sensitivity:Ratio64Vec2::ONE*200_000,
mouse:MouseState::default(),//t=0 does not cause divide by zero because it's immediately replaced
clamped_mouse_pos:glam::IVec2::ZERO,
angle_pitch_lower_limit:-Angle32::FRAC_PI_2,
angle_pitch_upper_limit:Angle32::FRAC_PI_2,
}
}
}
pub struct GameMechanicsState{ pub struct GameMechanicsState{
pub stage_id:u32, pub stage_id:u32,
//jump_counts:HashMap<u32,u32>, //jump_counts:HashMap<u32,u32>,
@ -527,7 +543,7 @@ pub struct PhysicsState{
//This is not the same as Reset which teleports you to Spawn0 //This is not the same as Reset which teleports you to Spawn0
spawn_point:Planar64Vec3, spawn_point:Planar64Vec3,
} }
#[derive(Clone)] #[derive(Clone,Default)]
pub struct PhysicsOutputState{ pub struct PhysicsOutputState{
camera:PhysicsCamera, camera:PhysicsCamera,
body:Body, body:Body,

View File

@ -1,7 +1,6 @@
use crate::integer::Time; use crate::integer::Time;
use crate::physics::{MouseState,PhysicsInputInstruction}; use crate::physics::{MouseState,PhysicsInputInstruction};
use crate::instruction::{TimedInstruction,InstructionConsumer}; use crate::instruction::{TimedInstruction,InstructionConsumer};
#[derive(Debug)] #[derive(Debug)]
pub enum InputInstruction { pub enum InputInstruction {
MoveMouse(glam::IVec2), MoveMouse(glam::IVec2),
@ -14,20 +13,22 @@ pub enum InputInstruction {
Jump(bool), Jump(bool),
Zoom(bool), Zoom(bool),
Reset, Reset,
}
pub enum Instruction{
Input(InputInstruction),
Render, Render,
//Idle: there were no input events, but the simulation is safe to advance to this timestep Resize(winit::dpi::PhysicalSize<u32>),
//for interpolation / networking / playback reasons, most playback heads will always want //Graphics(crate::graphics_worker::Instruction),
//to be 1 instruction ahead to generate the next state for interpolation.
} }
pub fn new(physics:crate::physics::PhysicsState,graphics_worker:crate::compat_worker::INWorker<crate::graphics_worker::GraphicsInstruction>)->crate::compat_worker::QNWorker<TimedInstruction<InputInstruction>>{ pub fn new(mut physics:crate::physics::PhysicsState,mut graphics_worker:crate::compat_worker::INWorker<crate::graphics_worker::Instruction>)->crate::compat_worker::QNWorker<TimedInstruction<Instruction>>{
let mut mouse_blocking=true; let mut mouse_blocking=true;
let mut last_mouse_time=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::compat_worker::QNWorker::new(move |ins:TimedInstruction<InputInstruction>|{ crate::compat_worker::QNWorker::new(move |ins:TimedInstruction<Instruction>|{
let mut render=false; if if let Some(phys_input)=match &ins.instruction{
if if let Some(phys_input)=match ins.instruction{ Instruction::Input(input_instruction)=>match input_instruction{
InputInstruction::MoveMouse(m)=>{ &InputInstruction::MoveMouse(m)=>{
if mouse_blocking{ if mouse_blocking{
//tell the game state which is living in the past about its future //tell the game state which is living in the past about its future
timeline.push_front(TimedInstruction{ timeline.push_front(TimedInstruction{
@ -50,16 +51,18 @@ pub enum InputInstruction {
last_mouse_time=ins.time; last_mouse_time=ins.time;
None None
}, },
InputInstruction::MoveForward(s)=>Some(PhysicsInputInstruction::SetMoveForward(s)), &InputInstruction::MoveForward(s)=>Some(PhysicsInputInstruction::SetMoveForward(s)),
InputInstruction::MoveLeft(s)=>Some(PhysicsInputInstruction::SetMoveLeft(s)), &InputInstruction::MoveLeft(s)=>Some(PhysicsInputInstruction::SetMoveLeft(s)),
InputInstruction::MoveBack(s)=>Some(PhysicsInputInstruction::SetMoveBack(s)), &InputInstruction::MoveBack(s)=>Some(PhysicsInputInstruction::SetMoveBack(s)),
InputInstruction::MoveRight(s)=>Some(PhysicsInputInstruction::SetMoveRight(s)), &InputInstruction::MoveRight(s)=>Some(PhysicsInputInstruction::SetMoveRight(s)),
InputInstruction::MoveUp(s)=>Some(PhysicsInputInstruction::SetMoveUp(s)), &InputInstruction::MoveUp(s)=>Some(PhysicsInputInstruction::SetMoveUp(s)),
InputInstruction::MoveDown(s)=>Some(PhysicsInputInstruction::SetMoveDown(s)), &InputInstruction::MoveDown(s)=>Some(PhysicsInputInstruction::SetMoveDown(s)),
InputInstruction::Jump(s)=>Some(PhysicsInputInstruction::SetJump(s)), &InputInstruction::Jump(s)=>Some(PhysicsInputInstruction::SetJump(s)),
InputInstruction::Zoom(s)=>Some(PhysicsInputInstruction::SetZoom(s)), &InputInstruction::Zoom(s)=>Some(PhysicsInputInstruction::SetZoom(s)),
InputInstruction::Reset=>Some(PhysicsInputInstruction::Reset), InputInstruction::Reset=>Some(PhysicsInputInstruction::Reset),
InputInstruction::Render=>{render=true;Some(PhysicsInputInstruction::Idle)}, },
Instruction::Resize(_)=>Some(PhysicsInputInstruction::Idle),
Instruction::Render=>Some(PhysicsInputInstruction::Idle),
}{ }{
//non-mouse event //non-mouse event
timeline.push_back(TimedInstruction{ timeline.push_back(TimedInstruction{
@ -104,8 +107,14 @@ pub enum InputInstruction {
}); });
} }
} }
if render{ match ins.instruction{
graphics_worker.send(crate::graphics_worker::GraphicsInstruction::Render(physics.output(),ins.time)); Instruction::Render=>{
graphics_worker.send(crate::graphics_worker::Instruction::Render(physics.output(),ins.time,physics.next_mouse.pos)).unwrap();
},
Instruction::Resize(size)=>{
graphics_worker.send(crate::graphics_worker::Instruction::Resize(size)).unwrap();
},
_=>(),
} }
}) })
} }

View File

@ -1,5 +1,5 @@
use crate::physics::PhysicsInstruction; use crate::physics::PhysicsInstruction;
use crate::physics_context::InputInstruction; use crate::physics_worker::InputInstruction;
use crate::instruction::TimedInstruction; use crate::instruction::TimedInstruction;
pub enum RunInstruction{ pub enum RunInstruction{
@ -14,13 +14,18 @@ pub enum RunInstruction{
struct RunContext{ struct RunContext{
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<>>
device:wgpu::Device,
queue:wgpu::Queue,
screen_size:glam::UVec2, screen_size:glam::UVec2,
user_settings:crate::settings::UserSettings, user_settings:crate::settings::UserSettings,
window:winit::window::Window, window:winit::window::Window,
//physics_thread:crate::worker::QNWorker<TimedInstruction<InputInstruction>>, physics_thread:crate::compat_worker::QNWorker<TimedInstruction<crate::physics_worker::Instruction>>,
} }
impl RunContext{ impl RunContext{
fn get_middle_of_screen(&self)->winit::dpi::PhysicalPosition<f32>{
winit::dpi::PhysicalPosition::new(self.screen_size.x as f32/2.0, self.screen_size.y as f32/2.0)
}
fn window_event(&mut self,time:crate::integer::Time,event: winit::event::WindowEvent) { fn window_event(&mut self,time:crate::integer::Time,event: winit::event::WindowEvent) {
match event { match event {
winit::event::WindowEvent::DroppedFile(path)=>{ winit::event::WindowEvent::DroppedFile(path)=>{
@ -49,7 +54,7 @@ impl RunContext{
winit::keyboard::Key::Named(winit::keyboard::NamedKey::Tab)=>{ winit::keyboard::Key::Named(winit::keyboard::NamedKey::Tab)=>{
if s{ if s{
self.manual_mouse_lock=false; self.manual_mouse_lock=false;
match self.window.set_cursor_position(winit::dpi::PhysicalPosition::new(self.screen_size.x as f32/2.0, self.screen_size.y as f32/2.0)){ match self.window.set_cursor_position(self.get_middle_of_screen()){
Ok(())=>(), Ok(())=>(),
Err(e)=>println!("Could not set cursor position: {:?}",e), Err(e)=>println!("Could not set cursor position: {:?}",e),
} }
@ -112,7 +117,7 @@ impl RunContext{
}{ }{
self.physics_thread.send(TimedInstruction{ self.physics_thread.send(TimedInstruction{
time, time,
instruction:input_instruction, instruction:crate::physics_worker::Instruction::Input(input_instruction),
}).unwrap(); }).unwrap();
} }
}, },
@ -123,13 +128,13 @@ impl RunContext{
} }
} }
fn device_event(&self,time:crate::integer::Time,event: winit::event::DeviceEvent) { fn device_event(&mut self,time:crate::integer::Time,event: winit::event::DeviceEvent) {
match event { match event {
winit::event::DeviceEvent::MouseMotion { winit::event::DeviceEvent::MouseMotion {
delta,//these (f64,f64) are integers on my machine delta,//these (f64,f64) are integers on my machine
} => { } => {
if self.manual_mouse_lock{ if self.manual_mouse_lock{
match self.window.set_cursor_position(winit::dpi::PhysicalPosition::new(self.screen_size.x as f32/2.0, self.screen_size.y as f32/2.0)){ match self.window.set_cursor_position(self.get_middle_of_screen()){
Ok(())=>(), Ok(())=>(),
Err(e)=>println!("Could not set cursor position: {:?}",e), Err(e)=>println!("Could not set cursor position: {:?}",e),
} }
@ -141,7 +146,7 @@ impl RunContext{
self.mouse.pos+=delta; self.mouse.pos+=delta;
self.physics_thread.send(TimedInstruction{ self.physics_thread.send(TimedInstruction{
time, time,
instruction:InputInstruction::MoveMouse(self.mouse.pos), instruction:crate::physics_worker::Instruction::Input(InputInstruction::MoveMouse(self.mouse.pos)),
}).unwrap(); }).unwrap();
}, },
winit::event::DeviceEvent::MouseWheel { winit::event::DeviceEvent::MouseWheel {
@ -151,7 +156,7 @@ impl RunContext{
if false{//self.physics.style.use_scroll{ if false{//self.physics.style.use_scroll{
self.physics_thread.send(TimedInstruction{ self.physics_thread.send(TimedInstruction{
time, time,
instruction:InputInstruction::Jump(true),//activates the immediate jump path, but the style modifier prevents controls&CONTROL_JUMP bit from being set to auto jump instruction:crate::physics_worker::Instruction::Input(InputInstruction::Jump(true)),//activates the immediate jump path, but the style modifier prevents controls&CONTROL_JUMP bit from being set to auto jump
}).unwrap(); }).unwrap();
} }
} }
@ -179,14 +184,14 @@ impl RunContextSetup{
None None
}.unwrap_or(crate::default_models()); }.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(); let mut physics=crate::physics::PhysicsState::default();
physics.load_user_settings(&user_settings); physics.load_user_settings(&user_settings);
physics.generate_models(&indexed_model_instances); physics.generate_models(&indexed_model_instances);
let mut graphics=crate::graphics::GraphicsState::new(&context.device,&context.queue,&context.config);
graphics.load_user_settings(&user_settings);
graphics.generate_models(&context.device,&context.queue,indexed_model_instances);
Self{ Self{
user_settings, user_settings,
window, window,
@ -195,20 +200,25 @@ impl RunContextSetup{
} }
} }
fn into_context(self)->RunContext{ fn into_context(self,setup_context:crate::setup::SetupContext)->RunContext{
let screen_size=glam::uvec2(setup_context.config.width,setup_context.config.height);
let graphics_thread=crate::graphics_worker::new(self.graphics,setup_context.config,setup_context.surface,&setup_context.device,&setup_context.queue);
RunContext{ RunContext{
manual_mouse_lock:false, manual_mouse_lock:false,
mouse:crate::physics::MouseState::default(), mouse:crate::physics::MouseState::default(),
//make sure to update this!!!!!
screen_size,
device:setup_context.device,
queue:setup_context.queue,
user_settings:self.user_settings, user_settings:self.user_settings,
window:self.window, window:self.window,
physics:self.physics, physics_thread:crate::physics_worker::new(self.physics,graphics_thread),
graphics:self.graphics,
} }
} }
pub fn into_worker(self,setup_context:crate::setup::SetupContext)->crate::worker::QNWorker<TimedInstruction<RunInstruction>>{ pub fn into_worker(self,setup_context:crate::setup::SetupContext)->crate::compat_worker::QNWorker<TimedInstruction<RunInstruction>>{
let run_context=self.into_context(); let mut run_context=self.into_context(setup_context);
crate::worker::QNWorker::new(move |ins:TimedInstruction<RunInstruction>|{ crate::compat_worker::QNWorker::new(move |ins:TimedInstruction<RunInstruction>|{
match ins.instruction{ match ins.instruction{
RunInstruction::RequestRedraw=>{ RunInstruction::RequestRedraw=>{
run_context.window.request_redraw(); run_context.window.request_redraw();
@ -220,13 +230,20 @@ impl RunContextSetup{
run_context.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); run_context.physics_thread.send(
setup_context.config.height=size.height.max(1); TimedInstruction{
setup_context.surface.configure(&setup_context.device,&setup_context.config); time:ins.time,
run_context.physics_thread.send(TimedInstruction{time:ins.time,instruction:PhysicsInstruction::Resize(size)}); instruction:crate::physics_worker::Instruction::Resize(size)
}
).unwrap();
} }
RunInstruction::Render=>{ RunInstruction::Render=>{
// run_context.physics_thread.send(
TimedInstruction{
time:ins.time,
instruction:crate::physics_worker::Instruction::Render
}
).unwrap();
} }
} }
}) })

View File

@ -47,8 +47,8 @@ impl SetupContextPartial1{
fn create_surface(self,window:&winit::window::Window)->Result<SetupContextPartial2,wgpu::CreateSurfaceError>{ fn create_surface(self,window:&winit::window::Window)->Result<SetupContextPartial2,wgpu::CreateSurfaceError>{
Ok(SetupContextPartial2{ Ok(SetupContextPartial2{
backends:self.backends, backends:self.backends,
surface:unsafe{self.instance.create_surface(window)}?,
instance:self.instance, instance:self.instance,
surface:unsafe{self.instance.create_surface(window)}?
}) })
} }
} }
@ -231,7 +231,7 @@ impl SetupContextSetup{
let run=crate::run::RunContextSetup::new(&setup_context,window); let run=crate::run::RunContextSetup::new(&setup_context,window);
//the thread that spawns the physics thread //the thread that spawns the physics thread
let run_thread=run.into_worker(setup_context); let mut run_thread=run.into_worker(setup_context);
println!("Entering render loop..."); println!("Entering render loop...");
let root_time=std::time::Instant::now(); let root_time=std::time::Instant::now();