Signatur
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örigeHTMLCanvasElementbzw.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 dieGPUTexturezurü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 odernull(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);
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);
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');
};