UNPKG

playcanvas

Version:

Open-source WebGL/WebGPU 3D engine for the web

175 lines (174 loc) 5.21 kB
var __defProp = Object.defineProperty; var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value); import { TRACEID_GPU_TIMINGS } from "../../core/constants.js"; import { Debug } from "../../core/debug.js"; import { Tracing } from "../../core/tracing.js"; class GpuProfiler { constructor() { /** * Profiling slots allocated for the current frame, storing the names of the slots. * * @type {string[]} * @ignore */ __publicField(this, "frameAllocations", []); /** * Map of past frame allocations, indexed by renderVersion * * @type {Map<number, string[]>} * @ignore */ __publicField(this, "pastFrameAllocations", /* @__PURE__ */ new Map()); /** * True if enabled in the current frame. * * @private */ __publicField(this, "_enabled", false); /** * The enable request for the next frame. * * @private */ __publicField(this, "_enableRequest", false); /** * The time it took to render the last frame on GPU, or 0 if the profiler is not enabled. * * @private */ __publicField(this, "_frameTime", 0); /** * Per-pass timing data, with accumulated timings for passes with the same name. * * @type {Map<string, number>} * @private */ __publicField(this, "_passTimings", /* @__PURE__ */ new Map()); /** * Cache for parsed pass names to avoid repeated string operations. * * @type {Map<string, string>} * @private */ __publicField(this, "_nameCache", /* @__PURE__ */ new Map()); /** * The maximum number of slots that can be allocated during the frame. */ __publicField(this, "maxCount", 9999); } loseContext() { this.pastFrameAllocations.clear(); } /** * True to enable the profiler. * * @type {boolean} */ set enabled(value) { this._enableRequest = value; } get enabled() { return this._enableRequest; } /** * Get the per-pass timing data. * * @type {Map<string, number>} * @ignore */ get passTimings() { return this._passTimings; } processEnableRequest() { if (this._enableRequest !== this._enabled) { this._enabled = this._enableRequest; if (!this._enabled) { this._frameTime = 0; } } } request(renderVersion) { this.pastFrameAllocations.set(renderVersion, this.frameAllocations); this.frameAllocations = []; } /** * Parse a render pass name to a simplified form for stats. * Uses a cache to avoid repeated string operations. * * @param {string} name - The original pass name (e.g., "RenderPassCompose"). * @returns {string} The parsed name (e.g., "compose"). * @private */ _parsePassName(name) { let parsedName = this._nameCache.get(name); if (parsedName === void 0) { if (name.startsWith("RenderPass")) { parsedName = name.substring(10); } else { parsedName = name; } this._nameCache.set(name, parsedName); } return parsedName; } report(renderVersion, timings) { if (timings) { const allocations = this.pastFrameAllocations.get(renderVersion); if (!allocations) { return; } Debug.assert(allocations.length === timings.length); if (timings.length > 0) { this._frameTime = timings.reduce((sum, t) => sum + t, 0); } this._passTimings.clear(); for (let i = 0; i < allocations.length; ++i) { const name = allocations[i]; const timing = timings[i]; const parsedName = this._parsePassName(name); this._passTimings.set(parsedName, (this._passTimings.get(parsedName) || 0) + timing); } if (Tracing.get(TRACEID_GPU_TIMINGS)) { Debug.trace(TRACEID_GPU_TIMINGS, `-- GPU timings for frame ${renderVersion} --`); let total = 0; for (let i = 0; i < allocations.length; ++i) { const name = allocations[i]; total += timings[i]; Debug.trace(TRACEID_GPU_TIMINGS, `${timings[i].toFixed(2)} ms ${name}`); } Debug.trace(TRACEID_GPU_TIMINGS, `${total.toFixed(2)} ms TOTAL`); } } this.pastFrameAllocations.delete(renderVersion); } /** * Allocate a slot for GPU timing during the frame. This slot is valid only for the current * frame. This allows multiple timers to be used during the frame, each with a unique name. * * @param {string} name - The name of the slot. * @returns {number} The assigned slot index, or -1 if the slot count exceeds the maximum number * of slots. * * @ignore */ getSlot(name) { if (this.frameAllocations.length >= this.maxCount) { return -1; } const slot = this.frameAllocations.length; this.frameAllocations.push(name); return slot; } /** * Number of slots allocated during the frame. * * @ignore */ get slotCount() { return this.frameAllocations.length; } } export { GpuProfiler };