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">
1 lines • 18.4 kB
Source Map (JSON)
{"version":3,"file":"RenderableGCSystem.mjs","sources":["../../../../../src/rendering/renderers/shared/texture/RenderableGCSystem.ts"],"sourcesContent":["import { ExtensionType } from '../../../../extensions/Extensions';\nimport { type RenderGroup } from '../../../../scene/container/RenderGroup';\nimport { cleanArray, cleanHash } from '../../../../utils/data/clean';\nimport { type RenderOptions } from '../system/AbstractRenderer';\n\nimport type { Container } from '../../../../scene/container/Container';\nimport type { Renderer } from '../../types';\nimport type { RenderPipe } from '../instructions/RenderPipe';\nimport type { Renderable } from '../Renderable';\nimport type { System } from '../system/System';\n\nlet renderableGCTick = 0;\n\n/**\n * Options for the {@link RenderableGCSystem}.\n * @category rendering\n * @property {boolean} [renderableGCActive=true] - If set to true, this will enable the garbage collector on the renderables.\n * @property {number} [renderableGCAMaxIdle=60000] -\n * The maximum idle frames before a texture is destroyed by garbage collection.\n * @property {number} [renderableGCCheckCountMax=60000] - time between two garbage collections.\n * @advanced\n */\nexport interface RenderableGCSystemOptions\n{\n /**\n * If set to true, this will enable the garbage collector on the GPU.\n * @default true\n */\n renderableGCActive: boolean;\n /**\n * The maximum idle frames before a texture is destroyed by garbage collection.\n * @default 60 * 60\n */\n renderableGCMaxUnusedTime: number;\n /**\n * Frames between two garbage collections.\n * @default 600\n */\n renderableGCFrequency: number;\n}\n\n/**\n * The RenderableGCSystem is responsible for cleaning up GPU resources that are no longer being used.\n *\n * When rendering objects like sprites, text, etc - GPU resources are created and managed by the renderer.\n * If these objects are no longer needed but not properly destroyed (via sprite.destroy()), their GPU resources\n * would normally leak. This system prevents that by automatically cleaning up unused GPU resources.\n *\n * Key features:\n * - Runs every 30 seconds by default to check for unused resources\n * - Cleans up resources not rendered for over 1 minute\n * - Works independently of rendering - will clean up even when not actively rendering\n * - When cleaned up resources are needed again, new GPU objects are quickly assigned from a pool\n * - Can be disabled with renderableGCActive:false for manual control\n *\n * Best practices:\n * - Always call destroy() explicitly when done with renderables (e.g. sprite.destroy())\n * - This system is a safety net, not a replacement for proper cleanup\n * - Adjust frequency and timeouts via options if needed\n * @example\n * ```js\n * // Sprite created but reference lost without destroy\n * let sprite = new Sprite(texture);\n *\n * // internally the renderer will assign a resource to the sprite\n * renderer.render(sprite);\n *\n * sprite = null; // Reference lost but GPU resources still exist\n *\n * // After 1 minute of not being rendered:\n * // - RenderableGC will clean up the sprite's GPU resources\n * // - JS garbage collector can then clean up the sprite itself\n * ```\n * @category rendering\n * @advanced\n */\nexport class RenderableGCSystem implements System<RenderableGCSystemOptions>\n{\n /**\n * Extension metadata for registering this system with the renderer.\n * @ignore\n */\n public static extension = {\n type: [\n ExtensionType.WebGLSystem,\n ExtensionType.WebGPUSystem,\n ],\n name: 'renderableGC',\n priority: 0\n } as const;\n\n /**\n * Default configuration options for the garbage collection system.\n * These can be overridden when initializing the renderer.\n */\n public static defaultOptions: RenderableGCSystemOptions = {\n /** Enable/disable the garbage collector */\n renderableGCActive: true,\n /** Time in ms before an unused resource is collected (default 1 minute) */\n renderableGCMaxUnusedTime: 60000,\n /** How often to run garbage collection in ms (default 30 seconds) */\n renderableGCFrequency: 30000,\n };\n\n /** Maximum time in ms a resource can be unused before being garbage collected */\n public maxUnusedTime: number;\n\n /** Reference to the renderer this system belongs to */\n private _renderer: Renderer;\n\n /** Array of renderables being tracked for garbage collection */\n private readonly _managedRenderables: Renderable[] = [];\n /** ID of the main GC scheduler handler */\n private _handler: number;\n /** How frequently GC runs in ms */\n private _frequency: number;\n /** Current timestamp used for age calculations */\n private _now: number;\n\n /** Array of hash objects being tracked for cleanup */\n private readonly _managedHashes: {context: any, hash: string}[] = [];\n /** ID of the hash cleanup scheduler handler */\n private _hashHandler: number;\n\n /** Array of arrays being tracked for cleanup */\n private readonly _managedArrays: {context: any, hash: string}[] = [];\n /** ID of the array cleanup scheduler handler */\n private _arrayHandler: number;\n\n /**\n * Creates a new RenderableGCSystem instance.\n * @param renderer - The renderer this garbage collection system works for\n */\n constructor(renderer: Renderer)\n {\n this._renderer = renderer;\n }\n\n /**\n * Initializes the garbage collection system with the provided options.\n * @param options - Configuration options for the renderer\n */\n public init(options: RenderableGCSystemOptions): void\n {\n options = { ...RenderableGCSystem.defaultOptions, ...options };\n\n this.maxUnusedTime = options.renderableGCMaxUnusedTime;\n this._frequency = options.renderableGCFrequency;\n\n this.enabled = options.renderableGCActive;\n }\n\n /**\n * Gets whether the garbage collection system is currently enabled.\n * @returns True if GC is enabled, false otherwise\n */\n get enabled(): boolean\n {\n return !!this._handler;\n }\n\n /**\n * Enables or disables the garbage collection system.\n * When enabled, schedules periodic cleanup of resources.\n * When disabled, cancels all scheduled cleanups.\n */\n set enabled(value: boolean)\n {\n if (this.enabled === value) return;\n\n if (value)\n {\n // Schedule periodic garbage collection\n this._handler = this._renderer.scheduler.repeat(\n () => this.run(),\n this._frequency,\n false\n );\n\n // Schedule periodic hash table cleanup\n this._hashHandler = this._renderer.scheduler.repeat(\n () =>\n {\n for (const hash of this._managedHashes)\n {\n hash.context[hash.hash] = cleanHash(hash.context[hash.hash]);\n }\n },\n this._frequency\n );\n\n // Schedule periodic array cleanup\n this._arrayHandler = this._renderer.scheduler.repeat(\n () =>\n {\n for (const array of this._managedArrays)\n {\n cleanArray(array.context[array.hash]);\n }\n },\n this._frequency\n );\n }\n else\n {\n // Cancel all scheduled cleanups\n this._renderer.scheduler.cancel(this._handler);\n this._renderer.scheduler.cancel(this._hashHandler);\n this._renderer.scheduler.cancel(this._arrayHandler);\n }\n }\n\n /**\n * Adds a hash table to be managed by the garbage collector.\n * @param context - The object containing the hash table\n * @param hash - The property name of the hash table\n */\n public addManagedHash<T>(context: T, hash: string): void\n {\n this._managedHashes.push({ context, hash: hash as string });\n }\n\n /**\n * Adds an array to be managed by the garbage collector.\n * @param context - The object containing the array\n * @param hash - The property name of the array\n */\n public addManagedArray<T>(context: T, hash: string): void\n {\n this._managedArrays.push({ context, hash: hash as string });\n }\n\n /**\n * Updates the GC timestamp and tracking before rendering.\n * @param options - The render options\n * @param options.container - The container to render\n */\n public prerender({\n container\n }: RenderOptions): void\n {\n this._now = performance.now();\n\n // The gcTick is a monotonically increasing counter that tracks render cycles\n // Each time we render, we increment the global renderableGCTick counter\n // and assign the new tick value to the render group being rendered.\n // This lets us know which render groups were rendered in the current frame\n // versus ones that haven't been rendered recently.\n // The instruction set also gets updated with this tick value to track\n // when its renderables were last used.\n container.renderGroup.gcTick = renderableGCTick++;\n\n this._updateInstructionGCTick(container.renderGroup, container.renderGroup.gcTick);\n }\n\n /**\n * Starts tracking a renderable for garbage collection.\n * @param renderable - The renderable to track\n */\n public addRenderable(renderable: Renderable): void\n {\n if (!this.enabled) return;\n\n if (renderable._lastUsed === -1)\n {\n this._managedRenderables.push(renderable);\n renderable.once('destroyed', this._removeRenderable, this);\n }\n\n renderable._lastUsed = this._now;\n }\n\n /**\n * Performs garbage collection by cleaning up unused renderables.\n * Removes renderables that haven't been used for longer than maxUnusedTime.\n */\n public run(): void\n {\n const now = this._now;\n const managedRenderables = this._managedRenderables;\n const renderPipes = this._renderer.renderPipes;\n let offset = 0;\n\n for (let i = 0; i < managedRenderables.length; i++)\n {\n const renderable = managedRenderables[i];\n\n if (renderable === null)\n {\n offset++;\n continue;\n }\n\n const renderGroup = renderable.renderGroup ?? renderable.parentRenderGroup;\n const currentTick = renderGroup?.instructionSet?.gcTick ?? -1;\n\n // Update last used time if the renderable's group was rendered this tick\n if ((renderGroup?.gcTick ?? 0) === currentTick)\n {\n renderable._lastUsed = now;\n }\n\n // Clean up if unused for too long\n if (now - renderable._lastUsed > this.maxUnusedTime)\n {\n if (!renderable.destroyed)\n {\n const rp = renderPipes as unknown as Record<string, RenderPipe>;\n\n if (renderGroup)renderGroup.structureDidChange = true;\n\n rp[renderable.renderPipeId].destroyRenderable(renderable);\n }\n\n renderable._lastUsed = -1;\n offset++;\n renderable.off('destroyed', this._removeRenderable, this);\n }\n else\n {\n managedRenderables[i - (offset)] = renderable;\n }\n }\n\n managedRenderables.length -= offset;\n }\n\n /** Cleans up the garbage collection system. Disables GC and removes all tracked resources. */\n public destroy(): void\n {\n this.enabled = false;\n this._renderer = null as any as Renderer;\n this._managedRenderables.length = 0;\n this._managedHashes.length = 0;\n this._managedArrays.length = 0;\n }\n\n /**\n * Removes a renderable from being tracked when it's destroyed.\n * @param renderable - The renderable to stop tracking\n */\n private _removeRenderable(renderable: Container): void\n {\n const index = this._managedRenderables.indexOf(renderable as Renderable);\n\n if (index >= 0)\n {\n renderable.off('destroyed', this._removeRenderable, this);\n this._managedRenderables[index] = null;\n }\n }\n\n /**\n * Updates the GC tick counter for a render group and its children.\n * @param renderGroup - The render group to update\n * @param gcTick - The new tick value\n */\n private _updateInstructionGCTick(renderGroup: RenderGroup, gcTick: number): void\n {\n renderGroup.instructionSet.gcTick = gcTick;\n\n for (const child of renderGroup.renderGroupChildren)\n {\n this._updateInstructionGCTick(child, gcTick);\n }\n }\n}\n"],"names":[],"mappings":"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"}