import type { AnyBuiltin, OmitBuiltins } from '../../builtin.ts';
import type { IndexFlag, IndirectFlag, TgpuBuffer, VertexFlag } from '../buffer/buffer.ts';
import type { TgpuQuerySet } from '../querySet/querySet.ts';
import { type Disarray, type UndecorateRecord } from '../../data/dataTypes.ts';
import { type ResolvedSnippet } from '../../data/snippet.ts';
import { type AnyVecInstance, type BaseData, type U16, type U32, type v4f, Void, type WgslArray, type WgslStruct } 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 { AnyVertexAttribs } from '../../shared/vertexFormat.ts';
import { type TgpuBindGroup, type TgpuBindGroupLayout, type TgpuLayoutEntry } from '../../tgpuBindGroupLayout.ts';
import type { LogResources } from '../../tgsl/consoleLog/types.ts';
import type { ResolutionCtx, SelfResolvable } from '../../types.ts';
import { type AnyAutoCustoms, type AutoFragmentIn, type AutoFragmentOut, type AutoVertexIn, type AutoVertexOut } from '../function/autoIO.ts';
import type { TgpuFragmentFn } from '../function/tgpuFragmentFn.ts';
import type { TgpuVertexFn } from '../function/tgpuVertexFn.ts';
import type { ExperimentalTgpuRoot } from '../root/rootTypes.ts';
import type { TgpuSlot } from '../slot/slotTypes.ts';
import { type TgpuVertexLayout } from '../vertexLayout/vertexLayout.ts';
import { type TgpuCommandEncoder } from '../commandEncoder/commandEncoder.ts';
import type { ColorAttachment, DepthStencilAttachment } from '../commandEncoder/attachments.ts';
import { type TgpuRenderCommands } from '../commandEncoder/renderPass.ts';
import { type Timeable, type TimestampWritesPriors } from './timeable.ts';
import { type PrimitiveOffsetInfo } from '../../data/offsetUtils.ts';
import type { RestoreContext } from '../../serial/types.ts';
export interface RenderPipelineInternals {
    readonly core: RenderPipelineCore;
    readonly priors: TgpuRenderPipelinePriors & TimestampWritesPriors;
    readonly root: ExperimentalTgpuRoot;
    readonly materialize: () => GPURenderPipeline;
}
export interface TgpuRenderPipelineSoul extends TgpuDeviceOwningSoul<'render-pipeline', GPURenderPipeline> {
    usedBindGroupLayouts?: TgpuBindGroupLayout[] | undefined;
    usedVertexLayouts?: TgpuVertexLayout[] | undefined;
    fragmentOut?: BaseData | undefined;
    bindGroups?: [TgpuBindGroupLayout, TgpuBindGroup | GPUBindGroup][] | undefined;
    vertexBuffers?: [TgpuVertexLayout, (TgpuBuffer<BaseData> & VertexFlag) | GPUBuffer][] | undefined;
    indexBuffer?: {
        buffer: (TgpuBuffer<BaseData> & IndexFlag) | GPUBuffer;
        indexFormat: GPUIndexFormat;
        offsetBytes?: number | undefined;
        sizeBytes?: number | undefined;
    } | undefined;
    stencilReference?: GPUStencilValue | undefined;
    timestampWrites?: TimestampWritesPriors['timestampWrites'];
    performanceCallback?: TimestampWritesPriors['performanceCallback'];
    nonTransferablePriors?: string[] | undefined;
}
export type TgpuPrimitiveState = GPUPrimitiveState | (Omit<GPUPrimitiveState, 'stripIndexFormat'> & {
    stripIndexFormat?: U32 | U16;
}) | undefined;
export type TgpuColorTargetState = (Omit<GPUColorTargetState, 'format'> & {
    /**
     * The {@link GPUTextureFormat} of this color target. The pipeline will only be compatible with
     * {@link GPURenderPassEncoder}s which use a {@link GPUTextureView} of this format in the
     * corresponding color attachment.
     *
     * @default navigator.gpu.getPreferredCanvasFormat()
     */
    format?: GPUTextureFormat | undefined;
}) | undefined;
export interface HasIndexBuffer {
    readonly hasIndexBuffer: true;
    drawIndexed(indexCount: number, instanceCount?: number, firstIndex?: number, baseVertex?: number, firstInstance?: number): void;
}
export interface TgpuRenderPipeline<in Targets = never> extends TgpuNamable, SelfResolvable, Timeable {
    readonly [$internal]: RenderPipelineInternals;
    readonly [$soul]: TgpuRenderPipelineSoul;
    readonly resourceType: 'render-pipeline';
    readonly hasIndexBuffer: boolean;
    with<TData extends WgslArray | Disarray>(vertexLayout: TgpuVertexLayout<TData>, buffer: (TgpuBuffer<TData> & VertexFlag) | GPUBuffer): this;
    /**
     * @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 draw calls into the given render pass or render bundle
     * encoder, letting multiple pipelines share one pass (and one submission).
     */
    with(pass: TgpuRenderCommands): this;
    /**
     * Directs subsequent draw calls into the given command encoder. Each draw
     * records its own render pass; the caller owns the submission.
     */
    with(encoder: TgpuCommandEncoder): this;
    with(encoder: GPUCommandEncoder): this;
    with(pass: GPURenderPassEncoder): this;
    with(bundleEncoder: GPURenderBundleEncoder): this;
    /**
     * Attaches texture views to the pipeline's targets (outputs).
     *
     * @example
     * // Draw 3 vertices onto the context's canvas
     * pipeline
     *   .withColorAttachment({ view: context })
     *   .draw(3)
     *
     * @param attachment The object should match the shape
     * returned by the fragment shader, with values matching the {@link ColorAttachment} type.
     */
    withColorAttachment(attachment: FragmentOutToColorAttachment<Targets>): this;
    withDepthStencilAttachment(attachment: DepthStencilAttachment): this;
    withStencilReference(reference: GPUStencilValue): this;
    withIndexBuffer(buffer: TgpuBuffer<BaseData> & IndexFlag, offsetElements?: number, sizeElements?: number): this & HasIndexBuffer;
    withIndexBuffer(buffer: GPUBuffer, indexFormat: GPUIndexFormat, offsetBytes?: number, sizeBytes?: number): this & HasIndexBuffer;
    draw(vertexCount: number, instanceCount?: number, firstVertex?: number, firstInstance?: number): void;
    /**
     * Immediately resolves the pipeline, then awaits `device.createRenderPipelineAsync()`.
     * 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;
    /**
     * Draws primitives using parameters read from a buffer.
     * The buffer must contain 4 consecutive u32 values (vertexCount, instanceCount, firstVertex, firstInstance).
     * To get the correct offset within complex data structures, use `d.memoryLayoutOf(...)`.
     *
     * @param indirectBuffer - Buffer marked with 'indirect' usage containing draw parameters or raw GPUBuffer
     * @param indirectOffset - PrimitiveOffsetInfo pointing to the first draw parameter. If not provided, starts at offset 0. To obtain safe offsets, use `d.memoryLayoutOf(...)`.
     */
    drawIndirect(indirectBuffer: (TgpuBuffer<BaseData> & IndirectFlag) | GPUBuffer, indirectOffset?: PrimitiveOffsetInfo | number): void;
    /**
     * Draws indexed primitives using parameters read from a buffer.
     * The buffer must contain 5 consecutive 32-bit integer values (indexCount u32, instanceCount u32, firstIndex u32, baseVertex i32, firstInstance u32).
     * To get the correct offset within complex data structures, use `d.memoryLayoutOf(...)`.
     *
     * @param indirectBuffer - Buffer marked with 'indirect' usage containing draw parameters or raw GPUBuffer
     * @param indirectOffset - PrimitiveOffsetInfo pointing to the first draw parameter. If not provided, starts at offset 0. To obtain safe offsets, use `d.memoryLayoutOf(...)`.
     */
    drawIndexedIndirect(indirectBuffer: (TgpuBuffer<BaseData> & IndirectFlag) | GPUBuffer, indirectOffset?: PrimitiveOffsetInfo | number): void;
}
export declare namespace TgpuRenderPipeline {
    interface DescriptorBase {
        /**
         * Describes the primitive-related properties of the pipeline.
         */
        primitive?: TgpuPrimitiveState | undefined;
        /**
         * Describes the optional depth-stencil properties, including the testing, operations, and bias.
         */
        depthStencil?: GPUDepthStencilState | undefined;
        /**
         * Describes the multi-sampling properties of the pipeline.
         */
        multisample?: GPUMultisampleState | undefined;
    }
    interface Descriptor extends DescriptorBase {
        vertex: TgpuVertexFn | ((input: AutoVertexIn<Record<string, never>>) => AutoVertexOut<AnyAutoCustoms>);
        fragment?: TgpuFragmentFn | ((input: AutoFragmentIn<Record<string, never>>) => AutoFragmentOut<undefined | v4f | AnyAutoCustoms>) | undefined;
        attribs?: AnyVertexAttribs | undefined;
        targets?: AnyFragmentTargets | undefined;
    }
}
export type FragmentOutToTargets<T> = T extends undefined | AnyBuiltin | Void | Record<string, never> ? Record<string, never> | undefined : T extends {
    readonly [$internal]: unknown;
} | number | boolean | AnyVecInstance ? TgpuColorTargetState : T extends Record<string, unknown> ? {
    [Key in keyof OmitBuiltins<T>]?: TgpuColorTargetState;
} | undefined : TgpuColorTargetState | Record<string, TgpuColorTargetState>;
export type FragmentOutToColorAttachment<T> = T extends {
    readonly [$internal]: unknown;
} ? ColorAttachment : T extends Record<string, unknown> ? {
    [Key in keyof UndecorateRecord<T>]: ColorAttachment;
} : Record<string, never>;
export type AnyFragmentTargets = TgpuColorTargetState | Record<string, TgpuColorTargetState>;
export type AnyFragmentColorAttachment = ColorAttachment | Record<string, ColorAttachment>;
export type RenderPipelineCoreOptions = {
    root: ExperimentalTgpuRoot;
    slotBindings: [TgpuSlot<unknown>, unknown][];
    /** Undefined for precompiled pipelines, which are never resolved again */
    descriptor: TgpuRenderPipeline.Descriptor | undefined;
};
export declare function INTERNAL_createRenderPipeline(options: RenderPipelineCoreOptions): TgpuRenderPipelineImpl;
export declare function INTERNAL_restoreRenderPipeline(soul: TgpuRenderPipelineSoul, ctx: RestoreContext): TgpuRenderPipeline;
type TgpuRenderPipelinePriors = {
    readonly vertexLayoutMap?: Map<TgpuVertexLayout, (TgpuBuffer<BaseData> & VertexFlag) | GPUBuffer> | undefined;
    readonly bindGroupLayoutMap?: Map<TgpuBindGroupLayout, TgpuBindGroup | GPUBindGroup> | undefined;
    readonly colorAttachment?: AnyFragmentColorAttachment | undefined;
    readonly depthStencilAttachment?: DepthStencilAttachment | undefined;
    readonly stencilReference?: GPUStencilValue | undefined;
    readonly indexBuffer?: {
        buffer: (TgpuBuffer<BaseData> & IndexFlag) | GPUBuffer;
        indexFormat: GPUIndexFormat;
        offsetBytes?: number | undefined;
        sizeBytes?: number | undefined;
    } | undefined;
    /** A pass the pipeline draws into, but does not own */
    readonly pass?: TgpuRenderCommands | undefined;
    /** An encoder the pipeline records its own passes into, but does not submit */
    readonly encoder?: TgpuCommandEncoder | undefined;
} & TimestampWritesPriors;
type Memo = {
    pipeline: GPURenderPipeline;
    usedBindGroupLayouts: TgpuBindGroupLayout[];
    catchall: [number, TgpuBindGroup] | undefined;
    logResources: LogResources | undefined;
    usedVertexLayouts: TgpuVertexLayout[];
    fragmentOut: BaseData | undefined;
};
declare class TgpuRenderPipelineImpl implements TgpuRenderPipeline {
    #private;
    readonly [$internal]: RenderPipelineInternals;
    readonly [$soul]: TgpuRenderPipelineSoul;
    readonly resourceType = "render-pipeline";
    [$getNameForward]: RenderPipelineCore;
    constructor(core: RenderPipelineCore, priors: TgpuRenderPipelinePriors);
    [$resolve](ctx: ResolutionCtx): ResolvedSnippet;
    toString(): string;
    $name(label: string): this;
    with<TData extends WgslArray>(vertexLayout: TgpuVertexLayout<TData>, buffer: TgpuBuffer<TData> & VertexFlag): this;
    with(bindGroupLayout: TgpuBindGroupLayout, bindGroup: TgpuBindGroup): this;
    with(bindGroupLayout: TgpuBindGroupLayout, bindGroup: GPUBindGroup): this;
    with(bindGroup: TgpuBindGroup): this;
    with<TData extends WgslArray | Disarray>(vertexLayout: TgpuVertexLayout<TData>, buffer: GPUBuffer): this;
    with(pass: TgpuRenderCommands): this;
    with(encoder: TgpuCommandEncoder): this;
    with(encoder: GPUCommandEncoder): this;
    with(pass: GPURenderPassEncoder): this;
    with(bundleEncoder: GPURenderBundleEncoder): this;
    withPerformanceCallback(callback: (start: bigint, end: bigint) => void | Promise<void>): this;
    withTimestampWrites(options: {
        querySet: TgpuQuerySet<'timestamp'> | GPUQuerySet;
        beginningOfPassWriteIndex?: number;
        endOfPassWriteIndex?: number;
    }): this;
    withColorAttachment(attachment: AnyFragmentColorAttachment): this;
    withDepthStencilAttachment(attachment: DepthStencilAttachment): this;
    withStencilReference(reference: GPUStencilValue): this;
    withIndexBuffer(buffer: TgpuBuffer<BaseData> & IndexFlag, offsetElements?: number, sizeElements?: number): this & HasIndexBuffer;
    withIndexBuffer(buffer: GPUBuffer, indexFormat: GPUIndexFormat, offsetBytes?: number, sizeBytes?: number): this & HasIndexBuffer;
    initAsync(): Promise<void>;
    initSync(): void;
    get hasIndexBuffer(): boolean;
    draw(vertexCount: number, instanceCount?: number, firstVertex?: number, firstInstance?: number): void;
    drawIndexed(indexCount: number, instanceCount?: number, firstIndex?: number, baseVertex?: number, firstInstance?: number): void;
    drawIndirect(indirectBuffer: (TgpuBuffer<BaseData> & IndirectFlag) | GPUBuffer, indirectOffset?: PrimitiveOffsetInfo | number): void;
    drawIndexedIndirect(indirectBuffer: (TgpuBuffer<BaseData> & IndirectFlag) | GPUBuffer, indirectOffset?: PrimitiveOffsetInfo | number): void;
}
declare class RenderPipelineCore implements SelfResolvable {
    #private;
    readonly [$internal] = true;
    readonly options: RenderPipelineCoreOptions;
    constructor(options: RenderPipelineCoreOptions);
    static precompiled(root: ExperimentalTgpuRoot, memo: Memo): RenderPipelineCore;
    [$resolve](ctx: ResolutionCtx): ResolvedSnippet;
    toString(): string;
    get performanceCallbackQuerySet(): TgpuQuerySet<"timestamp"> | undefined;
    initAsync(): Promise<void>;
    initSync(): void;
    unwrap(): Memo;
    resolveAndCreateShaderModule(): {
        resolutionResult: import("../../resolutionCtx.ts").ResolutionResult;
        descriptor: GPURenderPipelineDescriptor;
        connectedAttribs: import("../vertexLayout/connectAttributesToShader.ts").ConnectAttributesToShaderResult;
        fragmentOut: WgslStruct<import("../function/ioSchema.ts").WithLocations<Record<string, BaseData>>>;
    };
}
/**
 * Assumes vertexOut and fragmentIn are matching when it comes to the keys, that is fragmentIn's keyset is a subset of vertexOut's
 * Logs a warning, when they don't match in terms of custom locations
 */
export declare function matchUpVaryingLocations(vertexOut: TgpuVertexFn.Out | undefined, fragmentIn: TgpuFragmentFn.In | undefined, vertexFnName: string, fragmentFnName: string): Record<string, number>;
export {};
