typegpu
Version:
A thin layer between JS and WebGPU/WGSL that improves development experience and allows for faster iteration.
60 lines (59 loc) • 1.95 kB
JavaScript
import { validateProp } from "../nameUtils.js";
import { getName, setName } from "../shared/meta.js";
import { $internal } from "../shared/symbols.js";
import { schemaCallWrapper } from "./schemaCallWrapper.js";
// ----------
// Public API
// ----------
/**
* Creates a struct schema that can be used to construct GPU buffers.
* Ensures proper alignment and padding of properties (as opposed to a `d.unstruct` schema).
* The order of members matches the passed in properties object.
*
* @example
* const CircleStruct = d.struct({ radius: d.f32, pos: d.vec3f });
*
* @param props Record with `string` keys and `TgpuData` values,
* each entry describing one struct member.
*/
export function struct(props) {
return INTERNAL_createStruct(props, false);
}
export function abstruct(props) {
return INTERNAL_createStruct(props, true);
}
// --------------
// Implementation
// --------------
export function INTERNAL_createStruct(props, isAbstruct) {
Object.keys(props).forEach((key) => {
const result = validateProp(key);
if (!result.success) {
throw new Error(`Invalid property key '${key}'${result.error ? `: ${result.error}` : ''}`);
}
});
// In the schema call, create and return a deep copy
// by wrapping all the values in corresponding schema calls.
const structSchema = (instanceProps) => Object.fromEntries(Object.entries(props).map(([key, schema]) => [
key,
schemaCallWrapper(schema, instanceProps?.[key]),
]));
Object.setPrototypeOf(structSchema, WgslStructImpl);
structSchema.propTypes = props;
Object.defineProperty(structSchema, $internal, {
value: {
isAbstruct,
},
});
return structSchema;
}
const WgslStructImpl = {
type: 'struct',
$name(label) {
setName(this, label);
return this;
},
toString() {
return `struct:${getName(this) ?? '<unnamed>'}`;
},
};