Start · Sprachen · JavaScript · Referenz · GPUQueue

GPUQueue

Schnittstelle

Das <code>GPUQueue</code>-Interface der WebGPU API steuert die Ausführung aufgezeichneter Befehlspuffer auf der GPU und bietet Methoden zum direkten Schreiben von Puffer- und Texturdaten.

seit JavaScript Baseline 2025: Chrome/Edge 113+, Firefox 141+ (Win Kategorie: webapi

Signatur

interface GPUQueue

Beschreibung

Eine GPUQueue ist die Befehlswarteschlange eines GPUDevice. Man erzeugt sie nicht selbst, sondern greift über device.queue darauf zu. Jedes Gerät hat genau eine Standard-Queue. Alles, was die GPU tatsächlich ausführen soll, landet früher oder später in dieser Queue: fertig kodierte GPUCommandBuffer-Objekte, Datenuploads in Puffer und Texturen sowie Kopien aus Bildquellen.

Die wichtigsten Methoden:

  • submit(commandBuffers): Übergibt ein Array von Befehlspuffern (erzeugt mit GPUCommandEncoder.finish()) an die GPU zur Ausführung.
  • writeBuffer(buffer, bufferOffset, data, dataOffset?, size?): Schreibt Daten aus einem ArrayBuffer, TypedArray oder DataView in einen GPUBuffer. Der Puffer braucht dafür das Usage-Flag GPUBufferUsage.COPY_DST.
  • writeTexture(destination, data, dataLayout, size): Schreibt Rohdaten in eine GPUTexture.
  • copyExternalImageToTexture(source, destination, copySize): Kopiert ein ImageBitmap, HTMLCanvasElement, HTMLVideoElement, VideoFrame o. Ä. in eine Textur.
  • onSubmittedWorkDone(): Gibt ein Promise<undefined> zurück, das erfüllt wird, sobald die GPU alle bis dahin übergebene Arbeit erledigt hat.
  • label: Ein frei wählbarer Name. Er taucht in Fehlermeldungen und Debug-Werkzeugen auf.

Alle Methoden arbeiten asynchron gegenüber der GPU. Der Aufruf kehrt sofort zurück, und die eigentliche Arbeit läuft später auf der Grafikkarte. Die Reihenfolge bleibt dabei erhalten: Ein writeBuffer() vor einem submit() ist garantiert sichtbar, wenn die übergebenen Befehle laufen. Deshalb eignen sich writeBuffer() und writeTexture() gut für häufige, kleine Aktualisierungen wie Uniforms pro Frame. Ein manuelles Mappen von Staging-Puffern ist dafür nicht nötig.

Rückgabewert

Typ
undefined | Promise<undefined>
Beschreibung
submit(), writeBuffer(), writeTexture() und copyExternalImageToTexture() geben undefined zurück. onSubmittedWorkDone() gibt ein Promise<undefined> zurück.

Beispiele

Queue holen und einen Render-Pass übergeben

const adapter = await navigator.gpu?.requestAdapter();
if (!adapter) throw new Error('WebGPU nicht verfügbar');
const device = await adapter.requestDevice();
const queue = device.queue; // keine Instanziierung – kommt vom Gerät
queue.label = 'Haupt-Queue';

const canvas = document.querySelector('canvas');
const context = canvas.getContext('webgpu');
context.configure({ device, format: navigator.gpu.getPreferredCanvasFormat() });

const encoder = device.createCommandEncoder();
const pass = encoder.beginRenderPass({
  colorAttachments: [{
    view: context.getCurrentTexture().createView(),
    clearValue: { r: 0.1, g: 0.2, b: 0.4, a: 1 },
    loadOp: 'clear',
    storeOp: 'store'
  }]
});
pass.end();

queue.submit([encoder.finish()]);
console.log(queue.label);
Haupt-Queue

Uniform-Puffer pro Frame mit writeBuffer aktualisieren

const uniformBuffer = device.createBuffer({
  size: 16, // 4 × float32
  usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST
});

const frame = (time) => {
  const uniforms = new Float32Array([time / 1000, canvas.width, canvas.height, 0]);
  device.queue.writeBuffer(uniformBuffer, 0, uniforms);
  // ... Befehle kodieren, die uniformBuffer nutzen, dann:
  // device.queue.submit([encoder.finish()]);
  requestAnimationFrame(frame);
};
requestAnimationFrame(frame);

Bild in eine Textur laden

const response = await fetch('/img/logo.png');
const bitmap = await createImageBitmap(await response.blob());

const texture = device.createTexture({
  size: [bitmap.width, bitmap.height],
  format: 'rgba8unorm',
  usage: GPUTextureUsage.TEXTURE_BINDING |
         GPUTextureUsage.COPY_DST |
         GPUTextureUsage.RENDER_ATTACHMENT
});

device.queue.copyExternalImageToTexture(
  { source: bitmap, flipY: true },
  { texture },
  [bitmap.width, bitmap.height]
);
console.log('Textur:', texture.width, 'x', texture.height);
Textur: 256 x 256

Auf das Ende der GPU-Arbeit warten (Compute-Ergebnis messen)

const start = performance.now();
const encoder = device.createCommandEncoder();
const pass = encoder.beginComputePass();
pass.setPipeline(computePipeline);
pass.setBindGroup(0, bindGroup);
pass.dispatchWorkgroups(64);
pass.end();

device.queue.submit([encoder.finish()]);
await device.queue.onSubmittedWorkDone();
console.log(`GPU fertig nach ${(performance.now() - start).toFixed(1)} ms`);
GPU fertig nach 3.4 ms