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
JavaScript
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;
}
}