typegpu
Version:
A thin layer between JS and WebGPU/WGSL that improves development experience and allows for faster iteration.
75 lines (74 loc) • 2.36 kB
JavaScript
import { getResolutionCtx } from "../../execMode.js";
import { makeDereferenceable } from "../../tgsl/makeDereferenceable.js";
import { makeResolvable } from "../../tgsl/makeResolvable.js";
import { $gpuValueOf, $internal, $providing } from "../../shared/symbols.js";
import { getGpuValueRecursively } from "../valueProxyUtils.js";
import { isAccessor, isMutableAccessor, } from "./slotTypes.js";
// ----------
// Public API
// ----------
export function lazy(compute) {
if (getResolutionCtx()) {
throw new Error('Cannot create tgpu.lazy objects during shader resolution.');
}
return new TgpuLazyImpl(compute, undefined);
}
// --------------
// Implementation
// --------------
class TgpuLazyImpl {
[$internal];
[$providing];
static {
TgpuLazyImpl.prototype.resourceType = 'lazy';
makeDereferenceable(makeResolvable(TgpuLazyImpl.prototype, {
asString: () => 'lazy',
resolve(_ctx) {
throw new Error(`Unreachable, is never resolved directly`);
},
}), {
codegenMode: {
get() {
return this.#getValue();
},
},
normalMode: {
get() {
return this.#getValue();
},
},
});
}
constructor(compute, providing) {
this[$internal] = {
compute,
};
this[$providing] = providing;
}
get [$gpuValueOf]() {
const ctx = getResolutionCtx();
if (!ctx) {
throw new Error(`Cannot access tgpu.lazy's value outside of resolution.`);
}
return getGpuValueRecursively(ctx.unwrap(this));
}
get $() {
return this[$gpuValueOf];
}
#getValue() {
const ctx = getResolutionCtx();
if (!ctx) {
throw new Error(`Cannot access tgpu.lazy's value outside of resolution.`);
}
return getGpuValueRecursively(ctx.unwrap(this));
}
with(slot, value) {
return new TgpuLazyImpl(this[$internal].compute.bind(this), {
inner: this[$providing]?.inner ?? this,
pairs: [
...(this[$providing]?.pairs ?? []),
[isAccessor(slot) || isMutableAccessor(slot) ? slot.slot : slot, value],
],
});
}
}