Signatur
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
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');
}
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`);
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-extensionsverfügbar. PrüfegetExtension()deshalb immer aufnull. - Nur WebGL 1: In WebGL-2-Kontexten gibt es diese Erweiterung nicht. Dort nimmst du
gl.deleteQuery()undEXT_disjoint_timer_query_webgl2. - Nicht zu früh löschen: Wenn du eine Abfrage löschst, bevor
QUERY_RESULT_AVAILABLE_EXTtrueliefert, geht das Messergebnis verloren. - Ein gelöschtes Objekt nicht weiterverwenden.
isQueryEXT()liefert danachfalse. - 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.