Skip to content

Commit 6b125cb

Browse files
authored
docs: WESL Interoperability guide (#1046)
1 parent eebefdd commit 6b125cb

File tree

2 files changed

+143
-0
lines changed

2 files changed

+143
-0
lines changed

apps/typegpu-docs/astro.config.mjs

+4
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,10 @@ export default defineConfig({
125125
label: 'WebGPU Interoperability',
126126
slug: 'integration/webgpu-interoperability',
127127
},
128+
{
129+
label: 'WESL Interoperability',
130+
slug: 'integration/wesl-interoperability',
131+
},
128132
{
129133
label: 'Working with wgpu-matrix',
130134
slug: 'integration/working-with-wgpu-matrix',
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
---
2+
title: WESL Interoperability
3+
---
4+
5+
:::caution[In development]
6+
This functionality is under **heavy** development. This guide acts mostly as a Northern Star for the functionality we would
7+
like to achieve. If you'd like to follow the development, join our Discord server!
8+
:::
9+
10+
We are working with [WESL](https://wesl-lang.dev), a community standard for enhanced WGSL, to enable
11+
hybrid programs that mix-and-match between *shader-centric* and *host-centric* approaches. Shaders written in
12+
WGSL or [WESL](https://wesl-lang.dev) can be reflected into JS/TS as TypeGPU definitions, with proper types
13+
generated on the fly.
14+
15+
- ✨ Take advantage of type-safe buffers while keeping your shaders in WESL
16+
- ⚔️ Eliminate manual byte alignment and padding
17+
18+
## Setting up
19+
20+
This functionality is provided as an extension to [`wesl-plugin`](https://wesl-lang.dev/docs/Getting-Started-JavaScript).
21+
Consult their documentation on what to install, and how to use it with your bundler of choice.
22+
23+
Our official [`wesl-ext-typepgu`](https://github.com/software-mansion-labs/wesl-ext-typegpu) package extends the capabilities of `wesl-plugin`.
24+
Install it before proceeding.
25+
26+
import { Tabs, TabItem } from '@astrojs/starlight/components';
27+
28+
<Tabs syncKey="package-manager">
29+
<TabItem label="npm" icon="seti:npm">
30+
```sh frame=none
31+
npm add --save-dev wesl-ext-typegpu
32+
```
33+
</TabItem>
34+
<TabItem label="pnpm" icon="pnpm">
35+
```sh frame=none
36+
pnpm add -D wesl-ext-typegpu
37+
```
38+
</TabItem>
39+
<TabItem label="yarn" icon="seti:yarn">
40+
```sh frame=none
41+
yarn add -D wesl-ext-typegpu
42+
```
43+
</TabItem>
44+
</Tabs>
45+
46+
Next up, reference the extension in your bundler's configuration. Below is an example using Vite.
47+
48+
```ts {4, 7} "typegpuExtension"
49+
import { defineConfig } from "vite";
50+
import weslPlugin from "wesl-plugin/vite";
51+
import { linkBuildExtension } from "wesl-plugin";
52+
import { typegpuExtension } from "wesl-ext-typegpu";
53+
54+
export default defineConfig({
55+
plugins: [weslPlugin({ extensions: [linkBuildExtension, typegpuExtension] })],
56+
});
57+
```
58+
59+
And finally, to let the TypeScript language server know where to look for typing of the
60+
.wgsl/.wesl you're importing, change the following in your tsconfig.json:
61+
62+
```json
63+
{
64+
// ...
65+
"include": [/* all other files you're including */, ".wesl/types"]
66+
// ...
67+
}
68+
```
69+
70+
## Reflection
71+
72+
Let's say we have to following shader program, split across two files.
73+
74+
```wgsl title="shaders/shared.wesl"
75+
struct BoidState {
76+
position: vec3f,
77+
velocity: vec3f,
78+
}
79+
80+
struct Fish {
81+
kind: u32,
82+
state: BoidState,
83+
}
84+
```
85+
86+
```wgsl title="shaders/main.wesl"
87+
use package::shared::Fish;
88+
89+
@group(0) @binding(0) var<storage, read_write> fish: array<Fish>;
90+
91+
@compute @workgroup_size(32)
92+
fn main() {
93+
// ...
94+
}
95+
```
96+
97+
Given a shader written in WGSL/WESL, we can use the `?typegpu` query parameter to import
98+
reified references to any struct definition.
99+
100+
```ts twoslash title="main.ts"
101+
// @filename ./mock-imports.ts
102+
// @noErrors
103+
// ---cut---
104+
// Importing a WGSL struct into JS
105+
import { Fish } from './shaders/shared.wesl?typegpu';
106+
// ---cut-start---
107+
// @filename: ./main.ts
108+
import tgpu from 'typegpu';
109+
import * as d from 'typegpu/data';
110+
const root = await tgpu.init();
111+
const BoidState = d.struct({
112+
position: d.vec3f,
113+
velocity: d.vec3f,
114+
});
115+
116+
const Fish = d.struct({
117+
kind: d.u32,
118+
state: BoidState,
119+
});
120+
// ---cut-end---
121+
122+
const FishArray = (n: number) => d.arrayOf(Fish, n);
123+
124+
const buffer = root.createBuffer(FishArray(512)).$usage('storage');
125+
// ^?
126+
127+
// Updating the 123rd fish's position
128+
buffer.writePartial([
129+
{
130+
idx: 123,
131+
value: {
132+
state: {
133+
posit
134+
// ^|
135+
},
136+
}
137+
}
138+
]);
139+
```

0 commit comments

Comments
 (0)