Start · Sprachen · JavaScript · Referenz · EXT_disjoint_timer_query.deleteQueryEXT()

EXT_disjoint_timer_query.deleteQueryEXT()

Methode

Löscht ein zuvor mit <code>createQueryEXT()</code> erzeugtes <code>WebGLQuery</code>-Objekt und gibt die zugehörigen GPU-Ressourcen frei.

seit JavaScript WebGL 1 Extension; eingeschränkte Verfügbarkeit (u Kategorie: webapi

Signatur

EXT_disjoint_timer_query.deleteQueryEXT(query)

Beschreibung

Die Methode deleteQueryEXT() der WebGL-Erweiterung EXT_disjoint_timer_query löscht ein WebGLQuery-Objekt, das zuvor mit createQueryEXT() angelegt wurde. Damit werden die zugehörigen Ressourcen im Grafiktreiber freigegeben.

Einsetzen solltest du sie, sobald du eine Zeitmessungs-Abfrage nicht mehr brauchst, zum Beispiel nach einem abgeschlossenen Profiling-Durchlauf oder beim Aufräumen eines Renderers. Wer in jedem Frame neue Abfragen anlegt, sollte alte Abfragen nach dem Auslesen konsequent löschen oder besser einen Pool wiederverwendbarer Abfrage-Objekte führen.

Ist die Abfrage gerade aktiv, also zwischen beginQueryEXT() und endQueryEXT(), wird sie beim Löschen automatisch beendet. Ein gelöschtes Objekt darf danach nicht mehr verwendet werden. Aufrufe damit erzeugen WebGL-Fehler wie INVALID_OPERATION.

Die Erweiterung ist nur für WebGL 1 gedacht. In WebGL 2 nutzt du stattdessen WebGL2RenderingContext.deleteQuery() zusammen mit der Erweiterung EXT_disjoint_timer_query_webgl2.

Parameter

Name Typ Default Beschreibung
$query Pflicht WebGLQuery | null Das zu löschende Abfrage-Objekt, erzeugt mit createQueryEXT(). Bei null passiert nichts.

Rückgabewert

Typ
void
Beschreibung
Kein Rückgabewert (undefined).

Beispiele

Abfrage anlegen und wieder löschen

const canvas = document.createElement('canvas');
const gl = canvas.getContext('webgl');
const ext = gl?.getExtension('EXT_disjoint_timer_query');

if (ext) {
  const query = ext.createQueryEXT();
  console.log(ext.isQueryEXT(query)); // true

  ext.deleteQueryEXT(query);
  console.log(ext.isQueryEXT(query)); // false
} else {
  console.log('EXT_disjoint_timer_query nicht verfügbar');
}
true false

GPU-Zeit messen und Abfrage nach dem Auslesen freigeben

const gl = document.querySelector('canvas').getContext('webgl');
const ext = gl.getExtension('EXT_disjoint_timer_query');

const measure = (drawFn) => new Promise((resolve, reject) => {
  const query = ext.createQueryEXT();
  ext.beginQueryEXT(ext.TIME_ELAPSED_EXT, query);
  drawFn();
  ext.endQueryEXT(ext.TIME_ELAPSED_EXT);

  const poll = () => {
    const available = ext.getQueryObjectEXT(query, ext.QUERY_RESULT_AVAILABLE_EXT);
    const disjoint = gl.getParameter(ext.GPU_DISJOINT_EXT);

    if (available && !disjoint) {
      const ns = ext.getQueryObjectEXT(query, ext.QUERY_RESULT_EXT);
      ext.deleteQueryEXT(query); // Ressourcen freigeben
      resolve(ns / 1e6);
    } else if (disjoint) {
      ext.deleteQueryEXT(query); // Ergebnis unbrauchbar, trotzdem aufräumen
      reject(new Error('Messung ungültig (disjoint)'));
    } else {
      requestAnimationFrame(poll);
    }
  };
  requestAnimationFrame(poll);
});

const ms = await measure(() => gl.drawArrays(gl.TRIANGLES, 0, 3));
console.log(`GPU-Zeit: ${ms.toFixed(3)} ms`);
GPU-Zeit: 0.042 ms

Alle Abfragen beim Aufräumen des Renderers löschen

class GpuProfiler {
  constructor(gl) {
    this.ext = gl.getExtension('EXT_disjoint_timer_query');
    this.queries = new Set();
  }

  create() {
    const q = this.ext.createQueryEXT();
    this.queries.add(q);
    return q;
  }

  dispose() {
    for (const q of this.queries) {
      this.ext.deleteQueryEXT(q);
    }
    this.queries.clear();
  }
}

const profiler = new GpuProfiler(document.querySelector('canvas').getContext('webgl'));
profiler.create();
profiler.dispose();
console.log(profiler.queries.size);

// Wichtig · Fallstricke

  • Verfügbarkeit: Wegen der Timing-Angriffe (Spectre, GLitch) wurde die Erweiterung in vielen Browsern deaktiviert oder hinter Flags versteckt, in Firefox ist sie z. B. oft nur mit webgl.enable-privileged-extensions verfügbar. Prüfe getExtension() deshalb immer auf null.
  • Nur WebGL 1: In WebGL-2-Kontexten gibt es diese Erweiterung nicht. Dort nimmst du gl.deleteQuery() und EXT_disjoint_timer_query_webgl2.
  • Nicht zu früh löschen: Wenn du eine Abfrage löschst, bevor QUERY_RESULT_AVAILABLE_EXT true liefert, geht das Messergebnis verloren.
  • Ein gelöschtes Objekt nicht weiterverwenden. isQueryEXT() liefert danach false.
  • Geht der Kontext verloren (webglcontextlost), werden alle Abfragen ungültig. Du musst sie nach der Wiederherstellung neu anlegen.
  • Du musst nicht mehr benötigte Abfragen zwar nicht zwingend löschen, weil der Garbage Collector sie irgendwann freigibt. Wenn du sie aber selbst löschst, wächst der Speicher in Render-Schleifen nicht unkontrolliert an.