<commit_before>import System from '../System';
import GLProgram from './GLProgram';
import { generateUniformsSync,
    defaultValue,
    compileProgram } from './utils';

let UID = 0;

/**
 * Helper class to create a webGL Texture
 *
 * @class
 * @memberof PIXI.systems
 * @extends PIXI.System
 */
export default class ShaderSystem extends System
{
    /**
     * @param {PIXI.Renderer} renderer - A reference to the current renderer
     */
    constructor(renderer)
    {
        super(renderer);

        /**
         * The current WebGL rendering context
         *
         * @member {WebGLRenderingContext}
         */
        this.gl = null;

        this.shader = null;
        this.program = null;

        this.id = UID++;
    }

    contextChange(gl)
    {
        this.gl = gl;
    }

    /**
     * Changes the current shader to the one given in parameter
     *
     * @param {PIXI.Shader} shader - the new shader
     * @param {boolean} dontSync - false if the shader should automatically sync its uniforms.
     * @returns {PIXI.glCore.glProgram} the glProgram that belongs to the shader.
     */
    bind(shader, dontSync)
    {
        shader.uniforms.globals = this.renderer.globalUniforms;

        const program = shader.program;
        const glProgram = program.glPrograms[this.renderer.CONTEXT_UID] || this.generateShader(shader);

        this.shader = shader;

        // TODO - some current pixi plugins bypass this.. so it not safe to use yet..
        if (this.program !== program)
        {
            this.program = program;
            this.gl.useProgram(glProgram.program);
        }

        if (!dontSync)
        {
            this.syncUniformGroup(shader.uniformGroup);
        }

        return glProgram;
    }

    /**
     * Uploads the uniforms values to the currently bound shader.
     *
     * @param {object} uniforms - the uniforms valiues that be applied to the current shader
     */
    setUniforms(uniforms)
    {
        const shader = this.shader.program;
        const glProgram = shader.glPrograms[this.renderer.CONTEXT_UID];

        shader.syncUniforms(glProgram.uniformData, uniforms, this.renderer);
    }

    syncUniformGroup(group)
    {
        const glProgram = this.getglProgram();

        if (!group.static || group.dirtyId !== glProgram.uniformGroups[group.id])
        {
            glProgram.uniformGroups[group.id] = group.dirtyId;
            const syncFunc = group.syncUniforms[this.shader.program.id] || this.createSyncGroups(group);

            syncFunc(glProgram.uniformData, group.uniforms, this.renderer);
        }
    }

    createSyncGroups(group)
    {
        group.syncUniforms[this.shader.program.id] = generateUniformsSync(group, this.shader.program.uniformData);

        return group.syncUniforms[this.shader.program.id];
    }

    /**
     * Returns the underlying GLShade rof the currently bound shader.
     * This can be handy for when you to have a little more control over the setting of your uniforms.
     *
     * @return {PIXI.glCore.Shader} the glProgram for the currently bound Shader for this context
     */
    getglProgram()
    {
        if (this.shader)
        {
            return this.shader.program.glPrograms[this.renderer.CONTEXT_UID];
        }

        return null;
    }

    /**
     * Generates a glProgram verion of the Shader provided.
     *
     * @private
     * @param {PIXI.Shader} shader the shader that the glProgram will be based on.
     * @return {PIXI.glCore.glProgram} A shiney new glProgram
     */
    generateShader(shader)
    {<commit_msg>Adds a caching layer to generateSyncUniforms (#4792)<commit_after>import System from '../System';
import GLProgram from './GLProgram';
import { generateUniformsSync,
    defaultValue,
    compileProgram } from './utils';

let UID = 0;

/**
 * Helper class to create a webGL Texture
 *
 * @class
 * @memberof PIXI.systems
 * @extends PIXI.System
 */
export default class ShaderSystem extends System
{
    /**
     * @param {PIXI.Renderer} renderer - A reference to the current renderer
     */
    constructor(renderer)
    {
        super(renderer);

        /**
         * The current WebGL rendering context
         *
         * @member {WebGLRenderingContext}
         */
        this.gl = null;

        this.shader = null;
        this.program = null;

        /**
         * Cache to holds the generated functions. Stored against UniformObjects unique signiture
         * @type {Object}
         * @private
         */
        this.cache = {};

        this.id = UID++;
    }

    contextChange(gl)
    {
        this.gl = gl;
    }

    /**
     * Changes the current shader to the one given in parameter
     *
     * @param {PIXI.Shader} shader - the new shader
     * @param {boolean} dontSync - false if the shader should automatically sync its uniforms.
     * @returns {PIXI.glCore.glProgram} the glProgram that belongs to the shader.
     */
    bind(shader, dontSync)
    {
        shader.uniforms.globals = this.renderer.globalUniforms;

        const program = shader.program;
        const glProgram = program.glPrograms[this.renderer.CONTEXT_UID] || this.generateShader(shader);

        this.shader = shader;

        // TODO - some current pixi plugins bypass this.. so it not safe to use yet..
        if (this.program !== program)
        {
            this.program = program;
            this.gl.useProgram(glProgram.program);
        }

        if (!dontSync)
        {
            this.syncUniformGroup(shader.uniformGroup);
        }

        return glProgram;
    }

    /**
     * Uploads the uniforms values to the currently bound shader.
     *
     * @param {object} uniforms - the uniforms valiues that be applied to the current shader
     */
    setUniforms(uniforms)
    {
        const shader = this.shader.program;
        const glProgram = shader.glPrograms[this.renderer.CONTEXT_UID];

        shader.syncUniforms(glProgram.uniformData, uniforms, this.renderer);
    }

    syncUniformGroup(group)
    {
        const glProgram = this.getglProgram();

        if (!group.static || group.dirtyId !== glProgram.uniformGroups[group.id])
        {
            glProgram.uniformGroups[group.id] = group.dirtyId;
            const syncFunc = group.syncUniforms[this.shader.program.id] || this.createSyncGroups(group);

            syncFunc(glProgram.uniformData, group.uniforms, this.renderer);
        }
    }

    createSyncGroups(group)
    {
        const id = this.getSignature(group, this.shader.program.uniformData);

        if (!this.cache[id])
        {
            this.cache[id] = generateUniformsSync(group, this.shader.program.uniformData);
        }

        group.syncUniforms[this.shader.program.id] = this.cache[id];

        return group.syncUniforms[this.shader.program.id];
    }

    /**
     * Takes a uniform group and data and generates a unique signiture for them.
     *
     * @param {PIXI.UniformGroup} group the uniform group to get signiture of
     * @param {Object} uniformData uniform information generated by the shader
     * @returns {String} Unique signiture of the uniform group
     * @private
     */
    getSignature(group, uniformData)
    {
        const uniforms = group.uniforms;

        let sig = '';

        for (const i in uniforms)
        {
            if (uniformData[i])
            {
                sig += i + uniformData[i].type;
            }
            else
            {
                sig += i;
            }
        }

        return sig;
    }

    /**
     * Returns the underlying GLShade rof the currently bound shader.
     * This can be handy for when you to have a little more control over the setting of your uniforms.
     *
     * @return {PIXI.glCore.Shader} the glProgram for the currently bound Shader for this context
     */
    getglProgram()
    {
        if (this.shader)
        {
            return this.shader.program.glPrograms[this.renderer.CONTEXT_UID];
        }

        return null;
    }

    /**
     * Generates a glProgram verion of the Shader provided.
     *
     * @private
     * @param {PIXI.Shader} shader the shader that the glProgram will be based on.
     * @return {PIXI.glCore.glProgram} A shiney new glProgram
     */
    generateShader(shader)
    {
{'fraction_non_alphanumeric': 0.09816247582205029, 'fraction_numerical': 0.0007253384912959381, 'mean_word_length': 2.0903997011580127, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7646566', 'n_tokens_mistral': 2405, 'n_tokens_neox': 2335, 'n_words': 630}