[][src]Struct emu_core::compile_impls::GlslKernel

pub struct GlslKernel { /* fields omitted */ }

A convenience builder for GLSL compute kernels

The following is a baseline example.


let kernel: GlslKernel = GlslKernel::new()
    .param_mut::<[f32], _>("float[] data")
    .param::<f32, _>("float scalar")
    .with_kernel_code("data[gl_GlobalInvocationID.x] = data[gl_GlobalInvocationID.x] * scalar;");
let spirv_or_finished = compile::<GlslKernel, GlslKernelCompile, _, GlobalCache>(kernel)?;
// now at this point you can call `.finish` to turn `spirv_or_finished` into
// a finished `DeviceFnMut`

Methods

impl GlslKernel[src]

pub fn new() -> Self[src]

Initializes the builder

pub fn spawn(self, num_threads: u32) -> Self[src]

Spawns threads within each thread block

This essentially adds on a new dimension with the given size to the space of threads for each thread block. The dimensions are "x", "y", and "z" in that order. If no threads are spawned, the space of threads is 1-dimensional and of size 1. If this is called more than 3 times, the dimensions are collapsed to a single dimension with size equal to the product of the sizes of all prior dimensions.


let kernel: GlslKernel = GlslKernel::new()
    .spawn(32)
    .spawn(32)
    .param_mut::<[f32], _>("float[] data")
    .param::<f32, _>("float scalar")
    .with_kernel_code(r#"
uint index = (1 << 10) * gl_GlobalInvocationID.x + gl_GlobalInvocationID.y;
data[index] = data[index] * scalar;
    "#);
let spirv_or_finished = compile::<GlslKernel, GlslKernelCompile, _, GlobalCache>(kernel)?;
// now at this point you can call `.finish` to turn `spirv_or_finished` into
// a finished `DeviceFnMut`

pub fn with_struct<T: GlslStruct>(self) -> Self[src]

Appends a GLSL structure definition for the type which this function is generic over

This can be used for any type that implements GlslStruct.

use {emu_core::prelude::*, emu_glsl::*, zerocopy::*};

#[repr(C)]
#[derive(AsBytes, FromBytes, Copy, Clone, Default, Debug, GlslStruct, PartialEq)]
struct Shape {
    pos: [f32; 2],
    num_edges: u32,
    radius: f32
}

fn main() -> Result<(), Box<dyn std::error::Error>> {
    futures::executor::block_on(assert_device_pool_initialized());
    // create some shapes on the GPU
    let mut shapes: DeviceBox<[Shape]> = vec![Shape {
        pos: [100.0, 100.0],
        num_edges: 6,
        radius: 100.0
    }; 1024].as_device_boxed_mut()?;

    // define a kernel to scale and translate
    let kernel: GlslKernel = GlslKernel::new()
        .with_struct::<Shape>()
        .param_mut::<[Shape], _>("Shape[] shapes")
        // in practice, you should probably combine scale and translate in 1 struct
        .param::<f32, _>("float scale")
        .param::<[f32; 2], _>("vec2 translate")
        .with_kernel_code(r#"
shapes[gl_GlobalInvocationID.x].pos += translate;
shapes[gl_GlobalInvocationID.x].radius *= scale;
    "#);
    let spirv_or_finished = compile::<GlslKernel, GlslKernelCompile, _, GlobalCache>(kernel)?;
    let finished = spirv_or_finished.finish()?;

    // run
    unsafe {
        spawn(1024).launch(call!(
            finished, &mut shapes,
            &DeviceBox::new(2.0f32)?,
            &DeviceBox::new([-100.0f32; 2])?
        ))?;
    }

    // check result
    assert_eq!(futures::executor::block_on(shapes.get())?, vec![Shape {
        pos: [0.0; 2],
        num_edges: 6,
        radius: 200.0
    }; 1024].into_boxed_slice());
    Ok(())
}

pub fn with_const(
    self,
    left_hand: impl Into<String>,
    right_hand: impl Into<String>
) -> Self
[src]

Appends a constant definition using the give left hand and right hand sides


let kernel: GlslKernel = GlslKernel::new()
    .param_mut::<[f32], _>("float[] data")
    .param::<f32, _>("float scalar")
    .with_kernel_code("data[gl_GlobalInvocationID.x] = data[gl_GlobalInvocationID.x] * scalar + pi;")
    .with_const("int pi", "3");
let spirv_or_finished = compile::<GlslKernel, GlslKernelCompile, _, GlobalCache>(kernel)?;
// now at this point you can call `.finish` to turn `spirv_or_finished` into
// a finished `DeviceFnMut`

pub fn share(self, shared: impl Into<String>) -> Self[src]

Creates a shared variable using the given code


let kernel: GlslKernel = GlslKernel::new()
    .spawn(64)
    .share("float scratchpad[64]")
    .param_mut::<[f32], _>("float[] data")
    .param::<f32, _>("float scalar")
    .with_kernel_code(r#"
scratchpad[gl_LocalInvocationID.x] = data[gl_GlobalInvocationID.x];
// if we had a more complex access pattern, we might want a barrier() right here to ensure
// all memory has been downloaded to the shraed scratchpad
scratchpad[gl_LocalInvocationID.x] = scratchpad[gl_LocalInvocationID.x] * scratchpad[gl_LocalInvocationID.x];
scratchpad[gl_LocalInvocationID.x] = scratchpad[gl_LocalInvocationID.x] * scalar;
scratchpad[gl_LocalInvocationID.x] = scratchpad[gl_LocalInvocationID.x] * 2;
data[gl_GlobalInvocationID.x] = scratchpad[gl_LocalInvocationID.x];
    "#);
let spirv_or_finished = compile::<GlslKernel, GlslKernelCompile, _, GlobalCache>(kernel)?;
// now at this point you can call `.finish` to turn `spirv_or_finished` into
// a finished `DeviceFnMut`

pub fn param<T: ?Sized, I: Into<String>>(self, param: I) -> Self[src]

Generates code for a buffer through which constant data can be passed into the kernel

pub fn param_mut<T: ?Sized, I: Into<String>>(self, param: I) -> Self[src]

Generates code for a buffer through which mutable data can be passed into the kernel

pub fn with_helper_code(self, code: impl Into<String>) -> Self[src]

Adds the given helper code

This helper code may include additional type or function definitions.


let kernel: GlslKernel = GlslKernel::new()
    .param_mut::<[f32], _>("float[] data")
    .with_helper_code(r#"
float invert(float x) {
    return -x;
}
    "#)
    .with_kernel_code("data[gl_GlobalInvocationID.x] = invert(data[gl_GlobalInvocationID.x]);");
let spirv_or_finished = compile::<GlslKernel, GlslKernelCompile, _, GlobalCache>(kernel)?;
// now at this point you can call `.finish` to turn `spirv_or_finished` into
// a finished `DeviceFnMut`

pub fn with_kernel_code(self, code: impl Into<String>) -> Self[src]

Adds the body code for the kernel

This body code is simply wrapped in a void main function.

Trait Implementations

impl CompileToSpirv<GlslKernel, Vec<u32>> for GlslKernelCompile[src]

impl Hash for GlslKernel[src]

Auto Trait Implementations

impl RefUnwindSafe for GlslKernel

impl Send for GlslKernel

impl Sync for GlslKernel

impl Unpin for GlslKernel

impl UnwindSafe for GlslKernel

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T, U> AsDeviceBoxed<T> for U where
    T: AsBytes + ?Sized,
    U: Borrow<T>, 
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.