---
title: init
description: Creates the public `Gpu` context. `init()` creates the device only; canvas-backed rendering is explicit through `surface(gpu, canvas, opts)`.
---

# init



## Import

```ts
import { init } from "vgpu";
```

Browser code imports from `vgpu`; Node GPU tests import from `vgpu/node`; deterministic unit tests import from `vgpu/mock`.

## Signature

```ts
import type { Gpu } from "vgpu";
import type { RequiredDeviceLimits, VGPUAdapter } from "vgpu/core";

declare function init(options?: InitOptions): Promise<Gpu>;

interface InitOptions {
  readonly adapter?: VGPUAdapter;
  readonly powerPreference?: GPUPowerPreference;
  readonly requiredFeatures?: readonly GPUFeatureName[];
  readonly requiredLimits?: RequiredDeviceLimits;
  readonly label?: string;
}
```

## Parameters

| Param                    | Type                        | Required | Default     | Notes                                                                                                                                                                                                                                                                                                                                                          |
| ------------------------ | --------------------------- | -------: | ----------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| options                  | `InitOptions`               |        ✖ | `{}`        | Device creation options only. Canvas size, DPR, and auto-resize belong to `surface(gpu, canvas, opts)`.                                                                                                                                                                                                                                                        |
| options.adapter          | `VGPUAdapter`               |        ✖ | `undefined` | Explicit adapter. If omitted in `vgpu`, `navigator.gpu.requestAdapter()` is used; `vgpu/node` and `vgpu/mock` provide adapter factories.                                                                                                                                                                                                                       |
| options.powerPreference  | `GPUPowerPreference`        |        ✖ | `undefined` | Forwarded to `navigator.gpu.requestAdapter({ powerPreference })`.                                                                                                                                                                                                                                                                                              |
| options.requiredFeatures | `readonly GPUFeatureName[]` |        ✖ | `undefined` | Optional device features to enable, forwarded to `adapter.requestDevice` (e.g. `"depth-clip-control"` for `DrawOptions.unclippedDepth`). Checked against the adapter's supported features first: a name the adapter lacks fails init with `VGPU-FEATURE-UNSUPPORTED` instead of a native rejection. `device.features` reflects exactly the requested features. |
| options.requiredLimits   | `RequiredDeviceLimits`      |        ✖ | `undefined` | Forwarded unchanged to `adapter.requestDevice`. Unsupported names/values reject device creation.                                                                                                                                                                                                                                                               |
| options.label            | `string`                    |        ✖ | `undefined` | Reserved public option; current main API (`vgpu`) device creation does not use it as a debug label.                                                                                                                                                                                                                                                            |

**Returns:** `Promise<Gpu>` — the context every factory takes first: `surface(gpu, ...)`,
`target(gpu, ...)`, `draw(gpu, ...)`, `effect(gpu, ...)`, `compute(gpu, ...)`, `geometry(gpu, ...)`,
`frame(gpu, cb)` / `frameLoop(gpu, cb)`, `storage(gpu, ...)`, `uniforms(gpu, ...)`,
`sampler(gpu, ...)`, and `bundle(gpu, ...)`.

**Throws:** `VGPU-RING1-UNSUPPORTED` when WebGPU is unavailable, adapter request returns `null`, or an entrypoint lacks an adapter factory — use `vgpu/mock` in tests, `vgpu/node` in Node, or pass a valid adapter; `VGPU-FEATURE-UNSUPPORTED` when `requiredFeatures` names a feature the adapter does not support — remove the unsupported name(s) or run on an adapter that supports them.

## Examples

```ts
import { init, effect, frame, target } from "vgpu/mock";

const gpu = await init();
const colorTarget = target(gpu, { size: [64, 64], format: "rgba8unorm" });
const shader = effect(gpu, `
  @fragment fn fs_main(@location(0) uv: vec2f) -> @location(0) vec4f {
    return vec4f(uv, 0.0, 1.0);
  }
`);

frame(gpu, (currentFrame) => {
  currentFrame.pass({ target: colorTarget }, (p) => p.draw(shader));
});
```

```ts
import { init, effect, frame, surface } from "vgpu";

declare const canvas: HTMLCanvasElement;

const gpu = await init({
  // Request only when a vertex entry actually reads storage and the adapter supports it.
  requiredLimits: { maxStorageBuffersInVertexStage: 1 },
});
const canvasSurface = surface(gpu, canvas, { dpr: [1, 2] });
const shader = effect(gpu, `@fragment fn fs_main() -> @location(0) vec4f { return vec4f(1); }`);

frame(gpu, (currentFrame) => {
  currentFrame.pass({ target: canvasSurface }, (p) => p.draw(shader));
});
```

```ts
import { init, createMockAdapter, timer } from "vgpu/mock";

// Feature-gated device: GPU pass timing needs "timestamp-query".
const gpu = await init({
  adapter: createMockAdapter({ features: ["timestamp-query"] }),
  requiredFeatures: ["timestamp-query"],
});
const gpuTimer = timer(gpu);
gpuTimer.onResults((spans) => console.table(spans));
```

The granted feature makes `timer(gpu)` succeed. In a browser, drop the `adapter` option — `requiredFeatures` is forwarded to the real adapter the same way.

## Notes

* Choose the entrypoint for the runtime: use `vgpu` in browsers with WebGPU; use `vgpu/node` for headless Node rendering with a real adapter; use `vgpu/mock` for deterministic tests that do not require a GPU. Keep application code on the same `init(options?)` shape so the switch is local.
* Request optional features only when a code path uses them: `"timestamp-query"` enables `timer(gpu)`, `"depth-clip-control"` enables `DrawOptions.unclippedDepth`, and `"indirect-first-instance"` enables indirect draws that provide a non-zero first instance. Do not request features speculatively; unsupported names fail `init`.
* In tests, declare and request a mock feature explicitly: `init({ adapter: createMockAdapter({ features: ["timestamp-query"] }), requiredFeatures: ["timestamp-query"] })` lets you exercise feature gates instead of silently relying on defaults.
* `init(canvas)` is intentionally not supported. Create surfaces explicitly with `surface(gpu, canvas)`.
* `size`, `dpr`, and `autoResize` are `SurfaceOptions`, not `InitOptions`.
* The browser, node, and mock entrypoints all use the same `init(options?)` shape.
* In `vgpu/mock`, the default adapter declares no optional features. Pass `adapter: createMockAdapter({ features: [...] })` to test feature-gated paths deterministically; `requiredFeatures` outside that set fails with `VGPU-FEATURE-UNSUPPORTED`, and granted features appear on `gpu.device.features`.
* **See also:** `Gpu`, `Surface`, `Target`, `FrameRunner`.


---

For a semantic overview of all documentation, see [/sitemap.md](/sitemap.md)

For an index of all available documentation, see [/llms.txt](/llms.txt)

For agent-facing discovery, including API and MCP surfaces, see [/agents.md](/agents.md)