import type { Scene } from "./Scene"; export type GraphBuffer = { id: string; array: string; usage?: string[]; sync?: "frame" | "loadout"; }; export type GraphTexture = { id: string; format?: string; size?: [number | "canvas", number | "canvas", number?]; usage?: string[]; mipLevelCount?: number; transient?: boolean; }; export type GraphSampler = { id: string; magFilter?: "nearest" | "linear"; minFilter?: "nearest" | "linear"; mipmapFilter?: "nearest" | "linear"; addressModeU?: "clamp-to-edge" | "repeat" | "mirror-repeat"; addressModeV?: "clamp-to-edge" | "repeat" | "mirror-repeat"; anisotropyClamp?: number; }; export type GraphBinding = { group: number; binding: number; resource: string; }; export type ComputePassOptions = { id?: string; code: string; entry?: string; dispatch?: [number, number?, number?]; after?: string[]; bindings?: GraphBinding[]; buffers?: GraphBuffer[]; textures?: GraphTexture[]; samplers?: GraphSampler[]; }; let nextComputePass = 1; /** A graph-authored compute pass; attaching or updating it rebuilds the Scene loadout. */ export class ComputePass { readonly id: string; code: string; entry: string; dispatch: [number, number, number]; after: string[]; bindings: GraphBinding[]; buffers: GraphBuffer[]; textures: GraphTexture[]; samplers: GraphSampler[]; #scene?: Scene; constructor(options: ComputePassOptions) { if (!options?.code) throw new TypeError("ComputePass code is required"); this.id = options.id ?? `compute-${nextComputePass++}`; this.code = options.code; this.entry = options.entry ?? "main"; this.dispatch = [ options.dispatch?.[0] ?? 1, options.dispatch?.[1] ?? 1, options.dispatch?.[2] ?? 1, ]; this.after = [...(options.after ?? [])]; this.bindings = [...(options.bindings ?? [])]; this.buffers = [...(options.buffers ?? [])]; this.textures = [...(options.textures ?? [])]; this.samplers = [...(options.samplers ?? [])]; } update(options: Partial>) { if (options.code !== undefined) this.code = options.code; if (options.entry !== undefined) this.entry = options.entry; if (options.dispatch !== undefined) this.dispatch = [ options.dispatch[0], options.dispatch[1] ?? 1, options.dispatch[2] ?? 1, ]; if (options.after !== undefined) this.after = [...options.after]; if (options.bindings !== undefined) this.bindings = [...options.bindings]; if (options.buffers !== undefined) this.buffers = [...options.buffers]; if (options.textures !== undefined) this.textures = [...options.textures]; if (options.samplers !== undefined) this.samplers = [...options.samplers]; return this.#scene?.updateRenderGraph() ?? Promise.resolve(); } attach(scene?: Scene) { this.#scene = scene; } }