-
-
Save FredrikNoren/7c3535b11e99e8fcd8dd3d55f9a934a2 to your computer and use it in GitHub Desktop.
use tokio::{runtime::Builder, sync::{mpsc}}; | |
use winit::{event::{Event, WindowEvent}, event_loop::{ControlFlow, EventLoop}, window::{Window, WindowBuilder}}; | |
pub struct Gpu { | |
pub surface: wgpu::Surface, | |
pub device: wgpu::Device, | |
pub queue: wgpu::Queue, | |
pub sc_desc: wgpu::SwapChainDescriptor, | |
pub swap_chain: wgpu::SwapChain, | |
pub swapchain_format: wgpu::TextureFormat, | |
pub adapter: wgpu::Adapter, | |
} | |
impl Gpu { | |
pub async fn new(window: &Window) -> Self { | |
let size = window.inner_size(); | |
let swapchain_format = wgpu::TextureFormat::Bgra8UnormSrgb; | |
let instance = wgpu::Instance::new(wgpu::BackendBit::PRIMARY); | |
let surface = unsafe { instance.create_surface(window) }; | |
let adapter = instance | |
.request_adapter(&wgpu::RequestAdapterOptions { | |
power_preference: wgpu::PowerPreference::default(), | |
compatible_surface: Some(&surface), | |
}) | |
.await | |
.expect("Failed to find an appropiate adapter"); | |
let (device, queue) = adapter | |
.request_device( | |
&wgpu::DeviceDescriptor { | |
label: None, | |
features: wgpu::Features::NON_FILL_POLYGON_MODE, | |
limits: wgpu::Limits::default(), | |
}, | |
None, | |
) | |
.await | |
.expect("Failed to create device"); | |
let sc_desc = wgpu::SwapChainDescriptor { | |
usage: wgpu::TextureUsage::RENDER_ATTACHMENT, | |
format: swapchain_format, | |
width: size.width, | |
height: size.height, | |
present_mode: wgpu::PresentMode::Immediate, | |
}; | |
let swap_chain = device.create_swap_chain(&surface, &sc_desc); | |
Self { | |
sc_desc, | |
swap_chain, | |
device, | |
surface, | |
queue, | |
swapchain_format, | |
adapter, | |
} | |
} | |
fn clear(&self) { | |
let frame = self.swap_chain | |
.get_current_frame() | |
.expect("Failed to acquire next swap chain texture") | |
.output; | |
let mut encoder = self.device.create_command_encoder(&wgpu::CommandEncoderDescriptor { label: None }); | |
{ | |
encoder.begin_render_pass(&wgpu::RenderPassDescriptor { | |
label: None, | |
color_attachments: &[wgpu::RenderPassColorAttachment { | |
view: &frame.view, | |
resolve_target: None, | |
ops: wgpu::Operations { | |
load: wgpu::LoadOp::Clear(wgpu::Color::GREEN), | |
store: true, | |
}, | |
}], | |
depth_stencil_attachment: None, | |
}); | |
} | |
self.queue.submit(Some(encoder.finish())); | |
} | |
} | |
fn main() { | |
let runtime = Builder::new_multi_thread() | |
.enable_all() | |
.build() | |
.unwrap(); | |
let (event_tx, mut event_rx) = mpsc::unbounded_channel(); | |
let event_loop = EventLoop::new(); | |
let window = WindowBuilder::new().build(&event_loop).unwrap(); | |
runtime.block_on(async { | |
let gpu = Gpu::new(&window).await; | |
runtime.spawn(async move { | |
loop { | |
let event = event_rx.recv().await.unwrap(); | |
println!("{:?} {:?}", event, std::thread::current().id()); | |
gpu.clear(); | |
} | |
}); | |
}); | |
event_loop.run(move |event, _, control_flow| { | |
*control_flow = ControlFlow::Wait; | |
match &event { | |
Event::WindowEvent { event: WindowEvent::CloseRequested, .. } => *control_flow = ControlFlow::Exit, | |
_ => (), | |
} | |
event_tx.send(event.to_static()).unwrap(); | |
}); | |
} |
@LukasBombach Np! One additional problem I ran into; you can't do set_title on the window on any other thread than the main thread on some OS (can't remember if it was win or osx), so you might need to send stuff over to the main thread to do that (i.e. inside the event_loop.run thing)
I see. I also think you cannot create new windows from another thread as you needs ownership of the event loop, do you happen to know if that is correct?
👌
Quick note; I ended up moving away from this and just running the game loop on the main thread (like normal) instead, and integrating tokio by just creating a runtime and passing around Handle's to it, which can be used to spawn.
integrating tokio by just creating a runtime and passing around Handle's to it, which can be used to spawn
@FredrikNoren can you elaborate what you mean by this?
This is great, thanks!