{"version":3,"file":"GlProgram.mjs","sources":["../../../../../src/rendering/renderers/gl/shader/GlProgram.ts"],"sourcesContent":["import { createIdFromString } from '../../shared/utils/createIdFromString';\nimport { getMaxFragmentPrecision } from './program/getMaxFragmentPrecision';\nimport { addProgramDefines } from './program/preprocessors/addProgramDefines';\nimport { ensurePrecision } from './program/preprocessors/ensurePrecision';\nimport { insertVersion } from './program/preprocessors/insertVersion';\nimport { setProgramName } from './program/preprocessors/setProgramName';\nimport { stripVersion } from './program/preprocessors/stripVersion';\n\nimport type { TypedArray } from '../../shared/buffer/Buffer';\nimport type { ExtractedAttributeData } from './program/extractAttributesFromGlProgram';\n\n/** @internal */\nexport interface GlUniformData\n{\n    name: string;\n    index: number;\n    type: string;\n    size: number;\n    isArray: boolean;\n    value: any;\n}\n\n/** @internal */\nexport interface GlUniformBlockData\n{\n    index: number;\n    name: string;\n    size: number;\n    value?: TypedArray;\n}\n\n/**\n * The options for the gl program\n * @category rendering\n * @advanced\n */\nexport interface GlProgramOptions\n{\n    /** The fragment glsl shader source. */\n    fragment: string;\n    /** The vertex glsl shader source. */\n    vertex: string;\n    /** the name of the program, defaults to 'pixi-program' */\n    name?: string;\n    /** the preferred vertex precision for the shader, this may not be used if the device does not support it  */\n    preferredVertexPrecision?: string;\n    /** the preferred fragment precision for the shader, this may not be used if the device does not support it  */\n    preferredFragmentPrecision?: string;\n\n    transformFeedbackVaryings?: {names: string[], bufferMode: 'separate' | 'interleaved'};\n}\n\nconst processes: Record<string, ((source: string, options: any, isFragment?: boolean) => string)> = {\n    // strips any version headers..\n    stripVersion,\n    // adds precision string if not already present\n    ensurePrecision,\n    // add some defines if WebGL1 to make it more compatible with WebGL2 shaders\n    addProgramDefines,\n    // add the program name to the shader\n    setProgramName,\n    // add the version string to the shader header\n    insertVersion,\n};\n\nconst programCache: Record<string, GlProgram> = Object.create(null);\n\n/**\n * A wrapper for a WebGL Program. You can create one and then pass it to a shader.\n * This will manage the WebGL program that is compiled and uploaded to the GPU.\n *\n * To get the most out of this class, you should be familiar with glsl shaders and how they work.\n * @see https://developer.mozilla.org/en-US/docs/Web/API/WebGLProgram\n * @example\n *\n * // Create a new program\n * const program = new GlProgram({\n *   vertex: '...',\n *   fragment: '...',\n * });\n *\n *\n * There are a few key things that pixi shader will do for you automatically:\n * <br>\n * - If no precision is provided in the shader, it will be injected into the program source for you.\n * This precision will be taken form the options provided, if none is provided,\n * then the program will default to the defaultOptions.\n * <br>\n * - It will inject the program name into the shader source if none is provided.\n * <br>\n *  - It will set the program version to 300 es.\n *\n * For optimal usage and best performance, its best to reuse programs as much as possible.\n * You should use the {@link GlProgram.from} helper function to create programs.\n * @class\n * @category rendering\n * @advanced\n */\nexport class GlProgram\n{\n    /** The default options used by the program. */\n    public static defaultOptions: Partial<GlProgramOptions> = {\n        preferredVertexPrecision: 'highp',\n        preferredFragmentPrecision: 'mediump',\n    };\n\n    /** the fragment glsl shader source. */\n    public readonly fragment?: string;\n    /** the vertex glsl shader source */\n    public readonly vertex?: string;\n    /**\n     * attribute data extracted from the program once created this happens when the program is used for the first time\n     * @internal\n     */\n    public _attributeData: Record<string, ExtractedAttributeData>;\n    /**\n     * uniform data extracted from the program once created this happens when the program is used for the first time\n     * @internal\n     */\n    public _uniformData: Record<string, GlUniformData>;\n    /**\n     * uniform data extracted from the program once created this happens when the program is used for the first time\n     * @internal\n     */\n    public _uniformBlockData: Record<string, GlUniformBlockData>;\n    /** details on how to use this program with transform feedback */\n    public transformFeedbackVaryings?: {names: string[], bufferMode: 'separate' | 'interleaved'};\n    /**\n     * the key that identifies the program via its source vertex + fragment\n     * @internal\n     */\n    public readonly _key: number;\n    /**\n     * A cache key used to identify the program instance.\n     * @internal\n     */\n    public _cacheKey: string;\n\n    /**\n     * Creates a shiny new GlProgram. Used by WebGL renderer.\n     * @param options - The options for the program.\n     */\n    constructor(options: GlProgramOptions)\n    {\n        options = { ...GlProgram.defaultOptions, ...options };\n\n        // only need to check one as they both need to be the same or\n        // errors ensue!\n        const isES300 = options.fragment.indexOf('#version 300 es') !== -1;\n\n        const preprocessorOptions = {\n            stripVersion: isES300,\n            ensurePrecision: {\n                requestedFragmentPrecision: options.preferredFragmentPrecision,\n                requestedVertexPrecision: options.preferredVertexPrecision,\n                maxSupportedVertexPrecision: 'highp',\n                maxSupportedFragmentPrecision: getMaxFragmentPrecision(),\n            },\n            setProgramName: {\n                name: options.name,\n            },\n            addProgramDefines: isES300,\n            insertVersion: isES300\n        };\n\n        let fragment = options.fragment;\n        let vertex = options.vertex;\n\n        Object.keys(processes).forEach((processKey) =>\n        {\n            const processOptions = preprocessorOptions[processKey as keyof typeof preprocessorOptions];\n\n            fragment = processes[processKey](fragment, processOptions, true);\n            vertex = processes[processKey](vertex, processOptions, false);\n        });\n\n        this.fragment = fragment;\n        this.vertex = vertex;\n\n        this.transformFeedbackVaryings = options.transformFeedbackVaryings;\n\n        this._key = createIdFromString(`${this.vertex}:${this.fragment}`, 'gl-program');\n    }\n\n    /** destroys the program */\n    public destroy(): void\n    {\n        (this.fragment as null) = null;\n        (this.vertex as null) = null;\n\n        this._attributeData = null;\n        this._uniformData = null;\n        this._uniformBlockData = null;\n\n        this.transformFeedbackVaryings = null;\n\n        programCache[this._cacheKey] = null;\n    }\n\n    /**\n     * Helper function that creates a program for a given source.\n     * It will check the program cache if the program has already been created.\n     * If it has that one will be returned, if not a new one will be created and cached.\n     * @param options - The options for the program.\n     * @returns A program using the same source\n     */\n    public static from(options: GlProgramOptions): GlProgram\n    {\n        const key = `${options.vertex}:${options.fragment}`;\n\n        if (!programCache[key])\n        {\n            programCache[key] = new GlProgram(options);\n            programCache[key]._cacheKey = key;\n        }\n\n        return programCache[key];\n    }\n}\n"],"names":[],"mappings":"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"}