Browse Source

Examples: add GPU stats panel (#21509)

* add GPU stats panel

* track active queries, don't do anything if extension is null

* Add gpu stats panel to the lines fat example
Garrett Johnson 4 years ago
parent
commit
60b151ce03
2 changed files with 136 additions and 1 deletions
  1. 128 0
      examples/jsm/utils/GPUStatsPanel.js
  2. 8 1
      examples/webgl_lines_fat.html

+ 128 - 0
examples/jsm/utils/GPUStatsPanel.js

@@ -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 );
+
+			}
+
+		};
+
+	}
+
+}

+ 8 - 1
examples/webgl_lines_fat.html

@@ -18,6 +18,7 @@
 			import * as THREE from '../build/three.module.js';
 
 			import Stats from './jsm/libs/stats.module.js';
+			import { GPUStatsPanel } from './jsm/utils/GPUStatsPanel.js';
 
 			import { GUI } from './jsm/libs/dat.gui.module.js';
 			import { OrbitControls } from './jsm/controls/OrbitControls.js';
@@ -29,7 +30,7 @@
 			let line, renderer, scene, camera, camera2, controls;
 			let line1;
 			let matLine, matLineBasic, matLineDashed;
-			let stats;
+			let stats, gpuPanel;
 			let gui;
 
 			// viewport
@@ -130,6 +131,10 @@
 				stats = new Stats();
 				document.body.appendChild( stats.dom );
 
+				gpuPanel = new GPUStatsPanel( renderer.getContext() );
+				stats.addPanel( gpuPanel );
+				stats.showPanel( 0 );
+
 				initGui();
 
 			}
@@ -164,7 +169,9 @@
 				// renderer will set this eventually
 				matLine.resolution.set( window.innerWidth, window.innerHeight ); // resolution of the viewport
 
+				gpuPanel.startQuery();
 				renderer.render( scene, camera );
+				gpuPanel.endQuery();
 
 				// inset scene