DTolm / VkFFT

Vulkan/CUDA/HIP/OpenCL/Level Zero/Metal Fast Fourier Transform library
MIT License
1.52k stars 90 forks source link

[Announcement] Rust bindings for VkFFT #28

Open bmcdorman opened 3 years ago

bmcdorman commented 3 years ago

Hi,

I've put together some Rust bindings for VkFFT. You can find it here. It's certainly incomplete (particularly in documentation, examples, and safety guarantees), but I think it's close enough for other people to get some use from. Hopefully I'll be able to keep giving it some love for a while.

It assumes the Vulkan backend is used. Unfortunately the other backends would probably be best expressed through completely separate bindings. It further assumes vulkano (idiomatic Rust bindings for Vulkan) is also used.

I've appended a snippet of the first kernel FFT from sample_9 to give you a taste of the API.

Thanks for creating VkFFT!

// Configure kernel FFT
let config = Config::builder()
  .physical_device(context.physical)
  .device(context.device.clone())
  .fence(&context.fence)
  .queue(context.queue.clone())
  .buffer(kernel.clone())
  .command_pool(context.pool.clone())
  .kernel_convolution()
  .normalize()
  .coordinate_features(2)
  .batch_count(2)
  .r2c()
  .disable_reorder_four_step()
  .dim(&[32, 32])
  .build()?;

// Allocate a command buffer
let cmd_buffer = context.alloc_primary_cmd_buffer()?;

// Create command buffer handle
let builder =
  unsafe { UnsafeCommandBufferBuilder::new(&cmd_buffer, Kind::primary(), Flags::None)? };

// Configure FFT launch parameters
let mut params = LaunchParams::builder()
  .command_buffer(&builder)
  .build()?;

// Construct FFT "Application"
let mut app = App::new(config)?;

// Run forward FFT
app.forward(&mut params)?;

// Dispatch command buffer and wait for completion
let cmd_buffer = builder.build()?;
context.submit(cmd_buffer)?;
DTolm commented 3 years ago

Hello,

That's great to hear! Most certainly it will be useful for some people in the future. I will add the link to your repo to the description in the next update. If you have some thoughts/questions about VkFFT you encountered during the development - feel free to share them!

Best regards, Dmitrii Tolmachev

bmcdorman commented 3 years ago

Great! There were some things that could've made the process easier, but they're all from a code perspective. Functionality and performance are superb.

I'm still working through some parts of the implementation, so I'll keep you posted as questions arise!

Thanks again!

DTolm commented 3 years ago

Thank you for your response! I will briefly go over your suggestions:

Best regards, Dmitrii Tolmachev

bmcdorman commented 3 years ago

Thanks for the information! I'll probably require the buffers are specified in the LaunchParams. Retaining the original performance characteristics of the core library is a priority for us. In regards to the single header, I understand the appeal... perhaps as a part of the compilation process a single "amalgamated" header could be produced? I think that might strike the right balance between ease-of-use and implementation organization. I understand that's probably not a priority regardless, but thought I'd throw it out there.

In regards to the functions being static, one approach might be something like dr_wav does. They have a preprocessor define that determines if the implementations are included or just the prototypes (e.g., #define DR_WAV_IMPLEMENTATION). That said, the rewriting method we're using will suffice.

DTolm commented 3 years ago

Code organization improvement is a continuous process in VkFFT. Originally, I had over 100k lines of Vulkan static shaders (version 1.1.0) covering only a fraction of functionality that it is there today. The run-time generation solved this but if I started writing in it from the beginning - I probably would not have finished at all. The performance and features are the main driving force for me - and this is what really matters to the majority of users. Rest will come along with time.

I already have #define VKFFT_H and it will probably suffice to the need of static keyword (it will disable any further inclusions), though I have not tested it much. I just went with the safest way for now.