Start · Sprachen · JavaScript · Referenz · GPUCanvasContext

GPUCanvasContext

Schnittstelle

Stellt den WebGPU-Rendering-Kontext eines <code>&lt;canvas&gt;</code> dar, den <code>canvas.getContext("webgpu")</code> liefert. Er verbindet die Zeichenfläche mit einem <code>GPUDevice</code>.

seit JavaScript WebGPU – Chrome/Edge 113+, Safari 26+, Firefox 141 Kategorie: webapi

Signatur

interface GPUCanvasContext

Beschreibung

GPUCanvasContext ist die Brücke zwischen der WebGPU-API und einem <canvas>-Element im DOM. Das Objekt bekommst du über canvas.getContext("webgpu") (oder über OffscreenCanvas.getContext("webgpu")). Anders als bei 2D oder WebGL kann der Kontext direkt danach noch nichts anzeigen: Zuerst musst du ihn mit configure() an ein GPUDevice binden und dabei ein Texturformat festlegen.

Wichtige Mitglieder:

  • canvas (nur lesbar): Verweist auf das zugehörige HTMLCanvasElement bzw. OffscreenCanvas.
  • configure(configuration): Bindet den Kontext an ein Device und legt Format, Verwendungszweck (usage), Alpha-Modus, Farbraum und Tone-Mapping fest. Dabei wird die bisherige aktuelle Textur verworfen.
  • unconfigure(): Hebt die Konfiguration auf und gibt die zugehörigen Texturen frei.
  • getCurrentTexture(): Gibt die GPUTexture zurück, in die der aktuelle Frame gerendert wird. Der Browser stellt sie nach dem Abarbeiten der Aufgabe (in der Regel am Frame-Ende) automatisch dar.
  • getConfiguration(): Liefert die aktuelle Konfiguration oder null (neuere Ergänzung, noch nicht in allen Browsern).

Typischer Ablauf: Adapter und Device anfordern, den Kontext mit navigator.gpu.getPreferredCanvasFormat() konfigurieren und danach in jedem Frame (etwa in requestAnimationFrame) getCurrentTexture().createView() als Farbanhang eines Render-Passes verwenden.

Parameter

Name Typ Default Beschreibung
$configuration.device Pflicht GPUDevice Das Device, das in den Canvas rendert. Parameter von configure().
$configuration.format Pflicht GPUTextureFormat Texturformat der Canvas-Textur. Erlaubt sind "bgra8unorm", "rgba8unorm" und "rgba16float". Empfohlen ist navigator.gpu.getPreferredCanvasFormat().
$configuration.usage number (GPUTextureUsageFlags) GPUTextureUsage.RENDER_ATTACHMENT Wofür die Textur verwendet werden darf, z. B. zusätzlich COPY_SRC für Screenshots oder STORAGE_BINDING für Compute-Shader.
$configuration.alphaMode "opaque" | "premultiplied" "opaque" Legt fest, wie der Alphakanal mit der Seite zusammengesetzt wird. Bei "premultiplied" ist der Canvas durchsichtig.
$configuration.colorSpace "srgb" | "display-p3" "srgb" Farbraum, in dem die Pixelwerte ausgegeben werden.
$configuration.toneMapping { mode: "standard" | "extended" } { mode: "standard" } Mit "extended" und rgba16float ist HDR-Ausgabe möglich (neuere Ergänzung).
$configuration.viewFormats GPUTextureFormat[] [] Weitere Formate, die createView() verwenden darf, z. B. "bgra8unorm-srgb".

Beispiele

Kontext holen und konfigurieren

const canvas = document.querySelector('#gfx');

if (!navigator.gpu) throw new Error('WebGPU wird nicht unterstützt');

const adapter = await navigator.gpu.requestAdapter();
if (!adapter) throw new Error('Kein passender GPU-Adapter gefunden');
const device = await adapter.requestDevice();

const context = canvas.getContext('webgpu');
const format = navigator.gpu.getPreferredCanvasFormat();

context.configure({
  device,
  format,
  alphaMode: 'premultiplied'
});

console.log(context.canvas === canvas, format);
true "bgra8unorm" (je nach Plattform auch "rgba8unorm")

Canvas in jedem Frame mit einer Farbe löschen

const render = (time) => {
  const t = (Math.sin(time / 1000) + 1) / 2;
  const encoder = device.createCommandEncoder();
  const pass = encoder.beginRenderPass({
    colorAttachments: [{
      view: context.getCurrentTexture().createView(),
      clearValue: { r: t, g: 0.2, b: 1 - t, a: 1 },
      loadOp: 'clear',
      storeOp: 'store'
    }]
  });
  pass.end();
  device.queue.submit([encoder.finish()]);
  requestAnimationFrame(render);
};
requestAnimationFrame(render);

Auflösung bei Größenänderung anpassen

const observer = new ResizeObserver(([entry]) => {
  const dpr = window.devicePixelRatio;
  const max = device.limits.maxTextureDimension2D;
  const w = Math.round(entry.contentBoxSize[0].inlineSize * dpr);
  const h = Math.round(entry.contentBoxSize[0].blockSize * dpr);
  canvas.width = Math.max(1, Math.min(w, max));
  canvas.height = Math.max(1, Math.min(h, max));
  // Die nächste getCurrentTexture()-Textur hat automatisch die neue Größe
});
observer.observe(canvas);

console.log(context.getConfiguration?.()?.format);
"bgra8unorm"

WebGPU in einem Worker mit OffscreenCanvas

// main.js
const offscreen = document.querySelector('#gfx').transferControlToOffscreen();
const worker = new Worker('render-worker.js', { type: 'module' });
worker.postMessage({ canvas: offscreen }, [offscreen]);

// render-worker.js
self.onmessage = async ({ data }) => {
  const adapter = await navigator.gpu.requestAdapter();
  const device = await adapter.requestDevice();
  const ctx = data.canvas.getContext('webgpu');
  ctx.configure({ device, format: navigator.gpu.getPreferredCanvasFormat() });
  console.log('Worker-Kontext bereit');
};
Worker-Kontext bereit