UNPKG

typegpu

Version:

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

89 lines (88 loc) 2.99 kB
import { undecorate } from "./dataTypes.js"; import { DEV } from "../shared/env.js"; import { isNumericSchema } from "./wgslTypes.js"; /** * What happens to a snippet's origin when it's deep copied in JS, and left as is in WGSL? * e.g. `vec3f(vec3f(0, 1, 2))` */ export function fallthroughCopyOrigin(origin) { if (origin === 'runtime' || // runtime values stay runtime origin === 'constant' // constant values stay constant ) { // The origin is kept as-is return origin; } // All other origins become runtime return 'runtime'; } /** * Whether a snippet aliases a value that lives outside the current expression. * * @example * ```ts * function foo(a: number) { * const color = d.vec3f(1, 2, 3); * return color * a; * } * * // References: * // - color * // - a * // * // Not references: * // - d.vec3f(1, 2, 3) * // - color * a * ``` */ export function isAlias(snippet) { return !(snippet.origin === 'runtime' || snippet.origin === 'constant'); } export const originToPtrParams = { uniform: { space: 'uniform', access: 'read' }, readonly: { space: 'storage', access: 'read' }, mutable: { space: 'storage', access: 'read-write' }, workgroup: { space: 'workgroup', access: 'read-write' }, private: { space: 'private', access: 'read-write' }, function: { space: 'function', access: 'read-write' }, // Local declarations are also in the `function` address space 'local-def': { space: 'function', access: 'read-write' }, }; class SnippetImpl { value; dataType; origin; possibleSideEffects; constructor(value, dataType, origin, possibleSideEffects) { this.value = value; this.dataType = dataType; this.origin = origin; this.possibleSideEffects = possibleSideEffects; } } export function isSnippet(value) { return value instanceof SnippetImpl; } export function isSnippetNumeric(snippet) { return isNumericSchema(snippet.dataType); } export function snip(value, dataType, origin, possibleSideEffects = true) { if (DEV && isSnippet(value)) { // An early error, but not worth checking every time in production throw new Error('Cannot nest snippets'); } return new SnippetImpl(value, // We don't care about attributes in snippet land, so we discard that information. undecorate(dataType), origin, possibleSideEffects); } export function withDataType(dataType, snippet) { return new SnippetImpl(snippet.value, dataType, snippet.origin, snippet.possibleSideEffects); } export function withValue(value, snippet) { return new SnippetImpl(value, snippet.dataType, snippet.origin, snippet.possibleSideEffects); } export function withSideEffects(possibleSideEffects, snippet) { return new SnippetImpl(snippet.value, snippet.dataType, snippet.origin, possibleSideEffects); } export function noSideEffects(snippet) { return withSideEffects(/* possibleSideEffects */ false, snippet); }