typegpu
Version:
A thin layer between JS and WebGPU/WGSL that improves development experience and allows for faster iteration.
65 lines (64 loc) • 2.51 kB
JavaScript
import { isBuiltin } from "../../data/attributes.js";
import { getCustomLocation } from "../../data/dataTypes.js";
import { isData } from "../../data/dataTypes.js";
export function isAttribute(value) {
return typeof value?.format === 'string';
}
export function connectAttributesToShader(shaderInputLayout, attributes) {
const usedVertexLayouts = [];
if (isData(shaderInputLayout)) {
// Expecting a single attribute, no record.
if (!isAttribute(attributes)) {
throw new Error('Shader expected a single attribute, not a record of attributes to be passed in.');
}
usedVertexLayouts.push(attributes._layout);
return {
usedVertexLayouts,
bufferDefinitions: [
{
arrayStride: attributes._layout.stride,
stepMode: attributes._layout.stepMode,
attributes: [
{
format: attributes.format,
offset: attributes.offset,
shaderLocation: getCustomLocation(shaderInputLayout) ?? 0,
},
],
},
],
};
}
const bufferDefinitions = [];
const layoutToAttribListMap = new WeakMap();
let nextShaderLocation = 0;
for (const [key, member] of Object.entries(shaderInputLayout)) {
if (isBuiltin(member)) {
continue;
}
const matchingAttribute = attributes[key];
if (!matchingAttribute) {
throw new Error(`An attribute by the name of '${key}' was not provided to the shader.`);
}
const layout = matchingAttribute._layout;
let attribList = layoutToAttribListMap.get(layout);
if (!attribList) {
// First time seeing this layout
usedVertexLayouts.push(layout);
attribList = [];
bufferDefinitions.push({
arrayStride: layout.stride,
stepMode: layout.stepMode,
attributes: attribList,
});
layoutToAttribListMap.set(layout, attribList);
}
nextShaderLocation = getCustomLocation(member) ?? nextShaderLocation;
attribList.push({
format: matchingAttribute.format,
offset: matchingAttribute.offset,
shaderLocation: nextShaderLocation++,
});
}
return { usedVertexLayouts, bufferDefinitions };
}