WebGL
Khronos
 

WebGL EXT_disjoint_timer_query Extension Draft Specification

Name

EXT_disjoint_timer_query

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: July 15, 2014
Revision: 4

Number

WebGL extension #26

Dependencies

Written against the WebGL API 1.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 WebGLTimerQueryEXT : WebGLObject {
    };

    [NoInterfaceObject]
    interface EXT_disjoint_timer_query {
      const GLenum QUERY_COUNTER_BITS_EXT      = 0x8864;
      const GLenum CURRENT_QUERY_EXT           = 0x8865;
      const GLenum QUERY_RESULT_EXT            = 0x8866;
      const GLenum QUERY_RESULT_AVAILABLE_EXT  = 0x8867;
      const GLenum TIME_ELAPSED_EXT            = 0x88BF;
      const GLenum TIMESTAMP_EXT               = 0x8E28;
      const GLenum GPU_DISJOINT_EXT            = 0x8FBB;

      WebGLTimerQueryEXT? createQueryEXT();
      void deleteQueryEXT(WebGLTimerQueryEXT? query);
      [WebGLHandlesContextLoss] boolean isQueryEXT(WebGLTimerQueryEXT? query);
      void beginQueryEXT(enum target, WebGLTimerQueryEXT? query);
      void endQueryEXT(enum target);
      void queryCounterEXT(WebGLTimerQueryEXT? query, enum target);
      any getQueryEXT(enum target, enum pname);
      any getQueryObjectEXT(WebGLTimerQueryEXT? query, enum pname);
    };
  

New Functions

WebGLTimerQueryEXT? createQueryEXT()
void deleteQueryEXT(WebGLTimerQueryEXT? query)
boolean isQueryEXT(WebGLTimerQueryEXT? query)
Returns true if the passed WebGLTimerQueryEXT is valid and false otherwise. Returns false if the query's invalidated flag is set.
void beginQueryEXT(GLenum target, WebGLTimerQueryEXT? query)
target accepts TIME_ELAPSED_EXT.
void endQueryEXT(GLenum target)
target accepts TIME_ELAPSED_EXT.
void queryCounterEXT(WebGLTimerQueryEXT? query, GLenum target)
target accepts TIMESTAMP_EXT.
any getQueryEXT(GLenum target, GLenum pname)
target accepts TIME_ELAPSED_EXT or TIMESTAMP_EXT. pname accepts CURRENT_QUERY_EXT or QUERY_COUNTER_BITS_EXT.
The return type of this method depends on the parameter queried:
pnamereturned type
CURRENT_QUERY_EXTWebGLTimerQueryEXT?
QUERY_COUNTER_BITS_EXTGLint
any getQueryObjectEXT(WebGLTimerQueryEXT? query, GLenum pname)
pname accepts QUERY_RESULT_EXT or QUERY_RESULT_AVAILABLE_EXT.
The return type of this method depends on the parameter queried:
pnamereturned type
QUERY_RESULT_EXTGLuint64EXT
QUERY_RESULT_AVAILABLE_EXTboolean

In order to ensure consistent behavior across platforms, queries' results must only be made available when the user agent's event loop is not executing a task. In other words:

New Tokens

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 beginQueryEXT/endQueryEXT.
        var ext = gl.getExtension('EXT_disjoint_timer_query');
        var query = ext.createQueryEXT();
        ext.beginQueryEXT(ext.TIME_ELAPSED_EXT, query);

        // Draw object
        gl.drawElements(...);

        ext.endQueryEXT(ext.TIME_ELAPSED_EXT);

        // At some point in the future, after returning control to the browser and being called again:
        var available = ext.getQueryObjectEXT(query, ext.QUERY_RESULT_AVAILABLE_EXT);
        var disjoint = gl.getParamater(ext.GPU_DISJOINT_EXT);

        if (available && !disjoint) {
          // See how much time the rendering of the object took in nanoseconds.
          var timeElapsed = ext.getQueryObjectEXT(query, ext.QUERY_RESULT_EXT);

          // 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');
        var startQuery = ext.createQueryEXT();
        var endQuery = ext.createQueryEXT();
        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 = ext.getQueryObjectEXT(endQuery, ext.QUERY_RESULT_AVAILABLE_EXT);
        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 = ext.getQueryObjectEXT(startQuery, ext.QUERY_RESULT_EXT);
          var timeEnd = ext.getQueryObjectEXT(endQuery, ext.QUERY_RESULT_EXT);

          // 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);
        }
    

Issues

  1. Can getQueryObjectEXT be exposed in its current form according to ECMAScript semantics? ECMAScript's de-facto concurrency model is "shared nothing" communicating event loops. Is it acceptable for sequential calls to getQueryObjectEXT to return different answers? Note that Date.now() advances during script execution, so this may be fine; but if concerns are raised, then the API may need to be redesigned to use callbacks.

Revision History

Revision 1, 2013/04/02

Revision 2, 2013/04/03

Revision 3, 2014/02/12

Revision 4, 2014/07/15