WebGL
Khronos
 

WebGL EXT_disjoint_timer_query_webgl2 Extension Specification

Name

EXT_disjoint_timer_query_webgl2

Contact

WebGL working group (public_webgl 'at' khronos.org)

Contributors

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

Version

Last modified date: October 11, 2016
Revision: 2

Number

WebGL extension #33

Dependencies

Written against the WebGL API 2.0 specification.

Overview

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:

IDL

typedef unsigned long long GLuint64EXT;

[NoInterfaceObject]
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;

  void queryCounterEXT(WebGLQuery query, enum target);
};
  

New Functions

void queryCounterEXT(WebGLQuery query, GLenum target)
target accepts TIMESTAMP_EXT.

New Tokens

beginQuery(GLenum target, WebGLQuery? query)
target accepts TIME_ELAPSED_EXT.
void endQuery(GLenum target)
target accepts TIME_ELAPSED_EXT.
any getQuery(GLenum target, GLenum pname)
target and pname accept the following combinations of parameters. The return type of this method now depends on the parameter queried.
targetpnamereturned type
TIME_ELAPSED_EXTCURRENT_QUERYWebGLQuery?
TIMESTAMP_EXTCURRENT_QUERYnull
TIME_ELAPSED_EXTQUERY_COUNTER_BITS_EXTGLint
TIMESTAMP_EXTQUERY_COUNTER_BITS_EXTGLint
any getParameter(GLenum pname)
pname accepts TIMESTAMP_EXT or GPU_DISJOINT_EXT.
The return type depends on the parameter queried:
pnamereturned type
TIMESTAMP_EXTGLuint64EXT
GPU_DISJOINT_EXTboolean

Sample Code

        // Example (1) -- uses beginQuery/endQuery.
        var ext = gl.getExtension('EXT_disjoint_timer_query_webgl2');
        var 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:
        var available = gl.getQueryParameter(query, gl.QUERY_RESULT_AVAILABLE);
        var disjoint = gl.getParameter(ext.GPU_DISJOINT_EXT);

        if (available && !disjoint) {
          // See how much time the rendering of the object took in nanoseconds.
          var 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);
        }

        //----------------------------------------------------------------------

        // Example (2) -- same as the example above, but uses queryCounterEXT instead.
        var ext = gl.getExtension('EXT_disjoint_timer_query_webgl2');
        var startQuery = gl.createQuery();
        var 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:
        var available = gl.getQueryParameter(endQuery, gl.QUERY_RESULT_AVAILABLE);
        var disjoint = gl.getParameter(ext.GPU_DISJOINT_EXT);

        if (available && !disjoint) {
          // See how much time the rendering of the object took in nanoseconds.
          var timeStart = gl.getQueryParameter(startQuery, gl.QUERY_RESULT);
          var 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);
        }

        //----------------------------------------------------------------------

        // Example (3) -- check the number of timestamp bits to determine how to best
        // measure elapsed time.
        var ext = gl.getExtension('EXT_disjoint_timer_query_webgl2');
        var timeElapsedQuery;
        var startQuery;
        var endQuery;

        var 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:
        var disjoint = gl.getParameter(ext.GPU_DISJOINT_EXT);
        if (disjoint) {
          // Have to redo all of the measurements.
        } else {
          var available;
          if (useTimestamps) {
            available = gl.getQueryParameter(endQuery, gl.QUERY_RESULT_AVAILABLE);
          } else {
            available = gl.getQueryParameter(timeElapsedQuery, gl.QUERY_RESULT_AVAILABLE);
          }

          if (available) {
            var timeElapsed;
            if (useTimestamps) {
              // See how much time the rendering of the object took in nanoseconds.
              var timeStart = gl.getQueryParameter(startQuery, gl.QUERY_RESULT);
              var 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);
          }
        }
    

Revision History

Revision 1, 2016/09/30

Revision 2, 2016/10/11