Data Schemas
Writing a GPU program usually involves sharing data between the host (CPU) and the device (GPU), in this case between JavaScript and WGSL.
Any misalignments or misinterpretations of data can lead to bugs that are hard to debug (No console.log
on the GPU, I am afraid).
While data is strongly typed in WGSL shaders, we give up that type safety completely when writing and reading data in JavaScript/TypeScript.
This is precisely what TypeGPU data types help with.
Examples
Let’s look at some examples of defining custom data types using the typegpu/data
module. If you’re familiar with Zod, then this style of schema definitions may already seem familiar.
By defining the Circle
struct in TypeScript via TypeGPU, in a similar way to how we would in WGSL, we gain access to its TypeScript type
definition, which we can use to validate our data values. When reading from or writing data to the GPU, the type of the JavaScript value
is inferred automatically, and it’s enforced by TypeScript. Thanks to that, whenever we mistakenly set or assume a wrong value for an object,
we get a type error, avoiding unnecessary debugging afterwards. That’s a big improvement to the development process.
Defined data structures automatically measure and hold information about their memory layout parameters, which is useful for writing to and reading data from the GPU.
TypeGPU data types are essential for the library’s automated data marshalling capabilities.
Scalars, Vectors & Matrices
There are a few ways to categorize numeric data-types in TypeGPU.
- Characteristic (floating-point
f
, signed inti
, unsigned intu
). - Size in bits (8, 16, 32).
- Number of components (1, 2, 3, 4, …).
d.f32
, d.i32
and d.u32
all represent single-component 32-bit numeric values. When reading/writing values
in JS, they are all seen as just number
.
Vectors (d.vec2f
, d.vec3f
, …) are interpreted in JS as special objects, which can be created by “calling” the schema
with numeric components, e.g.:
Matrices work in a similar way.
For a comprehensive list of all available schemas, see the Data Schema Cheatsheet.
Structs
Values of different types can be grouped into structs.
Struct schemas adjust the padding and alignment automatically, so that they comply with WebGPU’s memory alignment rules.
It is also possible to override default byte alignment and size for particular fields via the align
and size
functions.
Arrays
To define arrays of known constant length, use the d.arrayOf
function. It accepts as arguments the array’s elements data type constructor and the length of the array.