stats-gl 0.2.0 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,32 +1,31 @@
1
- # stats-gl
1
+ # 📈 stats-gl
2
+ [![Version](https://img.shields.io/npm/v/stats-gl?style=flat&colorA=000000&colorB=000000)](https://www.npmjs.com/package/stats-gl)
2
3
 
3
- stats-gl is a simple, yet powerful JavaScript library designed to help you monitor and visualize your web application's performance in real-time. The library provides panels that display Frames per Second (FPS), Central Processing Unit (CPU) usage, and if supported, Graphics Processing Unit (GPU) usage.
4
+ WebGL Performance Monitor tool.
4
5
 
5
- Note: GPU Monitoring will be available on Safari after the v17 release.
6
+ 🔗 [Live Demo](https://stats.renaudrohlinger.com/)
6
7
 
7
- ## Table of Contents
8
- - [Description](#description)
9
- - [Installation](#installation)
10
- - [Example Usage](#example-usage)
11
- - [Parameters](#parameters)
12
- - [Contributing](#contributing)
13
- - [License](#license)
14
8
 
15
- ## Description
9
+ https://github.com/RenaudRohlinger/stats-gl/assets/15867665/3fdafff4-1357-4872-9baf-0629dbaf9d8c
16
10
 
17
- The Stats class exposes methods to create performance panels, log performance metrics, and manage the display and layout of these panels. The performance metrics are logged for FPS CPU and GPU. The GPU logging is only available if the user's browser supports the WebGL 2.0 `EXT_disjoint_timer_query_webgl2` extension.
11
+
12
+ ### ❗📢 Note: GPU Monitoring will be available on Safari after the v17 release.
13
+
14
+ ## 📚 Description
15
+
16
+ `stats-gl` is a comprehensive tool to monitor WebGL performance. The Stats class provides methods to create performance panels, log performance metrics, and manage the display and layout of these panels. The performance metrics logged include FPS, CPU, and GPU. The GPU logging is available only if the user's browser supports the WebGL 2.0 `EXT_disjoint_timer_query_webgl2` extension.
18
17
 
19
18
  In addition to logging real-time performance data, the class also provides methods to calculate and display average performance metrics over a specified interval.
20
19
 
21
- ## Installation
20
+ ## ⬇️ Installation
22
21
 
23
- Stats.js is available as an npm package. You can install it using the following command:
22
+ Stats-gl is available as an npm package. You can install it using the following command:
24
23
 
25
24
  ```bash
26
25
  npm install stats-gl
27
26
  ```
28
27
 
29
- ## Example Usage
28
+ ## 🧑‍💻 Example Usage
30
29
 
31
30
  Below is an example of how you can use this class in your code:
32
31
  ```js
@@ -38,6 +37,7 @@ const stats = new Stats({
38
37
  samplesLog: 100,
39
38
  samplesGraph: 10,
40
39
  precision: 2,
40
+ horizontal: true,
41
41
  minimal: false,
42
42
  mode: 0
43
43
  });
@@ -52,24 +52,62 @@ stats.begin();
52
52
  stats.end();
53
53
  ```
54
54
 
55
- ## Parameters
55
+
56
+ Quick start with threejs:
57
+ ```js
58
+ import * as THREE from 'three';
59
+
60
+ import Stats from 'https://www.unpkg.com/stats-gl';
61
+
62
+ const container = document.getElementById( 'container' );
63
+
64
+ const stats = new Stats();
65
+ container.appendChild( stats.container );
66
+
67
+ const renderer = new THREE.WebGLRenderer( { antialias: true } );
68
+ container.appendChild( renderer.domElement );
69
+
70
+ const scene = new THREE.Scene();
71
+
72
+ stats.init( renderer.domElement );
73
+
74
+ scene.onBeforeRender = function () {
75
+
76
+ stats.begin();
77
+
78
+ };
79
+
80
+ scene.onAfterRender = function () {
81
+
82
+ stats.end();
83
+
84
+ };
85
+ ```
86
+
87
+
88
+ ## ⚙️ Parameters
56
89
  The constructor for the Stats class accepts an options object with the following properties:
57
90
 
58
- - logsPerSecond: How often to log performance data, in logs per second.
59
- - samplesLog: Number of recent log samples to keep for computing averages.
60
- - samplesGraph: Number of recent graph samples to keep for computing averages.
61
- - precision: Precision of the data, in number of decimal places.
62
- - minimal: A boolean value to control the minimalistic mode of the panel display. If set to true, a simple click on the panel will switch between different metrics.
63
- - mode: Sets the initial panel to display - 0 for FPS, 1 for CPU, and 2 for GPU (if supported).
91
+ - `logsPerSecond`: How often to log performance data, in logs per second.
92
+ - `samplesLog`: Number of recent log samples to keep for computing averages.
93
+ - `samplesGraph`: Number of recent graph samples to keep for computing averages.
94
+ - `precision`: Precision of the data, in number of decimal places (only affects CPU and GPU).
95
+ - `minimal`: A boolean value to control the minimalistic mode of the panel display. If set to true, a simple click on the panel will switch between different metrics.
96
+ - `mode`: Sets the initial panel to display - 0 for FPS, 1 for CPU, and 2 for GPU (if supported).
97
+ - `horizontal`: Display the canvases on the X axis, set to align on vertical axis.
64
98
 
65
99
  All the parameters are optional and have default values. The class also provides other methods such as begin(), end(), init(canvas), etc. which can be used based on the requirement.
66
100
 
67
- Note: The init(canvas) method is used to start the GPU monitoring and must be called with a canvas context before begin().
68
101
 
69
- ## Contributing
70
- We welcome contributions to Stats.js. Before contributing, please read our contributing guidelines and code of conduct.
102
+ ## 🤝 Contributing
103
+ Contributions to Stats-gl are welcome.
71
104
 
72
105
  Please report any issues or bugs you encounter.
73
106
 
74
- ## License
75
- This project is licensed under the MIT License.
107
+ ## 📜 License
108
+ This project is licensed under the MIT License.
109
+
110
+ ## 🧑‍🎨 Maintainers :
111
+
112
+ - [`twitter 🐈‍⬛ @onirenaud`](https://twitter.com/onirenaud)
113
+ - [`twitter @utsuboco`](https://twitter.com/utsuboco)
package/dist/main.cjs ADDED
@@ -0,0 +1,191 @@
1
+ "use strict";
2
+ const panel = require("./panel.cjs");
3
+ class Stats {
4
+ constructor({ logsPerSecond = 20, samplesLog = 100, samplesGraph = 10, precision = 2, minimal = false, horizontal = true, mode = 0 } = {}) {
5
+ this.mode = mode;
6
+ this.horizontal = horizontal;
7
+ this.container = document.createElement("div");
8
+ this.container.style.cssText = "position:fixed;top:0;left:0;opacity:0.9;z-index:10000;";
9
+ if (minimal) {
10
+ this.container.style.cssText += "cursor:pointer";
11
+ }
12
+ this.canvasGpu = null;
13
+ this.gl = null;
14
+ this.query = null;
15
+ this.minimal = minimal;
16
+ this.beginTime = (performance || Date).now();
17
+ this.prevTime = this.beginTime;
18
+ this.prevCpuTime = this.beginTime;
19
+ this.frames = 0;
20
+ this.averageCpu = {
21
+ logs: [],
22
+ graph: []
23
+ };
24
+ this.averageGpu = {
25
+ logs: [],
26
+ graph: []
27
+ };
28
+ this.queryCreated = false;
29
+ this.fpsPanel = this.addPanel(new Stats.Panel("FPS", "#0ff", "#002"), 0);
30
+ this.msPanel = this.addPanel(new Stats.Panel("CPU", "#0f0", "#020"), 1);
31
+ this.gpuPanel = null;
32
+ this.samplesLog = samplesLog;
33
+ this.samplesGraph = samplesGraph;
34
+ this.precision = precision;
35
+ this.logsPerSecond = logsPerSecond;
36
+ if (this.minimal) {
37
+ this.container.addEventListener("click", (event) => {
38
+ event.preventDefault();
39
+ this.showPanel(++this.mode % this.container.children.length);
40
+ }, false);
41
+ this.mode = mode;
42
+ this.showPanel(this.mode);
43
+ } else {
44
+ window.addEventListener("resize", () => {
45
+ this.resizePanel(this.fpsPanel, 0);
46
+ this.resizePanel(this.msPanel, 1);
47
+ if (this.gpuPanel) {
48
+ this.resizePanel(this.gpuPanel, 2);
49
+ }
50
+ });
51
+ }
52
+ }
53
+ resizePanel(panel2, offset) {
54
+ if (this.minimal) {
55
+ panel2.canvas.style.display = "none";
56
+ } else {
57
+ panel2.canvas.style.display = "block";
58
+ if (this.horizontal) {
59
+ panel2.canvas.style.top = "0px";
60
+ panel2.canvas.style.left = offset * panel2.WIDTH / panel2.PR + "px";
61
+ } else {
62
+ panel2.canvas.style.left = "0px";
63
+ panel2.canvas.style.top = offset * panel2.HEIGHT / panel2.PR + "px";
64
+ }
65
+ }
66
+ }
67
+ addPanel(panel2, offset) {
68
+ if (panel2.canvas) {
69
+ this.container.appendChild(panel2.canvas);
70
+ this.resizePanel(panel2, offset);
71
+ }
72
+ return panel2;
73
+ }
74
+ showPanel(id) {
75
+ for (let i = 0; i < this.container.children.length; i++) {
76
+ const child = this.container.children[i];
77
+ child.style.display = i === id ? "block" : "none";
78
+ }
79
+ this.mode = id;
80
+ }
81
+ init(canvas) {
82
+ this.canvasGpu = canvas;
83
+ if (!this.canvasGpu)
84
+ return;
85
+ this.gl = this.canvasGpu.getContext("webgl2");
86
+ this.ext = this.gl ? this.gl.getExtension("EXT_disjoint_timer_query_webgl2") : null;
87
+ if (this.ext) {
88
+ this.gpuPanel = this.addPanel(new Stats.Panel("GPU", "#ff0", "#220"), 2);
89
+ }
90
+ }
91
+ begin() {
92
+ this.beginProfiling("cpu-started");
93
+ if (!this.gl || !this.ext)
94
+ return;
95
+ if (this.query) {
96
+ const available = this.gl.getQueryParameter(this.query, this.gl.QUERY_RESULT_AVAILABLE);
97
+ this.disjoint = this.gl.getParameter(this.ext.GPU_DISJOINT_EXT);
98
+ if (available && !this.disjoint) {
99
+ this.ns = this.gl.getQueryParameter(this.query, this.gl.QUERY_RESULT);
100
+ const ms = this.ns * 1e-6;
101
+ if (available || this.disjoint) {
102
+ this.gl.deleteQuery(this.query);
103
+ this.query = null;
104
+ }
105
+ if (available) {
106
+ this.addToAverage(ms, this.averageGpu);
107
+ }
108
+ }
109
+ }
110
+ if (!this.query) {
111
+ this.queryCreated = true;
112
+ this.query = this.gl.createQuery();
113
+ if (this.query) {
114
+ this.gl.beginQuery(this.ext.TIME_ELAPSED_EXT, this.query);
115
+ }
116
+ }
117
+ }
118
+ end() {
119
+ this.beginTime = this.endInternal();
120
+ this.endProfiling("cpu-started", "cpu-finished", "cpu-duration", this.averageCpu);
121
+ if (!this.gl || !this.ext)
122
+ return;
123
+ if (this.queryCreated && this.gl.getQuery(this.ext.TIME_ELAPSED_EXT, this.gl.CURRENT_QUERY)) {
124
+ this.gl.endQuery(this.ext.TIME_ELAPSED_EXT);
125
+ }
126
+ }
127
+ endInternal() {
128
+ this.frames++;
129
+ const time = (performance || Date).now();
130
+ if (time >= this.prevCpuTime + 1e3 / this.logsPerSecond) {
131
+ this.updatePanel(this.msPanel, this.averageCpu);
132
+ this.updatePanel(this.gpuPanel, this.averageGpu);
133
+ this.prevCpuTime = time;
134
+ }
135
+ if (time >= this.prevTime + 1e3) {
136
+ const fps = this.frames * 1e3 / (time - this.prevTime);
137
+ this.fpsPanel.update(fps, fps, 100, 100, 0);
138
+ this.prevTime = time;
139
+ this.frames = 0;
140
+ }
141
+ return time;
142
+ }
143
+ addToAverage(value, averageArray) {
144
+ averageArray.logs.push(value);
145
+ if (averageArray.logs.length > this.samplesLog) {
146
+ averageArray.logs.shift();
147
+ }
148
+ averageArray.graph.push(value);
149
+ if (averageArray.graph.length > this.samplesGraph) {
150
+ averageArray.graph.shift();
151
+ }
152
+ }
153
+ beginProfiling(marker) {
154
+ if (window.performance) {
155
+ window.performance.mark(marker);
156
+ }
157
+ }
158
+ endProfiling(startMarker, endMarker, measureName, averageArray) {
159
+ if (window.performance && endMarker) {
160
+ window.performance.mark(endMarker);
161
+ const cpuMeasure = performance.measure(measureName, startMarker, endMarker);
162
+ this.addToAverage(cpuMeasure.duration, averageArray);
163
+ }
164
+ }
165
+ updatePanel(panel2, averageArray) {
166
+ if (averageArray.logs.length > 0) {
167
+ let sumLog = 0;
168
+ let max = 0.01;
169
+ for (let i = 0; i < averageArray.logs.length; i++) {
170
+ sumLog += averageArray.logs[i];
171
+ if (averageArray.logs[i] > max) {
172
+ max = averageArray.logs[i];
173
+ }
174
+ }
175
+ let sumGraph = 0;
176
+ let maxGraph = 0.01;
177
+ for (let i = 0; i < averageArray.graph.length; i++) {
178
+ sumGraph += averageArray.graph[i];
179
+ if (averageArray.graph[i] > maxGraph) {
180
+ maxGraph = averageArray.graph[i];
181
+ }
182
+ }
183
+ if (panel2) {
184
+ panel2.update(sumLog / Math.min(averageArray.logs.length, this.samplesLog), sumGraph / Math.min(averageArray.graph.length, this.samplesGraph), max, maxGraph, this.precision);
185
+ }
186
+ }
187
+ }
188
+ }
189
+ Stats.Panel = panel;
190
+ module.exports = Stats;
191
+ //# sourceMappingURL=main.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"main.cjs","sources":["../lib/main.ts"],"sourcesContent":null,"names":["panel","Panel"],"mappings":"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"}
package/dist/main.js ADDED
@@ -0,0 +1,192 @@
1
+ import Panel from "./panel.js";
2
+ class Stats {
3
+ constructor({ logsPerSecond = 20, samplesLog = 100, samplesGraph = 10, precision = 2, minimal = false, horizontal = true, mode = 0 } = {}) {
4
+ this.mode = mode;
5
+ this.horizontal = horizontal;
6
+ this.container = document.createElement("div");
7
+ this.container.style.cssText = "position:fixed;top:0;left:0;opacity:0.9;z-index:10000;";
8
+ if (minimal) {
9
+ this.container.style.cssText += "cursor:pointer";
10
+ }
11
+ this.canvasGpu = null;
12
+ this.gl = null;
13
+ this.query = null;
14
+ this.minimal = minimal;
15
+ this.beginTime = (performance || Date).now();
16
+ this.prevTime = this.beginTime;
17
+ this.prevCpuTime = this.beginTime;
18
+ this.frames = 0;
19
+ this.averageCpu = {
20
+ logs: [],
21
+ graph: []
22
+ };
23
+ this.averageGpu = {
24
+ logs: [],
25
+ graph: []
26
+ };
27
+ this.queryCreated = false;
28
+ this.fpsPanel = this.addPanel(new Stats.Panel("FPS", "#0ff", "#002"), 0);
29
+ this.msPanel = this.addPanel(new Stats.Panel("CPU", "#0f0", "#020"), 1);
30
+ this.gpuPanel = null;
31
+ this.samplesLog = samplesLog;
32
+ this.samplesGraph = samplesGraph;
33
+ this.precision = precision;
34
+ this.logsPerSecond = logsPerSecond;
35
+ if (this.minimal) {
36
+ this.container.addEventListener("click", (event) => {
37
+ event.preventDefault();
38
+ this.showPanel(++this.mode % this.container.children.length);
39
+ }, false);
40
+ this.mode = mode;
41
+ this.showPanel(this.mode);
42
+ } else {
43
+ window.addEventListener("resize", () => {
44
+ this.resizePanel(this.fpsPanel, 0);
45
+ this.resizePanel(this.msPanel, 1);
46
+ if (this.gpuPanel) {
47
+ this.resizePanel(this.gpuPanel, 2);
48
+ }
49
+ });
50
+ }
51
+ }
52
+ resizePanel(panel, offset) {
53
+ if (this.minimal) {
54
+ panel.canvas.style.display = "none";
55
+ } else {
56
+ panel.canvas.style.display = "block";
57
+ if (this.horizontal) {
58
+ panel.canvas.style.top = "0px";
59
+ panel.canvas.style.left = offset * panel.WIDTH / panel.PR + "px";
60
+ } else {
61
+ panel.canvas.style.left = "0px";
62
+ panel.canvas.style.top = offset * panel.HEIGHT / panel.PR + "px";
63
+ }
64
+ }
65
+ }
66
+ addPanel(panel, offset) {
67
+ if (panel.canvas) {
68
+ this.container.appendChild(panel.canvas);
69
+ this.resizePanel(panel, offset);
70
+ }
71
+ return panel;
72
+ }
73
+ showPanel(id) {
74
+ for (let i = 0; i < this.container.children.length; i++) {
75
+ const child = this.container.children[i];
76
+ child.style.display = i === id ? "block" : "none";
77
+ }
78
+ this.mode = id;
79
+ }
80
+ init(canvas) {
81
+ this.canvasGpu = canvas;
82
+ if (!this.canvasGpu)
83
+ return;
84
+ this.gl = this.canvasGpu.getContext("webgl2");
85
+ this.ext = this.gl ? this.gl.getExtension("EXT_disjoint_timer_query_webgl2") : null;
86
+ if (this.ext) {
87
+ this.gpuPanel = this.addPanel(new Stats.Panel("GPU", "#ff0", "#220"), 2);
88
+ }
89
+ }
90
+ begin() {
91
+ this.beginProfiling("cpu-started");
92
+ if (!this.gl || !this.ext)
93
+ return;
94
+ if (this.query) {
95
+ const available = this.gl.getQueryParameter(this.query, this.gl.QUERY_RESULT_AVAILABLE);
96
+ this.disjoint = this.gl.getParameter(this.ext.GPU_DISJOINT_EXT);
97
+ if (available && !this.disjoint) {
98
+ this.ns = this.gl.getQueryParameter(this.query, this.gl.QUERY_RESULT);
99
+ const ms = this.ns * 1e-6;
100
+ if (available || this.disjoint) {
101
+ this.gl.deleteQuery(this.query);
102
+ this.query = null;
103
+ }
104
+ if (available) {
105
+ this.addToAverage(ms, this.averageGpu);
106
+ }
107
+ }
108
+ }
109
+ if (!this.query) {
110
+ this.queryCreated = true;
111
+ this.query = this.gl.createQuery();
112
+ if (this.query) {
113
+ this.gl.beginQuery(this.ext.TIME_ELAPSED_EXT, this.query);
114
+ }
115
+ }
116
+ }
117
+ end() {
118
+ this.beginTime = this.endInternal();
119
+ this.endProfiling("cpu-started", "cpu-finished", "cpu-duration", this.averageCpu);
120
+ if (!this.gl || !this.ext)
121
+ return;
122
+ if (this.queryCreated && this.gl.getQuery(this.ext.TIME_ELAPSED_EXT, this.gl.CURRENT_QUERY)) {
123
+ this.gl.endQuery(this.ext.TIME_ELAPSED_EXT);
124
+ }
125
+ }
126
+ endInternal() {
127
+ this.frames++;
128
+ const time = (performance || Date).now();
129
+ if (time >= this.prevCpuTime + 1e3 / this.logsPerSecond) {
130
+ this.updatePanel(this.msPanel, this.averageCpu);
131
+ this.updatePanel(this.gpuPanel, this.averageGpu);
132
+ this.prevCpuTime = time;
133
+ }
134
+ if (time >= this.prevTime + 1e3) {
135
+ const fps = this.frames * 1e3 / (time - this.prevTime);
136
+ this.fpsPanel.update(fps, fps, 100, 100, 0);
137
+ this.prevTime = time;
138
+ this.frames = 0;
139
+ }
140
+ return time;
141
+ }
142
+ addToAverage(value, averageArray) {
143
+ averageArray.logs.push(value);
144
+ if (averageArray.logs.length > this.samplesLog) {
145
+ averageArray.logs.shift();
146
+ }
147
+ averageArray.graph.push(value);
148
+ if (averageArray.graph.length > this.samplesGraph) {
149
+ averageArray.graph.shift();
150
+ }
151
+ }
152
+ beginProfiling(marker) {
153
+ if (window.performance) {
154
+ window.performance.mark(marker);
155
+ }
156
+ }
157
+ endProfiling(startMarker, endMarker, measureName, averageArray) {
158
+ if (window.performance && endMarker) {
159
+ window.performance.mark(endMarker);
160
+ const cpuMeasure = performance.measure(measureName, startMarker, endMarker);
161
+ this.addToAverage(cpuMeasure.duration, averageArray);
162
+ }
163
+ }
164
+ updatePanel(panel, averageArray) {
165
+ if (averageArray.logs.length > 0) {
166
+ let sumLog = 0;
167
+ let max = 0.01;
168
+ for (let i = 0; i < averageArray.logs.length; i++) {
169
+ sumLog += averageArray.logs[i];
170
+ if (averageArray.logs[i] > max) {
171
+ max = averageArray.logs[i];
172
+ }
173
+ }
174
+ let sumGraph = 0;
175
+ let maxGraph = 0.01;
176
+ for (let i = 0; i < averageArray.graph.length; i++) {
177
+ sumGraph += averageArray.graph[i];
178
+ if (averageArray.graph[i] > maxGraph) {
179
+ maxGraph = averageArray.graph[i];
180
+ }
181
+ }
182
+ if (panel) {
183
+ panel.update(sumLog / Math.min(averageArray.logs.length, this.samplesLog), sumGraph / Math.min(averageArray.graph.length, this.samplesGraph), max, maxGraph, this.precision);
184
+ }
185
+ }
186
+ }
187
+ }
188
+ Stats.Panel = Panel;
189
+ export {
190
+ Stats as default
191
+ };
192
+ //# sourceMappingURL=main.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"main.js","sources":["../lib/main.ts"],"sourcesContent":null,"names":[],"mappings":"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"}
package/dist/panel.cjs ADDED
@@ -0,0 +1,57 @@
1
+ "use strict";
2
+ class Panel {
3
+ constructor(name, fg, bg) {
4
+ this.name = name;
5
+ this.fg = fg;
6
+ this.bg = bg;
7
+ this.PR = Math.round(window.devicePixelRatio || 1);
8
+ this.WIDTH = 90 * this.PR;
9
+ this.HEIGHT = 48 * this.PR;
10
+ this.TEXT_X = 3 * this.PR;
11
+ this.TEXT_Y = 2 * this.PR;
12
+ this.GRAPH_X = 3 * this.PR;
13
+ this.GRAPH_Y = 15 * this.PR;
14
+ this.GRAPH_WIDTH = 84 * this.PR;
15
+ this.GRAPH_HEIGHT = 30 * this.PR;
16
+ this.canvas = document.createElement("canvas");
17
+ this.canvas.width = 90 * this.PR;
18
+ this.canvas.height = 48 * this.PR;
19
+ this.canvas.style.width = "90px";
20
+ this.canvas.style.height = "48px";
21
+ this.canvas.style.cssText = "width:90px;height:48px";
22
+ this.context = this.canvas.getContext("2d");
23
+ if (this.context) {
24
+ this.context.font = "bold " + 9 * this.PR + "px Helvetica,Arial,sans-serif";
25
+ this.context.textBaseline = "top";
26
+ this.context.fillStyle = this.bg;
27
+ this.context.fillRect(0, 0, this.WIDTH, this.HEIGHT);
28
+ this.context.fillStyle = this.fg;
29
+ this.context.fillText(this.name, this.TEXT_X, this.TEXT_Y);
30
+ this.context.fillRect(this.GRAPH_X, this.GRAPH_Y, this.GRAPH_WIDTH, this.GRAPH_HEIGHT);
31
+ this.context.fillStyle = this.bg;
32
+ this.context.globalAlpha = 0.9;
33
+ this.context.fillRect(this.GRAPH_X, this.GRAPH_Y, this.GRAPH_WIDTH, this.GRAPH_HEIGHT);
34
+ }
35
+ }
36
+ update(value, valueGraph, maxValue, maxGraph, decimals = 0) {
37
+ let min = Infinity, max = 0;
38
+ if (!this.context)
39
+ return;
40
+ min = Math.min(min, value);
41
+ max = Math.max(maxValue, value);
42
+ maxGraph = Math.max(maxGraph, valueGraph);
43
+ this.context.fillStyle = this.bg;
44
+ this.context.globalAlpha = 1;
45
+ this.context.fillRect(0, 0, this.WIDTH, this.GRAPH_Y);
46
+ this.context.fillStyle = this.fg;
47
+ this.context.fillText(value.toFixed(decimals) + " " + this.name + " (" + min.toFixed(decimals) + "-" + parseFloat(max.toFixed(decimals)) + ")", this.TEXT_X, this.TEXT_Y);
48
+ this.context.drawImage(this.canvas, this.GRAPH_X + this.PR, this.GRAPH_Y, this.GRAPH_WIDTH - this.PR, this.GRAPH_HEIGHT, this.GRAPH_X, this.GRAPH_Y, this.GRAPH_WIDTH - this.PR, this.GRAPH_HEIGHT);
49
+ this.context.fillRect(this.GRAPH_X + this.GRAPH_WIDTH - this.PR, this.GRAPH_Y, this.PR, this.GRAPH_HEIGHT);
50
+ this.context.fillStyle = this.bg;
51
+ this.context.globalAlpha = 0.9;
52
+ this.context.fillRect(this.GRAPH_X + this.GRAPH_WIDTH - this.PR, this.GRAPH_Y, this.PR, (1 - valueGraph / maxGraph) * this.GRAPH_HEIGHT);
53
+ }
54
+ }
55
+ ;
56
+ module.exports = Panel;
57
+ //# sourceMappingURL=panel.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"panel.cjs","sources":["../lib/panel.ts"],"sourcesContent":null,"names":[],"mappings":";AAAA,MAAM,MAAM;AAAA,EAgBR,YAAY,MAAc,IAAY,IAAY;AAE9C,SAAK,OAAO;AACZ,SAAK,KAAK;AACV,SAAK,KAAK;AACV,SAAK,KAAK,KAAK,MAAO,OAAO,oBAAoB,CAAE;AAE9C,SAAA,QAAQ,KAAK,KAAK;AAClB,SAAA,SAAS,KAAK,KAAK;AACnB,SAAA,SAAS,IAAI,KAAK;AAClB,SAAA,SAAS,IAAI,KAAK;AAClB,SAAA,UAAU,IAAI,KAAK;AACnB,SAAA,UAAU,KAAK,KAAK;AACpB,SAAA,cAAc,KAAK,KAAK;AACxB,SAAA,eAAe,KAAK,KAAK;AAEzB,SAAA,SAAS,SAAS,cAAc,QAAQ;AACxC,SAAA,OAAO,QAAQ,KAAK,KAAK;AACzB,SAAA,OAAO,SAAS,KAAK,KAAK;AAC1B,SAAA,OAAO,MAAM,QAAQ;AACrB,SAAA,OAAO,MAAM,SAAS;AACtB,SAAA,OAAO,MAAM,UAAU;AAE5B,SAAK,UAAU,KAAK,OAAO,WAAW,IAAI;AAE1C,QAAI,KAAK,SAAS;AACd,WAAK,QAAQ,OAAO,UAAW,IAAI,KAAK,KAAM;AAC9C,WAAK,QAAQ,eAAe;AAEvB,WAAA,QAAQ,YAAY,KAAK;AAC9B,WAAK,QAAQ,SAAS,GAAG,GAAG,KAAK,OAAO,KAAK,MAAM;AAE9C,WAAA,QAAQ,YAAY,KAAK;AAC9B,WAAK,QAAQ,SAAS,KAAK,MAAM,KAAK,QAAQ,KAAK,MAAM;AACpD,WAAA,QAAQ,SAAS,KAAK,SAAS,KAAK,SAAS,KAAK,aAAa,KAAK,YAAY;AAEhF,WAAA,QAAQ,YAAY,KAAK;AAC9B,WAAK,QAAQ,cAAc;AACtB,WAAA,QAAQ,SAAS,KAAK,SAAS,KAAK,SAAS,KAAK,aAAa,KAAK,YAAY;AAAA,IACzF;AAAA,EAEJ;AAAA,EAEA,OAAO,OAAe,YAAoB,UAAkB,UAAkB,WAAW,GAAG;AACpF,QAAA,MAAM,UAAU,MAAM;AAE1B,QAAI,CAAC,KAAK;AAAS;AAEb,UAAA,KAAK,IAAI,KAAK,KAAK;AACnB,UAAA,KAAK,IAAI,UAAU,KAAK;AACnB,eAAA,KAAK,IAAI,UAAU,UAAU;AAEnC,SAAA,QAAQ,YAAY,KAAK;AAC9B,SAAK,QAAQ,cAAc;AAC3B,SAAK,QAAQ,SAAS,GAAG,GAAG,KAAK,OAAO,KAAK,OAAO;AAC/C,SAAA,QAAQ,YAAY,KAAK;AACzB,SAAA,QAAQ,SAAS,MAAM,QAAQ,QAAQ,IAAI,MAAM,KAAK,OAAO,OAAO,IAAI,QAAQ,QAAQ,IAAI,MAAM,WAAW,IAAI,QAAQ,QAAQ,CAAC,IAAI,KAAK,KAAK,QAAQ,KAAK,MAAM;AAEnK,SAAA,QAAQ,UAAU,KAAK,QAAQ,KAAK,UAAU,KAAK,IAAI,KAAK,SAAS,KAAK,cAAc,KAAK,IAAI,KAAK,cAAc,KAAK,SAAS,KAAK,SAAS,KAAK,cAAc,KAAK,IAAI,KAAK,YAAY;AAElM,SAAK,QAAQ,SAAS,KAAK,UAAU,KAAK,cAAc,KAAK,IAAI,KAAK,SAAS,KAAK,IAAI,KAAK,YAAY;AAEpG,SAAA,QAAQ,YAAY,KAAK;AAC9B,SAAK,QAAQ,cAAc;AAE3B,SAAK,QAAQ,SAAS,KAAK,UAAU,KAAK,cAAc,KAAK,IAAI,KAAK,SAAS,KAAK,KAAM,IAAK,aAAa,YAAc,KAAK,YAAY;AAAA,EAC/I;AACJ;AAAC;;"}
package/dist/panel.js ADDED
@@ -0,0 +1,58 @@
1
+ class Panel {
2
+ constructor(name, fg, bg) {
3
+ this.name = name;
4
+ this.fg = fg;
5
+ this.bg = bg;
6
+ this.PR = Math.round(window.devicePixelRatio || 1);
7
+ this.WIDTH = 90 * this.PR;
8
+ this.HEIGHT = 48 * this.PR;
9
+ this.TEXT_X = 3 * this.PR;
10
+ this.TEXT_Y = 2 * this.PR;
11
+ this.GRAPH_X = 3 * this.PR;
12
+ this.GRAPH_Y = 15 * this.PR;
13
+ this.GRAPH_WIDTH = 84 * this.PR;
14
+ this.GRAPH_HEIGHT = 30 * this.PR;
15
+ this.canvas = document.createElement("canvas");
16
+ this.canvas.width = 90 * this.PR;
17
+ this.canvas.height = 48 * this.PR;
18
+ this.canvas.style.width = "90px";
19
+ this.canvas.style.height = "48px";
20
+ this.canvas.style.cssText = "width:90px;height:48px";
21
+ this.context = this.canvas.getContext("2d");
22
+ if (this.context) {
23
+ this.context.font = "bold " + 9 * this.PR + "px Helvetica,Arial,sans-serif";
24
+ this.context.textBaseline = "top";
25
+ this.context.fillStyle = this.bg;
26
+ this.context.fillRect(0, 0, this.WIDTH, this.HEIGHT);
27
+ this.context.fillStyle = this.fg;
28
+ this.context.fillText(this.name, this.TEXT_X, this.TEXT_Y);
29
+ this.context.fillRect(this.GRAPH_X, this.GRAPH_Y, this.GRAPH_WIDTH, this.GRAPH_HEIGHT);
30
+ this.context.fillStyle = this.bg;
31
+ this.context.globalAlpha = 0.9;
32
+ this.context.fillRect(this.GRAPH_X, this.GRAPH_Y, this.GRAPH_WIDTH, this.GRAPH_HEIGHT);
33
+ }
34
+ }
35
+ update(value, valueGraph, maxValue, maxGraph, decimals = 0) {
36
+ let min = Infinity, max = 0;
37
+ if (!this.context)
38
+ return;
39
+ min = Math.min(min, value);
40
+ max = Math.max(maxValue, value);
41
+ maxGraph = Math.max(maxGraph, valueGraph);
42
+ this.context.fillStyle = this.bg;
43
+ this.context.globalAlpha = 1;
44
+ this.context.fillRect(0, 0, this.WIDTH, this.GRAPH_Y);
45
+ this.context.fillStyle = this.fg;
46
+ this.context.fillText(value.toFixed(decimals) + " " + this.name + " (" + min.toFixed(decimals) + "-" + parseFloat(max.toFixed(decimals)) + ")", this.TEXT_X, this.TEXT_Y);
47
+ this.context.drawImage(this.canvas, this.GRAPH_X + this.PR, this.GRAPH_Y, this.GRAPH_WIDTH - this.PR, this.GRAPH_HEIGHT, this.GRAPH_X, this.GRAPH_Y, this.GRAPH_WIDTH - this.PR, this.GRAPH_HEIGHT);
48
+ this.context.fillRect(this.GRAPH_X + this.GRAPH_WIDTH - this.PR, this.GRAPH_Y, this.PR, this.GRAPH_HEIGHT);
49
+ this.context.fillStyle = this.bg;
50
+ this.context.globalAlpha = 0.9;
51
+ this.context.fillRect(this.GRAPH_X + this.GRAPH_WIDTH - this.PR, this.GRAPH_Y, this.PR, (1 - valueGraph / maxGraph) * this.GRAPH_HEIGHT);
52
+ }
53
+ }
54
+ ;
55
+ export {
56
+ Panel as default
57
+ };
58
+ //# sourceMappingURL=panel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"panel.js","sources":["../lib/panel.ts"],"sourcesContent":null,"names":[],"mappings":"AAAA,MAAM,MAAM;AAAA,EAgBR,YAAY,MAAc,IAAY,IAAY;AAE9C,SAAK,OAAO;AACZ,SAAK,KAAK;AACV,SAAK,KAAK;AACV,SAAK,KAAK,KAAK,MAAO,OAAO,oBAAoB,CAAE;AAE9C,SAAA,QAAQ,KAAK,KAAK;AAClB,SAAA,SAAS,KAAK,KAAK;AACnB,SAAA,SAAS,IAAI,KAAK;AAClB,SAAA,SAAS,IAAI,KAAK;AAClB,SAAA,UAAU,IAAI,KAAK;AACnB,SAAA,UAAU,KAAK,KAAK;AACpB,SAAA,cAAc,KAAK,KAAK;AACxB,SAAA,eAAe,KAAK,KAAK;AAEzB,SAAA,SAAS,SAAS,cAAc,QAAQ;AACxC,SAAA,OAAO,QAAQ,KAAK,KAAK;AACzB,SAAA,OAAO,SAAS,KAAK,KAAK;AAC1B,SAAA,OAAO,MAAM,QAAQ;AACrB,SAAA,OAAO,MAAM,SAAS;AACtB,SAAA,OAAO,MAAM,UAAU;AAE5B,SAAK,UAAU,KAAK,OAAO,WAAW,IAAI;AAE1C,QAAI,KAAK,SAAS;AACd,WAAK,QAAQ,OAAO,UAAW,IAAI,KAAK,KAAM;AAC9C,WAAK,QAAQ,eAAe;AAEvB,WAAA,QAAQ,YAAY,KAAK;AAC9B,WAAK,QAAQ,SAAS,GAAG,GAAG,KAAK,OAAO,KAAK,MAAM;AAE9C,WAAA,QAAQ,YAAY,KAAK;AAC9B,WAAK,QAAQ,SAAS,KAAK,MAAM,KAAK,QAAQ,KAAK,MAAM;AACpD,WAAA,QAAQ,SAAS,KAAK,SAAS,KAAK,SAAS,KAAK,aAAa,KAAK,YAAY;AAEhF,WAAA,QAAQ,YAAY,KAAK;AAC9B,WAAK,QAAQ,cAAc;AACtB,WAAA,QAAQ,SAAS,KAAK,SAAS,KAAK,SAAS,KAAK,aAAa,KAAK,YAAY;AAAA,IACzF;AAAA,EAEJ;AAAA,EAEA,OAAO,OAAe,YAAoB,UAAkB,UAAkB,WAAW,GAAG;AACpF,QAAA,MAAM,UAAU,MAAM;AAE1B,QAAI,CAAC,KAAK;AAAS;AAEb,UAAA,KAAK,IAAI,KAAK,KAAK;AACnB,UAAA,KAAK,IAAI,UAAU,KAAK;AACnB,eAAA,KAAK,IAAI,UAAU,UAAU;AAEnC,SAAA,QAAQ,YAAY,KAAK;AAC9B,SAAK,QAAQ,cAAc;AAC3B,SAAK,QAAQ,SAAS,GAAG,GAAG,KAAK,OAAO,KAAK,OAAO;AAC/C,SAAA,QAAQ,YAAY,KAAK;AACzB,SAAA,QAAQ,SAAS,MAAM,QAAQ,QAAQ,IAAI,MAAM,KAAK,OAAO,OAAO,IAAI,QAAQ,QAAQ,IAAI,MAAM,WAAW,IAAI,QAAQ,QAAQ,CAAC,IAAI,KAAK,KAAK,QAAQ,KAAK,MAAM;AAEnK,SAAA,QAAQ,UAAU,KAAK,QAAQ,KAAK,UAAU,KAAK,IAAI,KAAK,SAAS,KAAK,cAAc,KAAK,IAAI,KAAK,cAAc,KAAK,SAAS,KAAK,SAAS,KAAK,cAAc,KAAK,IAAI,KAAK,YAAY;AAElM,SAAK,QAAQ,SAAS,KAAK,UAAU,KAAK,cAAc,KAAK,IAAI,KAAK,SAAS,KAAK,IAAI,KAAK,YAAY;AAEpG,SAAA,QAAQ,YAAY,KAAK;AAC9B,SAAK,QAAQ,cAAc;AAE3B,SAAK,QAAQ,SAAS,KAAK,UAAU,KAAK,cAAc,KAAK,IAAI,KAAK,SAAS,KAAK,KAAM,IAAK,aAAa,YAAc,KAAK,YAAY;AAAA,EAC/I;AACJ;AAAC;"}
@@ -25,6 +25,7 @@ declare class Stats {
25
25
  mode: number;
26
26
  container: HTMLDivElement;
27
27
  minimal: boolean;
28
+ horizontal: boolean;
28
29
  beginTime: number;
29
30
  prevTime: number;
30
31
  prevCpuTime: number;
@@ -46,12 +47,13 @@ declare class Stats {
46
47
  query: WebGLQuery | null;
47
48
  disjoint: any;
48
49
  ns: any;
49
- constructor({ logsPerSecond, samplesLog, samplesGraph, precision, minimal, mode }?: {
50
+ constructor({ logsPerSecond, samplesLog, samplesGraph, precision, minimal, horizontal, mode }?: {
50
51
  logsPerSecond?: number | undefined;
51
52
  samplesLog?: number | undefined;
52
53
  samplesGraph?: number | undefined;
53
54
  precision?: number | undefined;
54
55
  minimal?: boolean | undefined;
56
+ horizontal?: boolean | undefined;
55
57
  mode?: number | undefined;
56
58
  });
57
59
  resizePanel(panel: Panel, offset: number): void;
package/lib/main.ts ADDED
@@ -0,0 +1,339 @@
1
+ import Panel from "./panel";
2
+
3
+ export interface AverageArray {
4
+ logs: number[];
5
+ graph: number[];
6
+ }
7
+
8
+
9
+ class Stats {
10
+ mode: number;
11
+ container: HTMLDivElement;
12
+ minimal: boolean;
13
+ horizontal: boolean;
14
+ beginTime: number;
15
+ prevTime: number;
16
+ prevCpuTime: number;
17
+ frames: number;
18
+ averageCpu: AverageArray;
19
+ averageGpu: AverageArray;
20
+ queryCreated: boolean;
21
+ fpsPanel: Panel;
22
+ static Panel: any;
23
+ msPanel: Panel;
24
+ gpuPanel: Panel | null;
25
+ samplesLog: number;
26
+ samplesGraph: number;
27
+ logsPerSecond: number;
28
+ precision: number;
29
+ canvasGpu: HTMLCanvasElement | null;
30
+ gl: WebGL2RenderingContext | null;
31
+ ext: any;
32
+ query: WebGLQuery | null;
33
+ disjoint: any;
34
+ ns: any;
35
+
36
+ constructor( { logsPerSecond = 20, samplesLog = 100, samplesGraph = 10, precision = 2, minimal = false, horizontal = true, mode = 0 } = {} ) {
37
+
38
+ this.mode = mode;
39
+ this.horizontal = horizontal;
40
+ this.container = document.createElement( 'div' );
41
+ this.container.style.cssText = 'position:fixed;top:0;left:0;opacity:0.9;z-index:10000;';
42
+
43
+ if ( minimal ) {
44
+
45
+ this.container.style.cssText += 'cursor:pointer';
46
+
47
+ }
48
+
49
+ this.canvasGpu = null;
50
+ this.gl = null;
51
+ this.query = null;
52
+
53
+ this.minimal = minimal;
54
+
55
+ this.beginTime = ( performance || Date ).now();
56
+ this.prevTime = this.beginTime;
57
+ this.prevCpuTime = this.beginTime;
58
+ this.frames = 0;
59
+ this.averageCpu = {
60
+ logs: [],
61
+ graph: []
62
+ };
63
+ this.averageGpu = {
64
+ logs: [],
65
+ graph: []
66
+ };
67
+
68
+ this.queryCreated = false;
69
+
70
+ this.fpsPanel = this.addPanel( new Stats.Panel( 'FPS', '#0ff', '#002' ), 0 );
71
+ this.msPanel = this.addPanel( new Stats.Panel( 'CPU', '#0f0', '#020' ), 1 );
72
+ this.gpuPanel = null;
73
+
74
+ this.samplesLog = samplesLog;
75
+ this.samplesGraph = samplesGraph;
76
+ this.precision = precision;
77
+ this.logsPerSecond = logsPerSecond;
78
+
79
+ if ( this.minimal ) {
80
+
81
+ this.container.addEventListener( 'click', ( event ) => {
82
+
83
+ event.preventDefault();
84
+ this.showPanel( ++ this.mode % this.container.children.length );
85
+
86
+ }, false );
87
+
88
+ this.mode = mode;
89
+ this.showPanel( this.mode );
90
+
91
+ } else {
92
+
93
+ window.addEventListener('resize', () =>{
94
+
95
+ this.resizePanel( this.fpsPanel, 0 );
96
+ this.resizePanel( this.msPanel, 1 );
97
+
98
+ if (this.gpuPanel) {
99
+ this.resizePanel( this.gpuPanel, 2 );
100
+ }
101
+ })
102
+ }
103
+
104
+ }
105
+
106
+ resizePanel( panel: Panel, offset: number) {
107
+
108
+ if ( this.minimal ) {
109
+
110
+ panel.canvas.style.display = 'none';
111
+
112
+ } else {
113
+
114
+ panel.canvas.style.display = 'block';
115
+ if (this.horizontal) {
116
+ panel.canvas.style.top = '0px';
117
+ panel.canvas.style.left = offset * panel.WIDTH / panel.PR + 'px';
118
+ } else {
119
+ panel.canvas.style.left = '0px';
120
+ panel.canvas.style.top = offset * panel.HEIGHT / panel.PR + 'px';
121
+
122
+ }
123
+ }
124
+ }
125
+
126
+ addPanel(panel: Panel, offset: number) {
127
+
128
+ if(panel.canvas) {
129
+
130
+ this.container.appendChild(panel.canvas);
131
+
132
+ this.resizePanel(panel, offset);
133
+
134
+ }
135
+
136
+ return panel;
137
+
138
+ }
139
+
140
+ showPanel( id: number ) {
141
+
142
+ for ( let i = 0; i < this.container.children.length; i ++ ) {
143
+ const child = this.container.children[i] as HTMLElement;
144
+
145
+ child.style.display = i === id ? 'block' : 'none';
146
+
147
+ }
148
+
149
+ this.mode = id;
150
+
151
+ }
152
+
153
+ init( canvas: any ) {
154
+
155
+ this.canvasGpu = canvas;
156
+ if ( ! this.canvasGpu ) return;
157
+ this.gl = this.canvasGpu.getContext( 'webgl2' );
158
+ this.ext = this.gl ? this.gl.getExtension( 'EXT_disjoint_timer_query_webgl2' ) : null;
159
+ if ( this.ext ) {
160
+
161
+ this.gpuPanel = this.addPanel( new Stats.Panel( 'GPU', '#ff0', '#220' ), 2 );
162
+
163
+ }
164
+
165
+ }
166
+
167
+ begin() {
168
+
169
+ this.beginProfiling( 'cpu-started' );
170
+ if ( ! this.gl || ! this.ext ) return;
171
+
172
+
173
+ if ( this.query ) {
174
+
175
+ const available = this.gl.getQueryParameter( this.query, this.gl.QUERY_RESULT_AVAILABLE );
176
+ this.disjoint = this.gl.getParameter( this.ext.GPU_DISJOINT_EXT );
177
+
178
+ if ( available && ! this.disjoint ) {
179
+
180
+ this.ns = this.gl.getQueryParameter( this.query, this.gl.QUERY_RESULT );
181
+ const ms = this.ns * 1e-6;
182
+
183
+ if ( available || this.disjoint ) {
184
+
185
+ this.gl.deleteQuery( this.query );
186
+ this.query = null;
187
+
188
+ }
189
+
190
+ if ( available ) {
191
+
192
+ this.addToAverage( ms, this.averageGpu );
193
+
194
+ }
195
+
196
+ }
197
+
198
+ }
199
+
200
+ if ( ! this.query ) {
201
+
202
+ this.queryCreated = true;
203
+ this.query = this.gl.createQuery();
204
+
205
+ if ( this.query ) {
206
+ this.gl.beginQuery( this.ext.TIME_ELAPSED_EXT, this.query );
207
+ }
208
+
209
+ }
210
+
211
+ }
212
+
213
+ end() {
214
+
215
+ this.beginTime = this.endInternal()
216
+
217
+ this.endProfiling( 'cpu-started', 'cpu-finished', 'cpu-duration', this.averageCpu );
218
+
219
+ if ( ! this.gl || ! this.ext ) return;
220
+
221
+
222
+ if ( this.queryCreated && this.gl.getQuery( this.ext.TIME_ELAPSED_EXT, this.gl.CURRENT_QUERY ) ) {
223
+
224
+ this.gl.endQuery( this.ext.TIME_ELAPSED_EXT );
225
+
226
+ }
227
+
228
+
229
+ }
230
+
231
+ endInternal() {
232
+
233
+ this.frames ++;
234
+ const time = ( performance || Date ).now();
235
+
236
+ if (time >= this.prevCpuTime + 1000 / this.logsPerSecond) {
237
+ this.updatePanel( this.msPanel, this.averageCpu );
238
+ this.updatePanel( this.gpuPanel, this.averageGpu );
239
+
240
+ this.prevCpuTime = time;
241
+ }
242
+
243
+ if ( time >= this.prevTime + 1000 ) {
244
+
245
+ const fps = ( this.frames * 1000 ) / ( time - this.prevTime );
246
+
247
+ this.fpsPanel.update(fps, fps, 100, 100, 0);
248
+
249
+ this.prevTime = time;
250
+ this.frames = 0;
251
+
252
+ }
253
+
254
+ return time;
255
+
256
+ }
257
+
258
+ addToAverage( value: number, averageArray: { logs: any; graph: any; } ) {
259
+
260
+ averageArray.logs.push( value );
261
+ if ( averageArray.logs.length > this.samplesLog ) {
262
+
263
+ averageArray.logs.shift();
264
+
265
+ }
266
+
267
+ averageArray.graph.push( value );
268
+ if ( averageArray.graph.length > this.samplesGraph ) {
269
+
270
+ averageArray.graph.shift();
271
+
272
+ }
273
+
274
+ }
275
+
276
+ beginProfiling( marker: string ) {
277
+
278
+ if ( window.performance ) {
279
+
280
+ window.performance.mark( marker );
281
+
282
+ }
283
+
284
+ }
285
+
286
+ endProfiling( startMarker: string | PerformanceMeasureOptions | undefined, endMarker: string | undefined, measureName: string, averageArray: {logs: number[], graph: number[]} ) {
287
+
288
+ if ( window.performance && endMarker ) {
289
+
290
+ window.performance.mark( endMarker );
291
+ const cpuMeasure = performance.measure( measureName, startMarker, endMarker );
292
+ this.addToAverage( cpuMeasure.duration, averageArray );
293
+
294
+ }
295
+
296
+ }
297
+
298
+ updatePanel(panel: { update: any; } | null, averageArray: {logs: number[], graph: number[]}) {
299
+
300
+ if (averageArray.logs.length > 0) {
301
+
302
+ let sumLog = 0;
303
+ let max = 0.01;
304
+
305
+ for (let i = 0; i < averageArray.logs.length; i++) {
306
+
307
+ sumLog += averageArray.logs[i];
308
+
309
+ if (averageArray.logs[i] > max) {
310
+ max = averageArray.logs[i];
311
+ }
312
+
313
+ }
314
+
315
+ let sumGraph = 0;
316
+ let maxGraph = 0.01;
317
+ for (let i = 0; i < averageArray.graph.length; i++) {
318
+
319
+ sumGraph += averageArray.graph[i];
320
+
321
+ if (averageArray.graph[i] > maxGraph) {
322
+ maxGraph = averageArray.graph[i];
323
+ }
324
+
325
+ }
326
+
327
+ if (panel) {
328
+ panel.update(sumLog / Math.min(averageArray.logs.length,this.samplesLog), sumGraph / Math.min(averageArray.graph.length,this.samplesGraph), max, maxGraph, this.precision);
329
+ }
330
+
331
+ }
332
+ }
333
+
334
+
335
+ }
336
+
337
+ Stats.Panel = Panel
338
+
339
+ export default Stats;
package/lib/panel.ts ADDED
@@ -0,0 +1,86 @@
1
+ class Panel {
2
+ canvas: HTMLCanvasElement;
3
+ context: CanvasRenderingContext2D | null;
4
+ name: string;
5
+ fg: string;
6
+ bg: string;
7
+ PR: number;
8
+ WIDTH: number;
9
+ HEIGHT: number;
10
+ TEXT_X: number;
11
+ TEXT_Y: number;
12
+ GRAPH_X: number;
13
+ GRAPH_Y: number;
14
+ GRAPH_WIDTH: number;
15
+ GRAPH_HEIGHT: number;
16
+
17
+ constructor(name: string, fg: string, bg: string) {
18
+
19
+ this.name = name;
20
+ this.fg = fg;
21
+ this.bg = bg;
22
+ this.PR = Math.round( window.devicePixelRatio || 1 );
23
+
24
+ this.WIDTH = 90 * this.PR;
25
+ this.HEIGHT = 48 * this.PR;
26
+ this.TEXT_X = 3 * this.PR;
27
+ this.TEXT_Y = 2 * this.PR;
28
+ this.GRAPH_X = 3 * this.PR;
29
+ this.GRAPH_Y = 15 * this.PR;
30
+ this.GRAPH_WIDTH = 84 * this.PR;
31
+ this.GRAPH_HEIGHT = 30 * this.PR;
32
+
33
+ this.canvas = document.createElement('canvas');
34
+ this.canvas.width = 90 * this.PR;
35
+ this.canvas.height = 48 * this.PR;
36
+ this.canvas.style.width = '90px';
37
+ this.canvas.style.height = '48px';
38
+ this.canvas.style.cssText = 'width:90px;height:48px';
39
+
40
+ this.context = this.canvas.getContext('2d');
41
+
42
+ if (this.context) {
43
+ this.context.font = 'bold ' + (9 * this.PR) + 'px Helvetica,Arial,sans-serif';
44
+ this.context.textBaseline = 'top';
45
+
46
+ this.context.fillStyle = this.bg;
47
+ this.context.fillRect(0, 0, this.WIDTH, this.HEIGHT);
48
+
49
+ this.context.fillStyle = this.fg;
50
+ this.context.fillText(this.name, this.TEXT_X, this.TEXT_Y);
51
+ this.context.fillRect(this.GRAPH_X, this.GRAPH_Y, this.GRAPH_WIDTH, this.GRAPH_HEIGHT);
52
+
53
+ this.context.fillStyle = this.bg;
54
+ this.context.globalAlpha = 0.9;
55
+ this.context.fillRect(this.GRAPH_X, this.GRAPH_Y, this.GRAPH_WIDTH, this.GRAPH_HEIGHT);
56
+ }
57
+
58
+ }
59
+
60
+ update(value: number, valueGraph: number, maxValue: number, maxGraph: number, decimals = 0) {
61
+ let min = Infinity, max = 0;
62
+
63
+ if (!this.context) return;
64
+
65
+ min = Math.min(min, value);
66
+ max = Math.max(maxValue, value);
67
+ maxGraph = Math.max(maxGraph, valueGraph);
68
+
69
+ this.context.fillStyle = this.bg;
70
+ this.context.globalAlpha = 1;
71
+ this.context.fillRect(0, 0, this.WIDTH, this.GRAPH_Y);
72
+ this.context.fillStyle = this.fg;
73
+ this.context.fillText(value.toFixed(decimals) + ' ' + this.name + ' (' + min.toFixed(decimals) + '-' + parseFloat(max.toFixed(decimals)) + ')', this.TEXT_X, this.TEXT_Y);
74
+
75
+ this.context.drawImage(this.canvas, this.GRAPH_X + this.PR, this.GRAPH_Y, this.GRAPH_WIDTH - this.PR, this.GRAPH_HEIGHT, this.GRAPH_X, this.GRAPH_Y, this.GRAPH_WIDTH - this.PR, this.GRAPH_HEIGHT);
76
+
77
+ this.context.fillRect(this.GRAPH_X + this.GRAPH_WIDTH - this.PR, this.GRAPH_Y, this.PR, this.GRAPH_HEIGHT);
78
+
79
+ this.context.fillStyle = this.bg;
80
+ this.context.globalAlpha = 0.9;
81
+
82
+ this.context.fillRect(this.GRAPH_X + this.GRAPH_WIDTH - this.PR, this.GRAPH_Y, this.PR, ((1 - (valueGraph / maxGraph))) * this.GRAPH_HEIGHT);
83
+ }
84
+ };
85
+
86
+ export default Panel;
package/package.json CHANGED
@@ -1,19 +1,31 @@
1
1
  {
2
2
  "name": "stats-gl",
3
- "version": "0.2.0",
3
+ "version": "1.0.0",
4
4
  "type": "module",
5
+ "author": "Renaud ROHLINGER (https://github.com/RenaudRohlinger)",
6
+ "homepage": "https://github.com/RenaudRohlinger/stats-gl",
7
+ "repository": "https://github.com/RenaudRohlinger/stats-gl",
8
+ "license": "MIT",
5
9
  "files": [
6
- "dist"
10
+ "dist/*",
11
+ "lib/*"
7
12
  ],
8
- "main": "./dist/stats-gl.umd.js",
9
- "module": "./dist/stats-gl.js",
10
13
  "types": "./dist/stats-gl.d.ts",
14
+ "main": "./dist/main.js",
15
+ "module": "./dist/main.mjs",
11
16
  "exports": {
12
17
  ".": {
13
- "import": "./dist/stats-gl.js",
14
- "require": "./dist/stats-gl.umd.js"
18
+ "types": "./dist/main.d.ts",
19
+ "require": "./dist/main.js",
20
+ "import": "./dist/main.mjs"
21
+ },
22
+ "./panel": {
23
+ "types": "./dist/panel.d.ts",
24
+ "require": "./dist/panel.js",
25
+ "import": "./dist/panel.mjs"
15
26
  }
16
27
  },
28
+ "sideEffects": false,
17
29
  "scripts": {
18
30
  "dev": "vite demo",
19
31
  "serve": "vite serve demo",
@@ -1,135 +0,0 @@
1
- var P = Object.defineProperty;
2
- var g = (o, t, i) => t in o ? P(o, t, { enumerable: !0, configurable: !0, writable: !0, value: i }) : o[t] = i;
3
- var s = (o, t, i) => (g(o, typeof t != "symbol" ? t + "" : t, i), i);
4
- class p {
5
- constructor(t, i, h) {
6
- s(this, "canvas");
7
- s(this, "context");
8
- s(this, "name");
9
- s(this, "fg");
10
- s(this, "bg");
11
- s(this, "PR");
12
- s(this, "WIDTH");
13
- s(this, "HEIGHT");
14
- s(this, "TEXT_X");
15
- s(this, "TEXT_Y");
16
- s(this, "GRAPH_X");
17
- s(this, "GRAPH_Y");
18
- s(this, "GRAPH_WIDTH");
19
- s(this, "GRAPH_HEIGHT");
20
- this.name = t, this.fg = i, this.bg = h, this.PR = Math.round(window.devicePixelRatio || 1), this.WIDTH = 90 * this.PR, this.HEIGHT = 48 * this.PR, this.TEXT_X = 3 * this.PR, this.TEXT_Y = 2 * this.PR, this.GRAPH_X = 3 * this.PR, this.GRAPH_Y = 15 * this.PR, this.GRAPH_WIDTH = 84 * this.PR, this.GRAPH_HEIGHT = 30 * this.PR, this.canvas = document.createElement("canvas"), this.canvas.width = 90 * this.PR, this.canvas.height = 48 * this.PR, this.canvas.style.width = "90px", this.canvas.style.height = "48px", this.canvas.style.cssText = "width:90px;height:48px", this.context = this.canvas.getContext("2d"), this.context && (this.context.font = "bold " + 9 * this.PR + "px Helvetica,Arial,sans-serif", this.context.textBaseline = "top", this.context.fillStyle = this.bg, this.context.fillRect(0, 0, this.WIDTH, this.HEIGHT), this.context.fillStyle = this.fg, this.context.fillText(this.name, this.TEXT_X, this.TEXT_Y), this.context.fillRect(this.GRAPH_X, this.GRAPH_Y, this.GRAPH_WIDTH, this.GRAPH_HEIGHT), this.context.fillStyle = this.bg, this.context.globalAlpha = 0.9, this.context.fillRect(this.GRAPH_X, this.GRAPH_Y, this.GRAPH_WIDTH, this.GRAPH_HEIGHT));
21
- }
22
- update(t, i, h, l, n = 0) {
23
- let a = 1 / 0, e = 0;
24
- this.context && (a = Math.min(a, t), e = Math.max(h, t), l = Math.max(l, i), this.context.fillStyle = this.bg, this.context.globalAlpha = 1, this.context.fillRect(0, 0, this.WIDTH, this.GRAPH_Y), this.context.fillStyle = this.fg, this.context.fillText(t.toFixed(n) + " " + this.name + " (" + a.toFixed(n) + "-" + parseFloat(e.toFixed(n)) + ")", this.TEXT_X, this.TEXT_Y), this.context.drawImage(this.canvas, this.GRAPH_X + this.PR, this.GRAPH_Y, this.GRAPH_WIDTH - this.PR, this.GRAPH_HEIGHT, this.GRAPH_X, this.GRAPH_Y, this.GRAPH_WIDTH - this.PR, this.GRAPH_HEIGHT), this.context.fillRect(this.GRAPH_X + this.GRAPH_WIDTH - this.PR, this.GRAPH_Y, this.PR, this.GRAPH_HEIGHT), this.context.fillStyle = this.bg, this.context.globalAlpha = 0.9, this.context.fillRect(this.GRAPH_X + this.GRAPH_WIDTH - this.PR, this.GRAPH_Y, this.PR, parseFloat((1 - i / l).toFixed(n)) * this.GRAPH_HEIGHT));
25
- }
26
- }
27
- const r = class r {
28
- constructor({ logsPerSecond: t = 20, samplesLog: i = 100, samplesGraph: h = 10, precision: l = 2, minimal: n = !1, mode: a = 0 } = {}) {
29
- s(this, "mode");
30
- s(this, "container");
31
- s(this, "minimal");
32
- s(this, "beginTime");
33
- s(this, "prevTime");
34
- s(this, "prevCpuTime");
35
- s(this, "frames");
36
- s(this, "averageCpu");
37
- s(this, "averageGpu");
38
- s(this, "queryCreated");
39
- s(this, "fpsPanel");
40
- s(this, "msPanel");
41
- s(this, "gpuPanel");
42
- s(this, "samplesLog");
43
- s(this, "samplesGraph");
44
- s(this, "logsPerSecond");
45
- s(this, "precision");
46
- s(this, "canvasGpu");
47
- s(this, "gl");
48
- s(this, "ext");
49
- s(this, "query");
50
- s(this, "disjoint");
51
- s(this, "ns");
52
- this.mode = a, this.container = document.createElement("div"), this.container.style.cssText = "position:fixed;top:0;left:0;opacity:0.9;z-index:10000;", n && (this.container.style.cssText += "cursor:pointer"), this.canvasGpu = null, this.gl = null, this.query = null, this.minimal = n, this.beginTime = (performance || Date).now(), this.prevTime = this.beginTime, this.prevCpuTime = this.beginTime, this.frames = 0, this.averageCpu = {
53
- logs: [],
54
- graph: []
55
- }, this.averageGpu = {
56
- logs: [],
57
- graph: []
58
- }, this.queryCreated = !1, this.fpsPanel = this.addPanel(new r.Panel("FPS", "#0ff", "#002"), 0), this.msPanel = this.addPanel(new r.Panel("CPU", "#0f0", "#020"), 1), this.gpuPanel = null, this.samplesLog = i, this.samplesGraph = h, this.precision = l, this.logsPerSecond = t, this.minimal ? (this.container.addEventListener("click", (e) => {
59
- e.preventDefault(), this.showPanel(++this.mode % this.container.children.length);
60
- }, !1), this.mode = a, this.showPanel(this.mode)) : window.addEventListener("resize", () => {
61
- this.resizePanel(this.fpsPanel, 0), this.resizePanel(this.msPanel, 1), this.gpuPanel && this.resizePanel(this.gpuPanel, 2);
62
- });
63
- }
64
- resizePanel(t, i) {
65
- this.minimal ? t.canvas.style.display = "none" : (t.canvas.style.display = "block", window.innerWidth < 700 ? (t.canvas.style.left = "0px", t.canvas.style.top = i * t.HEIGHT / t.PR + "px") : (t.canvas.style.top = "0px", t.canvas.style.left = i * t.WIDTH / t.PR + "px"));
66
- }
67
- addPanel(t, i) {
68
- return t.canvas && (this.container.appendChild(t.canvas), this.resizePanel(t, i)), t;
69
- }
70
- showPanel(t) {
71
- for (let i = 0; i < this.container.children.length; i++) {
72
- const h = this.container.children[i];
73
- h.style.display = i === t ? "block" : "none";
74
- }
75
- this.mode = t;
76
- }
77
- init(t) {
78
- this.canvasGpu = t, this.canvasGpu && (this.gl = this.canvasGpu.getContext("webgl2"), this.ext = this.gl ? this.gl.getExtension("EXT_disjoint_timer_query_webgl2") : null, this.ext && (this.gpuPanel = this.addPanel(new r.Panel("GPU", "#ff0", "#220"), 2)));
79
- }
80
- begin() {
81
- if (this.beginProfiling("cpu-started"), !(!this.gl || !this.ext)) {
82
- if (this.query) {
83
- const t = this.gl.getQueryParameter(this.query, this.gl.QUERY_RESULT_AVAILABLE);
84
- if (this.disjoint = this.gl.getParameter(this.ext.GPU_DISJOINT_EXT), t && !this.disjoint) {
85
- this.ns = this.gl.getQueryParameter(this.query, this.gl.QUERY_RESULT);
86
- const i = this.ns * 1e-6;
87
- (t || this.disjoint) && (this.gl.deleteQuery(this.query), this.query = null), t && this.addToAverage(i, this.averageGpu);
88
- }
89
- }
90
- this.query || (this.queryCreated = !0, this.query = this.gl.createQuery(), this.query && this.gl.beginQuery(this.ext.TIME_ELAPSED_EXT, this.query));
91
- }
92
- }
93
- end() {
94
- this.beginTime = this.endInternal(), this.endProfiling("cpu-started", "cpu-finished", "cpu-duration", this.averageCpu), !(!this.gl || !this.ext) && this.queryCreated && this.gl.getQuery(this.ext.TIME_ELAPSED_EXT, this.gl.CURRENT_QUERY) && this.gl.endQuery(this.ext.TIME_ELAPSED_EXT);
95
- }
96
- endInternal() {
97
- this.frames++;
98
- const t = (performance || Date).now();
99
- if (t >= this.prevCpuTime + 1e3 / this.logsPerSecond && (this.updatePanel(this.msPanel, this.averageCpu), this.updatePanel(this.gpuPanel, this.averageGpu), this.prevCpuTime = t), t >= this.prevTime + 1e3) {
100
- const i = this.frames * 1e3 / (t - this.prevTime);
101
- this.fpsPanel.update(i, i, 100, 100, 0), this.prevTime = t, this.frames = 0;
102
- }
103
- return t;
104
- }
105
- addToAverage(t, i) {
106
- i.logs.push(t), i.logs.length > this.samplesLog && i.logs.shift(), i.graph.push(t), i.graph.length > this.samplesGraph && i.graph.shift();
107
- }
108
- beginProfiling(t) {
109
- window.performance && window.performance.mark(t);
110
- }
111
- endProfiling(t, i, h, l) {
112
- if (window.performance && i) {
113
- window.performance.mark(i);
114
- const n = performance.measure(h, t, i);
115
- this.addToAverage(n.duration, l);
116
- }
117
- }
118
- updatePanel(t, i) {
119
- if (i.logs.length > 0) {
120
- let h = 0, l = 0.01;
121
- for (let e = 0; e < i.logs.length; e++)
122
- h += i.logs[e], i.logs[e] > l && (l = i.logs[e]);
123
- let n = 0, a = 0.01;
124
- for (let e = 0; e < i.graph.length; e++)
125
- n += i.graph[e], i.graph[e] > a && (a = i.graph[e]);
126
- t && t.update(h / Math.min(i.logs.length, this.samplesLog), n / Math.min(i.graph.length, this.samplesGraph), l, a, this.precision);
127
- }
128
- }
129
- };
130
- s(r, "Panel");
131
- let c = r;
132
- c.Panel = p;
133
- export {
134
- c as default
135
- };
@@ -1 +0,0 @@
1
- (function(o,e){typeof exports=="object"&&typeof module<"u"?module.exports=e():typeof define=="function"&&define.amd?define(e):(o=typeof globalThis<"u"?globalThis:o||self,o["Stats-Gl"]=e())})(this,function(){"use strict";var P=Object.defineProperty;var p=(o,e,n)=>e in o?P(o,e,{enumerable:!0,configurable:!0,writable:!0,value:n}):o[e]=n;var s=(o,e,n)=>(p(o,typeof e!="symbol"?e+"":e,n),n);class o{constructor(t,i,l){s(this,"canvas");s(this,"context");s(this,"name");s(this,"fg");s(this,"bg");s(this,"PR");s(this,"WIDTH");s(this,"HEIGHT");s(this,"TEXT_X");s(this,"TEXT_Y");s(this,"GRAPH_X");s(this,"GRAPH_Y");s(this,"GRAPH_WIDTH");s(this,"GRAPH_HEIGHT");this.name=t,this.fg=i,this.bg=l,this.PR=Math.round(window.devicePixelRatio||1),this.WIDTH=90*this.PR,this.HEIGHT=48*this.PR,this.TEXT_X=3*this.PR,this.TEXT_Y=2*this.PR,this.GRAPH_X=3*this.PR,this.GRAPH_Y=15*this.PR,this.GRAPH_WIDTH=84*this.PR,this.GRAPH_HEIGHT=30*this.PR,this.canvas=document.createElement("canvas"),this.canvas.width=90*this.PR,this.canvas.height=48*this.PR,this.canvas.style.width="90px",this.canvas.style.height="48px",this.canvas.style.cssText="width:90px;height:48px",this.context=this.canvas.getContext("2d"),this.context&&(this.context.font="bold "+9*this.PR+"px Helvetica,Arial,sans-serif",this.context.textBaseline="top",this.context.fillStyle=this.bg,this.context.fillRect(0,0,this.WIDTH,this.HEIGHT),this.context.fillStyle=this.fg,this.context.fillText(this.name,this.TEXT_X,this.TEXT_Y),this.context.fillRect(this.GRAPH_X,this.GRAPH_Y,this.GRAPH_WIDTH,this.GRAPH_HEIGHT),this.context.fillStyle=this.bg,this.context.globalAlpha=.9,this.context.fillRect(this.GRAPH_X,this.GRAPH_Y,this.GRAPH_WIDTH,this.GRAPH_HEIGHT))}update(t,i,l,r,a=0){let c=1/0,h=0;this.context&&(c=Math.min(c,t),h=Math.max(l,t),r=Math.max(r,i),this.context.fillStyle=this.bg,this.context.globalAlpha=1,this.context.fillRect(0,0,this.WIDTH,this.GRAPH_Y),this.context.fillStyle=this.fg,this.context.fillText(t.toFixed(a)+" "+this.name+" ("+c.toFixed(a)+"-"+parseFloat(h.toFixed(a))+")",this.TEXT_X,this.TEXT_Y),this.context.drawImage(this.canvas,this.GRAPH_X+this.PR,this.GRAPH_Y,this.GRAPH_WIDTH-this.PR,this.GRAPH_HEIGHT,this.GRAPH_X,this.GRAPH_Y,this.GRAPH_WIDTH-this.PR,this.GRAPH_HEIGHT),this.context.fillRect(this.GRAPH_X+this.GRAPH_WIDTH-this.PR,this.GRAPH_Y,this.PR,this.GRAPH_HEIGHT),this.context.fillStyle=this.bg,this.context.globalAlpha=.9,this.context.fillRect(this.GRAPH_X+this.GRAPH_WIDTH-this.PR,this.GRAPH_Y,this.PR,parseFloat((1-i/r).toFixed(a))*this.GRAPH_HEIGHT))}}const n=class n{constructor({logsPerSecond:t=20,samplesLog:i=100,samplesGraph:l=10,precision:r=2,minimal:a=!1,mode:c=0}={}){s(this,"mode");s(this,"container");s(this,"minimal");s(this,"beginTime");s(this,"prevTime");s(this,"prevCpuTime");s(this,"frames");s(this,"averageCpu");s(this,"averageGpu");s(this,"queryCreated");s(this,"fpsPanel");s(this,"msPanel");s(this,"gpuPanel");s(this,"samplesLog");s(this,"samplesGraph");s(this,"logsPerSecond");s(this,"precision");s(this,"canvasGpu");s(this,"gl");s(this,"ext");s(this,"query");s(this,"disjoint");s(this,"ns");this.mode=c,this.container=document.createElement("div"),this.container.style.cssText="position:fixed;top:0;left:0;opacity:0.9;z-index:10000;",a&&(this.container.style.cssText+="cursor:pointer"),this.canvasGpu=null,this.gl=null,this.query=null,this.minimal=a,this.beginTime=(performance||Date).now(),this.prevTime=this.beginTime,this.prevCpuTime=this.beginTime,this.frames=0,this.averageCpu={logs:[],graph:[]},this.averageGpu={logs:[],graph:[]},this.queryCreated=!1,this.fpsPanel=this.addPanel(new n.Panel("FPS","#0ff","#002"),0),this.msPanel=this.addPanel(new n.Panel("CPU","#0f0","#020"),1),this.gpuPanel=null,this.samplesLog=i,this.samplesGraph=l,this.precision=r,this.logsPerSecond=t,this.minimal?(this.container.addEventListener("click",h=>{h.preventDefault(),this.showPanel(++this.mode%this.container.children.length)},!1),this.mode=c,this.showPanel(this.mode)):window.addEventListener("resize",()=>{this.resizePanel(this.fpsPanel,0),this.resizePanel(this.msPanel,1),this.gpuPanel&&this.resizePanel(this.gpuPanel,2)})}resizePanel(t,i){this.minimal?t.canvas.style.display="none":(t.canvas.style.display="block",window.innerWidth<700?(t.canvas.style.left="0px",t.canvas.style.top=i*t.HEIGHT/t.PR+"px"):(t.canvas.style.top="0px",t.canvas.style.left=i*t.WIDTH/t.PR+"px"))}addPanel(t,i){return t.canvas&&(this.container.appendChild(t.canvas),this.resizePanel(t,i)),t}showPanel(t){for(let i=0;i<this.container.children.length;i++){const l=this.container.children[i];l.style.display=i===t?"block":"none"}this.mode=t}init(t){this.canvasGpu=t,this.canvasGpu&&(this.gl=this.canvasGpu.getContext("webgl2"),this.ext=this.gl?this.gl.getExtension("EXT_disjoint_timer_query_webgl2"):null,this.ext&&(this.gpuPanel=this.addPanel(new n.Panel("GPU","#ff0","#220"),2)))}begin(){if(this.beginProfiling("cpu-started"),!(!this.gl||!this.ext)){if(this.query){const t=this.gl.getQueryParameter(this.query,this.gl.QUERY_RESULT_AVAILABLE);if(this.disjoint=this.gl.getParameter(this.ext.GPU_DISJOINT_EXT),t&&!this.disjoint){this.ns=this.gl.getQueryParameter(this.query,this.gl.QUERY_RESULT);const i=this.ns*1e-6;(t||this.disjoint)&&(this.gl.deleteQuery(this.query),this.query=null),t&&this.addToAverage(i,this.averageGpu)}}this.query||(this.queryCreated=!0,this.query=this.gl.createQuery(),this.query&&this.gl.beginQuery(this.ext.TIME_ELAPSED_EXT,this.query))}}end(){this.beginTime=this.endInternal(),this.endProfiling("cpu-started","cpu-finished","cpu-duration",this.averageCpu),!(!this.gl||!this.ext)&&this.queryCreated&&this.gl.getQuery(this.ext.TIME_ELAPSED_EXT,this.gl.CURRENT_QUERY)&&this.gl.endQuery(this.ext.TIME_ELAPSED_EXT)}endInternal(){this.frames++;const t=(performance||Date).now();if(t>=this.prevCpuTime+1e3/this.logsPerSecond&&(this.updatePanel(this.msPanel,this.averageCpu),this.updatePanel(this.gpuPanel,this.averageGpu),this.prevCpuTime=t),t>=this.prevTime+1e3){const i=this.frames*1e3/(t-this.prevTime);this.fpsPanel.update(i,i,100,100,0),this.prevTime=t,this.frames=0}return t}addToAverage(t,i){i.logs.push(t),i.logs.length>this.samplesLog&&i.logs.shift(),i.graph.push(t),i.graph.length>this.samplesGraph&&i.graph.shift()}beginProfiling(t){window.performance&&window.performance.mark(t)}endProfiling(t,i,l,r){if(window.performance&&i){window.performance.mark(i);const a=performance.measure(l,t,i);this.addToAverage(a.duration,r)}}updatePanel(t,i){if(i.logs.length>0){let l=0,r=.01;for(let h=0;h<i.logs.length;h++)l+=i.logs[h],i.logs[h]>r&&(r=i.logs[h]);let a=0,c=.01;for(let h=0;h<i.graph.length;h++)a+=i.graph[h],i.graph[h]>c&&(c=i.graph[h]);t&&t.update(l/Math.min(i.logs.length,this.samplesLog),a/Math.min(i.graph.length,this.samplesGraph),r,c,this.precision)}}};s(n,"Panel");let e=n;return e.Panel=o,e});