File size: 2,470 Bytes
b797337
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
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 if ( gl.isContextLost() === false ) {

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

			}

		};

	}

}