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.
- OS: Ubuntu 18.04 LTS
- CPU: Intel(R) Core(TM) i7-3930K CPU @ 3.20GHz
- GPU: NVIDIA GeForce RTX 2070

Runtime Environment
- Requires Vulkan 1.1 Runtime
- Vulkan 1.1 supported Graphics Driver
To compile compute shader GLSL into SPIR-V, we recommend Vulkan SDK to compile with.