{"version":3,"file":"BindGroup.mjs","sources":["../../../../../src/rendering/renderers/gpu/shader/BindGroup.ts"],"sourcesContent":["import { type GCable } from '../../shared/GCSystem';\n\nimport type { BindResource } from './BindResource';\n\n/**\n * A bind group is a collection of resources that are bound together for use by a shader.\n * They are essentially a wrapper for the WebGPU BindGroup class. But with the added bonus\n * that WebGL can also work with them.\n * @see https://gpuweb.github.io/gpuweb/#dictdef-gpubindgroupdescriptor\n * @example\n * // Create a bind group with a single texture and sampler\n * const bindGroup = new BindGroup({\n *    uTexture: texture.source,\n *    uTexture: texture.style,\n * });\n *\n * Bind groups resources must implement the {@link BindResource} interface.\n * The following resources are supported:\n * - {@link TextureSource}\n * - {@link TextureStyle}\n * - {@link Buffer}\n * - {@link BufferResource}\n * - {@link UniformGroup}\n *\n * The keys in the bind group must correspond to the names of the resources in the GPU program.\n *\n * This bind group class will also watch for changes in its resources ensuring that the changes\n * are reflected in the WebGPU BindGroup.\n * @category rendering\n * @advanced\n */\nexport class BindGroup\n{\n    /** The resources that are bound together for use by a shader. */\n    public resources: Record<string, BindResource> = Object.create(null);\n    /**\n     * a key used internally to match it up to a WebGPU Bindgroup\n     * @internal\n     */\n    public _key: string;\n    private _dirty = true;\n\n    /**\n     * Create a new instance eof the Bind Group.\n     * @param resources - The resources that are bound together for use by a shader.\n     */\n    constructor(resources?: Record<string, BindResource>)\n    {\n        let index = 0;\n\n        for (const i in resources)\n        {\n            const resource: BindResource = resources[i];\n\n            this.setResource(resource, index++);\n        }\n\n        this._updateKey();\n    }\n\n    /**\n     * Updates the key if its flagged as dirty. This is used internally to\n     * match this bind group to a WebGPU BindGroup.\n     * @internal\n     */\n    public _updateKey(): void\n    {\n        if (!this._dirty) return;\n\n        this._dirty = false;\n\n        const keyParts = [];\n        let index = 0;\n\n        // TODO - lets use big ints instead of strings...\n        for (const i in this.resources)\n        {\n            // TODO make this consistent...\n            keyParts[index++] = this.resources[i]._resourceId;\n        }\n\n        this._key = keyParts.join('|');\n    }\n\n    /**\n     * Set a resource at a given index. this function will\n     * ensure that listeners will be removed from the current resource\n     * and added to the new resource.\n     * @param resource - The resource to set.\n     * @param index - The index to set the resource at.\n     */\n    public setResource(resource: BindResource, index: number): void\n    {\n        const currentResource = this.resources[index];\n\n        if (resource === currentResource) return;\n\n        currentResource?.off?.('change', this.onResourceChange, this);\n        resource.on?.('change', this.onResourceChange, this);\n\n        this.resources[index] = resource;\n        this._dirty = true;\n    }\n\n    /**\n     * Returns the resource at the current specified index.\n     * @param index - The index of the resource to get.\n     * @returns - The resource at the specified index.\n     */\n    public getResource(index: number): BindResource\n    {\n        return this.resources[index];\n    }\n\n    /**\n     * Used internally to 'touch' each resource, to ensure that the GC\n     * knows that all resources in this bind group are still being used.\n     * @param now - The current time in milliseconds.\n     * @param tick - The current tick.\n     * @internal\n     */\n    public _touch(now: number, tick: number): void\n    {\n        const resources = this.resources;\n\n        for (const i in resources)\n        {\n            (resources[i] as BindResource & GCable)._gcLastUsed = now;\n            resources[i]._touched = tick;\n        }\n    }\n\n    /** Destroys this bind group and removes all listeners. */\n    public destroy()\n    {\n        const resources = this.resources;\n\n        for (const i in resources)\n        {\n            const resource = resources[i];\n\n            resource?.off?.('change', this.onResourceChange, this);\n        }\n\n        this.resources = null;\n    }\n\n    protected onResourceChange(resource: BindResource)\n    {\n        this._dirty = true;\n\n        // check if a resource has been destroyed, if it has then we need to destroy this bind group\n        // using this bind group with a destroyed resource will cause the renderer to explode :)\n        if (resource.destroyed)\n        {\n            this.destroy();\n        }\n        else\n        {\n            this._updateKey();\n        }\n    }\n}\n"],"names":[],"mappings":";AA+BO,MAAM,SAAA,CACb;AAAA;AAAA;AAAA;AAAA;AAAA,EAcI,YAAY,SAAA,EACZ;AAbA;AAAA,IAAA,IAAA,CAAO,SAAA,mBAA0C,MAAA,CAAO,MAAA,CAAO,IAAI,CAAA;AAMnE,IAAA,IAAA,CAAQ,MAAA,GAAS,IAAA;AAQb,IAAA,IAAI,KAAA,GAAQ,CAAA;AAEZ,IAAA,KAAA,MAAW,KAAK,SAAA,EAChB;AACI,MAAA,MAAM,QAAA,GAAyB,UAAU,CAAC,CAAA;AAE1C,MAAA,IAAA,CAAK,WAAA,CAAY,UAAU,KAAA,EAAO,CAAA;AAAA,IACtC;AAEA,IAAA,IAAA,CAAK,UAAA,EAAW;AAAA,EACpB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOO,UAAA,GACP;AACI,IAAA,IAAI,CAAC,KAAK,MAAA,EAAQ;AAElB,IAAA,IAAA,CAAK,MAAA,GAAS,KAAA;AAEd,IAAA,MAAM,WAAW,EAAC;AAClB,IAAA,IAAI,KAAA,GAAQ,CAAA;AAGZ,IAAA,KAAA,MAAW,CAAA,IAAK,KAAK,SAAA,EACrB;AAEI,MAAA,QAAA,CAAS,KAAA,EAAO,CAAA,GAAI,IAAA,CAAK,SAAA,CAAU,CAAC,CAAA,CAAE,WAAA;AAAA,IAC1C;AAEA,IAAA,IAAA,CAAK,IAAA,GAAO,QAAA,CAAS,IAAA,CAAK,GAAG,CAAA;AAAA,EACjC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASO,WAAA,CAAY,UAAwB,KAAA,EAC3C;AACI,IAAA,MAAM,eAAA,GAAkB,IAAA,CAAK,SAAA,CAAU,KAAK,CAAA;AAE5C,IAAA,IAAI,aAAa,eAAA,EAAiB;AAElC,IAAA,eAAA,EAAiB,GAAA,GAAM,QAAA,EAAU,IAAA,CAAK,gBAAA,EAAkB,IAAI,CAAA;AAC5D,IAAA,QAAA,CAAS,EAAA,GAAK,QAAA,EAAU,IAAA,CAAK,gBAAA,EAAkB,IAAI,CAAA;AAEnD,IAAA,IAAA,CAAK,SAAA,CAAU,KAAK,CAAA,GAAI,QAAA;AACxB,IAAA,IAAA,CAAK,MAAA,GAAS,IAAA;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOO,YAAY,KAAA,EACnB;AACI,IAAA,OAAO,IAAA,CAAK,UAAU,KAAK,CAAA;AAAA,EAC/B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASO,MAAA,CAAO,KAAa,IAAA,EAC3B;AACI,IAAA,MAAM,YAAY,IAAA,CAAK,SAAA;AAEvB,IAAA,KAAA,MAAW,KAAK,SAAA,EAChB;AACI,MAAC,SAAA,CAAU,CAAC,CAAA,CAA4B,WAAA,GAAc,GAAA;AACtD,MAAA,SAAA,CAAU,CAAC,EAAE,QAAA,GAAW,IAAA;AAAA,IAC5B;AAAA,EACJ;AAAA;AAAA,EAGO,OAAA,GACP;AACI,IAAA,MAAM,YAAY,IAAA,CAAK,SAAA;AAEvB,IAAA,KAAA,MAAW,KAAK,SAAA,EAChB;AACI,MAAA,MAAM,QAAA,GAAW,UAAU,CAAC,CAAA;AAE5B,MAAA,QAAA,EAAU,GAAA,GAAM,QAAA,EAAU,IAAA,CAAK,gBAAA,EAAkB,IAAI,CAAA;AAAA,IACzD;AAEA,IAAA,IAAA,CAAK,SAAA,GAAY,IAAA;AAAA,EACrB;AAAA,EAEU,iBAAiB,QAAA,EAC3B;AACI,IAAA,IAAA,CAAK,MAAA,GAAS,IAAA;AAId,IAAA,IAAI,SAAS,SAAA,EACb;AACI,MAAA,IAAA,CAAK,OAAA,EAAQ;AAAA,IACjB,CAAA,MAEA;AACI,MAAA,IAAA,CAAK,UAAA,EAAW;AAAA,IACpB;AAAA,EACJ;AACJ;;;;"}