UNPKG

typegpu

Version:

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

65 lines (64 loc) 2.61 kB
import { getName, setName } from "../../shared/meta.js"; import { $getNameForward, $internal, $resolve } from "../../shared/symbols.js"; import { shaderStageSlot } from "../slot/internalSlots.js"; import { createFnCore } from "./fnCore.js"; import { createIoSchema, separateAllAsPositional } from "./ioSchema.js"; import { stripTemplate } from "./templateUtils.js"; /** * Creates a shell of a typed entry function for the vertex shader stage. Any function * that implements this shell can run for each vertex, allowing the inner code to process * attributes and determine the final position of the vertex. * * @param options.in * Vertex attributes and builtins to be made available to functions that implement this shell. * @param options.out * A record containing the final position of the vertex, and any information * passed onto the fragment shader stage. */ export function vertexFn(options) { if (Object.keys(options.out).length === 0) { throw new Error(`A vertexFn output cannot be empty since it must include the 'position' builtin.`); } const shell = { in: options.in, out: options.out, argTypes: options.in && Object.keys(options.in).length !== 0 ? [createIoSchema(options.in)] : [], entryPoint: 'vertex', }; const call = (arg, ...values) => createVertexFn(shell, stripTemplate(arg, ...values)); return Object.assign(call, shell); } export function isTgpuVertexFn(value) { return value?.shell?.entryPoint === 'vertex'; } // -------------- // Implementation // -------------- function createVertexFn(shell, implementation) { const core = createFnCore(implementation, 'vertex'); const entryInput = separateAllAsPositional(shell.in ?? {}); const result = { shell, $uses(newExternals) { core.setExternals('userProvided', newExternals); return this; }, [$internal]: true, [$getNameForward]: core, $name(newLabel) { setName(this, newLabel); return this; }, [$resolve](ctx) { const outputWithLocation = createIoSchema(shell.out, ctx.varyingLocations).$name(`${getName(this) ?? ''}_Output`); if (typeof implementation === 'string') { core.setExternals('out', { Out: outputWithLocation }); } return ctx.withSlots([[shaderStageSlot, 'vertex']], () => core.resolve(ctx, [], outputWithLocation, entryInput)); }, toString() { return `vertexFn:${getName(core) ?? '<unnamed>'}`; }, }; return result; }