UNPKG

@luma.gl/shadertools

Version:

Shader module system for luma.gl

144 lines 5.17 kB
// 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(`@binding\\(\\s*(\\d+)\\s*\\)\\s*@group\\(\\s*(\\d+)\\s*\\)\\s*${WGSL_BINDABLE_VARIABLE_PATTERN}\\s*:\\s*([^;]+);`, 'g'), new RegExp(`@group\\(\\s*(\\d+)\\s*\\)\\s*@binding\\(\\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