EXT_disjoint_timer_query_webgl2
WebGL working group (public_webgl 'at' khronos.org)
Contributors to ARB_occlusion_query
Contributors to EXT_timer_query
Contributors to ARB_timer_query
Ben Vanik, Google Inc.
Daniel Koch, TransGaming Inc.
Florian Boesch (pyalot 'at' gmail.com)
Members of the WebGL working group
Last modified date: April 01, 2021
Revision: 3
WebGL extension #33
Written against the WebGL API 2.0 specification.
This extension exposes the EXT_disjoint_timer_query functionality to WebGL.
The following WebGL-specific behavioral changes apply:
Consult the above extension for documentation, issues and new functions and enumerants.
When this extension is enabled:
[Exposed=(Window,Worker), LegacyNoInterfaceObject] interface EXT_disjoint_timer_query_webgl2 { const GLenum QUERY_COUNTER_BITS_EXT = 0x8864; const GLenum TIME_ELAPSED_EXT = 0x88BF; const GLenum TIMESTAMP_EXT = 0x8E28; const GLenum GPU_DISJOINT_EXT = 0x8FBB; undefined queryCounterEXT(WebGLQuery query, GLenum target); };
target
accepts TIMESTAMP_EXT
.
target
accepts TIME_ELAPSED_EXT
.
target
accepts TIME_ELAPSED_EXT
.
target
and pname
accept the following combinations of
parameters. The return type of this method now depends on the parameter queried.
target | pname | returned type |
---|---|---|
TIME_ELAPSED_EXT | CURRENT_QUERY | WebGLQuery? |
TIMESTAMP_EXT | CURRENT_QUERY | null |
TIME_ELAPSED_EXT | QUERY_COUNTER_BITS_EXT | GLint |
TIMESTAMP_EXT | QUERY_COUNTER_BITS_EXT | GLint |
pname
accepts TIMESTAMP_EXT
or GPU_DISJOINT_EXT
.
pname | returned type |
---|---|
TIMESTAMP_EXT | GLuint64 |
GPU_DISJOINT_EXT | boolean |
// Example (1) -- uses beginQuery/endQuery. let ext = gl.getExtension('EXT_disjoint_timer_query_webgl2'); let query = gl.createQuery(); gl.beginQuery(ext.TIME_ELAPSED_EXT, query); // Draw object gl.drawElements(...); gl.endQuery(ext.TIME_ELAPSED_EXT); // ...at some point in the future, after returning control to the browser and being called again: // (Note that this code might be called multiple times) if (query) { let available = gl.getQueryParameter(query, gl.QUERY_RESULT_AVAILABLE); let disjoint = gl.getParameter(ext.GPU_DISJOINT_EXT); if (available && !disjoint) { // See how much time the rendering of the object took in nanoseconds. let timeElapsed = gl.getQueryParameter(query, gl.QUERY_RESULT); // Do something useful with the time. Note that care should be // taken to use all significant bits of the result, not just the // least significant 32 bits. adjustObjectLODBasedOnDrawTime(timeElapsed); } if (available || disjoint) { // Clean up the query object. gl.deleteQuery(query); // Don't re-enter this polling loop. query = null; } } //---------------------------------------------------------------------- // Example (2) -- same as the example above, but uses queryCounterEXT instead. let ext = gl.getExtension('EXT_disjoint_timer_query_webgl2'); let startQuery = gl.createQuery(); let endQuery = gl.createQuery(); ext.queryCounterEXT(startQuery, ext.TIMESTAMP_EXT); // Draw object gl.drawElements(...); ext.queryCounterEXT(endQuery, ext.TIMESTAMP_EXT); // ...at some point in the future, after returning control to the browser and being called again: // (Note that this code might be called multiple times) if (startQuery) { let available = gl.getQueryParameter(endQuery, gl.QUERY_RESULT_AVAILABLE); let disjoint = gl.getParameter(ext.GPU_DISJOINT_EXT); if (available && !disjoint) { // See how much time the rendering of the object took in nanoseconds. let timeStart = gl.getQueryParameter(startQuery, gl.QUERY_RESULT); let timeEnd = gl.getQueryParameter(endQuery, gl.QUERY_RESULT); // Do something useful with the time. Note that care should be // taken to use all significant bits of the result, not just the // least significant 32 bits. adjustObjectLODBasedOnDrawTime(timeEnd - timeStart); } if (available || disjoint) { // Clean up the query objects. gl.deleteQuery(startQuery); gl.deleteQuery(endQuery); // Don't re-enter this polling loop. startQuery = null; endQuery = null; } } //---------------------------------------------------------------------- // Example (3) -- check the number of timestamp bits to determine how to best // measure elapsed time. let ext = gl.getExtension('EXT_disjoint_timer_query_webgl2'); let timeElapsedQuery; let startQuery; let endQuery; let useTimestamps = false; if (gl.getQuery(ext.TIMESTAMP_EXT, ext.QUERY_COUNTER_BITS_EXT) > 0) { useTimestamps = true; } // Clear the disjoint state before starting to work with queries to increase // the chances that the results will be valid. gl.getParameter(ext.GPU_DISJOINT_EXT); if (useTimestamps) { startQuery = gl.createQuery(); endQuery = gl.createQuery(); ext.queryCounterEXT(startQuery, ext.TIMESTAMP_EXT); } else { timeElapsedQuery = gl.createQuery(); gl.beginQuery(ext.TIME_ELAPSED_EXT, timeElapsedQuery); } // Draw object gl.drawElements(...); if (useTimestamps) { ext.queryCounterEXT(endQuery, ext.TIMESTAMP_EXT); } else { gl.endQuery(ext.TIME_ELAPSED_EXT); } // ...at some point in the future, after returning control to the browser and being called again: // (Note that this code might be called multiple times) if (startQuery || endQuery || timeElapsedQuery) { let disjoint = gl.getParameter(ext.GPU_DISJOINT_EXT); let available; if (disjoint) { // Have to redo all of the measurements. } else { if (useTimestamps) { available = gl.getQueryParameter(endQuery, gl.QUERY_RESULT_AVAILABLE); } else { available = gl.getQueryParameter(timeElapsedQuery, gl.QUERY_RESULT_AVAILABLE); } if (available) { let timeElapsed; if (useTimestamps) { // See how much time the rendering of the object took in nanoseconds. let timeStart = gl.getQueryParameter(startQuery, gl.QUERY_RESULT); let timeEnd = gl.getQueryParameter(endQuery, gl.QUERY_RESULT); timeElapsed = timeEnd - timeStart; } else { timeElapsed = gl.getQueryParameter(query, gl.QUERY_RESULT); } // Do something useful with the time. Note that care should be // taken to use all significant bits of the result, not just the // least significant 32 bits. adjustObjectLODBasedOnDrawTime(timeElapsed); } } if (available || disjoint) { // Clean up the query objects. if (useTimestamps) { gl.deleteQuery(startQuery); gl.deleteQuery(endQuery); // Don't re-enter the polling loop above. startQuery = null; endQuery = null; } else { gl.deleteQuery(timeElapsedQuery); // Don't re-enter the polling loop above. timeElapsedQuery = null; } } }
Revision 1, 2016/09/30
Revision 2, 2016/10/11
Revision 3, 2021/04/01