pub trait GpuBackend: Debug {
// Required methods
fn name(&self) -> &str;
fn compile(
&mut self,
name: &str,
wgsl: &str,
) -> Result<GpuKernelId, GpuError>;
fn create_buffer(&mut self, data: &[u8]) -> Result<GpuBufferId, GpuError>;
fn create_buffer_uninit(
&mut self,
byte_len: usize,
) -> Result<GpuBufferId, GpuError>;
fn dispatch(
&mut self,
kernel: GpuKernelId,
buffers: &[GpuBufferId],
workgroups: [u32; 3],
) -> Result<(), GpuError>;
fn read_buffer(&mut self, buffer: GpuBufferId) -> Result<Vec<u8>, GpuError>;
// Provided method
fn dispatch_verified(
&mut self,
kernel: GpuKernelId,
buffers: &[GpuBufferId],
workgroups: [u32; 3],
threads_per_group: [u32; 3],
) -> Result<(), GpuError> { ... }
}Expand description
A GPU compute backend for bulk SIMD offload (Borsalino Level 1).
The runtime uses this to offload large vector operations: upload WASM linear-memory regions to buffers, dispatch a pre-compiled WGSL kernel, and read results back. Below the offload threshold the register IR executes element-wise on CPU.
Required Methods§
Sourcefn compile(&mut self, name: &str, wgsl: &str) -> Result<GpuKernelId, GpuError>
fn compile(&mut self, name: &str, wgsl: &str) -> Result<GpuKernelId, GpuError>
Compile a WGSL compute kernel (once, cached by the backend).
Sourcefn create_buffer(&mut self, data: &[u8]) -> Result<GpuBufferId, GpuError>
fn create_buffer(&mut self, data: &[u8]) -> Result<GpuBufferId, GpuError>
Create a GPU buffer initialized with data.
Sourcefn create_buffer_uninit(
&mut self,
byte_len: usize,
) -> Result<GpuBufferId, GpuError>
fn create_buffer_uninit( &mut self, byte_len: usize, ) -> Result<GpuBufferId, GpuError>
Create an uninitialized GPU buffer of byte_len bytes.
Sourcefn dispatch(
&mut self,
kernel: GpuKernelId,
buffers: &[GpuBufferId],
workgroups: [u32; 3],
) -> Result<(), GpuError>
fn dispatch( &mut self, kernel: GpuKernelId, buffers: &[GpuBufferId], workgroups: [u32; 3], ) -> Result<(), GpuError>
Dispatch a kernel over workgroups (x, y, z) with buffers bound
in order.
Each workgroup runs the backend’s default thread count. Prefer
dispatch_verified when the workgroup
size is known, so non-default thread counts dispatch correctly.
Sourcefn read_buffer(&mut self, buffer: GpuBufferId) -> Result<Vec<u8>, GpuError>
fn read_buffer(&mut self, buffer: GpuBufferId) -> Result<Vec<u8>, GpuError>
Read a buffer’s full contents back to host memory.
Provided Methods§
Sourcefn dispatch_verified(
&mut self,
kernel: GpuKernelId,
buffers: &[GpuBufferId],
workgroups: [u32; 3],
threads_per_group: [u32; 3],
) -> Result<(), GpuError>
fn dispatch_verified( &mut self, kernel: GpuKernelId, buffers: &[GpuBufferId], workgroups: [u32; 3], threads_per_group: [u32; 3], ) -> Result<(), GpuError>
Dispatch a kernel with an explicit per-workgroup thread count.
Like dispatch, but each workgroup runs
threads_per_group threads rather than a backend-implied default.
This matters for kernels whose WGSL declares a non-default
@workgroup_size: dispatch silently uses the backend’s default
(256 for Borsalino), which mis-dispatches such kernels.
Backends that verify workgroup divisibility (Borsalino’s
dispatch_verified) construct their proof from
(workgroups, threads_per_group) here; the divisibility check runs
on the x-dimension product workgroups[0] * threads_per_group[0],
matching Borsalino’s 1-D proof scope.
The default implementation forwards to dispatch,
ignoring threads_per_group. Concrete backends that honour explicit
workgroup sizes override this.
Dyn Compatibility§
This trait is dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety".