[−][src]Struct emu_core::device::Device
Represents a single device
Since its fields are public, you can easily construct and mutate a Device
's
WebGPU internals. To get a Device
from an existing device pool, you will want to use take
.
One thing to remember is that each Device
owns its data. So even though the device pool lets you create DeviceBox
s on different devices,
you cannot use them together in the same kernel.
Fields
device: Device
The WebGPU device wrapped by this data structure
queue: Queue
The queue this device exposes to submit work to
info: Option<DeviceInfo>
Information about the device
This is optional so that you don't need information to construct a Device
yourself.
Methods
impl Device
[src]
pub async fn all() -> Vec<Self>
[src]
Gets all detected devices
This is asynchronous because it may take a long time for all the devices that are detected to actually be available. However, you shouldn't actually use this. Unless you manually construct a pool of devices, a default device pool is implicitly created. So you should instead do one of the following.
- If you are developing a library, select a device from the pool with
select
/take
- If you are developing an application, construct a pool with
pool
or use the default pool
If you are using the default pool, don't forget to call assert_device_pool_initialized
before doing anthing with a device.
pub fn create_with_size<T>(&mut self, size: usize) -> DeviceBox<T> where
T: ?Sized,
[src]
T: ?Sized,
Creates a constant DeviceBox<T>
with size of given number of bytes
let mut device = &mut futures::executor::block_on(Device::all())[0]; let pi: DeviceBox<f32> = device.create_with_size(std::mem::size_of::<f32>());
pub fn create_with_size_mut<T>(&mut self, size: usize) -> DeviceBox<T> where
T: ?Sized,
[src]
T: ?Sized,
Creates a mutable DeviceBox<T>
with size of given number of bytes
let mut device = &mut futures::executor::block_on(Device::all())[0]; let mut data: DeviceBox<[f32]> = device.create_with_size(std::mem::size_of::<f32>() * 2048);
pub fn create_from<T: ?Sized, B: Borrow<T>>(
&mut self,
host_obj: B
) -> DeviceBox<T> where
T: AsBytes,
[src]
&mut self,
host_obj: B
) -> DeviceBox<T> where
T: AsBytes,
Creates a constant DeviceBox<T>
from a borrow of T
let mut device = &mut futures::executor::block_on(Device::all())[0]; let pi: DeviceBox<f32> = device.create_from(&3.1415);
pub fn create_from_mut<T: ?Sized, B: Borrow<T>>(
&mut self,
host_obj: B
) -> DeviceBox<T> where
T: AsBytes,
[src]
&mut self,
host_obj: B
) -> DeviceBox<T> where
T: AsBytes,
Creates a mutable DeviceBox<T>
from a borrow of T
let mut device = &mut futures::executor::block_on(Device::all())[0]; let data = vec![0.0; 2048]; let mut data_on_gpu: DeviceBox<[f32]> = device.create_from(data.as_slice());
pub fn set_from<T: ?Sized, B: Borrow<T>>(
&mut self,
device_obj: &mut DeviceBox<T>,
host_obj: B
) where
T: AsBytes,
[src]
&mut self,
device_obj: &mut DeviceBox<T>,
host_obj: B
) where
T: AsBytes,
Uploads data from the given borrow to T
to the given DeviceBox<T>
that lives on this (meaning self
) device
let mut device = &mut futures::executor::block_on(Device::all())[0]; let data = vec![0.0; 2048]; let mut data_on_gpu: DeviceBox<[f32]> = device.create_from_mut(data.as_slice()); device.set_from(&mut data_on_gpu, vec![0.5; 2048].as_slice());
pub async fn get<'_, '_, T>(
&'_ mut self,
device_obj: &'_ DeviceBox<[T]>
) -> Result<Box<[T]>, CompletionError> where
T: FromBytes + Copy,
[src]
&'_ mut self,
device_obj: &'_ DeviceBox<[T]>
) -> Result<Box<[T]>, CompletionError> where
T: FromBytes + Copy,
Downloads data from the given DeviceBox<T>
asynchronously and returns a boxed slice of T
This functions is asynchronous so you can either .await
it in an asynchronous context (like an async fn
or async
block) or you can
simply pass the returned future to an executor.
// get a device let mut device = &mut futures::executor::block_on(Device::all())[0]; // create some data on a GPU and mutate it in place let data = vec![0.0; 2048]; let mut data_on_gpu: DeviceBox<[f32]> = device.create_from_mut(data.as_slice()); device.set_from(&mut data_on_gpu, vec![0.5; 2048].as_slice()); // use `get` to download from the GPU assert_eq!(futures::executor::block_on(device.get(&data_on_gpu))?, vec![0.5; 2048].into_boxed_slice());
pub unsafe fn call<'a>(
&mut self,
device_fn_mut: &DeviceFnMut,
work_space_dim: (u32, u32, u32),
args: DeviceFnMutArgs<'a>
) -> Result<(), LaunchError>
[src]
&mut self,
device_fn_mut: &DeviceFnMut,
work_space_dim: (u32, u32, u32),
args: DeviceFnMutArgs<'a>
) -> Result<(), LaunchError>
Runs the given DeviceFnMut
on a multi-dimensional space of threads to launch and arguments to pass to the launched kernel
This is unsafe because it runs arbitrary code on a device.
let mut device = &mut futures::executor::block_on(Device::all())[0]; let data = vec![0.0; 2048]; let mut data_on_gpu: DeviceBox<[f32]> = device.create_from(data.as_slice()); // these are bytes so we first convert to 4-byte words let shader: Vec<u32> = convert_to_spirv(std::io::Cursor::new(vec![ // Magic number. Version number: 1.0. 0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, // Generator number: 0. Bound: 0. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Reserved word: 0. 0x00, 0x00, 0x00, 0x00, // OpMemoryModel. Logical. 0x0e, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, // GLSL450. 0x01, 0x00, 0x00, 0x00]))?; // then, we compile to a `DeviceFnMut` // the compilation here will fail at runtime because the above shader // doesn't have an entry point called main let shader_compiled = device.compile(ParamsBuilder::new().build(), "main", shader)?; // run unsafe { device.call(&shader_compiled, (1, 1, 1), ArgsBuilder::new().build())? };
pub fn compile<T: Into<String>, P: Borrow<[u32]>>(
&self,
program_params: DeviceFnMutParams,
program_entry: T,
program: P
) -> Result<DeviceFnMut, CompileError>
[src]
&self,
program_params: DeviceFnMutParams,
program_entry: T,
program: P
) -> Result<DeviceFnMut, CompileError>
Compiles a DeviceFnMut
using the given parameters, entry point name, and SPIR-V program
The entry point is where in the SPIR-V program the compiled kernel should be entered upon execution.
The entry point's name is anything implementing Into<String>
including &str
and String
while
the program itself is anything Borrow<[u32]>
including Vec<u32>
and &[u32]
.
// get a device to use let mut device = &mut futures::executor::block_on(Device::all())[0]; // these are bytes so we first convert to 4-byte words let shader: Vec<u32> = convert_to_spirv(std::io::Cursor::new(vec![ // Magic number. Version number: 1.0. 0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, // Generator number: 0. Bound: 0. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Reserved word: 0. 0x00, 0x00, 0x00, 0x00, // OpMemoryModel. Logical. 0x0e, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, // GLSL450. 0x01, 0x00, 0x00, 0x00]))?; // then, we compile to a `DeviceFnMut` // the compilation here will fail at runtime because the above shader // doesn't have an entry point called main let shader_compiled = device.compile(ParamsBuilder::new().build(), "main", shader)?;
Auto Trait Implementations
impl !RefUnwindSafe for Device
impl Send for Device
impl Sync for Device
impl Unpin for Device
impl UnwindSafe for Device
Blanket Implementations
impl<T> Any for T where
T: 'static + ?Sized,
[src]
T: 'static + ?Sized,
impl<T, U> AsDeviceBoxed<T> for U where
T: AsBytes + ?Sized,
U: Borrow<T>,
[src]
T: AsBytes + ?Sized,
U: Borrow<T>,
fn as_device_boxed(&Self) -> Result<DeviceBox<T>, NoDeviceError>
[src]
fn as_device_boxed_mut(&Self) -> Result<DeviceBox<T>, NoDeviceError>
[src]
impl<T> Borrow<T> for T where
T: ?Sized,
[src]
T: ?Sized,
impl<T> BorrowMut<T> for T where
T: ?Sized,
[src]
T: ?Sized,
fn borrow_mut(&mut self) -> &mut T
[src]
impl<T> From<T> for T
[src]
impl<T, U> Into<U> for T where
U: From<T>,
[src]
U: From<T>,
impl<T, U> TryFrom<U> for T where
U: Into<T>,
[src]
U: Into<T>,
type Error = Infallible
The type returned in the event of a conversion error.
fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>
[src]
impl<T, U> TryInto<U> for T where
U: TryFrom<T>,
[src]
U: TryFrom<T>,