Start · Sprachen · JavaScript · Referenz · GPUCommandEncoder.copyTextureToTexture()

GPUCommandEncoder.copyTextureToTexture()

Methode

Kodiert einen Befehl, der einen Bereich einer <code>GPUTexture</code> vollständig auf der GPU in eine andere (oder dieselbe) Textur kopiert.

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

Signatur

GPUCommandEncoder.prototype.copyTextureToTexture(source, destination, copySize)

Beschreibung

copyTextureToTexture() fügt dem Befehlspuffer, den ein GPUCommandEncoder aufbaut, einen Kopierbefehl hinzu. Dabei wird ein Texel-Bereich einer Quelltextur (Mip-Stufe, Ursprung, Array-Ebenen) in einen Bereich einer Zieltextur übertragen. Die Daten verlassen die GPU dabei nicht. Das macht die Methode deutlich schneller als ein Umweg über Puffer oder die CPU.

Typische Einsatzfälle:

  • Den Inhalt eines Render-Ziels für Nachbearbeitung oder Verlauf sichern, etwa beim Ping-Pong-Rendering oder bei zeitlichem Antialiasing (TAA).
  • Einzelne Kacheln aus einem Texturatlas in eine Array-Textur übertragen.
  • Manuell erzeugte Mip-Stufen umkopieren oder eine Textur in eine größere Textur übernehmen, wenn sie vergrößert werden muss.

Der Befehl wird erst ausgeführt, wenn der mit encoder.finish() erzeugte GPUCommandBuffer über device.queue.submit() abgeschickt wurde. Die Methode darf nicht aufgerufen werden, solange ein Render- oder Compute-Pass auf dem Encoder offen ist. Zuerst muss also pass.end() aufgerufen werden.

Quelle und Ziel müssen kopierkompatible Formate haben: Die Formate müssen gleich sein oder sich nur durch das Suffix -srgb unterscheiden. Außerdem muss die Anzahl der Samples übereinstimmen. Die Quelle braucht das Nutzungsflag GPUTextureUsage.COPY_SRC, das Ziel das Flag GPUTextureUsage.COPY_DST.

Parameter

Name Typ Default Beschreibung
$source Pflicht GPUTexelCopyTextureInfo (früher GPUImageCopyTexture) — Beschreibt die Quelle. Das Objekt enthält: texture (die GPUTexture, Pflichtangabe), mipLevel (Standard 0), origin (Startpunkt als {x, y, z} oder Array, Standard {x:0, y:0, z:0}; bei 2D-Array-Texturen ist z die Array-Ebene) und aspect ("all", "depth-only" oder "stencil-only", Standard "all").
$destination Pflicht GPUTexelCopyTextureInfo — Beschreibt das Ziel mit denselben Feldern wie source. Die Zieltextur braucht das Flag GPUTextureUsage.COPY_DST.
$copySize Pflicht GPUExtent3D ({width, height?, depthOrArrayLayers?} | number[]) — Größe des kopierten Bereichs in Texeln. height und depthOrArrayLayers haben den Standardwert 1. Bei komprimierten Formaten muss die Größe ein Vielfaches der Blockgröße sein.

Rückgabewert

Typ
undefined
Beschreibung
Kein Rückgabewert. Der Befehl wird nur im Encoder aufgezeichnet.

Beispiele

Ganze Textur auf der GPU duplizieren

const adapter = await navigator.gpu.requestAdapter();
const device = await adapter.requestDevice();

const size = { width: 256, height: 256 };

const src = device.createTexture({
  size,
  format: 'rgba8unorm',
  usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.COPY_DST | GPUTextureUsage.TEXTURE_BINDING
});

const dst = device.createTexture({
  size,
  format: 'rgba8unorm',
  usage: GPUTextureUsage.COPY_DST | GPUTextureUsage.TEXTURE_BINDING
});

// Quelle mit roten Pixeln füllen
const pixels = new Uint8Array(256 * 256 * 4);
for (let i = 0; i < pixels.length; i += 4) pixels.set([255, 0, 0, 255], i);
device.queue.writeTexture({ texture: src }, pixels, { bytesPerRow: 256 * 4 }, size);

const encoder = device.createCommandEncoder();
encoder.copyTextureToTexture({ texture: src }, { texture: dst }, size);
device.queue.submit([encoder.finish()]);
console.log('Kopierbefehl abgeschickt');
Kopierbefehl abgeschickt

Aktuelles Bild für einen Verlaufspuffer (TAA) sichern

// Vorher: device, context und ein historyTexture im Canvas-Format anlegen.
// Das Canvas muss mit usage: RENDER_ATTACHMENT | COPY_SRC konfiguriert sein.
context.configure({
  device,
  format: navigator.gpu.getPreferredCanvasFormat(),
  usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.COPY_SRC
});

const frame = () => {
  const current = context.getCurrentTexture();
  const encoder = device.createCommandEncoder();

  const pass = encoder.beginRenderPass({
    colorAttachments: [{
      view: current.createView(),
      loadOp: 'clear',
      clearValue: { r: 0, g: 0, b: 0, a: 1 },
      storeOp: 'store'
    }]
  });
  // ... Zeichenbefehle ...
  pass.end(); // Pass muss vor dem Kopieren beendet sein

  encoder.copyTextureToTexture(
    { texture: current },
    { texture: historyTexture },
    [current.width, current.height]
  );

  device.queue.submit([encoder.finish()]);
  requestAnimationFrame(frame);
};
requestAnimationFrame(frame);

Atlas-Kachel in eine Ebene einer Array-Textur kopieren

// atlas: 1024×1024, Kacheln zu je 128×128, Format rgba8unorm, mit COPY_SRC
const layers = device.createTexture({
  size: { width: 128, height: 128, depthOrArrayLayers: 64 },
  format: 'rgba8unorm',
  usage: GPUTextureUsage.COPY_DST | GPUTextureUsage.TEXTURE_BINDING
});

const encoder = device.createCommandEncoder();
const tilesPerRow = 8;
for (let i = 0; i < 64; i++) {
  encoder.copyTextureToTexture(
    { texture: atlas, origin: { x: (i % tilesPerRow) * 128, y: Math.floor(i / tilesPerRow) * 128 } },
    { texture: layers, origin: { x: 0, y: 0, z: i } }, // z = Array-Ebene
    { width: 128, height: 128 }
  );
}
device.queue.submit([encoder.finish()]);

// Wichtig · Fallstricke

  • Formatkompatibilität: Die Formate von Quelle und Ziel müssen gleich sein. Erlaubt ist nur der Unterschied beim Suffix -srgb, etwa rgba8unorm ↔ rgba8unorm-srgb. Eine Formatumwandlung wie rgba8unorm → rgba16float ist nicht möglich. Dafür braucht man einen Render-Pass mit einem Shader.
  • Fehler sind asynchron: Ungültige Aufrufe werfen keine Ausnahme. Stattdessen wird der Encoder ungültig, und der Fehler tritt erst bei finish() oder submit() als Validierungsfehler auf. Diese Fehler lassen sich mit device.pushErrorScope('validation') und popErrorScope() abfangen.
  • Häufige Fehlerursachen: fehlendes Flag COPY_SRC oder COPY_DST, ein Kopierbereich außerhalb der Mip-Stufe, unterschiedliche sampleCount und ein offener Pass auf dem Encoder.
  • Bei Tiefen- und Stencil-Formaten sowie bei Multisample-Texturen muss immer die gesamte Subressource kopiert werden. Teilbereiche sind dort nicht erlaubt.
  • Kopiert man innerhalb derselben Textur, dürfen sich die Subressourcen (Mip-Stufe bzw. Array-Ebene) von Quelle und Ziel nicht überschneiden.
  • Canvas-Texturen aus getCurrentTexture() lassen sich nur als Quelle nutzen, wenn beim Aufruf von configure() das Flag COPY_SRC gesetzt wurde.
  • Kompatibilität: WebGPU steht nur in sicheren Kontexten zur Verfügung und wird noch nicht von allen Browsern unterstützt. Deshalb vorher if (!navigator.gpu) prüfen. Ältere Spezifikationsstände verwenden den Typnamen GPUImageCopyTexture. Die Struktur ist dieselbe.