UNPKG

typegpu

Version:

A thin layer between JS and WebGPU/WGSL that improves development experience and allows for faster iteration.

270 lines (269 loc) 15.6 kB
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 {};