// HACKER NEWS — CYBERSECURITY
Testing WebGPU data layouts with Facet
When working on GPU compute shaders, it's common to want to share snippets of
configuration data between the host and the shader. Here's a toy example,
adapted from fidget-wgpu:
Thanks to the zerocopy annotations,
we can call as_bytes() and write the configuration data directly into a WebGPU
buffer, which is very convenient!
Unfortunately, there are often subtle difference between Rust and WebGPU's
layout rules. Do you know what's wrong with the above example?
Even more unfortunately, I'm writing bytecode VMs which run in compute
shaders, and their failure mode is often "congrats, your GPU now has
persistently spinning threads which can only be killed by rebooting your
computer".
After debugging the most recent reboot (thanks to the
WGSL offset computer),
I decided to fix the problem in a more systematic way.
There are existing options: wgsl_to_wgpu,
wgsl_bindgen, and
encase are all relevant to the
problem. However, I decided to roll my own to avoid more external dependencies
and build script wrangling. Specifically, I decided to write unit tests,
to add no overhead to a typical build.
(If you want to be pedantic, using unit tests does have a failure mode of
forgetting to test a new configuration object, but I'm not too worried about it)
We can find the WGSL struct layout using naga,
which is already in our dependency tree for shader compilation:
Then, we can cross-check against each member of the struct Config:
In WGSL, each row of a mat3x3 has 4 bytes of padding, so each row is 16 bytes
in total and the whole matrix is 48 bytes. In Rust, a [[f32; 3]; 3] object is
tightly packed and therefore occupies only 36 bytes.