share code with lib setup

This commit is contained in:
2026-02-18 09:11:25 -08:00
parent a39f0fe4db
commit 9a65740c54
3 changed files with 22 additions and 167 deletions

View File

@@ -8,5 +8,5 @@ mod window;
const TITLE:&'static str=concat!("Roblox Bot Player v",env!("CARGO_PKG_VERSION"));
fn main(){
setup::setup_and_start(TITLE);
pollster::block_on(setup::setup_and_start(TITLE));
}

View File

@@ -1,186 +1,38 @@
fn optional_features()->wgpu::Features{
wgpu::Features::TEXTURE_COMPRESSION_ASTC
|wgpu::Features::TEXTURE_COMPRESSION_ETC2
}
fn required_features()->wgpu::Features{
wgpu::Features::TEXTURE_COMPRESSION_BC
}
fn required_downlevel_capabilities()->wgpu::DownlevelCapabilities{
wgpu::DownlevelCapabilities{
flags:wgpu::DownlevelFlags::empty(),
shader_model:wgpu::ShaderModel::Sm5,
..wgpu::DownlevelCapabilities::default()
}
}
use strafesnet_roblox_bot_player::setup;
struct SetupContextPartial1{
backends:wgpu::Backends,
instance:wgpu::Instance,
}
fn create_window(title:&str,event_loop:&winit::event_loop::EventLoop<()>)->Result<winit::window::Window,winit::error::OsError>{
let mut attr=winit::window::WindowAttributes::default();
attr=attr.with_title(title);
event_loop.create_window(attr)
}
fn create_instance()->SetupContextPartial1{
let backends=wgpu::Backends::from_env().unwrap_or_default();
SetupContextPartial1{
backends,
instance:Default::default(),
}
}
impl SetupContextPartial1{
fn create_surface<'a>(self,window:&'a winit::window::Window)->Result<SetupContextPartial2<'a>,wgpu::CreateSurfaceError>{
Ok(SetupContextPartial2{
backends:self.backends,
surface:self.instance.create_surface(window)?,
instance:self.instance,
})
}
}
struct SetupContextPartial2<'a>{
backends:wgpu::Backends,
instance:wgpu::Instance,
surface:wgpu::Surface<'a>,
}
impl<'a> SetupContextPartial2<'a>{
fn pick_adapter(self)->SetupContextPartial3<'a>{
//TODO: prefer adapter that implements optional features
//let optional_features=optional_features();
let required_features=required_features();
//no helper function smh gotta write it myself
let adapters=pollster::block_on(self.instance.enumerate_adapters(self.backends));
let chosen_adapter=adapters.into_iter()
// reverse because we want to select adapters that appear first in ties,
// and max_by_key selects the last equal element in the iterator.
.rev()
.filter(|adapter|
adapter.is_surface_supported(&self.surface)
&&adapter.features().contains(required_features)
)
.max_by_key(|adapter|match adapter.get_info().device_type{
wgpu::DeviceType::IntegratedGpu=>3,
wgpu::DeviceType::DiscreteGpu=>4,
wgpu::DeviceType::VirtualGpu=>2,
wgpu::DeviceType::Other|wgpu::DeviceType::Cpu=>1,
});
let adapter=chosen_adapter.expect("No suitable GPU adapters found on the system!");
let adapter_info=adapter.get_info();
println!("Using {} ({:?})", adapter_info.name, adapter_info.backend);
let required_downlevel_capabilities=required_downlevel_capabilities();
let downlevel_capabilities=adapter.get_downlevel_capabilities();
assert!(
downlevel_capabilities.shader_model >= required_downlevel_capabilities.shader_model,
"Adapter does not support the minimum shader model required to run this example: {:?}",
required_downlevel_capabilities.shader_model
);
assert!(
downlevel_capabilities
.flags
.contains(required_downlevel_capabilities.flags),
"Adapter does not support the downlevel capabilities required to run this example: {:?}",
required_downlevel_capabilities.flags - downlevel_capabilities.flags
);
SetupContextPartial3{
surface:self.surface,
adapter,
}
}
}
struct SetupContextPartial3<'a>{
surface:wgpu::Surface<'a>,
adapter:wgpu::Adapter,
}
impl<'a> SetupContextPartial3<'a>{
fn request_device(self)->SetupContextPartial4<'a>{
let optional_features=optional_features();
let required_features=required_features();
// Make sure we use the texture resolution limits from the adapter, so we can support images the size of the surface.
let needed_limits=strafesnet_graphics::graphics::required_limits().using_resolution(self.adapter.limits());
let (device, queue)=pollster::block_on(self.adapter
.request_device(
&wgpu::DeviceDescriptor{
label:None,
required_features:(optional_features&self.adapter.features())|required_features,
required_limits:needed_limits,
memory_hints:wgpu::MemoryHints::Performance,
trace:wgpu::Trace::Off,
experimental_features:wgpu::ExperimentalFeatures::disabled(),
},
))
.expect("Unable to find a suitable GPU adapter!");
SetupContextPartial4{
surface:self.surface,
adapter:self.adapter,
device,
queue,
}
}
}
struct SetupContextPartial4<'a>{
surface:wgpu::Surface<'a>,
adapter:wgpu::Adapter,
device:wgpu::Device,
queue:wgpu::Queue,
}
impl<'a> SetupContextPartial4<'a>{
fn configure_surface(self,size:&'a winit::dpi::PhysicalSize<u32>)->SetupContext<'a>{
let mut config=self.surface
.get_default_config(&self.adapter, size.width, size.height)
.expect("Surface isn't supported by the adapter.");
let surface_view_format=config.format.add_srgb_suffix();
config.view_formats.push(surface_view_format);
config.present_mode=wgpu::PresentMode::AutoNoVsync;
self.surface.configure(&self.device, &config);
SetupContext{
surface:self.surface,
device:self.device,
queue:self.queue,
config,
}
}
}
pub struct SetupContext<'a>{
pub surface:wgpu::Surface<'a>,
pub device:wgpu::Device,
pub queue:wgpu::Queue,
pub config:wgpu::SurfaceConfiguration,
}
pub fn setup_and_start(title:&str){
pub async fn setup_and_start(title:&str){
let event_loop=winit::event_loop::EventLoop::new().unwrap();
println!("Initializing the surface...");
let partial_1=create_instance();
let window=create_window(title,&event_loop).unwrap();
let partial_2=partial_1.create_surface(&window).unwrap();
println!("Initializing the surface...");
let partial_3=partial_2.pick_adapter();
let instance=setup::step1::create_instance();
let partial_4=partial_3.request_device();
let surface=setup::step2::create_surface(&instance,&window).unwrap();
let adapter=setup::step3::pick_adapter(&instance,&surface).await.expect("No suitable GPU adapters found on the system!");
let (device,queue)=setup::step4::request_device(&adapter).await;
let size=window.inner_size();
let setup_context=partial_4.configure_surface(&size);
let config=setup::step5::configure_surface(&adapter,&device,&surface,(size.width,size.height));
//dedicated thread to ping request redraw back and resize the window doesn't seem logical
//the thread that spawns the physics thread
let mut window_thread=crate::window::WindowContext::new(
&window,
setup_context,
device,
queue,
surface,
config,
);
for arg in std::env::args().skip(1){

View File

@@ -193,12 +193,15 @@ impl WindowContext<'_>{
pub fn new<'a>(
window:&'a winit::window::Window,
setup_context:crate::setup::SetupContext<'a>,
device:wgpu::Device,
queue:wgpu::Queue,
surface:wgpu::Surface<'a>,
config:wgpu::SurfaceConfiguration,
)->WindowContext<'a>{
let screen_size=glam::uvec2(setup_context.config.width,setup_context.config.height);
let screen_size=glam::uvec2(config.width,config.height);
let bot=include_bytes!("../../web-demo/bhop_marble_7cf33a64-7120-4514-b9fa-4fe29d9523d.qbot");
let map=include_bytes!("../../web-demo/bhop_marble_5692093612.snfm");
let graphics=strafesnet_roblox_bot_player::graphics::Graphics::new(map,setup_context.device,setup_context.queue,setup_context.config).unwrap();
let graphics=strafesnet_roblox_bot_player::graphics::Graphics::new(map,device,queue,config).unwrap();
let bot=strafesnet_roblox_bot_player::bot::Bot::new(bot).unwrap();
WindowContext{
manual_mouse_lock:false,
@@ -208,7 +211,7 @@ impl WindowContext<'_>{
screen_size,
window,
physics_thread:crate::player::PlayerWorker::new(
setup_context.surface,
surface,
bot,
graphics,
),