filum

Easy GPGPU with Rust and Vulkan.

Provides a simple yet easy-to-use interface to do some computations actually done in parallel.

Example

Calculating Fibonacci sequence

```rust let context = Context::new().unwrap(); let numelements = 32usize; let view = BufferViewBuilder::new(&context) .bindarray::(numelements) .build() .unwrap(); // prepare compute shader let pipeline = PipelineBuilder::new(view.buffer()) .shader("data/fibonacci.comp.spv") .specialization(constants!(numelements as u32)) .build() .unwrap(); // send data to GPU device let mut v: Vec = (0..numelements as u32) .collect(); let binding = view.binding(); binding.updatearraycopying(&v); // execute computation pipeline.dispatch(numelements); // receive data from GPU device binding.fetcharraycopying(&mut v);

// outputs // [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765, 10946, 17711, 28657, 46368, 75025, 121393, 196418, 317811, 514229, 832040, 1346269] ```

## Features - High-level interface - Type-safe in-out buffer access - Vulkan compute kernel - Multiple layout binding support - Multiple shader stages support - Push constants - Specialization constants

## Another Example

Connected Component Labeling. This is actually an implementation of the algorithm below.

A Parallel Approach to Object Identification in Large-scale Images

https://www.academia.edu/29842500/

```rust let dim = (8usize, 8usize); let table: Vec = vec![ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, ]; let mut table: Vec = table.intoiter() .enumerate() .map(|(i, v)| if v == 0 { -1i32 } else { i as i32 }) .collect(); let len = table.len(); let context = Context::new().unwrap(); let bufferview = BufferViewBuilder::new(&context) .bindarray::(len) .build() .unwrap(); let buffer = bufferview.buffer(); let column = PipelineBuilder::new(buffer) .shader("data/column.comp.spv") .specialization(constants!(dim.0 as u32, dim.1 as u32)) .build() .unwrap(); let merge = PipelineBuilder::new(buffer) .shader("data/merge.comp.spv") .specialization(constants!(dim.0 as u32, dim.1 as u32)) .build() .unwrap(); let relabel = PipelineBuilder::new(buffer) .shader("data/relabel.comp.spv") .build() .unwrap(); let binding = bufferview.binding(); binding.updatearraycopying(&table); // column column.dispatch(dim.0); // merge { let mut stepindex = 0; let mut n = dim.0 >> 1; while n != 0 { println!("n {}, si {}", n, stepindex); let dispatch = DispatchBuilder::new(&merge) .workgroupcount(n, 1, 1) .pushconstants(constants!(stepindex as u32)) .build() .unwrap(); dispatch.dispatch(); n = n >> 1; stepindex += 1; } } // relabel relabel.dispatch(len); binding.fetcharray_copying(&mut table);

// outputs /* -1, -1, -1, -1, -1, -1, -1, -1, -1, 9, 9, -1, 12, 12, 12, -1, -1, 9, 9, -1, 12, 12, 12, -1, 9, 9, 9, -1, -1, -1, -1, 31, -1, 9, 9, 9, -1, -1, -1, 31, -1, -1, -1, -1, -1, 45, 45, -1, -1, 45, -1, 45, 45, 45, 45, -1, -1, 45, 45, 45, -1, -1, -1, -1, */ ```

Performance

Connected component labeling 8K Image

GPU computation took ~210ms including memory transfer operations.

image

Runtime Environment

To compile compute shader GLSL into SPIR-V, we recommend Vulkan SDK to compile with.