<!-- mobian-agent-page publisher="dailydev" canonical="https://daily.dev/posts/testing-webgpu-data-layouts-with-facet-wgh7iqcr3" -->

---
title: Testing WebGPU data layouts with Facet | daily.dev
description: A Rust developer shares a technique for catching WebGPU data layout mismatches between Rust structs and WGSL shader structs before they cause GPU hangs. After...
canonical: https://daily.dev/posts/testing-webgpu-data-layouts-with-facet-wgh7iqcr3
twitter:card: summary_large_image
twitter:site: @dailydotdev
og:type: website
og:site_name: daily.dev
og:title: Testing WebGPU data layouts with Facet | daily.dev
og:description: A Rust developer shares a technique for catching WebGPU data layout mismatches between Rust structs and WGSL shader structs before they cause GPU hangs. After...
og:url: https://daily.dev/posts/testing-webgpu-data-layouts-with-facet-wgh7iqcr3
og:image: https://api.daily.dev/og/posts/WgH7iqCr3.png
og:image:alt: Testing WebGPU data layouts with Facet
og:image:width: 1200
og:image:height: 630
og:locale: en
---

> ## Documentation Index
> Fetch the complete documentation index at: https://daily.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Testing WebGPU data layouts with Facet

**[Matt Keeter](https://daily.dev/sources/mattkeeter)** · 7 min read · 1 upvotes · 0 comments

## Summary

A Rust developer shares a technique for catching WebGPU data layout mismatches between Rust structs and WGSL shader structs before they cause GPU hangs. After hand-writing offset checks using the naga crate to parse WGSL and compare field offsets against Rust's std::mem::offset_of!, the author builds a more robust generic solution using the facet crate's runtime reflection. The resulting compare_struct_layout function automatically checks struct sizes, field offsets, and field sizes between Rust and WGSL definitions, and confirms no fields are missing on either side, including special handling for runtime-sized trailing arrays.

## Full article

daily.dev links to this article rather than hosting it. Read it at the original source: <https://mattkeeter.com/blog/2026-08-23-wgpu-facet>

## Questions this post answers

### why does my WGSL mat3x3 struct field have a different byte offset than my Rust struct field

WGSL pads each row of a mat3x3f to 16 bytes, making the matrix 48 bytes total, while a Rust [[f32; 3]; 3] is tightly packed at 36 bytes. This 12-byte discrepancy shifts the offset of any field placed after the matrix, which is exactly the kind of layout mismatch that silently corrupts GPU buffer data.

_daily.dev surfaces posts like this for developers chasing subtle WebGPU buffer layout bugs._

### how can I automatically test that my Rust struct layout matches my WGSL struct layout

Derive facet::Facet on the Rust struct (conditionally, for tests only) and use naga to parse the WGSL source, then write a generic function that cross-checks each field's offset and size using facet's runtime SHAPE reflection data against naga's parsed struct members, including handling for trailing runtime-sized arrays.

_Developers building CPU-GPU interchange layers track testing patterns like this on daily.dev._

## Similar posts on daily.dev

- [Introducing wgsl-rs](https://daily.dev/posts/introducing-wgsl-rs-ny7e7ryhk) · Lobsters · 4 upvotes · 1 comments
- [Cache-Conscious Data Layout in Rust: Field Zoning, False Sharing, and the 128-Byte Rule](https://daily.dev/posts/cache-conscious-data-layout-in-rust-field-zoning-false-sharing-and-the-128-byte-rule-47ojtsopq) · Hacker News · 0 upvotes · 0 comments
- [Offloading Rust To GPUs Proves Capable Of High Performance With Memory Safety](https://daily.dev/posts/offloading-rust-to-gpus-proves-capable-of-high-performance-with-memory-safety-6ojskq9d9) · Phoronix · 0 upvotes · 0 comments
- [Where Your Bytes Live: Memory Layout in Rust and Java](https://daily.dev/posts/where-your-bytes-live-memory-layout-in-rust-and-java-tjqya8qqa) · Medium · 4 upvotes · 1 comments

---

Tags: [#testing](https://daily.dev/tags/testing), [#rust](https://daily.dev/tags/rust), [#webgpu](https://daily.dev/tags/webgpu)

[View this post on daily.dev](https://daily.dev/posts/testing-webgpu-data-layouts-with-facet-wgh7iqcr3)

```json
{"@context":"https://schema.org","@graph":[{"@type":"Organization","@id":"https://daily.dev/#organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180},"sameAs":["https://twitter.com/dailydotdev","https://github.com/dailydotdev","https://www.linkedin.com/company/daily-dev-ltd"]},{"@type":"WebSite","@id":"https://daily.dev/#website","url":"https://daily.dev","name":"daily.dev","publisher":{"@id":"https://daily.dev/#organization"},"potentialAction":{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https://daily.dev/search?q={search_term_string}"},"query-input":"required name=search_term_string"}}]}
{"@context":"https://schema.org","@type":"TechArticle","headline":"Testing WebGPU data layouts with Facet","url":"https://daily.dev/posts/testing-webgpu-data-layouts-with-facet-wgh7iqcr3","mainEntityOfPage":{"@type":"WebPage","@id":"https://daily.dev/posts/testing-webgpu-data-layouts-with-facet-wgh7iqcr3"},"datePublished":"2026-08-23T13:10:26.198Z","dateModified":"2026-09-14T07:31:49.832Z","description":"A Rust developer shares a technique for catching WebGPU data layout mismatches between Rust structs and WGSL shader structs before they cause GPU hangs. After...","image":"https://media.daily.dev/image/upload/s--HRgLpUt6--/f_auto/v1722860399/public/Placeholder%2003","thumbnailUrl":"https://media.daily.dev/image/upload/s--HRgLpUt6--/f_auto/v1722860399/public/Placeholder%2003","isAccessibleForFree":true,"articleSection":"Matt Keeter","inLanguage":"en","publisher":{"@type":"Organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180}},"author":{"@type":"Organization","name":"Matt Keeter","logo":"https://media.daily.dev/image/upload/logos/placeholder.jpg","url":"https://daily.dev/sources/mattkeeter"},"commentCount":0,"discussionUrl":"https://daily.dev/posts/testing-webgpu-data-layouts-with-facet-wgh7iqcr3","interactionStatistic":[{"@type":"InteractionCounter","interactionType":{"@type":"LikeAction"},"userInteractionCount":1},{"@type":"InteractionCounter","interactionType":{"@type":"CommentAction"},"userInteractionCount":0}],"keywords":"testing,rust,webgpu","timeRequired":"PT7M"}
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https://daily.dev"},{"@type":"ListItem","position":2,"name":"Matt Keeter","item":"https://daily.dev/sources/mattkeeter"},{"@type":"ListItem","position":3,"name":"Testing WebGPU data layouts with Facet"}]}
{"@context":"https://schema.org","@type":"FAQPage","@id":"https://daily.dev/posts/testing-webgpu-data-layouts-with-facet-wgh7iqcr3#faq","mainEntity":[{"@type":"Question","name":"why does my WGSL mat3x3 struct field have a different byte offset than my Rust struct field","acceptedAnswer":{"@type":"Answer","text":"WGSL pads each row of a mat3x3f to 16 bytes, making the matrix 48 bytes total, while a Rust [[f32; 3]; 3] is tightly packed at 36 bytes. This 12-byte discrepancy shifts the offset of any field placed after the matrix, which is exactly the kind of layout mismatch that silently corrupts GPU buffer data. daily.dev surfaces posts like this for developers chasing subtle WebGPU buffer layout bugs."}},{"@type":"Question","name":"how can I automatically test that my Rust struct layout matches my WGSL struct layout","acceptedAnswer":{"@type":"Answer","text":"Derive facet::Facet on the Rust struct (conditionally, for tests only) and use naga to parse the WGSL source, then write a generic function that cross-checks each field's offset and size using facet's runtime SHAPE reflection data against naga's parsed struct members, including handling for trailing runtime-sized arrays. Developers building CPU-GPU interchange layers track testing patterns like this on daily.dev."}}]}
```

