How to Use WebGPU in Deno: A Complete Guide to GPU Computing
WebGPU in Deno is available as an unstable extension that exposes the browser-standard navigator.gpu API through the deno_webgpu crate, requiring the --unstable flag to enable GPU compute and rendering capabilities.
Deno implements the WebGPU specification as an unstable extension called deno_webgpu, allowing developers to leverage GPU acceleration for compute and graphics workloads directly in TypeScript. This implementation mirrors the browser's WebGPU API, exposing the familiar navigator.gpu interface while providing additional Deno-specific capabilities like backend selection and trace capture. The source code resides in the denoland/deno repository under the ext/webgpu directory.
Enabling WebGPU in Deno
Because the API remains unstable, you must launch Deno with the --unstable flag to access WebGPU functionality.
deno run --unstable your_script.ts
When you first access navigator.gpu, Deno automatically lazy-loads the WebGPU module. For explicit control over initialization, import the lazy loader directly from the internal extension path:
import { loadWebGPU } from "ext:deno_webgpu/00_init.js";
await loadWebGPU(); // Ensures the WebGPU module is available
Architecture of WebGPU in Deno
The WebGPU implementation in Deno follows a layered architecture that bridges the Rust-based wgpu library with JavaScript APIs.
Rust Operations Layer
At the core, ext/webgpu/lib.rs registers the WebGPU ops and creates the global GPU object. The op_create_gpu operation (lines 64-78) builds a GC-rooted GPU instance and stores helper globals for event handling. When you call gpu.requestAdapter(), the Rust side creates a wgpu Adapter and returns a wrapped GPUAdapter JavaScript object, honoring the DENO_WEBGPU_BACKEND environment variable for backend selection.
JavaScript Bindings Layer
The file ext/webgpu/01_webgpu.js provides the WebIDL-generated classes (e.g., GPU, GPUAdapter, GPUDevice) and registers error classes. It wires the Rust ops to JavaScript prototype methods and defines the denoNsWebGPU namespace for low-level capture operations like deviceStartCapture and deviceStopCapture.
Lazy Loading Mechanism
The ext/webgpu/00_init.js file exposes a loadWebGPU function that implements lazy initialization. This matches the browser's pattern where navigator.gpu is only instantiated upon first access, improving startup performance for scripts that do not require GPU resources.
Configuring the WebGPU Backend
Deno allows you to control the underlying GPU backend through environment variables, providing flexibility for different hardware and debugging scenarios.
Set DENO_WEBGPU_BACKEND to force a specific backend implementation:
# Force Vulkan on Linux or Windows
DENO_WEBGPU_BACKEND=vulkan deno run --unstable my_app.ts
# Force DirectX 12 on Windows
DENO_WEBGPU_BACKEND=dx12 deno run --unstable my_app.ts
The backend selection logic resides in ext/webgpu/lib.rs around line 60, where std::env::var("DENO_WEBGPU_BACKEND") is parsed into a wgpu Backends bit-mask.
For debugging, enable tracing with DENO_WEBGPU_TRACE to write wgpu trace files to a specified directory:
DENO_WEBGPU_TRACE=./trace deno run --unstable my_app.ts
Practical WebGPU Examples in Deno
Hello Triangle Rendering
The following example demonstrates a complete rendering pipeline using WebGPU in Deno, including shader loading and canvas configuration:
// hello_triangle.ts
await import("ext:deno_webgpu/00_init.js"); // Optional if using --unstable
const adapter = await navigator.gpu.requestAdapter();
if (!adapter) throw new Error("No GPU adapter found");
const device = await adapter.requestDevice();
const canvas = document.createElement("canvas");
document.body.appendChild(canvas);
const context = canvas.getContext("webgpu");
const format = navigator.gpu.getPreferredCanvasFormat();
context.configure({ device, format });
const shaderCode = await Deno.readTextFile(
"https://raw.githubusercontent.com/denoland/deno/main/tests/testdata/webgpu/hellotriangle_shader.wgsl",
);
const module = device.createShaderModule({ code: shaderCode });
const pipeline = device.createRenderPipeline({
vertex: { module, entryPoint: "vs_main" },
fragment: {
module,
entryPoint: "fs_main",
targets: [{ format }],
},
primitive: { topology: "triangle-list" },
});
function frame() {
const commandEncoder = device.createCommandEncoder();
const textureView = context.getCurrentTexture().createView();
const pass = commandEncoder.beginRenderPass({
colorAttachments: [
{ view: textureView, loadOp: "clear", clearValue: [0, 0, 0, 1] },
],
});
pass.setPipeline(pipeline);
pass.draw(3);
pass.end();
device.queue.submit([commandEncoder.finish()]);
requestAnimationFrame(frame);
}
requestAnimationFrame(frame);
The shader source is loaded from the Deno test suite at tests/testdata/webgpu/hellotriangle_shader.wgsl. The navigator.gpu.getPreferredCanvasFormat() method selects the optimal texture format for the platform (Bgra8unorm on desktop, Rgba8unorm on Android), implemented in ext/webgpu/lib.rs lines 152-162.
Capturing GPU Traces for Debugging
For debugging GPU operations, Deno exposes capture functions through the denoNsWebGPU namespace defined in ext/webgpu/01_webgpu.js:
import { denoNsWebGPU } from "ext:deno_webgpu/01_webgpu.js";
// Start a wgpu trace in the directory "./trace"
denoNsWebGPU.deviceStartCapture(gpuDevice, "./trace");
// ... normal rendering commands ...
// Stop the capture
denoNsWebGPU.deviceStopCapture(gpuDevice);
The capture operations are defined in ext/webgpu/lib.rs as op_webgpu_device_start_capture and op_webgpu_device_stop_capture, allowing you to generate trace files compatible with wgpu debugging tools.
Selecting a Specific Backend
Force a specific GPU backend using environment variables before launching your script:
# Force the Vulkan backend (useful on Linux CI)
DENO_WEBGPU_BACKEND=vulkan deno run --unstable my_app.ts
The backend selection logic in ext/webgpu/lib.rs (around line 60) parses DENO_WEBGPU_BACKEND into a wgpu Backends bit-mask, allowing you to override automatic backend detection.
Key Source Files for WebGPU in Deno
Understanding the implementation requires familiarity with these specific files in the denoland/deno repository:
| File | Role | Location |
|---|---|---|
ext/webgpu/lib.rs |
Core Rust implementation: ops registration, GPU object creation, adapter/device instantiation, and environment variable handling. |
lib.rs |
ext/webgpu/01_webgpu.js |
JavaScript surface layer: WebIDL-generated classes (GPU, GPUAdapter, GPUDevice), error bindings, and the denoNsWebGPU namespace for capture operations. |
01_webgpu.js |
ext/webgpu/00_init.js |
Lazy loader implementation that defers WebGPU initialization until first access, exporting the loadWebGPU function for explicit control. |
00_init.js |
ext/webgpu/README.md |
Extension documentation covering environment variables, backend options, and test suite information. | README.md |
tests/testdata/webgpu/hellotriangle_shader.wgsl |
Reference WGSL shader code used in official examples and test suites. | hellotriangle_shader.wgsl |
Summary
- WebGPU in Deno is implemented as the unstable
deno_webgpuextension, requiring the--unstableruntime flag to access GPU capabilities. - The architecture spans Rust operations in
ext/webgpu/lib.rs(handlingop_create_gpuand adapter creation) and JavaScript bindings inext/webgpu/01_webgpu.js(providing thenavigator.gpuinterface anddenoNsWebGPUdebugging namespace). - Lazy loading via
ext/webgpu/00_init.jsensures WebGPU resources are only initialized upon first access tonavigator.gpu. - Environment variables
DENO_WEBGPU_BACKENDandDENO_WEBGPU_TRACEallow backend selection (Vulkan, DirectX 12) and debugging trace generation respectively. - You can capture GPU traces programmatically using
denoNsWebGPU.deviceStartCapture()anddenoNsWebGPU.deviceStopCapture()for low-level debugging.
Frequently Asked Questions
Is WebGPU in Deno stable?
No, WebGPU in Deno is currently an unstable extension. You must run your scripts with the --unstable flag to access the API. The implementation resides in the ext/webgpu directory and is actively developed against the wgpu Rust library, but breaking changes may occur until the API stabilizes.
How do I enable WebGPU in Deno?
Enable WebGPU by passing the --unstable flag when running your Deno script: deno run --unstable your_script.ts. The navigator.gpu global becomes available automatically after the lazy loader in ext/webgpu/00_init.js initializes the extension upon first access.
Can I use WebGPU for compute shaders in Deno?
Yes, WebGPU in Deno supports both compute shaders and rendering pipelines. Once you obtain a GPUDevice via navigator.gpu.requestAdapter() followed by adapter.requestDevice(), you can create compute pipelines using device.createComputePipeline() and execute work via commandEncoder.beginComputePass().
What GPU backends does WebGPU in Deno support?
Deno's WebGPU implementation supports multiple backends through the underlying wgpu library, including Vulkan (Linux/Windows), DirectX 12 (Windows), and Metal (macOS). You can force a specific backend by setting the DENO_WEBGPU_BACKEND environment variable to values like vulkan, dx12, or metal before running your script.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →