{"version":3,"file":"GlShaderSystem.mjs","sources":["../../../../../src/rendering/renderers/gl/shader/GlShaderSystem.ts"],"sourcesContent":["import { ExtensionType } from '../../../../extensions/Extensions';\nimport { generateShaderSyncCode } from './GenerateShaderSyncCode';\nimport { generateProgram } from './program/generateProgram';\n\nimport type { BufferResource } from '../../shared/buffer/BufferResource';\nimport type { Shader } from '../../shared/shader/Shader';\nimport type { UniformGroup } from '../../shared/shader/UniformGroup';\nimport type { GlRenderingContext } from '../context/GlRenderingContext';\nimport type { WebGLRenderer } from '../WebGLRenderer';\nimport type { GlProgram } from './GlProgram';\nimport type { GlProgramData } from './GlProgramData';\n\n/** @internal */\nexport interface ShaderSyncData\n{\n    textureCount: number;\n    blockIndex: number;\n}\n\n/** @internal */\nexport type ShaderSyncFunction = (renderer: WebGLRenderer, shader: Shader, syncData: ShaderSyncData) => void;\n\n// default sync data so we don't create a new one each time!\nconst defaultSyncData: ShaderSyncData = {\n    textureCount: 0,\n    blockIndex: 0,\n};\n\n/**\n * System plugin to the renderer to manage the shaders for WebGL.\n * @category rendering\n * @advanced\n */\nexport class GlShaderSystem\n{\n    /** @ignore */\n    public static extension = {\n        type: [\n            ExtensionType.WebGLSystem,\n        ],\n        name: 'shader',\n    } as const;\n\n    /** @internal */\n    public _activeProgram: GlProgram = null;\n\n    private _programDataHash: Record<string, GlProgramData> = Object.create(null);\n    private readonly _renderer: WebGLRenderer;\n    /** @internal */\n    public _gl: WebGL2RenderingContext;\n    private _shaderSyncFunctions: Record<string, ShaderSyncFunction> = Object.create(null);\n\n    constructor(renderer: WebGLRenderer)\n    {\n        this._renderer = renderer;\n    }\n\n    protected contextChange(gl: GlRenderingContext): void\n    {\n        this._gl = gl;\n\n        this._programDataHash = Object.create(null);\n        /**\n         * these need to also be cleared as internally some uniforms are set as an optimisation as the sync\n         * function is generated. Specifically the texture ints.\n         */\n        this._shaderSyncFunctions = Object.create(null);\n        this._activeProgram = null;\n    }\n\n    /**\n     * Changes the current shader to the one given in parameter.\n     * @param shader - the new shader\n     * @param skipSync - false if the shader should automatically sync its uniforms.\n     * @returns the glProgram that belongs to the shader.\n     */\n    public bind(shader: Shader, skipSync?: boolean): void\n    {\n        this._setProgram(shader.glProgram);\n\n        if (skipSync) return;\n\n        defaultSyncData.textureCount = 0;\n        defaultSyncData.blockIndex = 0;\n\n        let syncFunction = this._shaderSyncFunctions[shader.glProgram._key];\n\n        if (!syncFunction)\n        {\n            syncFunction = this._shaderSyncFunctions[shader.glProgram._key] = this._generateShaderSync(shader, this);\n        }\n\n        // TODO: take into account number of TF buffers. Currently works only with interleaved\n        this._renderer.buffer.nextBindBase(!!shader.glProgram.transformFeedbackVaryings);\n        syncFunction(this._renderer, shader, defaultSyncData);\n    }\n\n    /**\n     * Updates the uniform group.\n     * @param uniformGroup - the uniform group to update\n     */\n    public updateUniformGroup(uniformGroup: UniformGroup): void\n    {\n        this._renderer.uniformGroup.updateUniformGroup(uniformGroup, this._activeProgram, defaultSyncData);\n    }\n\n    /**\n     * Binds a uniform block to the shader.\n     * @param uniformGroup - the uniform group to bind\n     * @param name - the name of the uniform block\n     * @param index - the index of the uniform block\n     */\n    public bindUniformBlock(uniformGroup: UniformGroup | BufferResource, name: string, index = 0): void\n    {\n        const bufferSystem = this._renderer.buffer;\n        const programData = this._getProgramData(this._activeProgram);\n\n        const isBufferResource = (uniformGroup as BufferResource)._bufferResource;\n\n        if (!isBufferResource)\n        {\n            this._renderer.ubo.updateUniformGroup(uniformGroup as UniformGroup);\n        }\n\n        const buffer = uniformGroup.buffer;\n\n        const glBuffer = bufferSystem.updateBuffer(buffer);\n\n        const boundLocation = bufferSystem.freeLocationForBufferBase(glBuffer);\n\n        if (isBufferResource)\n        {\n            const { offset, size } = (uniformGroup as BufferResource);\n\n            // trivial case of buffer resource, can be cached\n            if (offset === 0 && size === buffer.data.byteLength)\n            {\n                bufferSystem.bindBufferBase(glBuffer, boundLocation);\n            }\n            else\n            {\n                bufferSystem.bindBufferRange(glBuffer, boundLocation, offset);\n            }\n        }\n        else if (bufferSystem.getLastBindBaseLocation(glBuffer) !== boundLocation)\n        {\n            // confirmation that buffer isn't there yet\n            bufferSystem.bindBufferBase(glBuffer, boundLocation);\n        }\n\n        const uniformBlockIndex = this._activeProgram._uniformBlockData[name].index;\n\n        if (programData.uniformBlockBindings[index] === boundLocation) return;\n        programData.uniformBlockBindings[index] = boundLocation;\n\n        this._renderer.gl.uniformBlockBinding(programData.program, uniformBlockIndex, boundLocation);\n    }\n\n    private _setProgram(program: GlProgram)\n    {\n        if (this._activeProgram === program) return;\n\n        this._activeProgram = program;\n\n        const programData = this._getProgramData(program);\n\n        this._gl.useProgram(programData.program);\n    }\n\n    /**\n     * @param program - the program to get the data for\n     * @internal\n     */\n    public _getProgramData(program: GlProgram): GlProgramData\n    {\n        return this._programDataHash[program._key] || this._createProgramData(program);\n    }\n\n    private _createProgramData(program: GlProgram): GlProgramData\n    {\n        const key = program._key;\n\n        this._programDataHash[key] = generateProgram(this._gl, program);\n\n        return this._programDataHash[key];\n    }\n\n    public destroy(): void\n    {\n        for (const key of Object.keys(this._programDataHash))\n        {\n            this._programDataHash[key].destroy();\n        }\n\n        this._programDataHash = null;\n        this._shaderSyncFunctions = null;\n        this._activeProgram = null;\n        (this._renderer as null) = null;\n        this._gl = null;\n    }\n\n    /**\n     * Creates a function that can be executed that will sync the shader as efficiently as possible.\n     * Overridden by the unsafe eval package if you don't want eval used in your project.\n     * @param shader - the shader to generate the sync function for\n     * @param shaderSystem - the shader system to use\n     * @returns - the generated sync function\n     * @ignore\n     */\n    public _generateShaderSync(shader: Shader, shaderSystem: GlShaderSystem): ShaderSyncFunction\n    {\n        return generateShaderSyncCode(shader, shaderSystem);\n    }\n\n    public resetState(): void\n    {\n        this._activeProgram = null;\n    }\n}\n"],"names":[],"mappings":"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"}