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

EXT_disjoint_timer_query.isQueryEXT()

Methode

Prüft, ob das übergebene Objekt ein gültiges, noch nicht gelöschtes Timer-Query-Objekt (<code>WebGLTimerQueryEXT</code>) der Erweiterung <code>EXT_disjoint_timer_query</code> ist.

seit JavaScript WebGL-1-Erweiterung; Verfügbarkeit je nach Browser Kategorie: webapi

Signatur

EXT_disjoint_timer_query.isQueryEXT(query)

Beschreibung

Die Methode isQueryEXT() gehört zur WebGL-1-Erweiterung EXT_disjoint_timer_query. Mit dieser Erweiterung misst du, wie lange die GPU für eine Folge von Zeichenbefehlen braucht. Die Methode gibt true zurück, wenn das übergebene Objekt ein gültiges Query-Objekt ist. Die MDN-Dokumentation nennt es WebGLQuery, in WebGL 1 heißt der Typ WebGLTimerQueryEXT.

Gebraucht wird sie vor allem beim Aufräumen und Absichern: Bevor du ein Query-Objekt wiederverwendest, sein Ergebnis abfragst oder es mit deleteQueryEXT() löschst, kannst du prüfen, ob es noch gültig ist. Das hilft in Profiling-Werkzeugen, die viele Query-Objekte in einem Pool verwalten, und nach einem Kontextverlust (webglcontextlost).

Die Methode gibt false zurück, wenn du null übergibst, wenn das Objekt mit deleteQueryEXT() gelöscht wurde, wenn es aus einem anderen WebGL-Kontext stammt oder wenn der Kontext verloren gegangen ist. Nach den Regeln von OpenGL ES wird ein Name erst dann zu einem echten Query-Objekt, wenn er einmal mit beginQueryEXT() gebunden wurde. Deshalb liefern manche Umsetzungen direkt nach createQueryEXT() noch false.

In WebGL 2 gibt es die WebGL-1-Erweiterung nicht. Dort nutzt du EXT_disjoint_timer_query_webgl2 zusammen mit den eingebauten Methoden gl.createQuery() und gl.isQuery().

Parameter

Name Typ Default Beschreibung
$query Pflicht WebGLTimerQueryEXT | null Das zu prüfende Query-Objekt, normalerweise aus ext.createQueryEXT().

Beispiele

Gültigkeit vor und nach dem Löschen prüfen

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

if (!ext) {
  console.log('EXT_disjoint_timer_query nicht verfügbar');
} else {
  const query = ext.createQueryEXT();

  // Einmal binden, damit das Query-Objekt sicher angelegt ist
  ext.beginQueryEXT(ext.TIME_ELAPSED_EXT, query);
  ext.endQueryEXT(ext.TIME_ELAPSED_EXT);

  console.log('Vor dem Löschen:', ext.isQueryEXT(query));
  ext.deleteQueryEXT(query);
  console.log('Nach dem Löschen:', ext.isQueryEXT(query));
  console.log('null:', ext.isQueryEXT(null));
}
Vor dem Löschen: true Nach dem Löschen: false null: false

GPU-Zeit messen und nur gültige Queries auswerten

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

const measureGpu = (drawFn) => {
  const query = ext.createQueryEXT();
  ext.beginQueryEXT(ext.TIME_ELAPSED_EXT, query);
  drawFn();
  ext.endQueryEXT(ext.TIME_ELAPSED_EXT);
  return query;
};

const pollResult = (query) => new Promise((resolve, reject) => {
  const check = () => {
    if (!ext.isQueryEXT(query)) {
      reject(new Error('Query ungültig (gelöscht oder Kontext verloren)'));
      return;
    }
    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);
      resolve(ns / 1e6); // Millisekunden
    } else if (disjoint) {
      ext.deleteQueryEXT(query);
      reject(new Error('Messung verworfen (GPU_DISJOINT)'));
    } else {
      requestAnimationFrame(check);
    }
  };
  requestAnimationFrame(check);
});

const query = measureGpu(() => {
  gl.clearColor(0, 0, 0, 1);
  gl.clear(gl.COLOR_BUFFER_BIT);
});

try {
  const ms = await pollResult(query);
  console.log(`GPU-Zeit: ${ms.toFixed(3)} ms`);
} catch (err) {
  console.warn(err.message);
}
GPU-Zeit: 0.042 ms (Wert variiert)

Query-Pool nach Kontextverlust bereinigen

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

canvas.addEventListener('webglcontextlost', (e) => {
  e.preventDefault();
});

canvas.addEventListener('webglcontextrestored', () => {
  // Alte Objekte sind nach dem Kontextverlust ungültig
  pool = pool.filter((q) => ext && ext.isQueryEXT(q));
  ext = gl.getExtension('EXT_disjoint_timer_query');
  console.log('Verbleibende Queries:', pool.length);
});
Verbleibende Queries: 0