/*---------------------------------------------------------------------------------------------
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
* See LICENSE.md in the project root for license terms and full copyright notice.
*--------------------------------------------------------------------------------------------*/
/** @packageDocumentation
 * @module WebGL
 */
import { assert, Logger } from "@itwin/core-bentley";
import { FrontendLoggerCategory } from "../../../common/FrontendLoggerCategory";
import { System } from "./System";
/** A handle to the location of a uniform within a shader program
 * @internal
 */
export class UniformHandle {
    _location;
    _type = 0 /* DataType.Undefined */;
    _data = [];
    syncToken;
    constructor(location) { this._location = location; }
    static create(program, name) {
        let location = null;
        if (undefined !== program.glProgram) {
            location = System.instance.context.getUniformLocation(program.glProgram, name);
        }
        if (null === location) {
            const errMsg = `uniform ${name} not found in ${program.description}.`;
            if (System.instance.options.errorOnMissingUniform) {
                throw new Error(errMsg);
            }
            else {
                Logger.logError(FrontendLoggerCategory.Render, errMsg);
            }
        }
        return new UniformHandle(location);
    }
    updateData(type, data) {
        assert(0 /* DataType.Undefined */ !== type && 8 /* DataType.Int */ !== type && 3 /* DataType.Float */ !== type && 10 /* DataType.Uint */ !== type);
        let updated = this._type !== type;
        if (updated) {
            this._type = type;
            if (this._data.length !== data.length)
                this._data.length = data.length;
        }
        for (let i = 0; i < data.length; i++) {
            const datum = data[i];
            updated = updated || this._data[i] !== datum;
            this._data[i] = datum;
        }
        return updated;
    }
    updateDatum(type, datum) {
        assert(8 /* DataType.Int */ === type || 10 /* DataType.Uint */ === type || 3 /* DataType.Float */ === type);
        // NB: Yes, calling data.length without actually changing the length shows up as a significant performance bottleneck...
        if (this._data.length !== 1)
            this._data.length = 1;
        const updated = this._type !== type || this._data[0] !== datum;
        this._type = type;
        this._data[0] = datum;
        return updated;
    }
    setMatrix3(mat) {
        if (this.updateData(1 /* DataType.Mat3 */, mat.data))
            System.instance.context.uniformMatrix3fv(this._location, false, mat.data);
    }
    setMatrix4(mat) {
        if (this.updateData(2 /* DataType.Mat4 */, mat.data))
            System.instance.context.uniformMatrix4fv(this._location, false, mat.data);
    }
    setUniform1iv(data) {
        if (this.updateData(9 /* DataType.IntArray */, data))
            System.instance.context.uniform1iv(this._location, data);
    }
    setUniform1fv(data) {
        if (this.updateData(4 /* DataType.FloatArray */, data))
            System.instance.context.uniform1fv(this._location, data);
    }
    setUniform2fv(data) {
        if (this.updateData(5 /* DataType.Vec2 */, data))
            System.instance.context.uniform2fv(this._location, data);
    }
    setUniform3fv(data) {
        if (this.updateData(6 /* DataType.Vec3 */, data))
            System.instance.context.uniform3fv(this._location, data);
    }
    setUniform4fv(data) {
        if (this.updateData(7 /* DataType.Vec4 */, data))
            System.instance.context.uniform4fv(this._location, data);
    }
    setUniform1i(data) {
        if (this.updateDatum(8 /* DataType.Int */, data))
            System.instance.context.uniform1i(this._location, data);
    }
    setUniform1f(data) {
        if (this.updateDatum(3 /* DataType.Float */, data))
            System.instance.context.uniform1f(this._location, data);
    }
    setUniform1ui(data) {
        if (this.updateDatum(10 /* DataType.Uint */, data))
            System.instance.context.uniform1ui(this._location, data);
    }
    setUniformBitflags(data) {
        this.setUniform1ui(data);
    }
}
//# sourceMappingURL=UniformHandle.js.map