UNPKG

typegpu

Version:

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

82 lines (81 loc) 2.81 kB
import { isData } from "../../data/dataTypes.js"; import { snip } from "../../data/snippet.js"; import {} from "../../data/wgslTypes.js"; import { makeDereferenceable } from "../../tgsl/makeDereferenceable.js"; import { makeResolvable } from "../../tgsl/makeResolvable.js"; import { getName, setName } from "../../shared/meta.js"; import { $gpuValueOf, $internal, $soul } from "../../shared/symbols.js"; export function constant(dataType, value) { if (!isData(dataType)) { if (!Array.isArray(value)) { throw new Error(`Expected an array value for a partially-applied array schema, but received: ${typeof value}.`); } return new TgpuConstImpl(dataType(value.length), value); } return new TgpuConstImpl(dataType, value); } // -------------- // Implementation // -------------- function deepFreeze(object) { // Retrieve the property names defined on object const propNames = Reflect.ownKeys(object); // Freeze properties before freezing self for (const name of propNames) { // oxlint-disable-next-line typescript/no-explicit-any -- chill TypeScript const value = object[name]; if ((value && typeof value === 'object') || typeof value === 'function') { deepFreeze(value); } } return Object.freeze(object); } class TgpuConstImpl { [$soul]; static { TgpuConstImpl.prototype[$internal] = {}; TgpuConstImpl.prototype.resourceType = 'const'; makeDereferenceable(makeResolvable(TgpuConstImpl.prototype, { asString() { return `const:${getName(this) ?? '<unnamed>'}`; }, resolve(ctx) { const id = ctx.makeUniqueIdentifier(getName(this), 'global'); return ctx.gen.declareGlobalConst({ id, dataType: this.dataType, init: snip(this[$soul].value, this.dataType, 'constant'), }); }, }), { codegenMode: { getBaseSnippet(trackingProxy) { return snip(trackingProxy, this.dataType, 'constant-immutable-def', /* possibleSideEffects */ false); }, }, normalMode: { get() { return this[$soul].value; }, }, }); } constructor(dataType, value) { this[$soul] = { type: 'const', dataType, value: value && typeof value === 'object' ? deepFreeze(value) : value, label: undefined, }; } get dataType() { return this[$soul].dataType; } $name(label) { setName(this, label); return this; } }