|
@@ -0,0 +1,128 @@
|
|
|
+import Stats from '../libs/stats.module.js';
|
|
|
+
|
|
|
+// https://www.khronos.org/registry/webgl/extensions/EXT_disjoint_timer_query/
|
|
|
+// https://www.khronos.org/registry/webgl/extensions/EXT_disjoint_timer_query_webgl2/
|
|
|
+export class GPUStatsPanel extends Stats.Panel {
|
|
|
+
|
|
|
+ constructor( context, name = 'GPU MS' ) {
|
|
|
+
|
|
|
+ super( name, '#f90', '#210' );
|
|
|
+
|
|
|
+ let isWebGL2 = true;
|
|
|
+ let extension = context.getExtension( 'EXT_disjoint_timer_query_webgl2' );
|
|
|
+ if ( extension === null ) {
|
|
|
+
|
|
|
+ isWebGL2 = false;
|
|
|
+ extension = context.getExtension( 'EXT_disjoint_timer_query' );
|
|
|
+
|
|
|
+ if ( extension === null ) {
|
|
|
+
|
|
|
+ console.warn( 'GPUStatsPanel: disjoint_time_query extension not available.' );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ this.context = context;
|
|
|
+ this.extension = extension;
|
|
|
+ this.maxTime = 30;
|
|
|
+ this.activeQueries = 0;
|
|
|
+
|
|
|
+ this.startQuery = function () {
|
|
|
+
|
|
|
+ const gl = this.context;
|
|
|
+ const ext = this.extension;
|
|
|
+
|
|
|
+ if ( ext === null ) {
|
|
|
+
|
|
|
+ return;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ // create the query object
|
|
|
+ let query;
|
|
|
+ if ( isWebGL2 ) {
|
|
|
+
|
|
|
+ query = gl.createQuery();
|
|
|
+ gl.beginQuery( ext.TIME_ELAPSED_EXT, query );
|
|
|
+
|
|
|
+ } else {
|
|
|
+
|
|
|
+ query = ext.createQueryEXT();
|
|
|
+ ext.beginQueryEXT( ext.TIME_ELAPSED_EXT, query );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ this.activeQueries ++;
|
|
|
+
|
|
|
+ const checkQuery = () => {
|
|
|
+
|
|
|
+ // check if the query is available and valid
|
|
|
+ let available, disjoint, ns;
|
|
|
+ if ( isWebGL2 ) {
|
|
|
+
|
|
|
+ available = gl.getQueryParameter( query, gl.QUERY_RESULT_AVAILABLE );
|
|
|
+ disjoint = gl.getParameter( ext.GPU_DISJOINT_EXT );
|
|
|
+ ns = gl.getQueryParameter( query, gl.QUERY_RESULT );
|
|
|
+
|
|
|
+ } else {
|
|
|
+
|
|
|
+ available = ext.getQueryObjectEXT( query, ext.QUERY_RESULT_AVAILABLE_EXT );
|
|
|
+ disjoint = gl.getParameter( ext.GPU_DISJOINT_EXT );
|
|
|
+ ns = ext.getQueryObjectEXT( query, ext.QUERY_RESULT_EXT );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ const ms = ns * 1e-6;
|
|
|
+ if ( available ) {
|
|
|
+
|
|
|
+ // update the display if it is valid
|
|
|
+ if ( ! disjoint ) {
|
|
|
+
|
|
|
+ this.update( ms, this.maxTime );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ this.activeQueries --;
|
|
|
+
|
|
|
+
|
|
|
+ } else {
|
|
|
+
|
|
|
+ // otherwise try again the next frame
|
|
|
+ requestAnimationFrame( checkQuery );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ };
|
|
|
+
|
|
|
+ requestAnimationFrame( checkQuery );
|
|
|
+
|
|
|
+ };
|
|
|
+
|
|
|
+ this.endQuery = function () {
|
|
|
+
|
|
|
+ // finish the query measurement
|
|
|
+ const ext = this.extension;
|
|
|
+ const gl = this.context;
|
|
|
+
|
|
|
+ if ( ext === null ) {
|
|
|
+
|
|
|
+ return;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ if ( isWebGL2 ) {
|
|
|
+
|
|
|
+ gl.endQuery( ext.TIME_ELAPSED_EXT );
|
|
|
+
|
|
|
+ } else {
|
|
|
+
|
|
|
+ ext.endQueryEXT( ext.TIME_ELAPSED_EXT );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ };
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+}
|