Buckets:
| import { Panel } from "./panel.js"; | |
| const _Stats = class _Stats2 { | |
| constructor({ | |
| trackGPU = false, | |
| logsPerSecond = 30, | |
| samplesLog = 60, | |
| samplesGraph = 10, | |
| precision = 2, | |
| minimal = false, | |
| horizontal = true, | |
| mode = 0 | |
| } = {}) { | |
| this.gl = null; | |
| this.ext = null; | |
| this.activeQuery = null; | |
| this.gpuQueries = []; | |
| this.threeRendererPatched = false; | |
| this.frames = 0; | |
| this.renderCount = 0; | |
| this.isRunningCPUProfiling = false; | |
| this.totalCpuDuration = 0; | |
| this.totalGpuDuration = 0; | |
| this.totalGpuDurationCompute = 0; | |
| this.totalFps = 0; | |
| this.gpuPanel = null; | |
| this.gpuPanelCompute = null; | |
| this.averageFps = { logs: [], graph: [] }; | |
| this.averageCpu = { logs: [], graph: [] }; | |
| this.averageGpu = { logs: [], graph: [] }; | |
| this.averageGpuCompute = { logs: [], graph: [] }; | |
| this.handleClick = (event) => { | |
| event.preventDefault(); | |
| this.showPanel(++this.mode % this.dom.children.length); | |
| }; | |
| this.handleResize = () => { | |
| this.resizePanel(this.fpsPanel, 0); | |
| this.resizePanel(this.msPanel, 1); | |
| if (this.gpuPanel) | |
| this.resizePanel(this.gpuPanel, 2); | |
| if (this.gpuPanelCompute) | |
| this.resizePanel(this.gpuPanelCompute, 3); | |
| }; | |
| this.mode = mode; | |
| this.horizontal = horizontal; | |
| this.minimal = minimal; | |
| this.trackGPU = trackGPU; | |
| this.samplesLog = samplesLog; | |
| this.samplesGraph = samplesGraph; | |
| this.precision = precision; | |
| this.logsPerSecond = logsPerSecond; | |
| this.dom = document.createElement("div"); | |
| this.initializeDOM(); | |
| this.beginTime = performance.now(); | |
| this.prevTime = this.beginTime; | |
| this.prevCpuTime = this.beginTime; | |
| this.fpsPanel = this.addPanel(new _Stats2.Panel("FPS", "#0ff", "#002"), 0); | |
| this.msPanel = this.addPanel(new _Stats2.Panel("CPU", "#0f0", "#020"), 1); | |
| this.setupEventListeners(); | |
| } | |
| initializeDOM() { | |
| this.dom.style.cssText = ` | |
| position: fixed; | |
| top: 0; | |
| left: 0; | |
| opacity: 0.9; | |
| z-index: 10000; | |
| ${this.minimal ? "cursor: pointer;" : ""} | |
| `; | |
| } | |
| setupEventListeners() { | |
| if (this.minimal) { | |
| this.dom.addEventListener("click", this.handleClick); | |
| this.showPanel(this.mode); | |
| } else { | |
| window.addEventListener("resize", this.handleResize); | |
| } | |
| } | |
| async init(canvasOrGL) { | |
| if (!canvasOrGL) { | |
| console.error('Stats: The "canvas" parameter is undefined.'); | |
| return; | |
| } | |
| if (this.handleThreeRenderer(canvasOrGL)) | |
| return; | |
| if (await this.handleWebGPURenderer(canvasOrGL)) | |
| return; | |
| if (!this.initializeWebGL(canvasOrGL)) | |
| return; | |
| } | |
| handleThreeRenderer(renderer) { | |
| if (renderer.isWebGLRenderer && !this.threeRendererPatched) { | |
| this.patchThreeRenderer(renderer); | |
| this.gl = renderer.getContext(); | |
| if (this.trackGPU) { | |
| this.initializeGPUTracking(); | |
| } | |
| return true; | |
| } | |
| return false; | |
| } | |
| async handleWebGPURenderer(renderer) { | |
| if (renderer.isWebGPURenderer) { | |
| if (this.trackGPU) { | |
| renderer.backend.trackTimestamp = true; | |
| if (await renderer.hasFeatureAsync("timestamp-query")) { | |
| this.initializeWebGPUPanels(); | |
| } | |
| } | |
| this.info = renderer.info; | |
| return true; | |
| } | |
| return false; | |
| } | |
| initializeWebGPUPanels() { | |
| this.gpuPanel = this.addPanel(new _Stats2.Panel("GPU", "#ff0", "#220"), 2); | |
| this.gpuPanelCompute = this.addPanel( | |
| new _Stats2.Panel("CPT", "#e1e1e1", "#212121"), | |
| 3 | |
| ); | |
| } | |
| initializeWebGL(canvasOrGL) { | |
| if (canvasOrGL instanceof WebGL2RenderingContext) { | |
| this.gl = canvasOrGL; | |
| } else if (canvasOrGL instanceof HTMLCanvasElement || canvasOrGL instanceof OffscreenCanvas) { | |
| this.gl = canvasOrGL.getContext("webgl2"); | |
| if (!this.gl) { | |
| console.error("Stats: Unable to obtain WebGL2 context."); | |
| return false; | |
| } | |
| } else { | |
| console.error( | |
| "Stats: Invalid input type. Expected WebGL2RenderingContext, HTMLCanvasElement, or OffscreenCanvas." | |
| ); | |
| return false; | |
| } | |
| return true; | |
| } | |
| initializeGPUTracking() { | |
| if (this.gl) { | |
| this.ext = this.gl.getExtension("EXT_disjoint_timer_query_webgl2"); | |
| if (this.ext) { | |
| this.gpuPanel = this.addPanel(new _Stats2.Panel("GPU", "#ff0", "#220"), 2); | |
| } | |
| } | |
| } | |
| begin() { | |
| if (!this.isRunningCPUProfiling) { | |
| this.beginProfiling("cpu-started"); | |
| } | |
| if (!this.gl || !this.ext) | |
| return; | |
| if (this.activeQuery) { | |
| this.gl.endQuery(this.ext.TIME_ELAPSED_EXT); | |
| } | |
| this.activeQuery = this.gl.createQuery(); | |
| if (this.activeQuery) { | |
| this.gl.beginQuery(this.ext.TIME_ELAPSED_EXT, this.activeQuery); | |
| } | |
| } | |
| end() { | |
| this.renderCount++; | |
| if (this.gl && this.ext && this.activeQuery) { | |
| this.gl.endQuery(this.ext.TIME_ELAPSED_EXT); | |
| this.gpuQueries.push({ query: this.activeQuery }); | |
| this.activeQuery = null; | |
| } | |
| } | |
| update() { | |
| if (!this.info) { | |
| this.processGpuQueries(); | |
| } else { | |
| this.processWebGPUTimestamps(); | |
| } | |
| this.endProfiling("cpu-started", "cpu-finished", "cpu-duration"); | |
| this.updateAverages(); | |
| this.resetCounters(); | |
| } | |
| processWebGPUTimestamps() { | |
| this.totalGpuDuration = this.info.render.timestamp; | |
| this.totalGpuDurationCompute = this.info.compute.timestamp; | |
| this.addToAverage(this.totalGpuDurationCompute, this.averageGpuCompute); | |
| } | |
| updateAverages() { | |
| this.addToAverage(this.totalCpuDuration, this.averageCpu); | |
| this.addToAverage(this.totalGpuDuration, this.averageGpu); | |
| } | |
| resetCounters() { | |
| this.renderCount = 0; | |
| if (this.totalCpuDuration === 0) { | |
| this.beginProfiling("cpu-started"); | |
| } | |
| this.totalCpuDuration = 0; | |
| this.totalFps = 0; | |
| this.beginTime = this.endInternal(); | |
| } | |
| resizePanel(panel, offset) { | |
| panel.canvas.style.position = "absolute"; | |
| if (this.minimal) { | |
| panel.canvas.style.display = "none"; | |
| } else { | |
| panel.canvas.style.display = "block"; | |
| if (this.horizontal) { | |
| panel.canvas.style.top = "0px"; | |
| panel.canvas.style.left = offset * panel.WIDTH / panel.PR + "px"; | |
| } else { | |
| panel.canvas.style.left = "0px"; | |
| panel.canvas.style.top = offset * panel.HEIGHT / panel.PR + "px"; | |
| } | |
| } | |
| } | |
| addPanel(panel, offset) { | |
| if (panel.canvas) { | |
| this.dom.appendChild(panel.canvas); | |
| this.resizePanel(panel, offset); | |
| } | |
| return panel; | |
| } | |
| showPanel(id) { | |
| for (let i = 0; i < this.dom.children.length; i++) { | |
| const child = this.dom.children[i]; | |
| child.style.display = i === id ? "block" : "none"; | |
| } | |
| this.mode = id; | |
| } | |
| processGpuQueries() { | |
| if (!this.gl || !this.ext) | |
| return; | |
| this.totalGpuDuration = 0; | |
| this.gpuQueries.forEach((queryInfo, index) => { | |
| if (this.gl) { | |
| const available = this.gl.getQueryParameter(queryInfo.query, this.gl.QUERY_RESULT_AVAILABLE); | |
| const disjoint = this.gl.getParameter(this.ext.GPU_DISJOINT_EXT); | |
| if (available && !disjoint) { | |
| const elapsed = this.gl.getQueryParameter(queryInfo.query, this.gl.QUERY_RESULT); | |
| const duration = elapsed * 1e-6; | |
| this.totalGpuDuration += duration; | |
| this.gl.deleteQuery(queryInfo.query); | |
| this.gpuQueries.splice(index, 1); | |
| } | |
| } | |
| }); | |
| } | |
| endInternal() { | |
| this.frames++; | |
| const time = (performance || Date).now(); | |
| const elapsed = time - this.prevTime; | |
| if (time >= this.prevCpuTime + 1e3 / this.logsPerSecond) { | |
| const fps = Math.round(this.frames * 1e3 / elapsed); | |
| this.addToAverage(fps, this.averageFps); | |
| this.updatePanel(this.fpsPanel, this.averageFps, 0); | |
| this.updatePanel(this.msPanel, this.averageCpu, this.precision); | |
| this.updatePanel(this.gpuPanel, this.averageGpu, this.precision); | |
| if (this.gpuPanelCompute) { | |
| this.updatePanel(this.gpuPanelCompute, this.averageGpuCompute); | |
| } | |
| this.frames = 0; | |
| this.prevCpuTime = time; | |
| this.prevTime = time; | |
| } | |
| return time; | |
| } | |
| addToAverage(value, averageArray) { | |
| averageArray.logs.push(value); | |
| if (averageArray.logs.length > this.samplesLog) { | |
| averageArray.logs.shift(); | |
| } | |
| averageArray.graph.push(value); | |
| if (averageArray.graph.length > this.samplesGraph) { | |
| averageArray.graph.shift(); | |
| } | |
| } | |
| beginProfiling(marker) { | |
| if (window.performance) { | |
| window.performance.mark(marker); | |
| this.isRunningCPUProfiling = true; | |
| } | |
| } | |
| endProfiling(startMarker, endMarker, measureName) { | |
| if (window.performance && endMarker && this.isRunningCPUProfiling) { | |
| window.performance.mark(endMarker); | |
| const cpuMeasure = performance.measure(measureName, startMarker, endMarker); | |
| this.totalCpuDuration += cpuMeasure.duration; | |
| this.isRunningCPUProfiling = false; | |
| } | |
| } | |
| updatePanel(panel, averageArray, precision = 2) { | |
| if (averageArray.logs.length > 0) { | |
| let sumLog = 0; | |
| let max = 0.01; | |
| for (let i = 0; i < averageArray.logs.length; i++) { | |
| sumLog += averageArray.logs[i]; | |
| if (averageArray.logs[i] > max) { | |
| max = averageArray.logs[i]; | |
| } | |
| } | |
| let sumGraph = 0; | |
| let maxGraph = 0.01; | |
| for (let i = 0; i < averageArray.graph.length; i++) { | |
| sumGraph += averageArray.graph[i]; | |
| if (averageArray.graph[i] > maxGraph) { | |
| maxGraph = averageArray.graph[i]; | |
| } | |
| } | |
| if (panel) { | |
| panel.update(sumLog / Math.min(averageArray.logs.length, this.samplesLog), sumGraph / Math.min(averageArray.graph.length, this.samplesGraph), max, maxGraph, precision); | |
| } | |
| } | |
| } | |
| get domElement() { | |
| return this.dom; | |
| } | |
| patchThreeRenderer(renderer) { | |
| const originalRenderMethod = renderer.render; | |
| const statsInstance = this; | |
| renderer.render = function(scene, camera) { | |
| statsInstance.begin(); | |
| originalRenderMethod.call(this, scene, camera); | |
| statsInstance.end(); | |
| }; | |
| this.threeRendererPatched = true; | |
| } | |
| }; | |
| _Stats.Panel = Panel; | |
| let Stats = _Stats; | |
| export { | |
| Stats as default | |
| }; | |
| //# sourceMappingURL=main.js.map | |
Xet Storage Details
- Size:
- 10.2 kB
- Xet hash:
- 42c9330359bea9fb40f52f249fe368aa4273ce1c6f7d3c79d36f43980f4ad121
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.