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 33 Specifies that queries' results only become available at certain well-defined times. This extension provides the same functionality as EXT_disjoint_timer_query. The IDL, description, and extension name are specialized for WebGL 2.0, which incorporates query objects into the core specification. 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, GLenum target); }; target accepts TIME_ELAPSED_EXT. target accepts TIME_ELAPSED_EXT. target accepts TIMESTAMP_EXT. 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
pname accepts TIMESTAMP_EXT or GPU_DISJOINT_EXT.
The return type depends on the parameter queried:
pnamereturned type
TIMESTAMP_EXTGLuint64EXT
GPU_DISJOINT_EXTboolean
        // 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);
          }
        }
    
Split WebGL 2.0 specification of this extension into its own file for better comprehensibility. Fixed errors in sample code pointed out by @juj.