Start · Sprachen · JavaScript · Referenz · WebGL2RenderingContext.invalidateFramebuffer()

WebGL2RenderingContext.invalidateFramebuffer()

Methode

Teilt der GPU mit, dass der Inhalt bestimmter Framebuffer-Anhänge nicht mehr gebraucht wird und verworfen werden darf.

seit JavaScript WebGL 2.0 – Baseline: alle modernen Browser Kategorie: webapi

Signatur

WebGL2RenderingContext.prototype.invalidateFramebuffer(target, attachments)

Beschreibung

Mit invalidateFramebuffer() teilst du dem Treiber mit, dass der Inhalt eines oder mehrerer Anhänge (Farb-, Tiefen- oder Stencil-Puffer) des aktuell an target gebundenen Framebuffers nicht mehr gebraucht wird. Danach ist der Inhalt dieser Anhänge undefiniert. Die GPU muss ihn also weder aufbewahren noch in den Hauptspeicher zurückschreiben.

Die Methode ist vor allem ein Performance-Hinweis, besonders für mobile GPUs mit kachelbasiertem Rendering (tile-based rendering, z. B. Mali, Adreno, PowerVR, Apple). Solche GPUs rendern in einen schnellen Speicher direkt auf dem Chip und schreiben die Ergebnisse danach in den Grafikspeicher zurück. Invalidierst du zum Beispiel den Tiefenpuffer am Ende eines Render-Durchgangs, fällt dieses Zurückschreiben weg. Das spart Speicherbandbreite und damit Energie.

Typische Einsatzfälle:

  • Tiefen- und Stencil-Puffer nach dem letzten Zeichenaufruf eines Durchgangs verwerfen.
  • Einen Multisample-Renderbuffer nach blitFramebuffer() verwerfen.
  • Zu Beginn eines Frames den alten Inhalt verwerfen, wenn sowieso alles neu gezeichnet wird. Damit entfällt das Laden aus dem Speicher.

Soll nur ein rechteckiger Teilbereich verworfen werden, gibt es invalidateSubFramebuffer().

Parameter

Name Typ Default Beschreibung
$target Pflicht GLenum Bindungspunkt des Framebuffers: gl.FRAMEBUFFER, gl.DRAW_FRAMEBUFFER (gleichwertig zu FRAMEBUFFER) oder gl.READ_FRAMEBUFFER.
$attachments Pflicht GLenum[] Array der zu verwerfenden Anhänge. Bei einem eigenen Framebuffer-Objekt: gl.COLOR_ATTACHMENT0 bis gl.COLOR_ATTACHMENTn, gl.DEPTH_ATTACHMENT, gl.STENCIL_ATTACHMENT oder gl.DEPTH_STENCIL_ATTACHMENT. Beim Standard-Framebuffer (null gebunden): gl.COLOR, gl.DEPTH, gl.STENCIL.

Rückgabewert

Typ
void
Beschreibung
Kein Rückgabewert (undefined). Fehler meldet die Methode über gl.getError().

Beispiele

Tiefenpuffer nach dem Render-Durchgang verwerfen

const canvas = document.querySelector('canvas');
const gl = canvas.getContext('webgl2');

// Offscreen-Framebuffer mit Farbtextur und Tiefen-Renderbuffer
const fbo = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);

const colorTex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, colorTex);
gl.texStorage2D(gl.TEXTURE_2D, 1, gl.RGBA8, 512, 512);
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, colorTex, 0);

const depthRb = gl.createRenderbuffer();
gl.bindRenderbuffer(gl.RENDERBUFFER, depthRb);
gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT24, 512, 512);
gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, depthRb);

gl.viewport(0, 0, 512, 512);
gl.clearColor(0.1, 0.1, 0.1, 1);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
// ... Zeichenaufrufe ...

// Tiefenwerte werden nicht mehr gebraucht, nicht in den Speicher zurückschreiben
gl.invalidateFramebuffer(gl.FRAMEBUFFER, [gl.DEPTH_ATTACHMENT]);
gl.bindFramebuffer(gl.FRAMEBUFFER, null);

console.log(gl.getError() === gl.NO_ERROR);
true

Multisample-Puffer nach dem Auflösen per blitFramebuffer verwerfen

const gl = document.querySelector('canvas').getContext('webgl2');
const w = gl.drawingBufferWidth;
const h = gl.drawingBufferHeight;

// MSAA-Framebuffer
const msaaFbo = gl.createFramebuffer();
const msaaColor = gl.createRenderbuffer();
gl.bindRenderbuffer(gl.RENDERBUFFER, msaaColor);
gl.renderbufferStorageMultisample(gl.RENDERBUFFER, 4, gl.RGBA8, w, h);
gl.bindFramebuffer(gl.FRAMEBUFFER, msaaFbo);
gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, msaaColor);

gl.clearColor(0, 0.5, 1, 1);
gl.clear(gl.COLOR_BUFFER_BIT);
// ... Szene zeichnen ...

// In den Standard-Framebuffer auflösen
gl.bindFramebuffer(gl.READ_FRAMEBUFFER, msaaFbo);
gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, null);
gl.blitFramebuffer(0, 0, w, h, 0, 0, w, h, gl.COLOR_BUFFER_BIT, gl.NEAREST);

// Die Multisample-Daten werden nicht mehr benötigt
gl.invalidateFramebuffer(gl.READ_FRAMEBUFFER, [gl.COLOR_ATTACHMENT0]);

Standard-Framebuffer: Tiefe und Stencil verwerfen

const gl = document.querySelector('canvas').getContext('webgl2', { depth: true, stencil: true });

const renderFrame = () => {
  gl.bindFramebuffer(gl.FRAMEBUFFER, null);
  gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT);
  // ... Szene zeichnen ...

  // Beim Standard-Framebuffer heißen die Anhänge COLOR / DEPTH / STENCIL
  gl.invalidateFramebuffer(gl.FRAMEBUFFER, [gl.DEPTH, gl.STENCIL]);
  requestAnimationFrame(renderFrame);
};

requestAnimationFrame(renderFrame);

// Wichtig · Fallstricke

  • Der Inhalt ist danach undefiniert: Lies einen invalidierten Anhang erst wieder, wenn du ihn neu beschrieben hast, zum Beispiel per clear() oder durch Zeichnen. Sonst bekommst du Datenmüll oder sichtbare Artefakte.
  • Anhang-Namen hängen vom Framebuffer ab: Beim Standard-Framebuffer (null) sind nur gl.COLOR, gl.DEPTH und gl.STENCIL gültig. Bei eigenen Framebuffer-Objekten musst du COLOR_ATTACHMENTi, DEPTH_ATTACHMENT usw. verwenden. Falsche Werte lösen INVALID_ENUM aus, ungültige Farb-Indizes INVALID_OPERATION.
  • Nur ein Hinweis an den Treiber: Die Methode ist keine Garantie. Auf Desktop-GPUs bringt sie oft wenig oder nichts, auf kachelbasierten Mobil-GPUs spart sie dagegen oft deutlich Bandbreite. Falsch eingesetzt verursacht sie trotzdem Darstellungsfehler.
  • Rufe die Methode direkt nach dem letzten Zugriff auf, noch bevor du den Framebuffer wechselst. Dann kann der Treiber das Zurückschreiben wirklich einsparen.
  • Kompatibilität: Die Methode gibt es nur im WebGL-2-Kontext (getContext('webgl2')), nicht in WebGL 1. Alle aktuellen Browser unterstützen sie.
  • Bei preserveDrawingBuffer: false (Standard) verwirft der Browser den Standard-Framebuffer nach dem Anzeigen ohnehin. Beim Standard-Framebuffer lohnt sich die Methode deshalb vor allem für Tiefe und Stencil.