UNPKG

pixi.js

Version:

<p align="center"> <a href="https://pixijs.com" target="_blank" rel="noopener noreferrer"> <img height="150" src="https://files.pixijs.download/branding/pixijs-logo-transparent-dark.svg?v=1" alt="PixiJS logo"> </a> </p> <br/> <p align="center">

209 lines (206 loc) 6.87 kB
import { ExtensionType } from '../../../../extensions/Extensions.mjs'; import { cleanHash, cleanArray } from '../../../../utils/data/clean.mjs'; "use strict"; let renderableGCTick = 0; const _RenderableGCSystem = class _RenderableGCSystem { /** * Creates a new RenderableGCSystem instance. * @param renderer - The renderer this garbage collection system works for */ constructor(renderer) { /** Array of renderables being tracked for garbage collection */ this._managedRenderables = []; /** Array of hash objects being tracked for cleanup */ this._managedHashes = []; /** Array of arrays being tracked for cleanup */ this._managedArrays = []; this._renderer = renderer; } /** * Initializes the garbage collection system with the provided options. * @param options - Configuration options for the renderer */ init(options) { options = { ..._RenderableGCSystem.defaultOptions, ...options }; this.maxUnusedTime = options.renderableGCMaxUnusedTime; this._frequency = options.renderableGCFrequency; this.enabled = options.renderableGCActive; } /** * Gets whether the garbage collection system is currently enabled. * @returns True if GC is enabled, false otherwise */ get enabled() { return !!this._handler; } /** * Enables or disables the garbage collection system. * When enabled, schedules periodic cleanup of resources. * When disabled, cancels all scheduled cleanups. */ set enabled(value) { if (this.enabled === value) return; if (value) { this._handler = this._renderer.scheduler.repeat( () => this.run(), this._frequency, false ); this._hashHandler = this._renderer.scheduler.repeat( () => { for (const hash of this._managedHashes) { hash.context[hash.hash] = cleanHash(hash.context[hash.hash]); } }, this._frequency ); this._arrayHandler = this._renderer.scheduler.repeat( () => { for (const array of this._managedArrays) { cleanArray(array.context[array.hash]); } }, this._frequency ); } else { this._renderer.scheduler.cancel(this._handler); this._renderer.scheduler.cancel(this._hashHandler); this._renderer.scheduler.cancel(this._arrayHandler); } } /** * Adds a hash table to be managed by the garbage collector. * @param context - The object containing the hash table * @param hash - The property name of the hash table */ addManagedHash(context, hash) { this._managedHashes.push({ context, hash }); } /** * Adds an array to be managed by the garbage collector. * @param context - The object containing the array * @param hash - The property name of the array */ addManagedArray(context, hash) { this._managedArrays.push({ context, hash }); } /** * Updates the GC timestamp and tracking before rendering. * @param options - The render options * @param options.container - The container to render */ prerender({ container }) { this._now = performance.now(); container.renderGroup.gcTick = renderableGCTick++; this._updateInstructionGCTick(container.renderGroup, container.renderGroup.gcTick); } /** * Starts tracking a renderable for garbage collection. * @param renderable - The renderable to track */ addRenderable(renderable) { if (!this.enabled) return; if (renderable._lastUsed === -1) { this._managedRenderables.push(renderable); renderable.once("destroyed", this._removeRenderable, this); } renderable._lastUsed = this._now; } /** * Performs garbage collection by cleaning up unused renderables. * Removes renderables that haven't been used for longer than maxUnusedTime. */ run() { const now = this._now; const managedRenderables = this._managedRenderables; const renderPipes = this._renderer.renderPipes; let offset = 0; for (let i = 0; i < managedRenderables.length; i++) { const renderable = managedRenderables[i]; if (renderable === null) { offset++; continue; } const renderGroup = renderable.renderGroup ?? renderable.parentRenderGroup; const currentTick = renderGroup?.instructionSet?.gcTick ?? -1; if ((renderGroup?.gcTick ?? 0) === currentTick) { renderable._lastUsed = now; } if (now - renderable._lastUsed > this.maxUnusedTime) { if (!renderable.destroyed) { const rp = renderPipes; if (renderGroup) renderGroup.structureDidChange = true; rp[renderable.renderPipeId].destroyRenderable(renderable); } renderable._lastUsed = -1; offset++; renderable.off("destroyed", this._removeRenderable, this); } else { managedRenderables[i - offset] = renderable; } } managedRenderables.length -= offset; } /** Cleans up the garbage collection system. Disables GC and removes all tracked resources. */ destroy() { this.enabled = false; this._renderer = null; this._managedRenderables.length = 0; this._managedHashes.length = 0; this._managedArrays.length = 0; } /** * Removes a renderable from being tracked when it's destroyed. * @param renderable - The renderable to stop tracking */ _removeRenderable(renderable) { const index = this._managedRenderables.indexOf(renderable); if (index >= 0) { renderable.off("destroyed", this._removeRenderable, this); this._managedRenderables[index] = null; } } /** * Updates the GC tick counter for a render group and its children. * @param renderGroup - The render group to update * @param gcTick - The new tick value */ _updateInstructionGCTick(renderGroup, gcTick) { renderGroup.instructionSet.gcTick = gcTick; for (const child of renderGroup.renderGroupChildren) { this._updateInstructionGCTick(child, gcTick); } } }; /** * Extension metadata for registering this system with the renderer. * @ignore */ _RenderableGCSystem.extension = { type: [ ExtensionType.WebGLSystem, ExtensionType.WebGPUSystem ], name: "renderableGC", priority: 0 }; /** * Default configuration options for the garbage collection system. * These can be overridden when initializing the renderer. */ _RenderableGCSystem.defaultOptions = { /** Enable/disable the garbage collector */ renderableGCActive: true, /** Time in ms before an unused resource is collected (default 1 minute) */ renderableGCMaxUnusedTime: 6e4, /** How often to run garbage collection in ms (default 30 seconds) */ renderableGCFrequency: 3e4 }; let RenderableGCSystem = _RenderableGCSystem; export { RenderableGCSystem }; //# sourceMappingURL=RenderableGCSystem.mjs.map