docs: Add destructuring objects to docs and examples - #2926
Conversation
There was a problem hiding this comment.
Pull request overview
Updates the TypeGPU docs and example shaders to use JavaScript/TypeScript destructuring when reading struct-like GPU values (buffers/uniforms/layout accessors), and refreshes the example snapshot tests to match the new generated WGSL.
Changes:
- Refactor multiple examples to destructure fields from storage/uniform/layout-backed values for cleaner shader code.
- Update the compute-shaders fundamentals doc snippets to demonstrate destructuring-based access.
- Update individual example snapshot tests (inline WGSL) to reflect the new access/destructuring patterns in generated shader code.
Reviewed changes
Copilot reviewed 12 out of 12 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| apps/typegpu-docs/tests/individual-example-tests/slime-mold.test.ts | Updates WGSL snapshot to match destructured agent/params access and reordered Params declaration. |
| apps/typegpu-docs/tests/individual-example-tests/phong-reflection.test.ts | Updates WGSL snapshot to match destructured example controls access and variable naming (specularExponent). |
| apps/typegpu-docs/tests/individual-example-tests/confetti.test.ts | Updates WGSL snapshot to match destructured particle data access and resulting binding/layout output. |
| apps/typegpu-docs/tests/individual-example-tests/circles.test.ts | Updates WGSL snapshot to match destructured circle instance data access. |
| apps/typegpu-docs/src/examples/simulation/slime-mold/index.ts | Uses destructuring for agent state and params within the compute update step. |
| apps/typegpu-docs/src/examples/simulation/confetti/index.ts | Uses destructuring for per-particle seed/velocity in compute pipeline. |
| apps/typegpu-docs/src/examples/rendering/phong-reflection/index.ts | Uses destructuring for ambient/specular-related controls in fragment shader. |
| apps/typegpu-docs/src/examples/geometry/circles/index.ts | Uses destructuring for per-instance position/radius in vertex shader. |
| apps/typegpu-docs/src/examples/algorithms/jump-flood-distance/index.ts | Uses destructuring for brush uniform parameters in the seed-drawing pipeline. |
| apps/typegpu-docs/src/examples/algorithms/genetic-racing/index.ts | Refactors car state reads into a destructured local set of simulation variables. |
| apps/typegpu-docs/src/examples/algorithms/genetic-racing/ga.ts | Uses destructuring for fitness computation inputs (progress, aliveSteps). |
| apps/typegpu-docs/src/content/docs/fundamentals/compute-shaders.mdx | Updates documentation examples to show destructuring for particle position/velocity. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
There was a problem hiding this comment.
ℹ️ Minor suggestions only — nothing blocking.
Reviewed changes
- compute-shaders.mdx — both
simulatesnippets now destructure{ position, velocity }off the storage accessor instead of holding aparticlelocal. - 7 example shader files (genetic-racing
ga.ts/index.ts, jump-flood-distance, circles, phong-reflection, confetti, slime-mold) — property locals replaced with destructuring, including renames (angle: startAngle,angle: curAngle) and ad.vec2f()-wrappedposition. - 4 individual-example tests — inline WGSL snapshots regenerated to match the new destructuring codegen.
I ran the four updated example tests (circles, confetti, phong-reflection, slime-mold); all pass, confirming the destructured snippets compile and the snapshots match actual compiler output. Two rough edges worth a look, both cosmetic.
DeepSeek Flash (free via Pullfrog for OSS) | 𝕏
| let curAliveSteps = initCar.aliveSteps; | ||
| let curStallSteps = initCar.stallSteps; | ||
| const car = CarState(simLayout.$.state[i]); | ||
| let curPosition = d.vec2f(car.position); |
There was a problem hiding this comment.
Slight inconsistency: curPosition is lifted from car.position directly, while every other field is destructured with a rename in the block below. Since the point of this PR is showcasing destructuring, consider destructuring position too — e.g. const { position, angle: curAngle, speed: curSpeed, ... } = car; then let curPosition = d.vec2f(position);. Purely cosmetic.
| @group(0) @binding(2) var<storage, read_write> particleDataBuffer: array<ParticleData, 200>; | ||
| @group(0) @binding(1) var<storage, read_write> particleDataBuffer: array<ParticleData, 200>; | ||
|
|
||
| @group(0) @binding(2) var<uniform> time: f32; |
There was a problem hiding this comment.
FYI: the destructured rewrite reordered the generated bindings — time moved from @binding(1) to @binding(2) and the storage particleDataBuffer from @binding(2) to @binding(1). Semantically harmless (the pipeline layout resolves against the codegen labels and reorders the same way), but worth being aware that introducing a destructure here changed binding numbering.
Resolution Time Benchmark---
config:
themeVariables:
xyChart:
plotColorPalette: "#E63946, #3B82F6, #059669"
---
xychart
title "Random Branching (🔴 PR | 🔵 main | 🟢 release)"
x-axis "max depth" [1, 2, 3, 4, 5, 6, 7, 8]
y-axis "time (ms)"
line [0.81, 1.52, 3.00, 4.37, 5.53, 9.70, 16.84, 19.19]
line [0.66, 1.23, 2.83, 4.57, 5.76, 8.02, 16.16, 18.03]
line [0.72, 1.41, 2.93, 4.50, 5.43, 8.01, 17.05, 15.51]
---
config:
themeVariables:
xyChart:
plotColorPalette: "#E63946, #3B82F6, #059669"
---
xychart
title "Linear Recursion (🔴 PR | 🔵 main | 🟢 release)"
x-axis "max depth" [1, 2, 3, 4, 5, 6, 7, 8]
y-axis "time (ms)"
line [0.21, 0.37, 0.54, 0.58, 0.80, 0.86, 1.08, 1.20]
line [0.24, 0.41, 0.52, 0.59, 0.80, 0.77, 0.91, 1.06]
line [0.22, 0.34, 0.46, 0.56, 0.87, 0.87, 1.20, 1.15]
---
config:
themeVariables:
xyChart:
plotColorPalette: "#E63946, #3B82F6, #059669"
---
xychart
title "Full Tree (🔴 PR | 🔵 main | 🟢 release)"
x-axis "max depth" [1, 2, 3, 4, 5, 6, 7, 8]
y-axis "time (ms)"
line [0.71, 1.76, 2.70, 5.82, 9.88, 17.83, 40.17, 82.13]
line [0.77, 1.74, 2.40, 5.27, 8.81, 18.34, 39.73, 79.99]
line [0.60, 1.77, 2.52, 5.24, 8.48, 18.15, 42.33, 79.35]
|
Bundle size comparison (
|
| 🟢 Decreased | ➖ Unchanged | 🔴 Increased (max 1.34%) | ❔ Unknown |
|---|---|---|---|
| 0 | 302 | 23 | 0 |
import * as ... in PR vs import * as ... in target (did bundle size increase?):
| Test | tsdown |
|---|---|
| common_fullScreenTriangle.ts | 42.88 kB ( |
| STATIC_common.ts | 59.64 kB ( |
import { ... } in PR vs import * as ... in PR (is the library tree-Shakeable?):
| Test | tsdown |
|---|---|
| tgpu_init.ts | 264.40 kB ( |
| tgpu_initFromDevice.ts | 263.86 kB ( |
| tgpu_resolve.ts | 163.06 kB ( |
| tgpu_resolveWithContext.ts | 163.00 kB ( |
| tgpu_bindGroupLayout.ts | 62.32 kB ( |
| tgpu_mutableAccessor.ts | 57.61 kB ( |
| tgpu_accessor.ts | 57.61 kB ( |
| tgpu_privateVar.ts | 55.73 kB ( |
| tgpu_workgroupVar.ts | 55.73 kB ( |
| tgpu_const.ts | 55.15 kB ( |
| tgpu_lazy.ts | 54.95 kB ( |
| tgpu_fragmentFn.ts | 40.25 kB ( |
| tgpu_fn.ts | 40.19 kB ( |
| tgpu_vertexFn.ts | 40.06 kB ( |
| tgpu_computeFn.ts | 39.77 kB ( |
| tgpu_vertexLayout.ts | 28.33 kB ( |
| tgpu_comptime.ts | 15.93 kB ( |
| tgpu_unroll.ts | 1.75 kB ( |
| tgpu_slot.ts | 1.70 kB ( |
If you wish to run a comparison for other, slower bundlers, run the 'Tree-shake test' from the GitHub Actions menu.
|
pkg.pr.new packages benchmark commit |

No description provided.