@luma.gl/shadertools
Version:
Shader module system for luma.gl
144 lines • 5.17 kB
JavaScript
// luma.gl
// SPDX-License-Identifier: MIT
// Copyright (c) vis.gl contributors
import { WGSL_BINDABLE_VARIABLE_PATTERN, maskWGSLComments } from "./wgsl-binding-scan.js";
const WGSL_BINDING_DEBUG_REGEXES = [
new RegExp(`\\(\\s*(\\d+)\\s*\\)\\s*\\(\\s*(\\d+)\\s*\\)\\s*${WGSL_BINDABLE_VARIABLE_PATTERN}\\s*:\\s*([^;]+);`, 'g'),
new RegExp(`\\(\\s*(\\d+)\\s*\\)\\s*\\(\\s*(\\d+)\\s*\\)\\s*${WGSL_BINDABLE_VARIABLE_PATTERN}\\s*:\\s*([^;]+);`, 'g')
];
/** Builds a stable, table-friendly binding summary from assembled WGSL source. */
export function getShaderBindingDebugRowsFromWGSL(source, bindingAssignments = []) {
const maskedSource = maskWGSLComments(source);
const assignmentMap = new Map();
for (const bindingAssignment of bindingAssignments) {
assignmentMap.set(getBindingAssignmentKey(bindingAssignment.name, bindingAssignment.group, bindingAssignment.location), bindingAssignment.moduleName);
}
const rows = [];
for (const regex of WGSL_BINDING_DEBUG_REGEXES) {
regex.lastIndex = 0;
let match;
match = regex.exec(maskedSource);
while (match) {
const isBindingFirst = regex === WGSL_BINDING_DEBUG_REGEXES[0];
const binding = Number(match[isBindingFirst ? 1 : 2]);
const group = Number(match[isBindingFirst ? 2 : 1]);
const accessDeclaration = match[3]?.trim();
const name = match[4];
const resourceType = match[5].trim();
const moduleName = assignmentMap.get(getBindingAssignmentKey(name, group, binding));
rows.push(normalizeShaderBindingDebugRow({
name,
group,
binding,
owner: moduleName ? 'module' : 'application',
moduleName,
accessDeclaration,
resourceType
}));
match = regex.exec(maskedSource);
}
}
return rows.sort((left, right) => {
if (left.group !== right.group) {
return left.group - right.group;
}
if (left.binding !== right.binding) {
return left.binding - right.binding;
}
return left.name.localeCompare(right.name);
});
}
function normalizeShaderBindingDebugRow(row) {
const baseRow = {
name: row.name,
group: row.group,
binding: row.binding,
owner: row.owner,
kind: 'unknown',
moduleName: row.moduleName,
resourceType: row.resourceType
};
if (row.accessDeclaration) {
const access = row.accessDeclaration.split(',').map(value => value.trim());
if (access[0] === 'uniform') {
return { ...baseRow, kind: 'uniform', access: 'uniform' };
}
if (access[0] === 'storage') {
const storageAccess = access[1] || 'read_write';
return {
...baseRow,
kind: storageAccess === 'read' ? 'read-only-storage' : 'storage',
access: storageAccess
};
}
}
if (row.resourceType === 'sampler' || row.resourceType === 'sampler_comparison') {
return {
...baseRow,
kind: 'sampler',
samplerKind: row.resourceType === 'sampler_comparison' ? 'comparison' : 'filtering'
};
}
if (row.resourceType.startsWith('texture_storage_')) {
return {
...baseRow,
kind: 'storage-texture',
access: getStorageTextureAccess(row.resourceType),
viewDimension: getTextureViewDimension(row.resourceType)
};
}
if (row.resourceType.startsWith('texture_')) {
return {
...baseRow,
kind: 'texture',
viewDimension: getTextureViewDimension(row.resourceType),
sampleType: getTextureSampleType(row.resourceType),
multisampled: row.resourceType.startsWith('texture_multisampled_')
};
}
return baseRow;
}
function getBindingAssignmentKey(name, group, binding) {
return `${group}:${binding}:${name}`;
}
function getTextureViewDimension(resourceType) {
if (resourceType.includes('cube_array')) {
return 'cube-array';
}
if (resourceType.includes('2d_array')) {
return '2d-array';
}
if (resourceType.includes('cube')) {
return 'cube';
}
if (resourceType.includes('3d')) {
return '3d';
}
if (resourceType.includes('2d')) {
return '2d';
}
if (resourceType.includes('1d')) {
return '1d';
}
return undefined;
}
function getTextureSampleType(resourceType) {
if (resourceType.startsWith('texture_depth_')) {
return 'depth';
}
if (resourceType.includes('<i32>')) {
return 'sint';
}
if (resourceType.includes('<u32>')) {
return 'uint';
}
if (resourceType.includes('<f32>')) {
return 'float';
}
return undefined;
}
function getStorageTextureAccess(resourceType) {
const match = /,\s*([A-Za-z_][A-Za-z0-9_]*)\s*>$/.exec(resourceType);
return match?.[1];
}
//# sourceMappingURL=wgsl-binding-debug.js.map