Making a WGPU wrapper in common lisp

Common Lisp?

I’ve been eyeing common lisp since about 2012. I started out by reading Land of Lisp and found it way too hard for me at the time. I was still pretty new to programming and hadn’t tried my hand at anything remotely functional or with non C like syntax.

FFI

The eternal struggle when working with C libraries outside of C is FFI. Common Lisp apparently has a pretty solid FFI tool in CFFI, but you need to write all the bindings by hand and I’m lazy. I decided to go with a tool called cl-autowrap to help me generate the bindings I needed.

So how’s it going?

It’s a little rough, though that’s in part to my computer’s kind of weird configuration.

c2ffi (and thus cl-autwrap,) understandably expect some libraries (like a c standard library) to be available but on my first go, one wasn’t easily accessible. This made c2ffi generate bindings with warnings, which I promptly ignored, and resulted in some broken ffi bindings. I expected any serious errors like missing libraries to loudly complain, but this wasn’t the case.

Once I got past my instincts to ignore warnings and sorted out the missing libraries, I discovered another strange gotcha. When c2ffi references glibc, it is unable to generate some bindings that it is able to generate when referencing musl. I’m not really a C developer, and cl-autowrap is designed in such a way that after the bindings are generated, it will work with anything that shares the same C ABI (like musl and glibc) so this is where I stopped digging for now.

After getting past all that, I’m able to call some wgpu functions!!!

Here’s a quick snippet from the code which generates and loads the wgpu-native library

(cl:defpackage :marching-cubes-ffi)
(cl:in-package :marching-cubes-ffi)

(cl:defun rel-path (path)
  (cl:format cl:nil "~a" (cl:merge-pathnames path (uiop:getcwd))))


(cffi:define-foreign-type wgpu-bool (uint32) ())
(cffi:define-foreign-type wgpu-flags (uint32) ())
(autowrap:c-include (rel-path "./ffi/clibs.h")
                    :spec-path "./specs/")

(cffi:define-foreign-library (webgpu :search-path "./ffi/wgpu-native/target/release/")
  (cl:t (:default "libwgpu_native")))
(cffi:use-foreign-library webgpu)

A surprisingly low amount of code, right?

What’s next

Right now I’m trying to get a solid color rendered to a window. For some reason, when trying to create the surface, everything just hangs.

My follow up post will likely be about that and how I fixed it. I think it has to do with the surface descriptor not being correct.

You’ve landed on my blog!

Welcome!

I’ve been a programmer for over 19 years. In that time I’ve worked on games, large frontend projects, enterprise backend products, fun little tools, and generative artwork.

I use this space to talk about projects I’m currently working, show off workshops I intend to give, and rant about life and technology.


By [benbot], 2024-08-11