Created
August 9, 2021 12:31
-
-
Save FredrikNoren/7c3535b11e99e8fcd8dd3d55f9a934a2 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(); | |
}); | |
} |
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?
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
👌