import type { AnyComputeBuiltin } from '../../builtin.ts';
import type { TgpuQuerySet } from '../querySet/querySet.ts';
import { type ResolvedSnippet } from '../../data/snippet.ts';
import type { AnyWgslData } from '../../data/wgslTypes.ts';
import type { TgpuNamable } from '../../shared/meta.ts';
import type { TgpuDeviceOwningSoul } from '../../shared/soul.ts';
import { $getNameForward, $internal, $resolve, $soul } from '../../shared/symbols.ts';
import { type TgpuBindGroup, type TgpuBindGroupLayout, type TgpuLayoutEntry } from '../../tgpuBindGroupLayout.ts';
import { type TgpuCommandEncoder } from '../commandEncoder/commandEncoder.ts';
import { type TgpuComputePass } from '../commandEncoder/computePass.ts';
import type { LogResources } from '../../tgsl/consoleLog/types.ts';
import { type ResolutionCtx, type SelfResolvable } from '../../types.ts';
import type { IORecord } from '../function/fnTypes.ts';
import type { TgpuComputeFn } from '../function/tgpuComputeFn.ts';
import type { ExperimentalTgpuRoot } from '../root/rootTypes.ts';
import type { TgpuSlot } from '../slot/slotTypes.ts';
import type { PrimitiveOffsetInfo } from '../../data/offsetUtils.ts';
import type { RestoreContext } from '../../serial/types.ts';
import { type Timeable, type TimestampWritesPriors } from './timeable.ts';
import type { IndirectFlag, TgpuBuffer } from '../buffer/buffer.ts';
export interface ComputePipelineInternals {
    readonly core: ComputePipelineCore;
    readonly priors: TgpuComputePipelinePriors & TimestampWritesPriors;
    readonly root: ExperimentalTgpuRoot;
    readonly materialize: () => GPUComputePipeline;
}
export interface TgpuComputePipelineSoul extends TgpuDeviceOwningSoul<'compute-pipeline', GPUComputePipeline> {
    usedBindGroupLayouts?: TgpuBindGroupLayout[] | undefined;
    bindGroups?: [TgpuBindGroupLayout, TgpuBindGroup | GPUBindGroup][] | undefined;
    timestampWrites?: TimestampWritesPriors['timestampWrites'];
    performanceCallback?: TimestampWritesPriors['performanceCallback'];
    nonTransferablePriors?: string[] | undefined;
}
export interface TgpuComputePipeline extends TgpuNamable, SelfResolvable, Timeable {
    readonly [$internal]: ComputePipelineInternals;
    readonly [$soul]: TgpuComputePipelineSoul;
    readonly resourceType: 'compute-pipeline';
    /**
     * @deprecated This overload is outdated.
     * Call `pipeline.with(bindGroup)` instead.
     */
    with<Entries extends Record<string, TgpuLayoutEntry | null>>(bindGroupLayout: TgpuBindGroupLayout<Entries>, bindGroup: TgpuBindGroup<Entries>): this;
    with(bindGroupLayout: TgpuBindGroupLayout, bindGroup: GPUBindGroup): this;
    with(bindGroup: TgpuBindGroup): this;
    /**
     * Directs subsequent dispatches into the given compute pass, letting multiple
     * pipelines share one pass (and one submission).
     */
    with(pass: TgpuComputePass): this;
    /**
     * Directs subsequent dispatches into the given command encoder. Each dispatch
     * records its own compute pass; the caller owns the submission.
     */
    with(encoder: TgpuCommandEncoder): this;
    with(encoder: GPUCommandEncoder): this;
    with(pass: GPUComputePassEncoder): this;
    dispatchWorkgroups(x: number, y?: number, z?: number): void;
    /**
     * Immediately resolves the pipeline, then awaits `device.createComputePipelineAsync()`.
     * NOTE: it is not necessary to initialize pipelines manually.
     */
    initAsync(): Promise<void>;
    /**
     * Immediately resolves the pipeline and creates WebGPU resources.
     * NOTE: it is not necessary to initialize pipelines manually.
     */
    initSync(): void;
    /**
     * Dispatches compute workgroups using parameters read from a buffer.
     * The buffer must contain 3 consecutive u32 values (x, y, z workgroup counts).
     * To get the correct offset within complex data structures, use `d.memoryLayoutOf(...)`.
     *
     * @param indirectBuffer - Buffer marked with 'indirect' usage containing dispatch parameters or raw GPUBuffer
     * @param start - PrimitiveOffsetInfo pointing to the first dispatch parameter. If not provided, starts at offset 0. To obtain safe offsets, use `d.memoryLayoutOf(...)`.
     */
    dispatchWorkgroupsIndirect<T extends AnyWgslData>(indirectBuffer: (TgpuBuffer<T> & IndirectFlag) | GPUBuffer, start?: PrimitiveOffsetInfo | number): void;
}
export declare namespace TgpuComputePipeline {
    type Descriptor<Input extends IORecord<AnyComputeBuiltin> = IORecord<AnyComputeBuiltin>> = {
        compute: TgpuComputeFn<Input>;
    };
}
export declare function INTERNAL_createComputePipeline(root: ExperimentalTgpuRoot, slotBindings: [TgpuSlot<unknown>, unknown][], descriptor: TgpuComputePipeline.Descriptor): TgpuComputePipelineImpl;
export declare function INTERNAL_restoreComputePipeline(soul: TgpuComputePipelineSoul, ctx: RestoreContext): TgpuComputePipeline;
type TgpuComputePipelinePriors = {
    readonly bindGroupLayoutMap?: Map<TgpuBindGroupLayout, TgpuBindGroup | GPUBindGroup>;
    /** A pass the pipeline dispatches into, but does not own */
    readonly pass?: TgpuComputePass | undefined;
    /** An encoder the pipeline records its own passes into, but does not submit */
    readonly encoder?: TgpuCommandEncoder | undefined;
} & TimestampWritesPriors;
type Memo = {
    pipeline: GPUComputePipeline;
    usedBindGroupLayouts: TgpuBindGroupLayout[];
    catchall: [number, TgpuBindGroup] | undefined;
    logResources: LogResources | undefined;
};
declare class TgpuComputePipelineImpl implements TgpuComputePipeline {
    #private;
    readonly [$internal]: ComputePipelineInternals;
    readonly [$soul]: TgpuComputePipelineSoul;
    readonly resourceType = "compute-pipeline";
    readonly [$getNameForward]: ComputePipelineCore;
    constructor(core: ComputePipelineCore, priors: TgpuComputePipelinePriors);
    [$resolve](ctx: ResolutionCtx): ResolvedSnippet;
    toString(): string;
    with<Entries extends Record<string, TgpuLayoutEntry | null>>(bindGroupLayout: TgpuBindGroupLayout<Entries>, bindGroup: TgpuBindGroup<Entries>): this;
    with(bindGroupLayout: TgpuBindGroupLayout, bindGroup: GPUBindGroup): this;
    with(bindGroup: TgpuBindGroup): this;
    with(pass: TgpuComputePass): this;
    with(encoder: TgpuCommandEncoder): this;
    with(encoder: GPUCommandEncoder): this;
    with(pass: GPUComputePassEncoder): this;
    withPerformanceCallback(callback: (start: bigint, end: bigint) => void | Promise<void>): this;
    withTimestampWrites(options: {
        querySet: TgpuQuerySet<'timestamp'> | GPUQuerySet;
        beginningOfPassWriteIndex?: number;
        endOfPassWriteIndex?: number;
    }): this;
    dispatchWorkgroups(x: number, y?: number, z?: number): void;
    dispatchWorkgroupsIndirect<T extends AnyWgslData>(indirectBuffer: (TgpuBuffer<T> & IndirectFlag) | GPUBuffer, start?: PrimitiveOffsetInfo | number): void;
    initAsync(): Promise<void>;
    initSync(): void;
    $name(label: string): this;
}
declare class ComputePipelineCore implements SelfResolvable {
    #private;
    readonly [$internal] = true;
    readonly root: ExperimentalTgpuRoot;
    constructor(root: ExperimentalTgpuRoot, slotBindings: [TgpuSlot<unknown>, unknown][], descriptor: TgpuComputePipeline.Descriptor | undefined);
    static precompiled(root: ExperimentalTgpuRoot, memo: Memo): ComputePipelineCore;
    [$resolve](ctx: ResolutionCtx): ResolvedSnippet;
    toString(): string;
    get performanceCallbackQuerySet(): TgpuQuerySet<"timestamp"> | undefined;
    /**
     * @privateRemarks
     * This function cannot be a regular async function
     * because when called multiple times before the promise finishes,
     * we want it to return the same promise each time.
     */
    initAsync(): Promise<void>;
    initSync(): void;
    unwrap(): Memo;
    private resolveAndCreateShaderModule;
}
export {};
