Getting Started

Get up and running with ralph-gpu in minutes.

Installation

Install ralph-gpu using your preferred package manager:

Bash
npm install ralph-gpu
# or
pnpm add ralph-gpu

For better TypeScript support, also install WebGPU types:

Bash
# Optional but recommended for TypeScript
npm install -D @webgpu/types

Browser Support

WebGPU is a modern API and requires a compatible browser:

✅ Supported

  • Chrome 113+ (desktop)
  • Chrome 121+ (Android)
  • Edge 113+
  • Safari 17+ (macOS Sonoma, iOS 17)

⚠️ Limited

  • Firefox Nightly (behind flag)
  • Older browser versions

Warning

Always check gpu.isSupported() before initializing to handle unsupported browsers gracefully.

Basic Setup

Here's how to properly initialize ralph-gpu with error handling:

TypeScript
import { gpu, WebGPUNotSupportedError } from "ralph-gpu";
 
// Always check support first
if (!gpu.isSupported()) {
  console.log('WebGPU not supported');
  // Show fallback UI
  return;
}
 
try {
  const ctx = await gpu.init(canvas, {
    dpr: Math.min(window.devicePixelRatio, 2), // Limit pixel ratio
    debug: true // Enable debug logs
  });
} catch (e) {
  if (e instanceof WebGPUNotSupportedError) {
    // Browser doesn't support WebGPU
  }
}

Your First Shader

Let's create a simple animated gradient shader. This demonstrates the basics of creating a pass and running an animation loop:

TypeScript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import { gpu } from "ralph-gpu";
 
const canvas = document.querySelector('canvas')!;
const ctx = await gpu.init(canvas);
 
// Create a simple gradient shader
const gradient = ctx.pass(`
  @fragment
  fn main(@builtin(position) pos: vec4f) -> @location(0) vec4f {
    let uv = pos.xy / globals.resolution;
    return vec4f(uv, sin(globals.time) * 0.5 + 0.5, 1.0);
  }
`);
 
// Animation loop
function frame() {
  gradient.draw();
  requestAnimationFrame(frame);
}
frame();

What's happening here?

  • Line 7: We create a pass — a fullscreen fragment shader.
  • Line 10: globals.resolution gives us the canvas size.
  • Line 11: globals.time is automatically updated each frame.
  • Line 17: draw() renders the shader to the screen.

React Integration

Here's a complete React component with proper initialization, cleanup, and resize handling:

ShaderCanvas.tsx
import { useEffect, useRef } from "react";
import { gpu, GPUContext, Pass } from "ralph-gpu";
 
function ShaderCanvas() {
  const canvasRef = useRef<HTMLCanvasElement>(null);
 
  useEffect(() => {
    let ctx: GPUContext | null = null;
    let pass: Pass;
    let animationId: number;
    let disposed = false;
 
    async function init() {
      if (!canvasRef.current || !gpu.isSupported()) return;
 
      // Recommended: autoResize handles sizing and DPR automatically
      ctx = await gpu.init(canvasRef.current, {
        autoResize: true,
      });
 
      if (disposed) {
        ctx.dispose();
        return;
      }
 
      pass = ctx.pass(`
        @fragment
        fn main(@builtin(position) pos: vec4f) -> @location(0) vec4f {
          let uv = pos.xy / globals.resolution;
          return vec4f(uv, sin(globals.time) * 0.5 + 0.5, 1.0);
        }
      `);
 
      function frame() {
        if (disposed) return;
        pass.draw();
        animationId = requestAnimationFrame(frame);
      }
      frame();
    }
 
    init();
 
    return () => {
      disposed = true;
      cancelAnimationFrame(animationId);
      ctx?.dispose();
    };
  }, []);
 
  return <canvas ref={canvasRef} style={{ width: "100%", height: "100%" }} />;
}
 
export default ShaderCanvas;

Note

Key patterns:
  • • Use a disposed flag to prevent rendering after unmount
  • • Clean up with ctx.dispose() in the effect cleanup
  • • Use autoResize: true to handle canvas sizing and DPR automatically

Common Setup Issues

❓ Canvas is blank

Make sure you're calling draw() in a loop with requestAnimationFrame. Also check that the canvas has explicit dimensions.

❓ WebGPU not supported error

Check your browser version. Chrome 113+ and Safari 17+ are required. On Firefox, WebGPU must be enabled in about:config.

❓ Shader compilation errors

WGSL is strictly typed. Make sure all variables have explicit types and function return types are specified. Enable debug: true for detailed errors.

❓ Low frame rate / poor performance

Limit the device pixel ratio with dpr: Math.min(window.devicePixelRatio, 2) to avoid rendering at 4x resolution on high-DPI displays.

Next Steps