Skip to content

Instantly share code, notes, and snippets.

@expenses
Created May 11, 2022 15:54
Show Gist options
  • Save expenses/64a467b5f09462ad2441b9ceefe55b6f to your computer and use it in GitHub Desktop.
Save expenses/64a467b5f09462ad2441b9ceefe55b6f to your computer and use it in GitHub Desktop.
use std::any::Any;
struct Message {
func: Box<dyn FnOnce(Rc<wgpu::Device>) -> Box<dyn Any + Send> + Send>,
response_tx: std::sync::mpsc::Sender<Box<dyn Any + Send>>,
}
pub struct ThreadSafeDevice {
tx: async_std::channel::Sender<Message>,
}
impl ThreadSafeDevice {
fn new(device: Rc<wgpu::Device>) -> Self {
let (tx, rx) = async_std::channel::unbounded::<Message>();
wasm_bindgen_futures::spawn_local(async move {
while let Ok(message) = rx.recv().await {
let response = (message.func)(Rc::clone(&device));
message.response_tx.send(response).unwrap();
}
});
Self { tx }
}
pub(crate) fn call<T: Send + 'static, F: FnOnce(Rc<wgpu::Device>) -> T + Send + 'static>(
&self,
func: F,
) -> anyhow::Result<T> {
let (tx, rx) = std::sync::mpsc::channel();
let func_return_box = move |device| Box::new(func(device)) as Box<dyn Any + Send>;
let _ = self.tx.try_send(Message {
func: Box::new(func_return_box) as _,
response_tx: tx,
});
Ok(*rx
.recv()?
.downcast::<T>()
.map_err(|_| anyhow::anyhow!("Downcasting failed"))?)
}
pub(crate) fn create_texture(&self, desc: &wgpu::TextureDescriptor<'static>) -> wgpu::Texture {
let desc = desc.to_owned();
self.call(move |device| {
let desc = desc;
device.create_texture(&desc)
})
.unwrap()
}
pub(crate) fn create_sampler(&self, desc: &wgpu::SamplerDescriptor<'static>) -> wgpu::Sampler {
let desc = desc.to_owned();
self.call(move |device| {
let desc = desc;
device.create_sampler(&desc)
})
.unwrap()
}
pub(crate) fn create_bind_group(
&self,
desc: &wgpu::BindGroupDescriptor<'static>,
) -> wgpu::BindGroup {
let desc = desc.to_owned();
self.call(move |device| {
let desc = desc;
device.create_bind_group(&desc)
})
.unwrap()
}
pub(crate) fn create_shader_module(
&self,
desc: wgpu::ShaderModuleDescriptor<'static>,
) -> wgpu::ShaderModule {
let desc = desc;
self.call(move |device| {
let desc = desc;
device.create_shader_module(&desc)
})
.unwrap()
}
pub(crate) fn create_command_encoder(
&self,
desc: &wgpu::CommandEncoderDescriptor<'static>,
) -> wgpu::CommandEncoder {
let desc = desc.to_owned();
self.call(move |device| {
let desc = desc;
device.create_command_encoder(&desc)
})
.unwrap()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment