import { type TgpuBuffer, type UniformFlag } from './core/buffer/buffer.ts';
import { type TgpuComparisonSampler, type TgpuSampler } from './core/sampler/sampler.ts';
import { type PropsForSchema, type TgpuTexture, type TgpuTextureView } from './core/texture/texture.ts';
import { type SampledFlag } from './core/texture/usageExtension.ts';
import { type WgslExternalTexture, type WgslStorageTexture, type WgslTexture } from './data/texture.ts';
import type { TgpuRoot } from './core/root/rootTypes.ts';
import type { RestoreContext } from './serial/types.ts';
import type { BaseData } from './data/wgslTypes.ts';
import { type StorageFlag } from './extension.ts';
import type { TgpuNamable } from './shared/meta.ts';
import type { InferGPU, MemIdentity } from './shared/repr.ts';
import type { TgpuDeviceOwningSoul, TgpuSoul } from './shared/soul.ts';
import { $gpuValueOf, $internal, $soul } from './shared/symbols.ts';
import type { NullableToOptional, Prettify } from './shared/utilityTypes.ts';
import type { ResolvableObject, ShaderStage } from './types.ts';
import type { Unwrapper } from './unwrapper.ts';
import type { WgslComparisonSampler, WgslSampler } from './data/sampler.ts';
import { type TgpuBufferBinding, type TgpuMutable, type TgpuReadonly, type TgpuUniform } from './core/buffer/bufferBinding.ts';
export interface LayoutMembership {
    layout: TgpuBindGroupLayout;
    key: string;
    idx: number;
}
export type TgpuLayoutEntryBase = {
    /**
     * Limits this resource's visibility to specific shader stages.
     *
     * By default, each resource is visible to all shader stage types, but
     * depending on the underlying implementation, this may have performance implications.
     *
     * @default ['compute','fragment'] for mutable resources
     * @default ['compute','vertex','fragment'] for everything else
     */
    visibility?: ShaderStage[];
};
export type TgpuLayoutUniform = TgpuLayoutEntryBase & {
    uniform: BaseData;
};
export type TgpuLayoutStorage = TgpuLayoutEntryBase & {
    storage: BaseData | ((arrayLength: number) => BaseData);
    /** @default 'readonly' */
    access?: 'mutable' | 'readonly';
};
export type TgpuLayoutSampler = TgpuLayoutEntryBase & {
    sampler: 'filtering' | 'non-filtering';
};
export type TgpuLayoutComparisonSampler = TgpuLayoutEntryBase & {
    sampler: 'comparison';
};
export type TgpuLayoutTexture<TSchema extends WgslTexture = WgslTexture> = TgpuLayoutEntryBase & {
    texture: TSchema;
    sampleType?: GPUTextureSampleType;
};
export type TgpuLayoutStorageTexture<TSchema extends WgslStorageTexture = WgslStorageTexture> = TgpuLayoutEntryBase & {
    storageTexture: TSchema;
};
export type TgpuLayoutExternalTexture = TgpuLayoutEntryBase & {
    externalTexture: WgslExternalTexture;
};
export type TgpuLayoutEntry = TgpuLayoutUniform | TgpuLayoutStorage | TgpuLayoutSampler | TgpuLayoutComparisonSampler | TgpuLayoutTexture | TgpuLayoutStorageTexture | TgpuLayoutExternalTexture;
type UnwrapRuntimeConstructorInner<T extends BaseData | ((_: number) => BaseData)> = T extends (_: number) => BaseData ? ReturnType<T> : T;
export type UnwrapRuntimeConstructor<T extends BaseData | ((_: number) => BaseData)> = T extends unknown ? UnwrapRuntimeConstructorInner<T> : never;
export interface TgpuBindGroupLayoutSoul extends TgpuSoul<'bind-group-layout'> {
    readonly entries: Record<string, TgpuLayoutEntry | null>;
    index?: number | undefined;
}
/**
 * A residue soul: entries may hold runtime-local resources (texture views), so
 * the soul holds the layout and the created bind group instead of the recipe.
 * It is completed by `[$internal].materialize()`.
 */
export interface TgpuBindGroupSoul<Entries extends Record<string, TgpuLayoutEntry | null> = Record<string, TgpuLayoutEntry | null>> extends TgpuDeviceOwningSoul<'bind-group', GPUBindGroup> {
    readonly layout: TgpuBindGroupLayout<Entries>;
}
export interface TgpuBindGroupLayout<Entries extends Record<string, TgpuLayoutEntry | null> = Record<string, TgpuLayoutEntry | null>> extends TgpuNamable {
    readonly [$internal]: ResolvableObject[];
    readonly [$soul]: TgpuBindGroupLayoutSoul;
    readonly resourceType: 'bind-group-layout';
    readonly entries: Entries;
    readonly [$gpuValueOf]: {
        [K in keyof Entries]: InferLayoutEntry<Entries[K]>;
    };
    readonly $: {
        [K in keyof Entries]: InferLayoutEntry<Entries[K]>;
    };
    /**
     * An explicit numeric index assigned to this bind group layout. If undefined, a unique
     * index is assigned automatically during resolution. This can be changed with the
     * `.$idx()` method.
     */
    readonly index: number | undefined;
    /**
     * Associates this bind group layout with an explicit numeric index. When a call to this
     * method is omitted, a unique numeric index is assigned to it automatically.
     *
     * Used when generating WGSL code: `@group(${index}) @binding(...) ...;`
     */
    $idx(index?: number): this;
    /**
     * Creates a raw WebGPU resource based on the typed descriptor.
     * NOTE: This creates a new resource every time, better to use `root.unwrap(...)` instead.
     * @param unwrapper Used to unwrap any resources that this resource depends on.
     */
    unwrap(unwrapper: Unwrapper): GPUBindGroupLayout;
}
export type LayoutEntryToInput<T extends TgpuLayoutEntry | null> = TgpuLayoutEntry | null extends T ? TgpuBuffer<BaseData> | TgpuBufferBinding<BaseData> | GPUBuffer | TgpuSampler | GPUSampler | TgpuComparisonSampler | TgpuTexture | GPUTextureView | GPUExternalTexture : T extends TgpuLayoutUniform ? (TgpuBuffer<MemIdentity<UnwrapRuntimeConstructor<T['uniform']>>> & UniformFlag) | TgpuUniform<MemIdentity<UnwrapRuntimeConstructor<T['uniform']>>> | GPUBuffer : T extends TgpuLayoutStorage ? (TgpuBuffer<MemIdentity<UnwrapRuntimeConstructor<T['storage']>>> & StorageFlag) | (T extends {
    access: 'mutable';
} ? TgpuMutable<MemIdentity<UnwrapRuntimeConstructor<T['storage']>>> : TgpuReadonly<MemIdentity<UnwrapRuntimeConstructor<T['storage']>>>) | GPUBuffer : T extends TgpuLayoutSampler ? TgpuSampler | GPUSampler : T extends TgpuLayoutComparisonSampler ? TgpuComparisonSampler | GPUSampler : T extends TgpuLayoutTexture ? GPUTextureView | GPUTexture | (SampledFlag & TgpuTexture<Prettify<PropsForSchema<T['texture']>>>) | TgpuTextureView<WgslTexture> : T extends TgpuLayoutStorageTexture ? GPUTextureView | GPUTexture | (StorageFlag & TgpuTexture<Prettify<PropsForSchema<T['storageTexture']>>>) | TgpuTextureView<WgslStorageTexture> : T extends TgpuLayoutExternalTexture ? GPUExternalTexture : never;
export type InferLayoutEntry<T extends TgpuLayoutEntry | null> = T extends TgpuLayoutUniform ? InferGPU<T['uniform']> : T extends TgpuLayoutStorage ? InferGPU<UnwrapRuntimeConstructor<T['storage']>> : T extends TgpuLayoutSampler ? InferGPU<WgslSampler> : T extends TgpuLayoutComparisonSampler ? InferGPU<WgslComparisonSampler> : T extends TgpuLayoutTexture<infer TSchema> ? InferGPU<TSchema> : T extends TgpuLayoutStorageTexture<infer TSchema> ? InferGPU<TSchema> : T extends TgpuLayoutExternalTexture ? InferGPU<T['externalTexture']> : never;
export type ExtractBindGroupInputFromLayout<T extends Record<string, TgpuLayoutEntry | null>> = NullableToOptional<{
    [K in keyof T]: LayoutEntryToInput<T[K]>;
}>;
export type TgpuBindGroup<Entries extends Record<string, TgpuLayoutEntry | null> = Record<string, TgpuLayoutEntry | null>> = {
    readonly [$internal]: {
        readonly materialize: () => GPUBindGroup;
    };
    readonly [$soul]: TgpuBindGroupSoul<Entries>;
    readonly resourceType: 'bind-group';
    readonly layout: TgpuBindGroupLayout<Entries>;
    unwrap(unwrapper: Unwrapper): GPUBindGroup;
};
export declare function bindGroupLayout<Entries extends Record<string, TgpuLayoutEntry | null>>(entries: Entries): TgpuBindGroupLayout<Prettify<Entries>>;
export declare function INTERNAL_restoreBindGroupLayout(soul: TgpuBindGroupLayoutSoul): TgpuBindGroupLayout;
export declare function INTERNAL_restoreBindGroup(soul: TgpuBindGroupSoul, ctx: RestoreContext): TgpuBindGroup;
export declare function isBindGroupLayout(value: unknown): value is TgpuBindGroupLayout;
export declare function isBindGroup(value: unknown): value is TgpuBindGroup;
/**
 * @category Errors
 */
export declare class MissingBindingError extends Error {
    constructor(groupLabel: string | undefined, key: string);
}
export declare class TgpuBindGroupImpl<Entries extends Record<string, TgpuLayoutEntry | null> = Record<string, TgpuLayoutEntry | null>> implements TgpuBindGroup<Entries> {
    #private;
    readonly [$internal]: {
        readonly materialize: () => GPUBindGroup;
    };
    readonly [$soul]: TgpuBindGroupSoul<Entries>;
    readonly resourceType: "bind-group";
    constructor(root: TgpuRoot | undefined, layout: TgpuBindGroupLayout<Entries>, entries: ExtractBindGroupInputFromLayout<Entries>, raw?: GPUBindGroup);
    get layout(): TgpuBindGroupLayout<Entries>;
    get entries(): ExtractBindGroupInputFromLayout<Entries>;
    unwrap(unwrapper: Unwrapper): GPUBindGroup;
}
export {};
