Skip to main content
◆ Article

WebGPU vs TypeGPU Interactive Comparison

Interactive live demos that lay bare the real differences between the two in GPU execution performance, developer experience, and type safety — performance is exactly identical; the gap is all in engineering efficiency.

WebGPU TypeGPU WGSL Interactive Demo
[ 00 ]

Contents

Jump straight to a section.

  • 7 sections

Chrome 113+ / Edge 113+ / Safari 17+ is required to experience the live GPU demos; the memory layout, code comparison and performance chart remain fully interactive even without WebGPU support.

[ 01 ]

Key Insights

GPU execution performance is exactly identical; the real differences are in developer efficiency, type safety and memory layout management.

TypeGPU is a type-safe layer built on top of WebGPU, and the two deliver exactly the same GPU execution performance — because TypeGPU compiles TypeScript to WGSL at build time and calls the native WebGPU API directly at runtime. The real differences show up in development efficiency, type safety, and memory layout management. Every demo on this page runs live in the browser; drag the sliders and switch modes to verify it yourself.

Key insight: GPU execution performance is exactly the same for both; the differences lie in development efficiency, type safety and memory layout management.
[ 02 ]

Live Rendering Comparison

Drag the sliders and switch demo modes: both canvases render the same particle system in parallel, and the readouts refresh every frame.

LIVE GPU One Particle struct · two independent canvases
50,000
5x
Demo mode
Native WebGPU Hand-written WGSL + manual layout
60
FPS
0.8
GPU time · ms / frame
2.1
CPU cost · ms / frame
12
VRAM usage · MB
TypeGPU TypeScript + automatic layout
60
FPS
0.8
GPU time · ms / frame
0.4
CPU cost · ms / frame
12
VRAM usage · MB
[ 03 ]

Memory Layout Comparison

One and the same Particle struct: one side computes offset and stride by hand, the other is aligned automatically by typed-binary.

INTERACTIVE Click a button to change the field order and watch the manual layout offsets fall apart

Click the buttons to change the struct field order and see how error-prone manual layout is. A vec3f actually occupies 16 bytes (including 4 bytes of padding)!

WebGPU: offsets computed by hand
position (vec3f)
color (vec3f)
velocity (vec2f)
padding (wasted)
TypeGPU: declarative automatic layout
position (vec3f)
color (vec3f)
velocity (vec2f)
padding (auto-optimized)
The layout is always correct! TypeGPU's typed-binary computes every offset, stride and piece of padding automatically, and the WGSL struct definition is generated in sync. Change the Schema in one place and the whole project updates automatically.
  • [*]WGSL structhand-written string / generated from types
  • [*]offset and stridemanual / inferred automatically
  • [*]vec3f alignment16 bytes (incl. padding)
  • [*]field order changeedit 3 places / edit 1 place
  • [*]when errors surfaceruntime glitch / compile-time error
[ 04 ]

Live Code Complexity Comparison

Two ways to write the same feature: shader, pipeline setup and memory layout compared side by side.

INTERACTIVE Switching tabs only swaps the panel contents; it does not re-create the demo

Same functionality: native WebGPU takes about 142 lines of effective code, TypeGPU about 48. Switch tabs to compare how the shader, pipeline setup and memory layout are written.

WebGPU implementation ~142 lines of effective code
TypeGPU implementation ~48 lines of effective code
Effective lines of code for the same feature 142 → 48 ▼ 66%
Developer efficiency gain 3× ▲ 3.0×
Offsets maintained by hand 3 → 0 −3
[ 05 ]

GPU Execution Performance History (proving both perform identically)

As the particle count grows, the GPU execution time curves of WebGPU and TypeGPU overlap perfectly.

LIVE The curve is sampled and drawn live by the page

As the particle count grows, the GPU execution time curves of WebGPU and TypeGPU overlap perfectly, proving that TypeGPU's runtime performance is identical to native WebGPU's. The only difference shows up in CPU-side development efficiency.

Throughput and overhead

RATIO
GPU execution time · WebGPU 0.8 ms / frame
GPU execution time · TypeGPU 0.8 ms / frame
CPU cost · WebGPU 2.1 ms / frame
CPU cost · TypeGPU 0.4 ms / frame
GPU execution time · identical on both sides 0.8 ms ≈ 0
CPU cost ms / frame 2.1 → 0.4 ▼ 81%
[ 06 ]

Shader Code Walkthrough

The shaders running live on this page: hand-written WGSL on the WebGPU side, the same WGSL compiled from TypeScript on the TypeGPU side.

wgsl particle.compute.wgsl

      struct Particle {  pos: vec2f, vel: vec2f, color: vec3f, life: f32,}; @binding(0) @group(0) var<storage, read_write> particles: array<Particle>;@binding(1) @group(0) var<uniform> params: vec4f; @compute @workgroup_size(64)fn computeMain(@builtin(global_invocation_id) id: vec3u) {  let idx = id.x; let count = u32(params.x);  if (idx >= count) { return; }  var p = particles[idx];  let dt = params.y; let load = u32(params.z); let mode = u32(params.w);  if (mode == 0u) {    p.pos = p.pos + p.vel * dt;    p.vel.y = p.vel.y - 0.5 * dt;    if (p.pos.y < -1.0) { p.pos.y = -1.0; p.vel.y = p.vel.y * -0.8; }    if (p.pos.x < -1.0 || p.pos.x > 1.0) { p.vel.x = p.vel.x * -0.9; p.pos.x = clamp(p.pos.x, -1.0, 1.0); }  } else if (mode == 1u) {    let dir = vec2f(0.0, 0.0) - p.pos;    let dist = length(dir);    if (dist > 0.01) { p.vel = p.vel + normalize(dir) * 3.0 * dt; }    p.pos = p.pos + p.vel * dt; p.vel = p.vel * 0.995;  } else {    p.pos = p.pos + p.vel * dt; p.vel = p.vel * 0.999;    if (length(p.pos) > 1.0) { p.vel = p.vel * -0.95; p.pos = normalize(p.pos) * 0.98; }  }  var dummy = 0.0;  for (var i = 0u; i < load; i = i + 1u) { dummy = dummy + sin(f32(i) * 0.01 + p.pos.x) * 0.0001; }  p.pos.x = p.pos.x + dummy;  p.life = p.life - dt * 0.15;  if (p.life <= 0.0) {    p.life = 1.0; let seed = f32(idx);    p.pos = vec2f(fract(sin(seed * 12.9898) * 43758.5453) * 2.0 - 1.0, fract(sin(seed * 78.233) * 43758.5453) * 2.0 - 1.0);    p.vel = vec2f(fract(sin(seed * 43.123) * 23421.0) * 2.0 - 1.0, fract(sin(seed * 91.456) * 12345.0) * 2.0 - 1.0) * 0.5;  }  particles[idx] = p;}
  
wgsl particle.render.wgsl

      struct VertexOut {  @builtin(position) pos: vec4f,  @location(0) color: vec3f,  @location(1) life: f32,}; @vertexfn vertexMain(@location(0) pos: vec2f, @location(1) vel: vec2f, @location(2) color: vec3f, @location(3) life: f32) -> VertexOut {  var out: VertexOut; out.pos = vec4f(pos, 0.0, 1.0); out.color = color; out.life = life; return out;} @fragmentfn fragmentMain(@location(0) color: vec3f, @location(1) life: f32) -> @location(0) vec4f {  let alpha = smoothstep(0.0, 0.2, life); return vec4f(color * (0.5 + life * 0.5), alpha * 0.9);}
  
  • [*]particle buffer32 bytes / vertex
  • [*]attributespos · vel · color · life
  • [*]workgroup64 invocations
  • [*]compute pass1 dispatch / frame
  • [*]topologypoint-list
[ 07 ]

Core Conclusions

Identical performance, types moved to compile time, three times the efficiency — the whole gap lands on the engineering side.

GPU performance: exactly identical

TypeGPU compiles TypeScript to WGSL at build time and calls the native WebGPU API directly at runtime. GPU execution performance is exactly the same as native WebGPU, with zero extra overhead. The two overlapping curves in the chart above prove it.

Type safety: caught at compile time

TypeGPU eliminates the type gap between JS and WGSL. Buffer types, shader parameters and memory layout are validated at compile time, so errors are caught while you write code — instead of surfacing at runtime as strange visual glitches.

Development efficiency: 3x faster

For the same functionality, TypeGPU cuts the amount of code by over 60%. No offsets to compute by hand, no WGSL strings to maintain, no memory-alignment traps to worry about. Any TypeScript developer on the team can take part in GPU programming.

Related articles

Other long reads in the same layout: a design-system rework, a player embed and an Android teardown.
Comments Leave your thoughts
Guide