UNPKG

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