Start · Sprachen · JavaScript · Referenz · GPUTexture.destroy()

GPUTexture.destroy()

Methode

Zerstört eine <code>GPUTexture</code> und gibt ihren GPU-Speicher sofort frei, statt auf die Garbage Collection zu warten.

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

Signatur

GPUTexture.prototype.destroy()

Beschreibung

Die Methode destroy() der Schnittstelle GPUTexture zerstört die Textur. Danach darf sie nicht mehr verwendet werden: Befehle, die später an die Warteschlange übergeben werden und die Textur oder eine ihrer GPUTextureViews nutzen, führen zu einem Validierungsfehler.

WebGPU gibt GPU-Ressourcen auch frei, wenn das JavaScript-Objekt vom Garbage Collector eingesammelt wird. Wann das passiert, lässt sich aber nicht vorhersagen. Große Texturen belegen oft viele Megabyte Videospeicher, zum Beispiel Render-Targets, Tiefenpuffer, Shadow-Maps oder Texturatlanten. Deshalb solltest du destroy() ausdrücklich aufrufen, sobald du eine Textur nicht mehr brauchst. Das ist besonders wichtig, wenn du Texturen bei einer Größenänderung des Fensters neu erzeugst oder zwischen Szenen wechselst.

Der Aufruf lässt bereits übergebene Arbeit weiterlaufen. Die Implementierung wartet, bis alle vorher mit GPUQueue.submit() übergebenen Befehle, die die Textur nutzen, fertig sind. Erst dann gibt sie den Speicher wirklich frei. Du kannst destroy() also direkt nach einem submit() aufrufen.

Rückgabewert

Typ
undefined
Beschreibung
Kein Rückgabewert (undefined).

Beispiele

Textur erzeugen und wieder freigeben

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

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

console.log(texture.width, texture.format);

// ... Textur benutzen ...

texture.destroy(); // GPU-Speicher sofort freigeben
1024 rgba8unorm

Tiefenpuffer bei Größenänderung ersetzen

let depthTexture = null;

const resizeDepthTexture = (device, width, height) => {
  // Alte Textur zuerst zerstören, sonst bleibt ihr Speicher belegt
  depthTexture?.destroy();
  depthTexture = device.createTexture({
    size: [width, height],
    format: 'depth24plus',
    usage: GPUTextureUsage.RENDER_ATTACHMENT,
  });
};

const observer = new ResizeObserver(([entry]) => {
  const { width, height } = entry.contentRect;
  canvas.width = Math.max(1, Math.floor(width));
  canvas.height = Math.max(1, Math.floor(height));
  resizeDepthTexture(device, canvas.width, canvas.height);
});
observer.observe(canvas);

Direkt nach submit() zerstören ist sicher

const staging = device.createTexture({
  size: [256, 256],
  format: 'rgba8unorm',
  usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.COPY_DST,
});

const encoder = device.createCommandEncoder();
encoder.copyTextureToTexture(
  { texture: staging },
  { texture: targetTexture },
  [256, 256],
);
device.queue.submit([encoder.finish()]);

// Die bereits übergebene Kopie läuft trotzdem vollständig durch
staging.destroy();

await device.queue.onSubmittedWorkDone();
console.log('Kopie abgeschlossen, Staging-Textur freigegeben');
Kopie abgeschlossen, Staging-Textur freigegeben

Validierungsfehler bei Nutzung nach destroy() abfangen

device.pushErrorScope('validation');

texture.destroy();
device.queue.writeTexture(
  { texture },
  new Uint8Array(4 * 4 * 4),
  { bytesPerRow: 16 },
  [4, 4],
);

const error = await device.popErrorScope();
console.log(error ? 'Fehler: ' + error.message : 'kein Fehler');
Fehler: Destroyed texture [Texture] used in a submit. (Meldung variiert je nach Browser)

// Wichtig · Fallstricke

  • Nicht umkehrbar: Eine zerstörte Textur lässt sich nicht wiederherstellen. Brauchst du sie wieder, erzeugst du sie mit GPUDevice.createTexture() neu.
  • Keine Ausnahme: Nutzt du die Textur nach destroy(), wirft der Browser keinen JavaScript-Fehler. Stattdessen entsteht ein GPU-Validierungsfehler. Den fängst du mit pushErrorScope()/popErrorScope() oder mit dem Event uncapturederror ab.
  • Mehrfacher Aufruf: Du kannst destroy() mehrmals aufrufen. Nach dem ersten Aufruf hat das keine weitere Wirkung.
  • Canvas-Texturen: Die Texturen aus GPUCanvasContext.getCurrentTexture() verwaltet der Browser selbst. Zerstöre sie nicht von Hand.
  • Views: Alle GPUTextureViews der Textur werden mit ihr unbrauchbar. Bind Groups, die solche Views enthalten, sind danach ungültig.
  • Speicherlecks: Ohne destroy() kann sich bei häufig neu erzeugten Texturen (etwa bei jeder Größenänderung des Fensters) der Videospeicher füllen, bevor die Garbage Collection greift. Die Folge kann ein Geräteverlust sein (device.lost).
  • Kompatibilität: WebGPU gibt es nur in sicheren Kontexten und noch nicht auf allen Plattformen. Prüfe deshalb vorher, ob navigator.gpu vorhanden ist.