Skip to content

Instantly share code, notes, and snippets.

@FredrikNoren
Created August 9, 2021 12:31
Show Gist options
  • Save FredrikNoren/7c3535b11e99e8fcd8dd3d55f9a934a2 to your computer and use it in GitHub Desktop.
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();
});
}
@FredrikNoren
Copy link
Author

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.

@LukasBombach
Copy link

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?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment