[−][src]Struct emu_core::compile_impls::GlslKernel
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]
self,
left_hand: impl Into<String>,
right_hand: impl Into<String>
) -> Self
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]
fn compile_to_spirv(src: GlslKernel) -> Result<Spirv<Vec<u32>>, CompileError>
[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]
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>,