/*---------------------------------------------------------------------------------------------
* 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
 */
var __addDisposableResource = (this && this.__addDisposableResource) || function (env, value, async) {
    if (value !== null && value !== void 0) {
        if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected.");
        var dispose, inner;
        if (async) {
            if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined.");
            dispose = value[Symbol.asyncDispose];
        }
        if (dispose === void 0) {
            if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined.");
            dispose = value[Symbol.dispose];
            if (async) inner = dispose;
        }
        if (typeof dispose !== "function") throw new TypeError("Object not disposable.");
        if (inner) dispose = function() { try { inner.call(this); } catch (e) { return Promise.reject(e); } };
        env.stack.push({ value: value, dispose: dispose, async: async });
    }
    else if (async) {
        env.stack.push({ async: true });
    }
    return value;
};
var __disposeResources = (this && this.__disposeResources) || (function (SuppressedError) {
    return function (env) {
        function fail(e) {
            env.error = env.hasError ? new SuppressedError(e, env.error, "An error was suppressed during disposal.") : e;
            env.hasError = true;
        }
        var r, s = 0;
        function next() {
            while (r = env.stack.pop()) {
                try {
                    if (!r.async && s === 1) return s = 0, env.stack.push(r), Promise.resolve().then(next);
                    if (r.dispose) {
                        var result = r.dispose.call(r.value);
                        if (r.async) return s |= 2, Promise.resolve(result).then(next, function(e) { fail(e); return next(); });
                    }
                    else s |= 1;
                }
                catch (e) {
                    fail(e);
                }
            }
            if (s === 1) return env.hasError ? Promise.reject(env.error) : Promise.resolve();
            if (env.hasError) throw env.error;
        }
        return next();
    };
})(typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
    var e = new Error(message);
    return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
});
import { assert, dispose } from "@itwin/core-bentley";
import { BlurType } from "./CachedGeometry";
import { createClippingProgram } from "./ClippingProgram";
import { createAmbientOcclusionProgram } from "./glsl/AmbientOcclusion";
import { createBlurProgram } from "./glsl/Blur";
import { createEDLCalcBasicProgram, createEDLCalcFullProgram, createEDLFilterProgram, createEDLMixProgram } from "./glsl/EDL";
import { createClearPickAndColorProgram } from "./glsl/ClearPickAndColor";
import { createClearTranslucentProgram } from "./glsl/ClearTranslucent";
import { createCombine3TexturesProgram } from "./glsl/Combine3Textures";
import { createCombineTexturesProgram } from "./glsl/CombineTextures";
import { addEyeSpace, addFrustum, addShaderFlags } from "./glsl/Common";
import { createCompositeProgram } from "./glsl/Composite";
import { createCopyColorProgram } from "./glsl/CopyColor";
import { createCopyPickBuffersProgram } from "./glsl/CopyPickBuffers";
import { createVolClassBlendProgram, createVolClassColorUsingStencilProgram, createVolClassCopyZProgram, createVolClassSetBlendProgram, } from "./glsl/CopyStencil";
import { createEdgeBuilder } from "./glsl/Edge";
import { createEVSMProgram } from "./glsl/EVSMFromDepth";
import { addFeatureId, addFeatureSymbology, addRenderOrder, addUniformFeatureSymbology, mixFeatureColor } from "./glsl/FeatureSymbology";
import { addFragColorWithPreMultipliedAlpha, addPickBufferOutputs } from "./glsl/Fragment";
import { addLogDepth } from "./glsl/LogarithmicDepthBuffer";
import { addUnlitMonochrome } from "./glsl/Monochrome";
import createPlanarGridProgram from "./glsl/PlanarGrid";
import { createPointCloudBuilder, createPointCloudHiliter } from "./glsl/PointCloud";
import { createPointStringBuilder, createPointStringHiliter } from "./glsl/PointString";
import { createPolylineBuilder, createPolylineHiliter } from "./glsl/Polyline";
import { addColorOverrideMix, createClassifierRealityMeshHiliter, createRealityMeshBuilder, createRealityMeshHiliter, } from "./glsl/RealityMesh";
import { createSkyBoxProgram } from "./glsl/SkyBox";
import { createSkySphereBuilder } from "./glsl/SkySphere";
import { createSurfaceBuilder, createSurfaceHiliter } from "./glsl/Surface";
import { addTranslucency } from "./glsl/Translucency";
import { addModelViewMatrix } from "./glsl/Vertex";
import { ShaderProgramExecutor } from "./ShaderProgram";
import { System } from "./System";
import { TechniqueFlags, } from "./TechniqueFlags";
import { computeCompositeTechniqueId } from "./TechniqueId";
/** A rendering technique implemented using a single shader program, typically for some specialized purpose.
 * @internal
 */
export class SingularTechnique {
    program;
    // Note: Technique assumes ownership of a program
    constructor(program) { this.program = program; }
    getShader(_flags) { return this.program; }
    getShaderByIndex(_index) { return this.program; }
    getShaderCount() { return 1; }
    compileShaders() { return this.program.compile() === 0 /* CompileStatus.Success */; }
    get isDisposed() { return this.program.isDisposed; }
    [Symbol.dispose]() {
        this.program[Symbol.dispose]();
    }
    /** @deprecated in 5.0 - will not be removed until after 2026-06-13. Use [Symbol.dispose] instead. */
    dispose() {
        this[Symbol.dispose]();
    }
}
function numFeatureVariants(numBaseShaders) {
    return numBaseShaders * 3;
}
const numHiliteVariants = 2; // instanced and non-instanced.
const featureModes = [0 /* FeatureMode.None */, 1 /* FeatureMode.Pick */, 2 /* FeatureMode.Overrides */];
const scratchTechniqueFlags = new TechniqueFlags();
const scratchHiliteFlags = new TechniqueFlags();
/** A rendering technique implemented using multiple shader programs, selected based on TechniqueFlags.
 * @internal
 */
export class VariedTechnique {
    _basicPrograms = [];
    _clippingPrograms = [];
    /** TechniqueFlags identifying shader programs for which the fragment shader writes depth but does not contain any discards.
     * Buggy Intel HD 620/630 drivers incorrectly apply early-Z optimization in this case; we must insert a never-executed
     * conditional discard to prevent that.
     */
    _earlyZFlags = [];
    compileShaders() {
        let allCompiled = true;
        for (const program of this._basicPrograms) {
            if (program.compile() !== 0 /* CompileStatus.Success */)
                allCompiled = false;
        }
        for (const clipper of this._clippingPrograms)
            if (!clipper.compile())
                allCompiled = false;
        return allCompiled;
    }
    finishConstruction() {
        this._earlyZFlags.length = 0;
        // Confirm no empty entries in our array.
        let emptyShaderIndex = -1;
        assert(-1 === (emptyShaderIndex = this._basicPrograms.findIndex((prog) => undefined === prog)), `Shader index ${emptyShaderIndex} is undefined in ${this.constructor.name}`);
    }
    _isDisposed = false;
    get isDisposed() { return this._isDisposed; }
    [Symbol.dispose]() {
        if (this._isDisposed)
            return;
        for (const program of this._basicPrograms) {
            assert(undefined !== program);
            program[Symbol.dispose]();
        }
        this._basicPrograms.length = 0;
        for (const clipShaderObj of this._clippingPrograms) {
            assert(undefined !== clipShaderObj);
            clipShaderObj[Symbol.dispose]();
        }
        this._clippingPrograms.length = 0;
        this._isDisposed = true;
    }
    /** @deprecated in 5.0 - will not be removed until after 2026-06-13. Use [Symbol.dispose] instead. */
    dispose() {
        this[Symbol.dispose]();
    }
    constructor(numPrograms) {
        this._basicPrograms.length = numPrograms;
    }
    addShader(builder, flags, gl) {
        const descr = `${this._debugDescription}: ${flags.buildDescription()}`;
        builder.setDebugDescription(descr);
        if (System.instance.supportsLogZBuffer) {
            addLogDepth(builder);
            assert(!builder.frag.requiresEarlyZWorkaround);
            if (System.instance.fragDepthDoesNotDisableEarlyZ)
                builder.frag.requiresEarlyZWorkaround = -1 !== this._earlyZFlags.findIndex((x) => x.equals(flags));
        }
        const index = this.getShaderIndex(flags);
        this.addProgram(builder, index, gl);
        assert(!builder.frag.requiresEarlyZWorkaround);
    }
    addProgram(builder, index, gl) {
        assert(this._basicPrograms[index] === undefined);
        this._basicPrograms[index] = builder.buildProgram(gl);
        assert(this._basicPrograms[index] !== undefined);
        // Clipping programs always include a discard, so never require workaround.
        builder.frag.requiresEarlyZWorkaround = false;
        assert(this._clippingPrograms[index] === undefined);
        this._clippingPrograms[index] = createClippingProgram(builder);
        assert(this._clippingPrograms[index] !== undefined);
    }
    addHiliteShader(gl, instanced, classified, posType, create) {
        const builder = create(instanced, classified, posType);
        scratchHiliteFlags.initForHilite(0, instanced, classified, posType);
        this.addShader(builder, scratchHiliteFlags, gl);
    }
    addTranslucentShader(builder, flags, gl) {
        flags.isTranslucent = true;
        addTranslucency(builder);
        this.addShader(builder, flags, gl);
    }
    addFeatureId(builder, feat) {
        const frag = builder.frag;
        if (0 /* FeatureMode.None */ === feat) {
            addFragColorWithPreMultipliedAlpha(frag);
        }
        else {
            const vert = builder.vert;
            addFrustum(builder);
            addEyeSpace(builder);
            addModelViewMatrix(vert);
            addRenderOrder(frag);
            addFeatureId(builder, false);
            addPickBufferOutputs(frag);
        }
    }
    getShaderIndex(flags) {
        assert(!flags.isHilite || (!flags.isTranslucent && (flags.isClassified === 1 /* IsClassified.Yes */ || flags.hasFeatures)), "invalid technique flags");
        const index = this.computeShaderIndex(flags);
        assert(index < this._basicPrograms.length, "shader index out of bounds");
        return index;
    }
    getShader(flags) {
        const index = this.getShaderIndex(flags);
        let program;
        if (flags.hasClip) {
            const entry = this._clippingPrograms[index];
            assert(undefined !== entry);
            program = entry.getProgram(flags.numClipPlanes);
        }
        if (program === undefined)
            program = this._basicPrograms[index];
        return program;
    }
    // NB: Will ignore clipping shaders.
    getShaderByIndex(index) {
        return this._basicPrograms[index];
    }
    // NB: Will ignore clipping shaders.
    getShaderCount() {
        return this._basicPrograms.length;
    }
    /** For tests. */
    forEachProgram(func) {
        for (const basic of this._basicPrograms)
            func(basic);
        for (const clip of this._clippingPrograms) {
            const prog = clip.getProgram(1);
            assert(undefined !== prog);
            func(prog);
        }
    }
}
const positionTypes = ["quantized", "unquantized"];
class SurfaceTechnique extends VariedTechnique {
    static _kOpaque = 0;
    static _kTranslucent = 1;
    static _kInstanced = 2;
    static _kAnimated = 4;
    static _kWiremesh = 8;
    static _kShadowable = 16;
    static _kThematic = 32;
    static _kFeature = 48;
    static _kEdgeTestNeeded = SurfaceTechnique._kFeature * 3; // only when hasFeatures
    static _kHilite = SurfaceTechnique._kEdgeTestNeeded + SurfaceTechnique._kFeature * 2;
    // Classifiers are never animated or instanced. They do support shadows, thematic display, and translucency.
    // There are 3 base variations - 1 per feature mode - each with translucent/shadowed/thematic variants; plus 1 for hilite.
    static _kClassified = SurfaceTechnique._kHilite + numHiliteVariants;
    // 3 base classified variations - 1 per feature mode.
    // Plus thematic variant of each and shadowable variant of each = 9
    // Plus translucent variant of each of those = 18
    // Plus 1 hilite shader = 19
    static _kUnquantized = SurfaceTechnique._kClassified + 19;
    constructor(gl) {
        super(SurfaceTechnique._kUnquantized * 2);
        this._earlyZFlags = [
            TechniqueFlags.fromDescription("Opaque-Hilite-Overrides"),
            TechniqueFlags.fromDescription("Opaque-Instanced-Hilite-Overrides"),
            TechniqueFlags.fromDescription("Opaque-Hilite-Classified"),
            TechniqueFlags.fromDescription("Unquantized-Opaque-Hilite-Overrides"),
            TechniqueFlags.fromDescription("Unquantized-Opaque-Instanced-Hilite-Overrides"),
            TechniqueFlags.fromDescription("Unquantized-Opaque-Hilite-Classified"),
        ];
        const flags = scratchTechniqueFlags;
        for (const posType of positionTypes) {
            for (let instanced = 0 /* IsInstanced.No */; instanced <= 1 /* IsInstanced.Yes */; instanced++) {
                this.addHiliteShader(gl, instanced, 0 /* IsClassified.No */, posType, createSurfaceHiliter);
                for (let iAnimate = 0 /* IsAnimated.No */; iAnimate <= 1 /* IsAnimated.Yes */; iAnimate++) {
                    for (let shadowable = 0 /* IsShadowable.No */; shadowable <= 1 /* IsShadowable.Yes */; shadowable++) {
                        for (let wiremesh = 0 /* IsWiremesh.No */; wiremesh <= 1 /* IsWiremesh.Yes */; wiremesh++) {
                            for (let thematic = 0 /* IsThematic.No */; thematic <= 1 /* IsThematic.Yes */; thematic++) {
                                for (let edgeTestNeeded = 0 /* IsEdgeTestNeeded.No */; edgeTestNeeded <= 1 /* IsEdgeTestNeeded.Yes */; edgeTestNeeded++) {
                                    for (const featureMode of featureModes) {
                                        for (let iTranslucent = 0; iTranslucent <= 1; iTranslucent++) {
                                            if (0 /* FeatureMode.None */ !== featureMode || 0 /* IsEdgeTestNeeded.No */ === edgeTestNeeded) {
                                                if (1 /* IsThematic.Yes */ === thematic && 1 /* IsShadowable.Yes */ === shadowable)
                                                    continue; // currently this combination is disallowed.
                                                flags.reset(featureMode, instanced, shadowable, thematic, posType);
                                                flags.isAnimated = iAnimate;
                                                flags.isEdgeTestNeeded = edgeTestNeeded;
                                                flags.isTranslucent = 1 === iTranslucent;
                                                flags.isWiremesh = wiremesh;
                                                const builder = createSurfaceBuilder(flags);
                                                this.addShader(builder, flags, gl);
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
        this.addHiliteShader(gl, 0 /* IsInstanced.No */, 1 /* IsClassified.Yes */, "quantized", createSurfaceHiliter);
        this.addHiliteShader(gl, 0 /* IsInstanced.No */, 1 /* IsClassified.Yes */, "unquantized", createSurfaceHiliter);
        for (const posType of positionTypes) {
            for (let translucent = 0; translucent < 2; translucent++) {
                for (let shadowable = 0 /* IsShadowable.No */; shadowable <= 1 /* IsShadowable.Yes */; shadowable++) {
                    for (let thematic = 0 /* IsThematic.No */; thematic <= 1 /* IsThematic.Yes */; thematic++) {
                        for (const featureMode of featureModes) {
                            if (1 /* IsThematic.Yes */ === thematic && 1 /* IsShadowable.Yes */ === shadowable)
                                continue; // currently this combination is disallowed.
                            flags.reset(featureMode, 0 /* IsInstanced.No */, shadowable, thematic, posType);
                            flags.isClassified = 1 /* IsClassified.Yes */;
                            flags.isTranslucent = (0 !== translucent);
                            const builder = createSurfaceBuilder(flags);
                            if (flags.isTranslucent)
                                addTranslucency(builder);
                            this.addShader(builder, flags, gl);
                        }
                    }
                }
            }
        }
        this.finishConstruction();
    }
    get _debugDescription() { return "Surface"; }
    computeShaderIndex(flags) {
        assert(!(flags.isThematic && flags.isShadowable));
        const idxOffset = flags.positionType === "unquantized" ? SurfaceTechnique._kUnquantized : 0;
        if (flags.isClassified) {
            assert(!flags.isAnimated);
            assert(!flags.isInstanced);
            assert(!flags.isEdgeTestNeeded);
            // First classified shader is for hilite
            if (flags.isHilite)
                return SurfaceTechnique._kClassified + idxOffset;
            // The rest are organized in 3 groups of 6 - one group per feature mode.
            // Each group contains opaque, translucent, opaque+thematic, translucent+thematic, opaque+shadowable, and translucent+shadowable variants.
            let baseIndex = SurfaceTechnique._kClassified + 1;
            if (flags.isTranslucent)
                baseIndex += 1;
            if (flags.isShadowable)
                baseIndex += 2;
            if (flags.isThematic)
                baseIndex += 4;
            const featureOffset = 6 * flags.featureMode;
            return baseIndex + featureOffset + idxOffset;
        }
        else if (flags.isHilite) {
            assert(flags.hasFeatures);
            return SurfaceTechnique._kHilite + flags.isInstanced + idxOffset;
        }
        assert(flags.hasFeatures || flags.isEdgeTestNeeded === 0 /* IsEdgeTestNeeded.No */);
        let index = flags.isTranslucent ? SurfaceTechnique._kTranslucent : SurfaceTechnique._kOpaque;
        index += SurfaceTechnique._kInstanced * flags.isInstanced;
        index += SurfaceTechnique._kAnimated * flags.isAnimated;
        index += SurfaceTechnique._kShadowable * flags.isShadowable;
        index += SurfaceTechnique._kThematic * flags.isThematic;
        index += SurfaceTechnique._kWiremesh * flags.isWiremesh;
        if (flags.isEdgeTestNeeded)
            index += SurfaceTechnique._kEdgeTestNeeded + (flags.featureMode - 1) * SurfaceTechnique._kFeature;
        else
            index += SurfaceTechnique._kFeature * flags.featureMode;
        return index + idxOffset;
    }
}
class PolylineTechnique extends VariedTechnique {
    static _kOpaque = 0;
    static _kTranslucent = 1;
    static _kInstanced = 2;
    static _kFeature = 4;
    static _kHilite = numFeatureVariants(PolylineTechnique._kFeature);
    static _kUnquantized = PolylineTechnique._kHilite + numHiliteVariants;
    constructor(gl) {
        super(PolylineTechnique._kUnquantized * 2);
        this._earlyZFlags = [
            TechniqueFlags.fromDescription("Opaque-Hilite-Overrides"),
            TechniqueFlags.fromDescription("Opaque-Instanced-Hilite-Overrides"),
            TechniqueFlags.fromDescription("Unquantized-Opaque-Hilite-Overrides"),
            TechniqueFlags.fromDescription("Unquantized-Opaque-Instanced-Hilite-Overrides"),
        ];
        const flags = scratchTechniqueFlags;
        for (const posType of positionTypes) {
            for (let instanced = 0 /* IsInstanced.No */; instanced <= 1 /* IsInstanced.Yes */; instanced++) {
                this.addHiliteShader(gl, instanced, 0 /* IsClassified.No */, posType, (inst, _class, pos) => createPolylineHiliter(inst, pos));
                for (const featureMode of featureModes) {
                    flags.reset(featureMode, instanced, 0 /* IsShadowable.No */, 0 /* IsThematic.No */, posType);
                    const builder = createPolylineBuilder(instanced, posType);
                    addUnlitMonochrome(builder.frag);
                    // The translucent shaders do not need the element IDs.
                    const builderTrans = createPolylineBuilder(instanced, posType);
                    addUnlitMonochrome(builderTrans.frag);
                    if (2 /* FeatureMode.Overrides */ === featureMode) {
                        addFeatureSymbology(builderTrans, featureMode, 31 /* FeatureSymbologyOptions.Linear */);
                        addFeatureSymbology(builder, featureMode, 31 /* FeatureSymbologyOptions.Linear */);
                        this.addTranslucentShader(builderTrans, flags, gl);
                    }
                    else {
                        this.addTranslucentShader(builderTrans, flags, gl);
                        addFeatureSymbology(builder, featureMode, 0 /* FeatureSymbologyOptions.None */);
                    }
                    this.addFeatureId(builder, featureMode);
                    flags.reset(featureMode, instanced, 0 /* IsShadowable.No */, 0 /* IsThematic.No */, posType);
                    this.addShader(builder, flags, gl);
                }
            }
        }
        this.finishConstruction();
    }
    get _debugDescription() { return "Polyline"; }
    computeShaderIndex(flags) {
        const idxOffset = flags.positionType === "unquantized" ? PolylineTechnique._kUnquantized : 0;
        if (flags.isHilite) {
            assert(flags.hasFeatures);
            return PolylineTechnique._kHilite + flags.isInstanced + idxOffset;
        }
        let index = flags.isTranslucent ? PolylineTechnique._kTranslucent : PolylineTechnique._kOpaque;
        index += PolylineTechnique._kFeature * flags.featureMode;
        index += PolylineTechnique._kInstanced * flags.isInstanced;
        return index + idxOffset;
    }
}
class EdgeTechnique extends VariedTechnique {
    static _kOpaque = 0;
    static _kTranslucent = 1;
    static _kAnimated = 2;
    static _kInstanced = 4;
    static _kFeature = 8;
    static _kUnquantized = numFeatureVariants(EdgeTechnique._kFeature);
    _type;
    constructor(gl, type) {
        super(EdgeTechnique._kUnquantized * 2);
        this._type = type;
        const flags = scratchTechniqueFlags;
        for (const posType of positionTypes) {
            for (let instanced = 0 /* IsInstanced.No */; instanced <= 1 /* IsInstanced.Yes */; instanced++) {
                for (let iAnimate = 0 /* IsAnimated.No */; iAnimate <= 1 /* IsAnimated.Yes */; iAnimate++) {
                    for (const featureMode of featureModes) {
                        flags.reset(featureMode, instanced, 0 /* IsShadowable.No */, 0 /* IsThematic.No */, posType);
                        flags.isAnimated = iAnimate;
                        const builder = createEdgeBuilder(type, flags.isInstanced, flags.isAnimated, posType);
                        addUnlitMonochrome(builder.frag);
                        // The translucent shaders do not need the element IDs.
                        const builderTrans = createEdgeBuilder(type, flags.isInstanced, flags.isAnimated, posType);
                        addUnlitMonochrome(builderTrans.frag);
                        if (2 /* FeatureMode.Overrides */ === featureMode) {
                            addFeatureSymbology(builderTrans, featureMode, 31 /* FeatureSymbologyOptions.Linear */);
                            addFeatureSymbology(builder, featureMode, 31 /* FeatureSymbologyOptions.Linear */);
                            this.addTranslucentShader(builderTrans, flags, gl);
                        }
                        else {
                            this.addTranslucentShader(builderTrans, flags, gl);
                            addFeatureSymbology(builder, featureMode, 0 /* FeatureSymbologyOptions.None */);
                        }
                        this.addFeatureId(builder, featureMode);
                        flags.reset(featureMode, instanced, 0 /* IsShadowable.No */, 0 /* IsThematic.No */, posType);
                        flags.isAnimated = iAnimate;
                        this.addShader(builder, flags, gl);
                    }
                }
            }
        }
        this.finishConstruction();
    }
    get _debugDescription() { return this._type; }
    computeShaderIndex(flags) {
        let index = flags.isTranslucent ? EdgeTechnique._kTranslucent : EdgeTechnique._kOpaque;
        index += EdgeTechnique._kFeature * flags.featureMode;
        if (flags.isAnimated)
            index += EdgeTechnique._kAnimated;
        if (flags.isInstanced)
            index += EdgeTechnique._kInstanced;
        if ("unquantized" === flags.positionType)
            index += EdgeTechnique._kUnquantized;
        return index;
    }
}
class PointStringTechnique extends VariedTechnique {
    static _kOpaque = 0;
    static _kTranslucent = 1;
    static _kInstanced = 2;
    static _kFeature = 4;
    static _kHilite = numFeatureVariants(PointStringTechnique._kFeature);
    static _kUnquantized = PointStringTechnique._kHilite + numHiliteVariants;
    constructor(gl) {
        super(PointStringTechnique._kUnquantized * 2);
        const flags = scratchTechniqueFlags;
        for (const posType of positionTypes) {
            for (let instanced = 0 /* IsInstanced.No */; instanced <= 1 /* IsInstanced.Yes */; instanced++) {
                this.addHiliteShader(gl, instanced, 0 /* IsClassified.No */, posType, (inst, _class, pos) => createPointStringHiliter(inst, pos));
                for (const featureMode of featureModes) {
                    flags.reset(featureMode, instanced, 0 /* IsShadowable.No */, 0 /* IsThematic.No */, posType);
                    const builder = createPointStringBuilder(instanced, posType);
                    addUnlitMonochrome(builder.frag);
                    // The translucent shaders do not need the element IDs.
                    const builderTrans = createPointStringBuilder(instanced, posType);
                    addUnlitMonochrome(builderTrans.frag);
                    if (2 /* FeatureMode.Overrides */ === featureMode) {
                        addFeatureSymbology(builderTrans, featureMode, 29 /* FeatureSymbologyOptions.Point */);
                        addFeatureSymbology(builder, featureMode, 29 /* FeatureSymbologyOptions.Point */);
                        this.addTranslucentShader(builderTrans, flags, gl);
                    }
                    else {
                        this.addTranslucentShader(builderTrans, flags, gl);
                        addFeatureSymbology(builder, featureMode, 0 /* FeatureSymbologyOptions.None */);
                    }
                    this.addFeatureId(builder, featureMode);
                    flags.reset(featureMode, instanced, 0 /* IsShadowable.No */, 0 /* IsThematic.No */, posType);
                    this.addShader(builder, flags, gl);
                }
            }
        }
        this.finishConstruction();
    }
    get _debugDescription() { return "PointString"; }
    computeShaderIndex(flags) {
        const idxOffset = "quantized" === flags.positionType ? 0 : PointStringTechnique._kUnquantized;
        if (flags.isHilite) {
            assert(flags.hasFeatures);
            return PointStringTechnique._kHilite + flags.isInstanced + idxOffset;
        }
        let index = flags.isTranslucent ? PointStringTechnique._kTranslucent : PointStringTechnique._kOpaque;
        index += PointStringTechnique._kFeature * flags.featureMode;
        index += PointStringTechnique._kInstanced * flags.isInstanced;
        return index + idxOffset;
    }
}
class PointCloudTechnique extends VariedTechnique {
    static _kHilite = 8;
    constructor(gl) {
        super(PointCloudTechnique._kHilite + 2);
        for (let iClassified = 0 /* IsClassified.No */; iClassified <= 1 /* IsClassified.Yes */; iClassified++) {
            this.addHiliteShader(gl, 0 /* IsInstanced.No */, iClassified, "quantized", (_inst, classified) => createPointCloudHiliter(classified));
            const flags = scratchTechniqueFlags;
            for (let thematic = 0 /* IsThematic.No */; thematic <= 1 /* IsThematic.Yes */; thematic++) {
                const pointCloudFeatureModes = [0 /* FeatureMode.None */, 2 /* FeatureMode.Overrides */];
                for (const featureMode of pointCloudFeatureModes) {
                    flags.reset(featureMode, 0 /* IsInstanced.No */, 0 /* IsShadowable.No */, thematic, "quantized");
                    flags.isClassified = iClassified;
                    const builder = createPointCloudBuilder(flags.isClassified, featureMode, thematic);
                    if (2 /* FeatureMode.Overrides */ === featureMode) {
                        addUniformFeatureSymbology(builder, true);
                        addColorOverrideMix(builder.vert);
                        builder.vert.set(7 /* VertexShaderComponent.ApplyFeatureColor */, mixFeatureColor);
                    }
                    this.addFeatureId(builder, featureMode);
                    this.addShader(builder, flags, gl);
                }
            }
        }
        this.finishConstruction();
    }
    get _debugDescription() { return "PointCloud"; }
    computeShaderIndex(flags) {
        assert(flags.positionType === "quantized", "Unquantized point cloud positions not currently supported");
        if (flags.isHilite)
            return PointCloudTechnique._kHilite + flags.isClassified;
        else {
            let ndx = 0;
            if (flags.isClassified)
                ndx++;
            if (flags.featureMode !== 0 /* FeatureMode.None */)
                ndx += 2;
            if (flags.isThematic)
                ndx += 4;
            return ndx;
        }
    }
}
class RealityMeshTechnique extends VariedTechnique {
    static _numVariants = 194;
    constructor(gl) {
        super(RealityMeshTechnique._numVariants);
        this._earlyZFlags = [
            TechniqueFlags.fromDescription("Opaque-Hilite-Overrides"),
            TechniqueFlags.fromDescription("Opaque-Hilite-Classified"),
        ];
        this.addHiliteShader(gl, 0 /* IsInstanced.No */, 0 /* IsClassified.No */, "quantized", createRealityMeshHiliter);
        this.addHiliteShader(gl, 0 /* IsInstanced.No */, 1 /* IsClassified.Yes */, "quantized", createClassifierRealityMeshHiliter);
        for (let iClassified = 0 /* IsClassified.No */; iClassified <= 1 /* IsClassified.Yes */; iClassified++) {
            for (let iTranslucent = 0; iTranslucent <= 1; iTranslucent++) {
                for (let shadowable = 0 /* IsShadowable.No */; shadowable <= 1 /* IsShadowable.Yes */; shadowable++) {
                    for (let thematic = 0 /* IsThematic.No */; thematic <= 1 /* IsThematic.Yes */; thematic++) {
                        for (let wiremesh = 0 /* IsWiremesh.No */; wiremesh <= 1 /* IsWiremesh.Yes */; wiremesh++) {
                            for (let enableAtmosphere = 0 /* EnableAtmosphere.No */; enableAtmosphere <= 1 /* EnableAtmosphere.Yes */; enableAtmosphere++) {
                                const flags = scratchTechniqueFlags;
                                for (const featureMode of featureModes) {
                                    flags.reset(featureMode, 0 /* IsInstanced.No */, shadowable, thematic, "quantized");
                                    flags.isClassified = iClassified;
                                    flags.isWiremesh = wiremesh;
                                    flags.isTranslucent = 1 === iTranslucent;
                                    flags.enableAtmosphere = enableAtmosphere;
                                    const builder = createRealityMeshBuilder(flags);
                                    if (flags.isTranslucent) {
                                        addShaderFlags(builder);
                                        addTranslucency(builder);
                                    }
                                    else
                                        this.addFeatureId(builder, featureMode);
                                    this.addShader(builder, flags, gl);
                                }
                            }
                        }
                    }
                }
            }
        }
        this.finishConstruction();
    }
    get _debugDescription() { return "RealityMesh"; }
    computeShaderIndex(flags) {
        assert("quantized" === flags.positionType, "Unquantized reality mesh positions not currently supported.");
        if (flags.isHilite)
            return flags.isClassified ? 1 : 0;
        let ndx = 2;
        if (flags.isClassified)
            ndx++;
        if (flags.isShadowable)
            ndx += 2;
        if (flags.isTranslucent)
            ndx += 4;
        ndx += 8 * flags.featureMode;
        if (flags.isThematic)
            ndx += 24;
        if (flags.isWiremesh)
            ndx += 48;
        if (flags.enableAtmosphere)
            ndx += 96;
        return ndx;
    }
}
/**
 * More generalized version of VariedTechnique, without assuming usage of clipping, logDepth, eyeSpace, etc.
 * Similar to SingularTechnique in its simplicity, but with support for multiple shader programs per technique.
 */
class MultipleTechnique {
    _programs = [];
    _isDisposed = false;
    get isDisposed() { return this._isDisposed; }
    constructor(numPrograms) {
        this._programs.length = numPrograms;
    }
    getShaderIndex(flags) {
        assert(!flags.isHilite || (!flags.isTranslucent && (flags.isClassified === 1 /* IsClassified.Yes */ || flags.hasFeatures)), "invalid technique flags");
        const index = this.computeShaderIndex(flags);
        assert(index < this._programs.length, "shader index out of bounds");
        return index;
    }
    getShader(flags) {
        const index = this.getShaderIndex(flags);
        let program;
        if (program === undefined)
            program = this._programs[index];
        return program;
    }
    getShaderByIndex(index) {
        return this._programs[index];
    }
    getShaderCount() {
        return this._programs.length;
    }
    compileShaders() {
        let allCompiled = true;
        for (const program of this._programs) {
            if (program.compile() !== 0 /* CompileStatus.Success */)
                allCompiled = false;
        }
        return allCompiled;
    }
    [Symbol.dispose]() {
        if (this._isDisposed)
            return;
        for (const program of this._programs) {
            assert(undefined !== program);
            dispose(program);
        }
        this._programs.length = 0;
        this._isDisposed = true;
    }
    addShader(builder, flags, gl) {
        const descr = `${this._debugDescription}: ${flags.buildDescription()}`;
        builder.setDebugDescription(descr);
        const index = this.getShaderIndex(flags);
        this.addProgram(builder, index, gl);
        assert(!builder.frag.requiresEarlyZWorkaround);
    }
    addProgram(builder, index, gl) {
        assert(this._programs[index] === undefined);
        this._programs[index] = builder.buildProgram(gl);
        assert(this._programs[index] !== undefined);
    }
    finishConstruction() {
        // Confirm no empty entries in our array.
        let emptyShaderIndex = -1;
        assert(-1 === (emptyShaderIndex = this._programs.findIndex((prog) => undefined === prog)), `Shader index ${emptyShaderIndex} is undefined in ${this.constructor.name}`);
    }
}
class SkySphereTechnique extends MultipleTechnique {
    static _numVariants = 2; // one binary flag (2 ** 1)
    _isGradient;
    constructor(gl, isGradient) {
        super(SkySphereTechnique._numVariants);
        this._isGradient = isGradient;
        for (let enableAtmosphere = 0 /* EnableAtmosphere.No */; enableAtmosphere <= 1 /* EnableAtmosphere.Yes */; enableAtmosphere++) {
            const tempFlags = scratchTechniqueFlags;
            tempFlags.reset(0 /* FeatureMode.None */, 0 /* IsInstanced.No */, 0 /* IsShadowable.No */, 0 /* IsThematic.No */, "quantized");
            tempFlags.enableAtmosphere = enableAtmosphere;
            const builder = createSkySphereBuilder(isGradient, tempFlags);
            this.addShader(builder, tempFlags, gl);
        }
        this.finishConstruction();
    }
    get _debugDescription() { return `SkySphere-${this._isGradient ? "Gradient" : "Texture"}`; }
    computeShaderIndex(flags) {
        let index = 0;
        if (flags.enableAtmosphere)
            index += 1 << 0;
        return index;
    }
}
const techniquesByPriority = [
    // Compile these specific shader variations first because they seem most likely to be used immediately upon opening a file.
    { techniqueId: 0 /* TechniqueId.Surface */, specificShader: { featureMode: 0 /* FeatureMode.None */, isInstanced: 0 /* IsInstanced.No */, isShadowable: 0 /* IsShadowable.No */, isEdgeTestedNeeded: 0 /* IsEdgeTestNeeded.No */, isTranslucent: false } },
    { techniqueId: 0 /* TechniqueId.Surface */, specificShader: { featureMode: 1 /* FeatureMode.Pick */, isInstanced: 0 /* IsInstanced.No */, isShadowable: 0 /* IsShadowable.No */, isEdgeTestedNeeded: 0 /* IsEdgeTestNeeded.No */, isTranslucent: false } },
    { techniqueId: 0 /* TechniqueId.Surface */, specificShader: { featureMode: 1 /* FeatureMode.Pick */, isInstanced: 0 /* IsInstanced.No */, isShadowable: 0 /* IsShadowable.No */, isEdgeTestedNeeded: 1 /* IsEdgeTestNeeded.Yes */, isTranslucent: false } },
    { techniqueId: 0 /* TechniqueId.Surface */, specificShader: { featureMode: 2 /* FeatureMode.Overrides */, isInstanced: 0 /* IsInstanced.No */, isShadowable: 0 /* IsShadowable.No */, isEdgeTestedNeeded: 0 /* IsEdgeTestNeeded.No */, isTranslucent: false } },
    { techniqueId: 0 /* TechniqueId.Surface */, specificShader: { featureMode: 2 /* FeatureMode.Overrides */, isInstanced: 0 /* IsInstanced.No */, isShadowable: 0 /* IsShadowable.No */, isEdgeTestedNeeded: 1 /* IsEdgeTestNeeded.Yes */, isTranslucent: false } },
    { techniqueId: 0 /* TechniqueId.Surface */, specificShader: { featureMode: 0 /* FeatureMode.None */, isInstanced: 0 /* IsInstanced.No */, isShadowable: 0 /* IsShadowable.No */, isEdgeTestedNeeded: 0 /* IsEdgeTestNeeded.No */, isTranslucent: true } },
    { techniqueId: 0 /* TechniqueId.Surface */, specificShader: { featureMode: 1 /* FeatureMode.Pick */, isInstanced: 0 /* IsInstanced.No */, isShadowable: 0 /* IsShadowable.No */, isEdgeTestedNeeded: 0 /* IsEdgeTestNeeded.No */, isTranslucent: true } },
    { techniqueId: 0 /* TechniqueId.Surface */, specificShader: { featureMode: 1 /* FeatureMode.Pick */, isInstanced: 0 /* IsInstanced.No */, isShadowable: 0 /* IsShadowable.No */, isEdgeTestedNeeded: 1 /* IsEdgeTestNeeded.Yes */, isTranslucent: true } },
    { techniqueId: 0 /* TechniqueId.Surface */, specificShader: { featureMode: 2 /* FeatureMode.Overrides */, isInstanced: 0 /* IsInstanced.No */, isShadowable: 0 /* IsShadowable.No */, isEdgeTestedNeeded: 0 /* IsEdgeTestNeeded.No */, isTranslucent: true } },
    { techniqueId: 0 /* TechniqueId.Surface */, specificShader: { featureMode: 2 /* FeatureMode.Overrides */, isInstanced: 0 /* IsInstanced.No */, isShadowable: 0 /* IsShadowable.No */, isEdgeTestedNeeded: 1 /* IsEdgeTestNeeded.Yes */, isTranslucent: true } },
    // Next, compile all shaders in specific techniques.
    // Do surfaces first because (1) they are the most commonly used and (2) they take longer to compile.
    { techniqueId: 0 /* TechniqueId.Surface */ },
    { techniqueId: 4 /* TechniqueId.Edge */ },
    { techniqueId: 5 /* TechniqueId.SilhouetteEdge */ },
    { techniqueId: 1 /* TechniqueId.Polyline */ },
    { techniqueId: 3 /* TechniqueId.PointString */ },
    { techniqueId: 2 /* TechniqueId.PointCloud */ },
    { techniqueId: 7 /* TechniqueId.RealityMesh */ },
    // The following techniques take a trivial amount of time to compile - do them last
    { techniqueId: 16 /* TechniqueId.OITClearTranslucent */ },
    { techniqueId: 17 /* TechniqueId.CopyPickBuffers */ },
    { techniqueId: 18 /* TechniqueId.CopyColor */ },
    { techniqueId: 19 /* TechniqueId.CopyColorNoAlpha */ },
    { techniqueId: 21 /* TechniqueId.ClearPickAndColor */ },
    { techniqueId: 10 /* TechniqueId.CompositeTranslucent */ },
    { techniqueId: 9 /* TechniqueId.CompositeHilite */ },
    { techniqueId: 11 /* TechniqueId.CompositeHiliteAndTranslucent */ },
    { techniqueId: 12 /* TechniqueId.CompositeOcclusion */ },
    { techniqueId: 13 /* TechniqueId.CompositeTranslucentAndOcclusion */ },
    { techniqueId: 14 /* TechniqueId.CompositeHiliteAndOcclusion */ },
    { techniqueId: 15 /* TechniqueId.CompositeAll */ },
    { techniqueId: 20 /* TechniqueId.VolClassColorUsingStencil */ },
    { techniqueId: 22 /* TechniqueId.EVSMFromDepth */ },
    { techniqueId: 23 /* TechniqueId.SkyBox */ },
    { techniqueId: 24 /* TechniqueId.SkySphereGradient */ },
    { techniqueId: 25 /* TechniqueId.SkySphereTexture */ },
    { techniqueId: 26 /* TechniqueId.AmbientOcclusion */ },
    { techniqueId: 27 /* TechniqueId.Blur */ },
    { techniqueId: 28 /* TechniqueId.BlurTestOrder */ },
    { techniqueId: 29 /* TechniqueId.CombineTextures */ },
    { techniqueId: 31 /* TechniqueId.VolClassCopyZ */ },
    { techniqueId: 32 /* TechniqueId.VolClassSetBlend */ },
    { techniqueId: 33 /* TechniqueId.VolClassBlend */ },
    { techniqueId: 30 /* TechniqueId.Combine3Textures */ },
    { techniqueId: 8 /* TechniqueId.PlanarGrid */ },
    { techniqueId: 34 /* TechniqueId.EDLCalcBasic */ },
    { techniqueId: 35 /* TechniqueId.EDLCalcFull */ },
    { techniqueId: 36 /* TechniqueId.EDLFilter */ },
    { techniqueId: 37 /* TechniqueId.EDLMix */ },
];
const numTechniquesByPriority = techniquesByPriority.length;
/** A collection of rendering techniques accessed by ID.
 * @internal
 */
export class Techniques {
    _list = new Array(); // indexed by TechniqueId, which may exceed TechniqueId.NumBuiltIn for dynamic techniques.
    _dynamicTechniqueIds = new Array(); // technique ID = (index in this array) + TechniqueId.NumBuiltIn
    _techniqueByPriorityIndex = 0;
    _shaderIndex = 0;
    static create(gl) {
        const techs = new Techniques();
        techs.initializeBuiltIns(gl);
        return techs;
    }
    getTechnique(id) {
        assert(id < this._list.length, "technique index out of bounds");
        return this._list[id];
    }
    get numTechniques() {
        return this._list.length;
    }
    addDynamicTechnique(technique, name) {
        const id = this.getDynamicTechniqueId(name);
        if (undefined !== id)
            return id;
        this._dynamicTechniqueIds.push(name);
        this._list.push(technique);
        return 38 /* TechniqueId.NumBuiltIn */ + this._dynamicTechniqueIds.length - 1;
    }
    getDynamicTechniqueId(name) {
        const index = this._dynamicTechniqueIds.indexOf(name);
        return -1 !== index ? index + 38 /* TechniqueId.NumBuiltIn */ + index : undefined;
    }
    /** Execute each command in the list */
    execute(target, commands, renderPass) {
        const env_1 = { stack: [], error: void 0, hasError: false };
        try {
            assert(255 /* RenderPass.None */ !== renderPass, "invalid render pass");
            const executor = __addDisposableResource(env_1, new ShaderProgramExecutor(target, renderPass), false);
            for (const command of commands)
                command.execute(executor);
            System.instance.frameBufferStack.markTargetsDirty();
        }
        catch (e_1) {
            env_1.error = e_1;
            env_1.hasError = true;
        }
        finally {
            __disposeResources(env_1);
        }
    }
    /** Execute the commands for a single given classification primitive (the first 3 commands should be a push, the primitive, then a pop) */
    executeForIndexedClassifier(target, cmdsByIndex, renderPass) {
        // ###TODO: Disable shadows. Probably in the ClassifierTileTree's ViewFlagOverrides.
        this.execute(target, cmdsByIndex, renderPass);
    }
    /** Draw a single primitive. Usually used for special-purpose rendering techniques. */
    draw(params) {
        const env_2 = { stack: [], error: void 0, hasError: false };
        try {
            const tech = this.getTechnique(params.geometry.techniqueId);
            const program = tech.getShader(TechniqueFlags.defaults);
            const executor = __addDisposableResource(env_2, new ShaderProgramExecutor(params.target, params.renderPass, program), false);
            assert(executor.isValid);
            if (executor.isValid) {
                executor.draw(params);
            }
            System.instance.frameBufferStack.markTargetsDirty();
        }
        catch (e_2) {
            env_2.error = e_2;
            env_2.hasError = true;
        }
        finally {
            __disposeResources(env_2);
        }
    }
    get isDisposed() { return 0 === this._list.length; }
    [Symbol.dispose]() {
        for (const tech of this._list)
            dispose(tech);
        this._list.length = 0;
    }
    /** @deprecated in 5.0 - will not be removed until after 2026-06-13. Use [Symbol.dispose] instead. */
    dispose() {
        this[Symbol.dispose]();
    }
    // Chiefly for tests - compiles all shader programs - more generally programs are compiled on demand.
    compileShaders() {
        let allCompiled = true;
        for (const tech of this._list) {
            if (!tech.compileShaders())
                allCompiled = false;
        }
        return allCompiled;
    }
    /** Compile shader of next highest priority. Called when possible during an idle situation before any viewports exist. */
    idleCompileNextShader() {
        let compileStatus = 0 /* CompileStatus.Success */;
        let wasPreviouslyCompiled = false;
        do {
            if (this._techniqueByPriorityIndex >= numTechniquesByPriority)
                return false;
            let shader;
            let numShaders = 0;
            const pTech = techniquesByPriority[this._techniqueByPriorityIndex];
            const tech = this._list[pTech.techniqueId];
            if (pTech.specificShader !== undefined) { // if this entry consists of a specific shader, just compile that
                const flags = scratchTechniqueFlags;
                flags.reset(pTech.specificShader.featureMode, pTech.specificShader.isInstanced, pTech.specificShader.isShadowable, 0 /* IsThematic.No */, "quantized");
                flags.isEdgeTestNeeded = pTech.specificShader.isEdgeTestedNeeded;
                flags.isTranslucent = pTech.specificShader.isTranslucent;
                shader = tech.getShader(flags);
            }
            else { // if this entry only contains a techniqueId, then compile all uncompiled shaders for that technique
                shader = tech.getShaderByIndex(this._shaderIndex);
                this._shaderIndex++;
                numShaders = tech.getShaderCount();
            }
            if (shader.isCompiled)
                wasPreviouslyCompiled = true;
            else {
                compileStatus = shader.compile();
                wasPreviouslyCompiled = false;
            }
            if (this._shaderIndex >= numShaders) {
                this._techniqueByPriorityIndex++;
                this._shaderIndex = 0;
            }
        } while (wasPreviouslyCompiled);
        return compileStatus === 0 /* CompileStatus.Success */;
    }
    /** For tests. */
    forEachVariedProgram(func) {
        for (const technique of this._list)
            if (technique instanceof VariedTechnique)
                technique.forEachProgram(func);
    }
    constructor() { }
    initializeBuiltIns(gl) {
        this._list[16 /* TechniqueId.OITClearTranslucent */] = new SingularTechnique(createClearTranslucentProgram(gl));
        this._list[21 /* TechniqueId.ClearPickAndColor */] = new SingularTechnique(createClearPickAndColorProgram(gl));
        this._list[18 /* TechniqueId.CopyColor */] = new SingularTechnique(createCopyColorProgram(gl));
        this._list[19 /* TechniqueId.CopyColorNoAlpha */] = new SingularTechnique(createCopyColorProgram(gl, false));
        this._list[17 /* TechniqueId.CopyPickBuffers */] = new SingularTechnique(createCopyPickBuffersProgram(gl));
        this._list[22 /* TechniqueId.EVSMFromDepth */] = new SingularTechnique(createEVSMProgram(gl));
        this._list[23 /* TechniqueId.SkyBox */] = new SingularTechnique(createSkyBoxProgram(gl));
        this._list[24 /* TechniqueId.SkySphereGradient */] = new SkySphereTechnique(gl, true);
        this._list[25 /* TechniqueId.SkySphereTexture */] = new SkySphereTechnique(gl, false);
        this._list[26 /* TechniqueId.AmbientOcclusion */] = new SingularTechnique(createAmbientOcclusionProgram(gl));
        this._list[27 /* TechniqueId.Blur */] = new SingularTechnique(createBlurProgram(gl, BlurType.NoTest));
        this._list[28 /* TechniqueId.BlurTestOrder */] = new SingularTechnique(createBlurProgram(gl, BlurType.TestOrder));
        this._list[29 /* TechniqueId.CombineTextures */] = new SingularTechnique(createCombineTexturesProgram(gl));
        this._list[30 /* TechniqueId.Combine3Textures */] = new SingularTechnique(createCombine3TexturesProgram(gl));
        this._list[0 /* TechniqueId.Surface */] = new SurfaceTechnique(gl);
        this._list[4 /* TechniqueId.Edge */] = new EdgeTechnique(gl, "SegmentEdge");
        this._list[5 /* TechniqueId.SilhouetteEdge */] = new EdgeTechnique(gl, "Silhouette");
        this._list[1 /* TechniqueId.Polyline */] = new PolylineTechnique(gl);
        this._list[3 /* TechniqueId.PointString */] = new PointStringTechnique(gl);
        this._list[2 /* TechniqueId.PointCloud */] = new PointCloudTechnique(gl);
        this._list[7 /* TechniqueId.RealityMesh */] = new RealityMeshTechnique(gl);
        this._list[8 /* TechniqueId.PlanarGrid */] = new SingularTechnique(createPlanarGridProgram(gl));
        this._list[34 /* TechniqueId.EDLCalcBasic */] = new SingularTechnique(createEDLCalcBasicProgram(gl));
        this._list[35 /* TechniqueId.EDLCalcFull */] = new SingularTechnique(createEDLCalcFullProgram(gl));
        this._list[36 /* TechniqueId.EDLFilter */] = new SingularTechnique(createEDLFilterProgram(gl));
        this._list[37 /* TechniqueId.EDLMix */] = new SingularTechnique(createEDLMixProgram(gl));
        this._list[6 /* TechniqueId.IndexedEdge */] = new EdgeTechnique(gl, "IndexedEdge");
        this._list[31 /* TechniqueId.VolClassCopyZ */] = new SingularTechnique(createVolClassCopyZProgram(gl));
        this._list[32 /* TechniqueId.VolClassSetBlend */] = new SingularTechnique(createVolClassSetBlendProgram(gl));
        this._list[33 /* TechniqueId.VolClassBlend */] = new SingularTechnique(createVolClassBlendProgram(gl));
        this._list[20 /* TechniqueId.VolClassColorUsingStencil */] = new SingularTechnique(createVolClassColorUsingStencilProgram(gl));
        for (let compositeFlags = 1; compositeFlags <= 7; compositeFlags++) {
            const techId = computeCompositeTechniqueId(compositeFlags);
            this._list[techId] = new SingularTechnique(createCompositeProgram(compositeFlags, gl));
        }
        assert(this._list.length === 38 /* TechniqueId.NumBuiltIn */, "unexpected number of built-in techniques");
    }
}
//# sourceMappingURL=Technique.js.map