UNPKG

typegpu

Version:

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

247 lines (246 loc) 7.55 kB
// We import tsover-runtime, then use Symbol.* types, because tsdown strips the imported `Operator` // type no matter what. Seems like a bug in tsdown. // oxlint-disable-next-line no-unassigned-import import 'tsover-runtime'; import { $internal, isMarkedInternal } from "../shared/symbols.js"; export const Void = { [$internal]: {}, type: 'void', toString() { return 'void'; }, }; export const wgslTypeLiterals = [ 'bool', 'f32', 'f16', 'i32', 'u32', 'u16', 'vec2f', 'vec2h', 'vec2i', 'vec2u', 'vec2<bool>', 'vec3f', 'vec3h', 'vec3i', 'vec3u', 'vec3<bool>', 'vec4f', 'vec4h', 'vec4i', 'vec4u', 'vec4<bool>', 'mat2x2f', 'mat3x3f', 'mat4x4f', 'struct', 'array', 'ptr', 'atomic', 'decorated', 'abstractInt', 'abstractFloat', 'void', 'texture_1d', 'texture_storage_1d', 'texture_2d', 'texture_storage_2d', 'texture_multisampled_2d', 'texture_depth_2d', 'texture_depth_multisampled_2d', 'texture_2d_array', 'texture_storage_2d_array', 'texture_depth_2d_array', 'texture_cube', 'texture_depth_cube', 'texture_cube_array', 'texture_depth_cube_array', 'texture_3d', 'texture_storage_3d', 'texture_external', 'sampler', 'sampler_comparison', ]; // #endregion export function isVecInstance(value) { const v = value; return isMarkedInternal(v) && typeof v.kind === 'string' && v.kind.startsWith('vec'); } export function isVecBoolInstance(value) { return isVecInstance(value) && value.kind.includes('b'); } export function isVec2(value) { const v = value; return isMarkedInternal(v) && typeof v.type === 'string' && v.type.startsWith('vec2'); } export function isVec3(value) { const v = value; return isMarkedInternal(v) && typeof v.type === 'string' && v.type.startsWith('vec3'); } export function isVec4(value) { const v = value; return isMarkedInternal(v) && typeof v.type === 'string' && v.type.startsWith('vec4'); } export function isVec(value) { return isVec2(value) || isVec3(value) || isVec4(value); } export function isVecBool(value) { return isVec(value) && value.type.includes('b'); } export function isMatInstance(value) { const v = value; return (isMarkedInternal(v) && typeof v.kind?.startsWith === 'function' && v.kind.startsWith('mat')); } export function isMat2x2f(value) { return isMarkedInternal(value) && value?.type === 'mat2x2f'; } export function isMat3x3f(value) { return isMarkedInternal(value) && value?.type === 'mat3x3f'; } export function isMat4x4f(value) { return isMarkedInternal(value) && value?.type === 'mat4x4f'; } export function isMat(value) { return isMat2x2f(value) || isMat3x3f(value) || isMat4x4f(value); } export function isInteger(value) { return (isMarkedInternal(value) && ['abstractInt', 'i32', 'u32'].includes(value?.type)); } export function isIntegerVec(value) { return isVec(value) && isInteger(value.primitive); } export function isFloat32VecInstance(element) { return isVecInstance(element) && ['vec2f', 'vec3f', 'vec4f'].includes(element.kind); } export function isInteger32VecInstance(value) { return isVecInstance(value) && /[iu]$/.test(value.kind); } export function isUint32VecInstance(value) { return isVecInstance(value) && /[u]$/.test(value.kind); } export function isWgslData(value) { return isMarkedInternal(value) && wgslTypeLiterals.includes(value?.type); } /** * Checks whether passed in value is an array schema, * as opposed to, e.g., a disarray schema. * * Array schemas can be used to describe uniform and storage buffers, * whereas disarray schemas cannot. * * @example * isWgslArray(d.arrayOf(d.u32, 4)) // true * isWgslArray(d.disarray(d.u32, 4)) // false * isWgslArray(d.vec3f) // false */ export function isWgslArray(schema) { return isMarkedInternal(schema) && schema?.type === 'array'; } /** * Checks whether passed in value is a struct schema, * as opposed to, e.g., an unstruct schema. * * Struct schemas can be used to describe uniform and storage buffers, * whereas unstruct schemas cannot. * * @example * isWgslStruct(d.struct({ a: d.u32 })) // true * isWgslStruct(d.unstruct({ a: d.u32 })) // false * isWgslStruct(d.vec3f) // false */ export function isWgslStruct(schema) { return isMarkedInternal(schema) && schema?.type === 'struct'; } /** * Checks whether passed in value is a pointer schema. * * @example * isPtr(d.ptrFn(d.f32)) // true * isPtr(d.ptrPrivate(d.f32)) // true * isPtr(d.f32) // false */ export function isPtr(schema) { return isMarkedInternal(schema) && schema?.type === 'ptr'; } /** * Checks whether the passed in value is an atomic schema. * * @example * isAtomic(d.atomic(d.u32)) // true * isAtomic(d.u32) // false */ export function isAtomic(schema) { return isMarkedInternal(schema) && schema?.type === 'atomic'; } export function isAlignAttrib(value) { return isMarkedInternal(value) && value?.type === '@align'; } export function isSizeAttrib(value) { return isMarkedInternal(value) && value?.type === '@size'; } export function isLocationAttrib(value) { return isMarkedInternal(value) && value?.type === '@location'; } export function isInterpolateAttrib(value) { return isMarkedInternal(value) && value?.type === '@interpolate'; } export function isBuiltinAttrib(value) { return isMarkedInternal(value) && value?.type === '@builtin'; } export function isInvariantAttrib(value) { return isMarkedInternal(value) && value?.type === '@invariant'; } export function isDecorated(value) { return isMarkedInternal(value) && value?.type === 'decorated'; } export function isAbstractFloat(value) { return isMarkedInternal(value) && value.type === 'abstractFloat'; } export function isAbstractInt(value) { return isMarkedInternal(value) && value.type === 'abstractInt'; } export function isAbstract(value) { return isAbstractFloat(value) || isAbstractInt(value); } export function isConcrete(value) { return !isAbstract(value); } export function isVoid(value) { return isMarkedInternal(value) && value.type === 'void'; } export function isBool(value) { return isMarkedInternal(value) && value.type === 'bool'; } export function isNumericSchema(schema) { const type = schema?.type; return (isMarkedInternal(schema) && (type === 'abstractInt' || type === 'abstractFloat' || type === 'f32' || type === 'f16' || type === 'i32' || type === 'u32')); } export function isHalfPrecisionSchema(schema) { const type = schema?.type; return (isMarkedInternal(schema) && (type === 'f16' || type === 'vec2h' || type === 'vec3h' || type === 'vec4h')); } const ephemeralTypes = ['abstractInt', 'abstractFloat', 'f32', 'f16', 'i32', 'u32', 'bool']; /** * Returns true for schemas that are not naturally referential in JS (primitives). * @param schema * @returns */ export function isNaturallyEphemeral(schema) { return !isMarkedInternal(schema) || ephemeralTypes.includes(schema?.type); } export function WORKAROUND_getSchema(vec) { // TODO: Remove workaround // it's a workaround for circular dependencies caused by us using schemas in the shader generator // these schema properties are assigned on the prototype of vector and matrix instances // oxlint-disable-next-line typescript/no-explicit-any -- explained above return vec.schema; }