{"version":3,"file":"GCSystem.mjs","sources":["../../../../src/rendering/renderers/shared/GCSystem.ts"],"sourcesContent":["import { ExtensionType } from '../../../extensions/Extensions';\nimport { type RenderGroup } from '../../../scene/container/RenderGroup';\nimport { type GPUDataOwner, type Renderer } from '../types';\nimport { type Renderable } from './Renderable';\nimport { type RenderOptions } from './system/AbstractRenderer';\n\nimport type EventEmitter from 'eventemitter3';\nimport type { System } from './system/System';\n\n/**\n * Data stored on a GC-managed resource.\n * @category rendering\n * @advanced\n */\nexport interface GCData\n{\n    /** Index in the managed resources array */\n    index?: number;\n    /** Type of the resource */\n    type: 'resource' | 'renderable';\n}\n\n/**\n * Interface for resources that can be garbage collected.\n * @category rendering\n * @advanced\n */\nexport interface GCable extends GPUDataOwner\n{\n    /** Timestamp of last use */\n    _gcLastUsed: number;\n    /** GC tracking data, null if not being tracked */\n    _gcData?: GCData | null;\n    /** If set to true, the resource will be garbage collected automatically when it is not used. */\n    autoGarbageCollect?: boolean;\n    /** An optional callback for when an item is touched */\n    _onTouch?(now: number): void;\n}\n\ntype GCableEventEmitter = GCable & Pick<EventEmitter, 'once' | 'off'>;\n\ninterface GCResourceHashEntry\n{\n    context: any;\n    hash: string;\n    type: GCData['type'];\n    priority: number;\n}\n\n/**\n * Options for the {@link GCSystem}.\n * @category rendering\n * @advanced\n */\nexport interface GCSystemOptions\n{\n    /**\n     * If set to true, this will enable the garbage collector.\n     * @default true\n     */\n    gcActive: boolean;\n    /**\n     * The maximum time in milliseconds a resource can be unused before being garbage collected.\n     * @default 60000\n     */\n    gcMaxUnusedTime: number;\n    /**\n     * How frequently to run garbage collection in milliseconds.\n     * @default 30000\n     */\n    gcFrequency: number;\n}\n\n/**\n * A unified garbage collection system for managing GPU resources.\n * Resources register themselves with a cleanup callback and are automatically\n * cleaned up when they haven't been used for a specified amount of time.\n * @example\n * ```ts\n * // Register a resource for GC\n * gc.addResource(myResource, () => {\n *     // cleanup logic here\n *     myResource.unload();\n * });\n *\n * // Touch the resource when used (resets idle timer)\n * gc.touch(myResource);\n *\n * // Remove from GC tracking (e.g., on manual destroy)\n * gc.removeResource(myResource);\n * ```\n * @category rendering\n * @advanced\n */\nexport class GCSystem implements System<GCSystemOptions>\n{\n    /** @ignore */\n    public static extension = {\n        type: [\n            ExtensionType.WebGLSystem,\n            ExtensionType.WebGPUSystem,\n        ],\n        name: 'gc',\n        priority: 0,\n    } as const;\n\n    /** Default options for the GCSystem */\n    public static defaultOptions: GCSystemOptions = {\n        /** Enable/disable the garbage collector */\n        gcActive: true,\n        /** Time in ms before an unused resource is collected (default 1 minute) */\n        gcMaxUnusedTime: 60000,\n        /** How often to run garbage collection in ms (default 30 seconds) */\n        gcFrequency: 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 resources being tracked for garbage collection */\n    private readonly _managedResources: GCableEventEmitter[] = [];\n    private readonly _managedResourceHashes: GCResourceHashEntry[] = [];\n\n    /** ID of the GC scheduler handler */\n    private _handler: number;\n\n    /** How frequently GC runs in ms */\n    private _frequency: number;\n\n    /** Current timestamp used for age calculations */\n    public now: number;\n\n    private _ready = false;\n\n    /**\n     * Creates a new GCSystem 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\n     */\n    public init(options: GCSystemOptions): void\n    {\n        options = { ...GCSystem.defaultOptions, ...options };\n\n        this.maxUnusedTime = options.gcMaxUnusedTime;\n        this._frequency = options.gcFrequency;\n\n        this.enabled = options.gcActive;\n        this.now = performance.now();\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            this._handler = this._renderer.scheduler.repeat(\n                () =>\n                {\n                    this._ready = true;\n                },\n                this._frequency,\n                false\n            );\n        }\n        else\n        {\n            this._renderer.scheduler.cancel(this._handler);\n            this._handler = 0;\n        }\n    }\n\n    /**\n     * Called before rendering. Updates the current timestamp.\n     * @param options - The render options\n     * @param options.container - The container to render\n     */\n    protected prerender({ container }: RenderOptions): void\n    {\n        this.now = performance.now();\n        container.renderGroup.gcTick = this._renderer.tick++;\n\n        this._updateInstructionGCTick(container.renderGroup, container.renderGroup.gcTick);\n    }\n\n    /** Performs garbage collection after rendering. */\n    protected postrender(): void\n    {\n        if (!this._ready || !this.enabled) return;\n\n        this.run();\n        this._ready = false;\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    /**\n     * Registers a resource for garbage collection tracking.\n     * @param resource - The resource to track\n     * @param type - The type of resource to track\n     */\n    public addResource(resource: GCableEventEmitter, type: GCData['type']): void\n    {\n        // Already being tracked\n        if (resource._gcLastUsed !== -1)\n        {\n            resource._gcLastUsed = this.now;\n            resource._onTouch?.(this.now);\n\n            return;\n        }\n\n        const index = this._managedResources.length;\n\n        resource._gcData = {\n            index,\n            type,\n        };\n        resource._gcLastUsed = this.now;\n        resource._onTouch?.(this.now);\n        resource.once('unload', this.removeResource, this);\n\n        this._managedResources.push(resource);\n    }\n\n    /**\n     * Removes a resource from garbage collection tracking.\n     * Call this when manually destroying a resource.\n     * @param resource - The resource to stop tracking\n     */\n    public removeResource(resource: GCable): void\n    {\n        const gcData = resource._gcData;\n\n        if (!gcData) return;\n\n        const index = gcData.index;\n        const last = this._managedResources.length - 1;\n\n        // Swap with last element for O(1) removal\n        if (index !== last)\n        {\n            const lastResource = this._managedResources[last];\n\n            this._managedResources[index] = lastResource;\n            lastResource._gcData.index = index;\n        }\n\n        this._managedResources.length--;\n        resource._gcData = null;\n        resource._gcLastUsed = -1;\n    }\n\n    /**\n     * Registers a hash-based resource collection for garbage collection tracking.\n     * Resources in the hash will be automatically tracked and cleaned up when unused.\n     * @param context - The object containing the hash property\n     * @param hash - The property name on context that holds the resource hash\n     * @param type - The type of resources in the hash ('resource' or 'renderable')\n     * @param priority - Processing priority (lower values are processed first)\n     */\n    public addResourceHash(context: any, hash: string, type: GCData['type'], priority: number = 0): void\n    {\n        this._managedResourceHashes.push({\n            context,\n            hash,\n            type,\n            priority,\n        });\n\n        this._managedResourceHashes.sort((a, b) => a.priority - b.priority);\n    }\n\n    /**\n     * Performs garbage collection by cleaning up unused resources.\n     * Removes resources that haven't been used for longer than maxUnusedTime.\n     */\n    public run(): void\n    {\n        const now = performance.now();\n        const managedResourceHashes = this._managedResourceHashes;\n\n        for (const hashEntry of managedResourceHashes)\n        {\n            this.runOnHash(hashEntry, now);\n        }\n\n        let writeIndex = 0;\n\n        for (let i = 0; i < this._managedResources.length; i++)\n        {\n            const resource = this._managedResources[i];\n\n            writeIndex = this.runOnResource(resource, now, writeIndex);\n        }\n\n        this._managedResources.length = writeIndex;\n    }\n\n    protected updateRenderableGCTick(renderable: Renderable & GCable, now: number): void\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._gcLastUsed = now;\n            renderable._onTouch?.(now);\n        }\n    }\n\n    protected runOnResource(resource: GCableEventEmitter, now: number, writeIndex: number): number\n    {\n        const gcData = resource._gcData;\n\n        // special case for renderables as we do not check every frame if they are being used\n        if (gcData.type === 'renderable')\n        {\n            this.updateRenderableGCTick(resource as Renderable, now);\n        }\n\n        const isRecentlyUsed = now - resource._gcLastUsed < this.maxUnusedTime;\n\n        if (isRecentlyUsed || !resource.autoGarbageCollect)\n        {\n            this._managedResources[writeIndex] = resource;\n            gcData.index = writeIndex;\n            writeIndex++;\n        }\n        else\n        {\n            // Call the cleanup function\n            resource.unload();\n            resource._gcData = null;\n            resource._gcLastUsed = -1;\n            resource.off('unload', this.removeResource, this);\n        }\n\n        return writeIndex;\n    }\n\n    /**\n     * Creates a clone of the hash, copying all non-null entries up to (but not including) the stop key.\n     * @param hashValue - The original hash to clone from\n     * @param stopKey - The key to stop at (exclusive)\n     * @returns A new hash object with copied entries\n     */\n    private _createHashClone(hashValue: Record<string, GCable>, stopKey: string): Record<string, GCable>\n    {\n        const hashClone: Record<string, GCable> = Object.create(null);\n\n        for (const k in hashValue)\n        {\n            if (k === stopKey) break;\n            if (hashValue[k] !== null) hashClone[k] = hashValue[k];\n        }\n\n        return hashClone;\n    }\n\n    protected runOnHash(hashEntry: GCResourceHashEntry, now: number): void\n    {\n        const { context, hash, type } = hashEntry;\n\n        const hashValue = context[hash] as Record<string, GCable>;\n        let hashClone: Record<string, GCable> | null = null;\n        let nullCount = 0;\n\n        for (const key in hashValue)\n        {\n            const resource = hashValue[key];\n\n            // check if the value is null\n            if (resource === null)\n            {\n                nullCount++;\n\n                // Lazily create the clone to clean up null entries when threshold is reached\n                if (nullCount === 10000 && !hashClone)\n                {\n                    hashClone = this._createHashClone(hashValue, key);\n                }\n\n                continue;\n            }\n\n            // If no GC data, then the resource has been added since the last garbage collection\n            if (resource._gcLastUsed === -1)\n            {\n                resource._gcLastUsed = now;\n                resource._onTouch?.(now);\n\n                if (hashClone) hashClone[key] = resource;\n\n                continue;\n            }\n\n            // special case for renderables as we do not check every frame if they are being used\n            if (type === 'renderable')\n            {\n                this.updateRenderableGCTick(resource as Renderable, now);\n            }\n\n            const isRecentlyUsed = now - resource._gcLastUsed < this.maxUnusedTime;\n\n            if (!isRecentlyUsed && resource.autoGarbageCollect)\n            {\n                // Lazily create the clone only when we need to remove something\n                if (!hashClone)\n                {\n                    // we can set the value to null here to avoid having to create a new hash object\n                    // only when it crosses the 10000 threshold do we need to create a new hash object\n                    if (nullCount + 1 !== 10000)\n                    {\n                        hashValue[key] = null;\n                        nullCount++;\n                    }\n                    else\n                    {\n                        hashClone = this._createHashClone(hashValue, key);\n                    }\n                }\n\n                // Call the cleanup function\n                resource.unload();\n                resource._gcData = null;\n                resource._gcLastUsed = -1;\n            }\n            else if (hashClone)\n            {\n                hashClone[key] = resource;\n            }\n        }\n\n        // Only replace the hash if something was removed\n        if (hashClone)\n        {\n            context[hash] = hashClone;\n        }\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\n        this._managedResources.forEach((resource) =>\n        {\n            resource.off('unload', this.removeResource, this);\n        });\n        this._managedResources.length = 0;\n        this._managedResourceHashes.length = 0;\n        this._renderer = null as any as Renderer;\n    }\n}\n\n"],"names":[],"mappings":"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"}