calebwin / emu

The write-once-run-anywhere GPGPU library for Rust
https://calebwin.github.io/emu
MIT License
1.59k stars 53 forks source link

How to pass a 2D array of floats? #61

Closed wbrickner closed 2 years ago

wbrickner commented 2 years ago

How can I pass a 2D array of floats?

Preparing any sort of DeviceBox from a Vec<Vec<f32>> is a no-go it seems.

The dimensions of the vector are compile-time constants from the perspective of GLSL (they get formatted in). The dimensions are determined at runtime on the rust side.

Can I just flatten into a single buffer and the GLSL code won't notice?

wbrickner commented 2 years ago

Solved. This will work:

futures::executor::block_on(assert_device_pool_initialized());

let c = compile::<GlslKernel, GlslKernelCompile, Vec<u32>, GlobalCache>(
  GlslKernel::new()
    .param_mut::<[f32], _>(&format!("float[6][12] md"))
    .with_kernel_code(
      "
      for (int j = 0; j < 12; j++) {
        md[gl_GlobalInvocationID.x][j] = float(gl_GlobalInvocationID.x);
      }
      "
    )
)?.finish()?;

let mut md: DeviceBox<[f32]> = vec![0.; 6 * 12].as_device_boxed_mut()?;
unsafe { spawn(6).launch(call!(c.clone(), &mut md))?; }

let result = futures::executor::block_on(md.get())?;
for row in result.chunks(12) {
  println!("{:?}", row);
}

Prints:

[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]
[2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0]
[3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0]
[4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0]
[5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0]
calebwin commented 2 years ago

Awesome! Glad you got this to work! I'm not actively developing emu but I'm happy to review and merge PRs.

PS. - I'd be curious to hear what you're using emu for.