/** * @import { AppBase } from './app-base.js' * @import { ForwardRenderer } from '../scene/renderer/forward-renderer.js' * @import { GraphicsDevice } from '../platform/graphics/graphics-device.js' */ /** * Performance statistics for an application, accessed through {@link AppBase#stats}. Engine * measurements are read-only; {@link user} holds writable application-defined counters. * Includes frame cadence, CPU phase timings, overall GPU frame timing, and estimated GPU resource * memory usage. CPU timings, GPU timings and memory statistics are available in all builds, subject * to graphics capabilities. Primitive counting requires a debug or profiler build; see each getter * for its availability. * * Durations are in milliseconds and memory sizes are in bytes. Values are the latest available * measurements, not averages, except for {@link fps}, which refreshes approximately once per second. * Frame counters are published at the start of the next application tick; CPU timings are updated * when their respective phases finish. CPU phases overlap and must not all be added together. * CPU timings and counters are initially zero. GPU results arrive asynchronously and can describe * an older frame than the CPU measurements. * * GPU profiling is disabled by default. Enable it with * `app.graphicsDevice.gpuProfiler.enabled = true` when a profiler exists (see the example below). * WebGL requires the disjoint timer query extension; WebGPU requires the timestamp-query feature. * Enabling profiling on an unsupported device produces no timings. {@link gpuFrameTime} returns * undefined when profiling is disabled, unsupported, or no valid result has arrived. Reading stats * does not enable profiling. MiniStats also enables GPU profiling when it creates its GPU timer. * * Memory statistics estimate resources tracked by the application's graphics device, which may be * shared by applications. They do not represent total physical GPU memory usage or capacity, and * exclude untracked driver overhead and JavaScript memory. * * @example * const profiler = app.graphicsDevice.gpuProfiler; * if (profiler) { * profiler.enabled = true; * } * * app.on('frameend', () => { * const stats = app.stats; * console.log(stats.cpuUpdateTime, stats.cpuRenderTime, stats.gpuFrameTime); * }); * * @see AppBase#stats * @category Framework */ export class AppStats { /** * Create a new AppStats instance. * * @param {AppBase} app - The application. * @ignore */ constructor(app: AppBase); /** * @type {AppBase} * @private */ private _app; /** * @type {Map} * @private */ private _user; frame: { fps: number; ms: number; dt: number; updateStart: number; updateTime: number; renderStart: number; renderTime: number; physicsStart: number; physicsTime: number; scriptUpdateStart: number; scriptUpdate: number; scriptPostUpdateStart: number; scriptPostUpdate: number; animUpdateStart: number; animUpdate: number; cullTime: number; sortTime: number; skinTime: number; morphTime: number; instancingTime: number; primitives: number; gsplats: number; gsplatSort: number; gsplatBufferCopy: number; shaders: number; materials: number; cameras: number; shadowMapUpdates: number; shadowMapTime: number; depthMapTime: number; forwardTime: number; lightClustersTime: number; lightClusters: number; _timeToCountFrames: number; _fpsAccum: number; }; drawCalls: { forward: number; depth: number; shadow: number; immediate: number; misc: number; total: number; skinned: number; instanced: number; removedByInstancing: number; }; misc: { renderTargetCreationTime: number; }; particles: { updatesPerFrame: number; _updatesPerFrame: number; frameTime: number; _frameTime: number; }; shaders: { vsCompiled: number; fsCompiled: number; linked: number; materialShaders: number; compileTime: number; }; vram: { texShadow: number; texAsset: number; texLightmap: number; tex: number; vb: number; ib: number; ub: number; sb: number; }; gpu: Map; /** * Application-defined numeric counters. Returns the same map on every access. Entries can be * added, updated, deleted or cleared by the application; the engine never resets them. * Available in all builds. Values and their units are defined by the application. * * To display a counter in {@link MiniStats}, configure a graph with a path such as `user.ai`. * Counter names used in MiniStats must not contain dots, which separate path segments. * Initialize counters before accumulating values and reset per-frame totals on `frameupdate`. * * @type {Map} * @example * app.stats.user.set('ai', 0); * app.on('frameupdate', () => app.stats.user.set('ai', 0)); * * // Accumulate time spent in application code during this frame. * const start = performance.now(); * // ... run AI logic ... * app.stats.user.set('ai', app.stats.user.get('ai') + performance.now() - start); */ get user(): Map; /** * Total draw calls submitted during the previous frame, published at the start of the next * application tick. Available in all builds. * * @type {number} */ get drawCallCount(): number; /** * Total primitives submitted during the previous frame, published at the start of the next * application tick. Counts triangles, lines and points across all passes, including instances * and CPU-authored multi-draw commands. Counts are calculated before GPU clipping and culling. * * Available only in debug and profiler builds. Returns undefined in release and minified builds. * This is an estimate from draw parameters: GPU-generated indirect draws are excluded, and * primitive-restart indices in indexed strips are not inspected. No GPU readback is performed. * * @type {number|undefined} */ get primitiveCount(): number | undefined; /** * Interval between application ticks in milliseconds, including time outside the engine. * Unaffected by time scaling or delta-time clamping. Available in all builds. * * @type {number} */ get frameTime(): number; /** * Frame count over the latest approximately one-second reporting interval. Initially zero * until an interval completes. Available in all builds. * * @type {number} */ get fps(): number; /** * CPU duration of the latest application update in milliseconds, including component systems, * application update event listeners and input updates. Excludes graphics device updates. * Includes the other CPU update phase timings. Available in all builds. * * @type {number} */ get cpuUpdateTime(): number; /** * CPU duration of the latest scene render in milliseconds, including prerender and postrender * event listeners, hierarchy synchronization, batching and render command submission. Excludes * graphics device frameStart/frameEnd work and does not measure GPU execution. Retains the * latest measurement when rendering is skipped. Available in all builds. * * @type {number} */ get cpuRenderTime(): number; /** * CPU duration of the latest component systems update phase in milliseconds. Includes script * updates, physics and other systems subscribed to the update event. Part of * {@link cpuUpdateTime}. Available in all builds. * * @type {number} */ get cpuSystemUpdateTime(): number; /** * CPU duration of the latest component systems post-update phase in milliseconds, including * script postUpdate callbacks. Part of {@link cpuUpdateTime}. Available in all builds. * * @type {number} */ get cpuSystemPostUpdateTime(): number; /** * CPU duration of the latest dedicated animation-update phase in milliseconds, used by * {@link AnimComponentSystem}. Excludes the legacy {@link AnimationComponentSystem}, which * runs in the system update phase. Part of {@link cpuUpdateTime}. Available in all builds. * * @type {number} */ get cpuAnimationTime(): number; /** * CPU duration of the most recent physics step in milliseconds, including synchronization and * contact handling. Normally part of {@link cpuSystemUpdateTime}. Multiple manual steps are not * accumulated. Zero before any step or when physics is paused through its timeScale property. * Available in all builds. * * @type {number} */ get cpuPhysicsTime(): number; /** * Overall duration of the most recently resolved GPU frame in milliseconds. Available in all * builds when GPU profiling is supported and enabled. Returns undefined until a valid timing * arrives, when profiling is disabled, or after timing invalidation such as context loss. * Results arrive asynchronously and may be several frames old. * * WebGL measures a whole-frame timer query. WebGPU measures the span from the first profiled * pass beginning to the last pass ending, including gaps between passes. This is elapsed GPU * time, not GPU utilization, and is not the sum of potentially overlapping pass durations. * * @type {number|undefined} */ get gpuFrameTime(): number | undefined; /** * Total estimated GPU resource memory in bytes: textures, vertex buffers, index buffers, * uniform buffers and storage buffers. Available in all builds. * * @type {number} */ get vramTotalBytes(): number; /** * Estimated GPU texture memory in bytes. Available in all builds. * * @type {number} */ get vramTextureBytes(): number; /** * Estimated GPU vertex buffer memory in bytes. Available in all builds. * * @type {number} */ get vramVertexBufferBytes(): number; /** * Estimated GPU index buffer memory in bytes. Available in all builds. * * @type {number} */ get vramIndexBufferBytes(): number; /** * Estimated GPU uniform buffer memory in bytes. Available in all builds. Zero when no tracked * uniform buffers have been allocated. * * @type {number} */ get vramUniformBufferBytes(): number; /** * Estimated GPU storage buffer memory in bytes. Available in all builds. Zero on backends * without storage buffers or when none have been allocated. * * @type {number} */ get vramStorageBufferBytes(): number; /** @ignore */ get scene(): { meshInstances: number; lights: number; dynamicLights: number; bakedLights: number; updateShadersTime: number; }; /** @ignore */ get lightmapper(): { renderPasses: number; lightmapCount: number; totalRenderTime: number; forwardTime: number; fboTime: number; shadowMapTime: number; compileTime: number; shadersLinked: number; }; /** @ignore */ get batcher(): { createTime: number; updateLastFrameTime: number; }; /** * Update basic per-frame stats. Called every frame from `AppBase.tick`. * * @param {number} now - High-resolution timestamp for the current frame (ms). * @param {number} dt - Delta time in seconds (time-scaled, clamped). * @param {number} ms - Raw inter-frame time in ms. * @param {ForwardRenderer} renderer - The forward renderer. * @param {GraphicsDevice} device - The graphics device. * @ignore */ updateBasic(now: number, dt: number, ms: number, renderer: ForwardRenderer, device: GraphicsDevice): void; /** * Update detailed per-frame stats (profiler build only). Resets per-frame * counters on the renderer and graphics device. * * @param {ForwardRenderer} renderer - The forward renderer. * @param {GraphicsDevice} device - The graphics device. * @ignore */ updateDetailed(renderer: ForwardRenderer, device: GraphicsDevice): void; /** * Called at the end of each frame to reset per-frame statistics. * * @ignore */ frameEnd(): void; } import type { ForwardRenderer } from '../scene/renderer/forward-renderer.js'; import type { GraphicsDevice } from '../platform/graphics/graphics-device.js'; import type { AppBase } from './app-base.js';