import EventEmitter from 'eventemitter3';
import { GlProgram } from '../../gl/shader/GlProgram';
import { BindGroup } from '../../gpu/shader/BindGroup';
import { GpuProgram } from '../../gpu/shader/GpuProgram';
import type { GlProgramOptions } from '../../gl/shader/GlProgram';
import type { GpuProgramOptions } from '../../gpu/shader/GpuProgram';
/**
 * A record of {@link BindGroup}'s used by the shader.
 *
 * `Record<number, BindGroup>`
 * @memberof rendering
 */
export type ShaderGroups = Record<number, BindGroup>;
interface ShaderBase {
    /** The WebGL program used by the WebGL renderer. */
    glProgram?: GlProgram;
    /** The WebGPU program used by the WebGPU renderer. */
    gpuProgram?: GpuProgram;
    /**
     * A number that uses two bits on whether the shader is compatible with the WebGL renderer and/or the WebGPU renderer.
     * 0b00 - not compatible with either
     * 0b01 - compatible with WebGL
     * 0b10 - compatible with WebGPU
     * This is automatically set based on if a {@link GlProgram} or {@link GpuProgram} is provided.
     */
    compatibleRenderers?: number;
}
export interface GlShaderWith extends ShaderBase {
    /** The WebGL program used by the WebGL renderer. */
    glProgram: GlProgram;
}
export interface GpuShaderWith extends ShaderBase {
    /** The WebGPU program used by the WebGPU renderer. */
    gpuProgram: GpuProgram;
}
export interface ShaderWithGroupsDescriptor {
    /** A record of {@link BindGroup}'s used by the shader. */
    groups: ShaderGroups;
    /** an optional map of how to bind the groups. This is automatically generated by reading the WebGPU program */
    groupMap?: Record<string, Record<string, any>>;
}
interface ShaderWithResourcesDescriptor {
    /**
     * A key value of uniform resources used by the shader.
     * Under the hood pixi will look at the provided shaders and figure out where
     * the resources are mapped. Its up to you to make sure the resource key
     * matches the uniform name in the webGPU program. WebGL is a little more forgiving!
     */
    resources?: Record<string, any>;
}
/**
 * A descriptor for a shader
 * @memberof rendering
 */
export type ShaderWith = GlShaderWith | GpuShaderWith;
/**
 * A descriptor for a shader with groups.
 * @memberof rendering
 */
export type ShaderWithGroups = ShaderWithGroupsDescriptor & ShaderWith;
export interface IShaderWithGroups extends ShaderWithGroupsDescriptor, ShaderBase {
}
/**
 * A descriptor for a shader with resources. This is an easier way to work with uniforms.
 * especially when you are not working with bind groups
 * @memberof rendering
 */
export type ShaderWithResources = ShaderWithResourcesDescriptor & ShaderWith;
export interface IShaderWithResources extends ShaderWithResourcesDescriptor, ShaderBase {
}
export type ShaderDescriptor = ShaderWithGroups & ShaderWithResources;
type GlShaderFromWith = {
    gpu?: GpuProgramOptions;
    gl: GlProgramOptions;
};
type GpuShaderFromWith = {
    gpu: GpuProgramOptions;
    gl?: GlProgramOptions;
};
export type ShaderFromGroups = (GlShaderFromWith | GpuShaderFromWith) & Omit<ShaderWithGroups, 'glProgram' | 'gpuProgram'>;
export type ShaderFromResources = (GlShaderFromWith | GpuShaderFromWith) & Omit<ShaderWithResources, 'glProgram' | 'gpuProgram'>;
/**
 * The Shader class is an integral part of the PixiJS graphics pipeline.
 * Central to rendering in PixiJS are two key elements: A [shader] and a [geometry].
 * The shader incorporates a {@link GlProgram} for WebGL or a {@link GpuProgram} for WebGPU,
 * instructing the respective technology on how to render the geometry.
 *
 * The primary goal of the Shader class is to offer a unified interface compatible with both WebGL and WebGPU.
 * When constructing a shader, you need to provide both a WebGL program and a WebGPU program due to the distinctions
 * between the two rendering engines. If only one is provided, the shader won't function with the omitted renderer.
 *
 * Both WebGL and WebGPU utilize the same resource object when passed into the shader.
 * Post-creation, the shader's interface remains consistent across both WebGL and WebGPU.
 * The sole distinction lies in whether a glProgram or a gpuProgram is employed.
 *
 * Modifying shader uniforms, which can encompass:
 *  - TextureSampler {@link TextureStyle}
 *  - TextureSource {@link TextureSource}
 *  - UniformsGroups {@link UniformGroup}
 * @example
 *
 * const shader = new Shader({
 *     glProgram: glProgram,
 *     gpuProgram: gpuProgram,
 *     resources: {
 *         uTexture: texture.source,
 *         uSampler: texture.sampler,
 *         uColor: [1, 0, 0, 1],
 *     },
 * });
 *
 * // update the uniforms
 * shader.resources.uColor[1] = 1;
 * shader.resources.uTexture = texture2.source;
 * @class
 * @memberof rendering
 */
export declare class Shader extends EventEmitter<{
    'destroy': Shader;
}> {
    /** An instance of the GPU program used by the WebGPU renderer */
    gpuProgram: GpuProgram;
    /** An instance of the GL program used by the WebGL renderer */
    glProgram: GlProgram;
    /**
     * A number that uses two bits on whether the shader is compatible with the WebGL renderer and/or the WebGPU renderer.
     * 0b00 - not compatible with either
     * 0b01 - compatible with WebGL
     * 0b10 - compatible with WebGPU
     * This is automatically set based on if a {@link GlProgram} or {@link GpuProgram} is provided.
     */
    readonly compatibleRenderers: number;
    /** */
    groups: Record<number, BindGroup>;
    /** A record of the resources used by the shader. */
    resources: Record<string, any>;
    /**
     * A record of the uniform groups and resources used by the shader.
     * This is used by WebGL renderer to sync uniform data.
     * @internal
     * @ignore
     */
    _uniformBindMap: Record<number, Record<number, string>>;
    private readonly _ownedBindGroups;
    /**
     * Fired after rendering finishes.
     * @event rendering.Shader#destroy
     */
    /**
     * There are two ways to create a shader.
     * one is to pass in resources which is a record of uniform groups and resources.
     * another is to pass in groups which is a record of {@link BindGroup}s.
     * this second method is really to make use of shared {@link BindGroup}s.
     * For most cases you will want to use resources as they are easier to work with.
     * USe Groups if you want to share {@link BindGroup}s between shaders.
     * you cannot mix and match - either use resources or groups.
     * @param {ShaderWithResourcesDescriptor} options - The options for the shader using ShaderWithResourcesDescriptor.
     */
    constructor(options: ShaderWithResources);
    constructor(options: ShaderWithGroups);
    /**
     * Sometimes a resource group will be provided later (for example global uniforms)
     * In such cases, this method can be used to let the shader know about the group.
     * @param name - the name of the resource group
     * @param groupIndex - the index of the group (should match the webGPU shader group location)
     * @param bindIndex - the index of the bind point (should match the webGPU shader bind point)
     */
    addResource(name: string, groupIndex: number, bindIndex: number): void;
    private _buildResourceAccessor;
    /**
     * Use to destroy the shader when its not longer needed.
     * It will destroy the resources and remove listeners.
     * @param destroyPrograms - if the programs should be destroyed as well.
     * Make sure its not being used by other shaders!
     */
    destroy(destroyPrograms?: boolean): void;
    /**
     * A short hand function to create a shader based of a vertex and fragment shader.
     * @param options
     * @returns A shiny new PixiJS shader!
     */
    static from(options: ShaderFromGroups): Shader;
    static from(options: ShaderFromResources): Shader;
}
export {};
