webgpu-pipeline-kit
Version:
A type-safe declarative way of creating WebGPU pipelines
273 lines (256 loc) • 15.3 kB
TypeScript
import { LogLevelDesc } from 'loglevel';
type Color = {
r: number;
g: number;
b: number;
a?: number;
};
type NonEmptyArray<T> = [T, ...T[]];
type Decrement = [never, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
type OneOrBoth<A, B> = (A & Partial<B>) | (B & Partial<A>);
type Slice = {
min: number;
length: number;
};
type CopySlice = Slice & {
toIndex: number;
};
type ValueSlices<T> = {
values: T;
copySlices: CopySlice[];
};
type Vec3 = readonly [number, number, number];
type WPKPrimitiveMap = {
boolean: boolean;
string: string;
number: number;
};
type WPKInstanceFormat = _WPKInstanceFormat<4>;
type WPKInstanceOf<TFormat extends WPKInstanceFormat> = _WPKInstanceOf<TFormat, 4>;
type _WPKInstanceFormat<Depth extends number> = Depth extends never ? never : keyof WPKPrimitiveMap | _WPKInstanceFormat<Decrement[Depth]>[] | {
[key: string]: _WPKInstanceFormat<Decrement[Depth]>;
};
type _WPKInstanceOf<TObj, TDepth extends number> = TObj extends keyof WPKPrimitiveMap ? WPKPrimitiveMap[TObj] : TObj extends readonly [any, ...any[]] ? {
[K in keyof TObj]: _WPKInstanceOf<TObj[K], Decrement[TDepth]>;
} : TObj extends object ? {
[K in keyof TObj]: _WPKInstanceOf<TObj[K], Decrement[TDepth]>;
} : never;
type WPKCacheMutable<T, TKey> = {
mutate: (id: TKey, element: T) => void;
};
type WPKCacheResizeable<T> = {
add: (element: T) => string;
remove: (id: string) => void;
indexOf: (id: string) => number;
};
type WPKUniformCache<TUniformFormat extends WPKInstanceFormat, TMutable extends boolean> = {
isMutable: TMutable;
isDirty: () => boolean;
get: () => WPKInstanceOf<TUniformFormat>;
} & (TMutable extends true ? {
mutate: (element: WPKInstanceOf<TUniformFormat>) => void;
} : object);
type WPKEntityCache<TEntityFormat extends WPKInstanceFormat, TMutable extends boolean, TResizeable extends boolean> = {
isMutable: TMutable;
isResizeable: TResizeable;
count: () => number;
isDirty: () => boolean;
calculateChanges: () => ValueSlices<WPKInstanceOf<TEntityFormat>[]>;
} & (TMutable extends true ? WPKCacheMutable<WPKInstanceOf<TEntityFormat>, TResizeable extends true ? string : number> : object) & (TResizeable extends true ? WPKCacheResizeable<WPKInstanceOf<TEntityFormat>> : object);
type WPKTupleIndexes<T extends readonly unknown[]> = Extract<keyof T, `${number}`> extends `${infer N extends number}` ? N : never;
type WPKIsExact<A, B> = (<T>() => T extends A ? 1 : 2) extends (<T>() => T extends B ? 1 : 2) ? (<T>() => T extends B ? 1 : 2) extends (<T>() => T extends A ? 1 : 2) ? true : false : false;
type WPKIsTuple<T> = T extends readonly unknown[] ? number extends T['length'] ? false : true : false;
type _WPKMatchingPath<TType, TMatchingType, TPrefix extends string, TDepth extends number> = TDepth extends never ? never : TType extends readonly unknown[] ? WPKIsTuple<TType> extends true ? {
[I in WPKTupleIndexes<TType>]: WPKIsExact<TType[I], TMatchingType> extends true ? `${TPrefix}${I}` : _WPKMatchingPath<TType[I], TMatchingType, `${TPrefix}${I}.`, Decrement[TDepth]>;
}[WPKTupleIndexes<TType>] : never : TType extends object ? {
[K in keyof TType & string]: WPKIsExact<TType[K], TMatchingType> extends true ? `${TPrefix}${K}` : _WPKMatchingPath<TType[K], TMatchingType, `${TPrefix}${K}.`, Decrement[TDepth]>;
}[keyof TType & string] : never;
type WPKMatchingPath<TType, TMatchingType> = _WPKMatchingPath<TType, TMatchingType, '', 4>;
type WPKPrimitive8 = 'sint8' | 'snorm8' | 'uint8' | 'unorm8';
type WPKPrimitive16 = 'sint16' | 'snorm16' | 'uint16' | 'unorm16' | 'float16';
type WPKPrimitive32 = 'sint32' | 'uint32' | 'float32';
type WPKPrimitiveSignedInt = 'sint8' | 'sint16' | 'sint32';
type WPKPrimitive = WPKPrimitive8 | WPKPrimitive16 | WPKPrimitive32;
type WPKMatchingPathScalar<TFormat extends WPKInstanceFormat> = WPKMatchingPath<WPKInstanceOf<TFormat>, number>;
type WPKMatchingPathVec2<TFormat extends WPKInstanceFormat> = WPKMatchingPath<WPKInstanceOf<TFormat>, [number, number]>;
type WPKMatchingPathVec3<TFormat extends WPKInstanceFormat> = WPKMatchingPath<WPKInstanceOf<TFormat>, [number, number, number]>;
type WPKMatchingPathVec4<TFormat extends WPKInstanceFormat> = WPKMatchingPath<WPKInstanceOf<TFormat>, [number, number, number, number]>;
type WPKDatumType<TDatumType = WPKPrimitive> = {
datumType: TDatumType;
};
type WPKLayoutTypes<TDimension, TDatumType = WPKPrimitive> = WPKDatumType<TDatumType> & {
dimension: TDimension;
};
type WPKLayoutScalar = WPKLayoutTypes<'scalar'>;
type WPKLayoutVec2 = WPKLayoutTypes<'vec2'>;
type WPKLayoutVec3 = WPKLayoutTypes<'vec3', WPKPrimitive32>;
type WPKLayoutVec4 = WPKLayoutTypes<'vec4'>;
type WPKLayout = WPKLayoutScalar | WPKLayoutVec2 | WPKLayoutVec3 | WPKLayoutVec4;
type WPKPathScalar<TFormat extends WPKInstanceFormat> = WPKMatchingPathScalar<TFormat>;
type WPKPathVec2<TFormat extends WPKInstanceFormat> = WPKMatchingPathVec2<TFormat> | [
WPKMatchingPathScalar<TFormat>,
WPKMatchingPathScalar<TFormat>
];
type WPKPathVec3<TFormat extends WPKInstanceFormat> = WPKMatchingPathVec3<TFormat> | [
WPKMatchingPathScalar<TFormat>,
WPKMatchingPathScalar<TFormat>,
WPKMatchingPathScalar<TFormat>
];
type WPKPathVec4<TFormat extends WPKInstanceFormat> = WPKMatchingPathVec4<TFormat> | [
WPKMatchingPathScalar<TFormat>,
WPKMatchingPathScalar<TFormat>,
WPKMatchingPathScalar<TFormat>,
WPKMatchingPathScalar<TFormat>
];
type WPKUserFormatScalar<TFormat extends WPKInstanceFormat> = WPKDatumType & {
scalar: WPKPathScalar<TFormat>;
};
type WPKUserFormatVec2<TFormat extends WPKInstanceFormat> = WPKDatumType & {
vec2: WPKPathVec2<TFormat>;
};
type WPKUserFormatVec3<TFormat extends WPKInstanceFormat> = WPKDatumType<WPKPrimitive32> & {
vec3: WPKPathVec3<TFormat>;
};
type WPKUserFormatVec4<TFormat extends WPKInstanceFormat> = WPKDatumType & {
vec4: WPKPathVec4<TFormat>;
};
type WPKUserFormatEntityIndex<TEntityFormat extends WPKInstanceFormat> = WPKDatumType<WPKPrimitiveSignedInt> & {
entityIndexFromResizeableEntityCache: {
key: WPKMatchingPath<WPKInstanceOf<TEntityFormat>, string>;
target: WPKEntityCache<any, any, true>;
};
};
type WPKUserFormat<TFormat extends WPKInstanceFormat, TIsEntity extends boolean> = WPKUserFormatScalar<TFormat> | WPKUserFormatVec2<TFormat> | WPKUserFormatVec3<TFormat> | WPKUserFormatVec4<TFormat> | (TIsEntity extends true ? WPKUserFormatEntityIndex<TFormat> : never);
type WPKBufferType = 'uniform' | 'entity';
type WPKContentType = 'layout' | 'marshalled';
type WPKBufferTypes<TBufferType extends WPKBufferType, TContentType extends WPKContentType> = {
bufferType: TBufferType;
contentType: TContentType;
};
type WPKFormatLayout = NonEmptyArray<WPKLayout>;
type WPKFormatMarshall<TEntityFormat extends WPKInstanceFormat, TIsEntity extends boolean> = NonEmptyArray<WPKUserFormat<TEntityFormat, TIsEntity>>;
type WPKBufferDetailLayout = {
layout: WPKFormatLayout;
};
type WPKBufferDetailMarshall<TEntityFormat extends WPKInstanceFormat, TIsEntity extends boolean> = {
marshall: WPKFormatMarshall<TEntityFormat, TIsEntity>;
};
type WPKBufferFormatUniform<TUniformFormat extends WPKInstanceFormat> = WPKBufferTypes<'uniform', 'marshalled'> & WPKBufferDetailMarshall<TUniformFormat, false>;
type WPKBufferFormatEntityLayout = WPKBufferTypes<'entity', 'layout'> & WPKBufferDetailLayout;
type WPKBufferFormatEntityMarshalled<TEntityFormat extends WPKInstanceFormat> = WPKBufferTypes<'entity', 'marshalled'> & WPKBufferDetailMarshall<TEntityFormat, true>;
type WPKBufferFormatEntity<TEntityFormat extends WPKInstanceFormat> = WPKBufferFormatEntityLayout | WPKBufferFormatEntityMarshalled<TEntityFormat>;
type WPKBufferFormat<TUniformFormat extends WPKInstanceFormat, TEntityFormat extends WPKInstanceFormat> = WPKBufferFormatUniform<TUniformFormat> | WPKBufferFormatEntity<TEntityFormat>;
type WPKBufferFormatMap<TUniformFormat extends WPKInstanceFormat, TEntityFormat extends WPKInstanceFormat> = Record<string, WPKBufferFormat<TUniformFormat, TEntityFormat>>;
type WPKBufferFormatKeyEntity<TUniformFormat extends WPKInstanceFormat, TEntityFormat extends WPKInstanceFormat, TBufferFormats extends WPKBufferFormatMap<TUniformFormat, TEntityFormat>> = string & {
[K in keyof TBufferFormats]: TBufferFormats[K] extends WPKBufferFormatEntity<TEntityFormat> ? K : never;
}[keyof TBufferFormats];
type WPKBufferFormatKey<TUniformFormat extends WPKInstanceFormat, TEntityFormat extends WPKInstanceFormat, TBufferFormats extends WPKBufferFormatMap<TUniformFormat, TEntityFormat>> = string & (keyof TBufferFormats);
type WPKVertices = Vec3[];
type WPKIndices = Vec3[];
type WPKMesh = {
vertices: WPKVertices;
indices: WPKIndices;
topology: GPUPrimitiveTopology;
winding: GPUFrontFace;
};
type WPKWorkGroupSize = {
x: number;
y?: number;
z?: number;
};
type WPKHasEntryPoint = {
entryPoint: string;
};
type WPKBufferLocationType = 'mesh' | 'user-defined';
type WPKBufferLocationStep = 'vertex' | 'instance';
type WPKBufferLocationBase<TType extends WPKBufferLocationType, TStep extends WPKBufferLocationStep> = {
type: TType;
location: number;
step: TStep;
};
type WPKForeignBufferRef<TUniformFormat extends WPKInstanceFormat, TEntityFormat extends WPKInstanceFormat, TBufferFormatMap extends WPKBufferFormatMap<TUniformFormat, TEntityFormat>> = {
formats: TBufferFormatMap;
key: WPKBufferFormatKey<TUniformFormat, TEntityFormat, TBufferFormatMap>;
};
type WPKBufferLocationMesh = WPKBufferLocationBase<'mesh', 'vertex'> & {
format: 'float32x3';
};
type WPKBufferLocationUserDefined<TUniformFormat extends WPKInstanceFormat, TEntityFormat extends WPKInstanceFormat, TBufferFormatMap extends WPKBufferFormatMap<TUniformFormat, TEntityFormat>> = WPKBufferLocationBase<'user-defined', 'instance'> & {
buffer: WPKBufferFormatKeyEntity<TUniformFormat, TEntityFormat, TBufferFormatMap>;
};
type WPKBufferLocation<TUniformFormat extends WPKInstanceFormat, TEntityFormat extends WPKInstanceFormat, TBufferFormatMap extends WPKBufferFormatMap<TUniformFormat, TEntityFormat>> = WPKBufferLocationMesh | WPKBufferLocationUserDefined<TUniformFormat, TEntityFormat, TBufferFormatMap>;
type WPKRenderPass<TUniformFormat extends WPKInstanceFormat, TEntityFormat extends WPKInstanceFormat, TBufferFormatMap extends WPKBufferFormatMap<TUniformFormat, TEntityFormat>> = {
vertex: WPKHasEntryPoint & {
bufferLocations: Array<WPKBufferLocation<TUniformFormat, TEntityFormat, TBufferFormatMap>>;
};
fragment: WPKHasEntryPoint;
};
type WPKBufferBindingRef<TUniformFormat extends WPKInstanceFormat, TEntityFormat extends WPKInstanceFormat, TBufferFormatMap extends WPKBufferFormatMap<TUniformFormat, TEntityFormat>> = WPKBufferFormatKey<TUniformFormat, TEntityFormat, TBufferFormatMap> | WPKForeignBufferRef<any, any, any>;
type WPKBufferBinding<TUniformFormat extends WPKInstanceFormat, TEntityFormat extends WPKInstanceFormat, TBufferFormatMap extends WPKBufferFormatMap<TUniformFormat, TEntityFormat>> = {
group: number;
binding: number;
buffer: WPKBufferBindingRef<TUniformFormat, TEntityFormat, TBufferFormatMap>;
};
type WPKComputePass = WPKHasEntryPoint & {
workGroupSize: WPKWorkGroupSize;
};
type WPKComputeShader<TUniformFormat extends WPKInstanceFormat, TEntityFormat extends WPKInstanceFormat, TBufferFormatMap extends WPKBufferFormatMap<TUniformFormat, TEntityFormat>> = {
compute: {
shader: string;
bufferBindings: Array<WPKBufferBinding<TUniformFormat, TEntityFormat, TBufferFormatMap>>;
passes: Array<WPKComputePass>;
};
};
type WPKRenderShader<TUniformFormat extends WPKInstanceFormat, TEntityFormat extends WPKInstanceFormat, TBufferFormatMap extends WPKBufferFormatMap<TUniformFormat, TEntityFormat>> = {
render: {
shader: string;
bufferBindings: Array<WPKBufferBinding<TUniformFormat, TEntityFormat, TBufferFormatMap>>;
passes: Array<WPKRenderPass<TUniformFormat, TEntityFormat, TBufferFormatMap>>;
mesh: WPKMesh;
};
};
type WPKShader<TUniformFormat extends WPKInstanceFormat, TEntityFormat extends WPKInstanceFormat, TBufferFormatMap extends WPKBufferFormatMap<TUniformFormat, TEntityFormat>> = OneOrBoth<WPKComputeShader<TUniformFormat, TEntityFormat, TBufferFormatMap>, WPKRenderShader<TUniformFormat, TEntityFormat, TBufferFormatMap>>;
type WPKPipelineDefinition<TUniformFormat extends WPKInstanceFormat, TEntityFormat extends WPKInstanceFormat, TBufferFormatMap extends WPKBufferFormatMap<TUniformFormat, TEntityFormat>> = {
name: string;
shader: WPKShader<TUniformFormat, TEntityFormat, TBufferFormatMap>;
bufferFormats: TBufferFormatMap;
uniformCache: WPKUniformCache<TUniformFormat, any>;
entityCache: WPKEntityCache<TEntityFormat, any, any>;
};
type WPKPipelineOptions = {
clear: Color;
isAntiAliased: boolean;
};
type WPKPipelineRunner = {
invoke: (options: WPKPipelineOptions) => Promise<void>;
};
declare const factories: {
color: {
BLACK: Color;
RED: Color;
GREEN: Color;
BLUE: Color;
WHITE: Color;
of(r?: number, g?: number, b?: number, a?: number): Color;
};
cache: {
ofUniform: <TUniformFormat extends WPKInstanceFormat, TMutable extends boolean>(_uniformFormat: TUniformFormat, initialUniform: WPKInstanceOf<TUniformFormat>, mutable: TMutable) => WPKUniformCache<TUniformFormat, TMutable>;
ofEntitiesFixedSize: <TEntityFormat extends WPKInstanceFormat, TMutable extends boolean>(_entityFormat: TEntityFormat, mutable: TMutable, ...elements: WPKInstanceOf<TEntityFormat>[]) => WPKEntityCache<TEntityFormat, TMutable, false>;
ofEntitiesResizeable: <TEntityFormat extends WPKInstanceFormat, TMutable extends boolean>(_entityFormat: TEntityFormat, mutable: TMutable) => WPKEntityCache<TEntityFormat, TMutable, true>;
};
mesh: {
of: (type: GPUPrimitiveTopology, vertices: WPKVertices, indices: WPKIndices, winding: GPUFrontFace) => WPKMesh;
triangle: (topProportion: number, axis?: Vec3) => WPKMesh;
cube: () => WPKMesh;
sphere(subdivisions: number): WPKMesh;
};
pipelineRunner: {
of: (canvas: HTMLCanvasElement, definitions_0: WPKPipelineDefinition<any, any, any>, ...definitions: WPKPipelineDefinition<any, any, any>[]) => Promise<WPKPipelineRunner>;
};
shader: {
ofForeignBufferRef: <TUniformFormat extends WPKInstanceFormat, TEntityFormat extends WPKInstanceFormat, TBufferFormatMap extends WPKBufferFormatMap<TUniformFormat, TEntityFormat>>(_foreignUniformFormat: TUniformFormat, _foreignEntityFormat: TEntityFormat, foreignBufferFormats: TBufferFormatMap, key: WPKBufferFormatKey<TUniformFormat, TEntityFormat, TBufferFormatMap>) => WPKForeignBufferRef<TUniformFormat, TEntityFormat, TBufferFormatMap>;
};
};
type WPKLogNamespace = 'buffer' | 'cache' | 'data' | 'mesh' | 'pipeline';
declare const setLogLevel: (level: LogLevelDesc, namespace?: WPKLogNamespace) => void;
export { type WPKBufferFormatMap, type WPKInstanceFormat, type WPKInstanceOf, type WPKLogNamespace, type WPKPipelineDefinition, type WPKPipelineOptions, type WPKShader, factories, setLogLevel };