@luma.gl/shadertools 9.3.0-alpha.6 → 9.3.0-alpha.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/dist.dev.js +2550 -330
- package/dist/dist.min.js +1803 -283
- package/dist/index.cjs +2495 -358
- package/dist/index.cjs.map +4 -4
- package/dist/index.d.ts +9 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/lib/preprocessor/preprocessor.d.ts.map +1 -1
- package/dist/lib/preprocessor/preprocessor.js +4 -3
- package/dist/lib/preprocessor/preprocessor.js.map +1 -1
- package/dist/lib/shader-assembler.d.ts +10 -0
- package/dist/lib/shader-assembler.d.ts.map +1 -1
- package/dist/lib/shader-assembler.js +12 -2
- package/dist/lib/shader-assembler.js.map +1 -1
- package/dist/lib/shader-assembly/assemble-shaders.d.ts +23 -2
- package/dist/lib/shader-assembly/assemble-shaders.d.ts.map +1 -1
- package/dist/lib/shader-assembly/assemble-shaders.js +211 -11
- package/dist/lib/shader-assembly/assemble-shaders.js.map +1 -1
- package/dist/lib/shader-assembly/wgsl-binding-debug.d.ts +37 -0
- package/dist/lib/shader-assembly/wgsl-binding-debug.d.ts.map +1 -0
- package/dist/lib/shader-assembly/wgsl-binding-debug.js +140 -0
- package/dist/lib/shader-assembly/wgsl-binding-debug.js.map +1 -0
- package/dist/lib/shader-generator/glsl/generate-glsl.js +3 -0
- package/dist/lib/shader-generator/glsl/generate-glsl.js.map +1 -1
- package/dist/lib/shader-generator/wgsl/generate-wgsl.d.ts.map +1 -1
- package/dist/lib/shader-generator/wgsl/generate-wgsl.js +3 -0
- package/dist/lib/shader-generator/wgsl/generate-wgsl.js.map +1 -1
- package/dist/lib/shader-module/shader-module-uniform-layout.d.ts +22 -0
- package/dist/lib/shader-module/shader-module-uniform-layout.d.ts.map +1 -0
- package/dist/lib/shader-module/shader-module-uniform-layout.js +112 -0
- package/dist/lib/shader-module/shader-module-uniform-layout.js.map +1 -0
- package/dist/lib/shader-module/shader-module.d.ts +11 -5
- package/dist/lib/shader-module/shader-module.d.ts.map +1 -1
- package/dist/lib/shader-module/shader-module.js.map +1 -1
- package/dist/lib/utils/uniform-types.d.ts +11 -7
- package/dist/lib/utils/uniform-types.d.ts.map +1 -1
- package/dist/modules/engine/picking/picking.d.ts +3 -0
- package/dist/modules/engine/picking/picking.d.ts.map +1 -1
- package/dist/modules/engine/picking/picking.js +3 -0
- package/dist/modules/engine/picking/picking.js.map +1 -1
- package/dist/modules/engine/skin/skin.d.ts +7 -6
- package/dist/modules/engine/skin/skin.d.ts.map +1 -1
- package/dist/modules/engine/skin/skin.js +3 -5
- package/dist/modules/engine/skin/skin.js.map +1 -1
- package/dist/modules/lighting/gouraud-material/gouraud-material.d.ts +1 -0
- package/dist/modules/lighting/gouraud-material/gouraud-material.d.ts.map +1 -1
- package/dist/modules/lighting/gouraud-material/gouraud-material.js +3 -0
- package/dist/modules/lighting/gouraud-material/gouraud-material.js.map +1 -1
- package/dist/modules/lighting/ibl/ibl.d.ts +26 -0
- package/dist/modules/lighting/ibl/ibl.d.ts.map +1 -0
- package/dist/modules/lighting/ibl/ibl.js +33 -0
- package/dist/modules/lighting/ibl/ibl.js.map +1 -0
- package/dist/modules/lighting/lambert-material/lambert-material.d.ts +10 -0
- package/dist/modules/lighting/lambert-material/lambert-material.d.ts.map +1 -0
- package/dist/modules/lighting/lambert-material/lambert-material.js +33 -0
- package/dist/modules/lighting/lambert-material/lambert-material.js.map +1 -0
- package/dist/modules/lighting/lambert-material/lambert-shaders-glsl.d.ts +3 -0
- package/dist/modules/lighting/lambert-material/lambert-shaders-glsl.d.ts.map +1 -0
- package/dist/modules/lighting/lambert-material/lambert-shaders-glsl.js +60 -0
- package/dist/modules/lighting/lambert-material/lambert-shaders-glsl.js.map +1 -0
- package/dist/modules/lighting/lambert-material/lambert-shaders-wgsl.d.ts +2 -0
- package/dist/modules/lighting/lambert-material/lambert-shaders-wgsl.d.ts.map +1 -0
- package/dist/modules/lighting/lambert-material/lambert-shaders-wgsl.js +73 -0
- package/dist/modules/lighting/lambert-material/lambert-shaders-wgsl.js.map +1 -0
- package/dist/modules/lighting/lights/lighting-glsl.d.ts +1 -1
- package/dist/modules/lighting/lights/lighting-glsl.d.ts.map +1 -1
- package/dist/modules/lighting/lights/lighting-glsl.js +43 -55
- package/dist/modules/lighting/lights/lighting-glsl.js.map +1 -1
- package/dist/modules/lighting/lights/lighting-wgsl.d.ts +1 -1
- package/dist/modules/lighting/lights/lighting-wgsl.d.ts.map +1 -1
- package/dist/modules/lighting/lights/lighting-wgsl.js +43 -65
- package/dist/modules/lighting/lights/lighting-wgsl.js.map +1 -1
- package/dist/modules/lighting/lights/lighting.d.ts +104 -86
- package/dist/modules/lighting/lights/lighting.d.ts.map +1 -1
- package/dist/modules/lighting/lights/lighting.js +96 -83
- package/dist/modules/lighting/lights/lighting.js.map +1 -1
- package/dist/modules/lighting/no-material/dirlight.d.ts +7 -2
- package/dist/modules/lighting/no-material/dirlight.d.ts.map +1 -1
- package/dist/modules/lighting/no-material/dirlight.js +3 -1
- package/dist/modules/lighting/no-material/dirlight.js.map +1 -1
- package/dist/modules/lighting/pbr-material/pbr-material-glsl.d.ts +1 -1
- package/dist/modules/lighting/pbr-material/pbr-material-glsl.d.ts.map +1 -1
- package/dist/modules/lighting/pbr-material/pbr-material-glsl.js +524 -28
- package/dist/modules/lighting/pbr-material/pbr-material-glsl.js.map +1 -1
- package/dist/modules/lighting/pbr-material/pbr-material-wgsl.d.ts +2 -2
- package/dist/modules/lighting/pbr-material/pbr-material-wgsl.d.ts.map +1 -1
- package/dist/modules/lighting/pbr-material/pbr-material-wgsl.js +706 -50
- package/dist/modules/lighting/pbr-material/pbr-material-wgsl.js.map +1 -1
- package/dist/modules/lighting/pbr-material/pbr-material.d.ts +110 -61
- package/dist/modules/lighting/pbr-material/pbr-material.d.ts.map +1 -1
- package/dist/modules/lighting/pbr-material/pbr-material.js +85 -9
- package/dist/modules/lighting/pbr-material/pbr-material.js.map +1 -1
- package/dist/modules/lighting/pbr-material/pbr-projection.d.ts.map +1 -1
- package/dist/modules/lighting/pbr-material/pbr-projection.js +2 -1
- package/dist/modules/lighting/pbr-material/pbr-projection.js.map +1 -1
- package/dist/modules/lighting/phong-material/phong-material.d.ts +1 -0
- package/dist/modules/lighting/phong-material/phong-material.d.ts.map +1 -1
- package/dist/modules/lighting/phong-material/phong-material.js +4 -0
- package/dist/modules/lighting/phong-material/phong-material.js.map +1 -1
- package/dist/modules/lighting/phong-material/phong-shaders-glsl.d.ts +2 -2
- package/dist/modules/lighting/phong-material/phong-shaders-glsl.d.ts.map +1 -1
- package/dist/modules/lighting/phong-material/phong-shaders-glsl.js +15 -4
- package/dist/modules/lighting/phong-material/phong-shaders-glsl.js.map +1 -1
- package/dist/modules/lighting/phong-material/phong-shaders-wgsl.d.ts +1 -1
- package/dist/modules/lighting/phong-material/phong-shaders-wgsl.d.ts.map +1 -1
- package/dist/modules/lighting/phong-material/phong-shaders-wgsl.js +36 -5
- package/dist/modules/lighting/phong-material/phong-shaders-wgsl.js.map +1 -1
- package/dist/modules/math/fp64/fp64-arithmetic-glsl.d.ts +1 -1
- package/dist/modules/math/fp64/fp64-arithmetic-glsl.d.ts.map +1 -1
- package/dist/modules/math/fp64/fp64-arithmetic-glsl.js +41 -10
- package/dist/modules/math/fp64/fp64-arithmetic-glsl.js.map +1 -1
- package/dist/modules/math/fp64/fp64-arithmetic-wgsl.d.ts +2 -0
- package/dist/modules/math/fp64/fp64-arithmetic-wgsl.d.ts.map +1 -0
- package/dist/modules/math/fp64/fp64-arithmetic-wgsl.js +212 -0
- package/dist/modules/math/fp64/fp64-arithmetic-wgsl.js.map +1 -0
- package/dist/modules/math/fp64/fp64.d.ts +1 -0
- package/dist/modules/math/fp64/fp64.d.ts.map +1 -1
- package/dist/modules/math/fp64/fp64.js +8 -2
- package/dist/modules/math/fp64/fp64.js.map +1 -1
- package/package.json +3 -3
- package/src/index.ts +19 -2
- package/src/lib/preprocessor/preprocessor.ts +6 -3
- package/src/lib/shader-assembler.ts +17 -2
- package/src/lib/shader-assembly/assemble-shaders.ts +377 -12
- package/src/lib/shader-assembly/wgsl-binding-debug.ts +216 -0
- package/src/lib/shader-generator/glsl/generate-glsl.ts +7 -1
- package/src/lib/shader-generator/wgsl/generate-wgsl.ts +6 -0
- package/src/lib/shader-module/shader-module-uniform-layout.ts +194 -0
- package/src/lib/shader-module/shader-module.ts +16 -6
- package/src/lib/utils/uniform-types.ts +24 -9
- package/src/modules/engine/picking/picking.ts +3 -0
- package/src/modules/engine/skin/skin.ts +3 -5
- package/src/modules/lighting/gouraud-material/gouraud-material.ts +4 -0
- package/src/modules/lighting/ibl/ibl.ts +44 -0
- package/src/modules/lighting/lambert-material/lambert-material.ts +42 -0
- package/src/modules/lighting/lambert-material/lambert-shaders-glsl.ts +61 -0
- package/src/modules/lighting/lambert-material/lambert-shaders-wgsl.ts +73 -0
- package/src/modules/lighting/lights/lighting-glsl.ts +43 -55
- package/src/modules/lighting/lights/lighting-wgsl.ts +43 -65
- package/src/modules/lighting/lights/lighting.ts +186 -123
- package/src/modules/lighting/no-material/dirlight.ts +3 -1
- package/src/modules/lighting/pbr-material/pbr-material-glsl.ts +524 -28
- package/src/modules/lighting/pbr-material/pbr-material-wgsl.ts +706 -50
- package/src/modules/lighting/pbr-material/pbr-material.ts +111 -18
- package/src/modules/lighting/pbr-material/pbr-projection.ts +2 -1
- package/src/modules/lighting/phong-material/phong-material.ts +5 -0
- package/src/modules/lighting/phong-material/phong-shaders-glsl.ts +15 -4
- package/src/modules/lighting/phong-material/phong-shaders-wgsl.ts +36 -5
- package/src/modules/math/fp64/fp64-arithmetic-glsl.ts +41 -10
- package/src/modules/math/fp64/fp64-arithmetic-wgsl.ts +212 -0
- package/src/modules/math/fp64/fp64.ts +9 -3
|
@@ -8,13 +8,24 @@ import {getPlatformShaderDefines} from './platform-defines';
|
|
|
8
8
|
import {injectShader, DECLARATION_INJECT_MARKER} from './shader-injections';
|
|
9
9
|
import {transpileGLSLShader} from '../shader-transpiler/transpile-glsl-shader';
|
|
10
10
|
import {checkShaderModuleDeprecations} from '../shader-module/shader-module';
|
|
11
|
+
import {validateShaderModuleUniformLayout} from '../shader-module/shader-module-uniform-layout';
|
|
11
12
|
import type {ShaderInjection} from './shader-injections';
|
|
12
13
|
import type {ShaderModule} from '../shader-module/shader-module';
|
|
13
14
|
import {ShaderHook, normalizeShaderHooks, getShaderHooks} from './shader-hooks';
|
|
14
15
|
import {assert} from '../utils/assert';
|
|
15
16
|
import {getShaderInfo} from '../glsl-utils/get-shader-info';
|
|
17
|
+
import {getShaderBindingDebugRowsFromWGSL, type ShaderBindingDebugRow} from './wgsl-binding-debug';
|
|
16
18
|
|
|
17
19
|
const INJECT_SHADER_DECLARATIONS = `\n\n${DECLARATION_INJECT_MARKER}\n`;
|
|
20
|
+
const MODULE_WGSL_BINDING_DECLARATION_REGEXES = [
|
|
21
|
+
/@binding\(\s*(auto|\d+)\s*\)\s*@group\(\s*(\d+)\s*\)\s*(var(?:<[^>]+>)?\s+([A-Za-z_][A-Za-z0-9_]*))/g,
|
|
22
|
+
/@group\(\s*(\d+)\s*\)\s*@binding\(\s*(auto|\d+)\s*\)\s*(var(?:<[^>]+>)?\s+([A-Za-z_][A-Za-z0-9_]*))/g
|
|
23
|
+
] as const;
|
|
24
|
+
const WGSL_BINDING_DECLARATION_REGEXES = [
|
|
25
|
+
/@binding\(\s*(\d+)\s*\)\s*@group\(\s*(\d+)\s*\)\s*(var(?:<[^>]+>)?\s+([A-Za-z_][A-Za-z0-9_]*))/g,
|
|
26
|
+
/@group\(\s*(\d+)\s*\)\s*@binding\(\s*(\d+)\s*\)\s*(var(?:<[^>]+>)?\s+([A-Za-z_][A-Za-z0-9_]*))/g
|
|
27
|
+
] as const;
|
|
28
|
+
const RESERVED_APPLICATION_GROUP_0_BINDING_LIMIT = 100;
|
|
18
29
|
|
|
19
30
|
/**
|
|
20
31
|
* Precision prologue to inject before functions are injected in shader
|
|
@@ -78,6 +89,8 @@ type AssembleStageOptions = {
|
|
|
78
89
|
prologue?: boolean;
|
|
79
90
|
/** logger object */
|
|
80
91
|
log?: any;
|
|
92
|
+
/** @internal Stable per-assembler WGSL binding assignments. */
|
|
93
|
+
_bindingRegistry?: Map<string, number>;
|
|
81
94
|
};
|
|
82
95
|
|
|
83
96
|
export type HookFunction = {hook: string; header: string; footer: string; signature?: string};
|
|
@@ -94,21 +107,28 @@ export function assembleWGSLShader(
|
|
|
94
107
|
options: AssembleShaderOptions & {
|
|
95
108
|
/** Single WGSL shader */
|
|
96
109
|
source: string;
|
|
110
|
+
/** @internal Stable per-assembler WGSL binding assignments. */
|
|
111
|
+
_bindingRegistry?: Map<string, number>;
|
|
97
112
|
}
|
|
98
113
|
): {
|
|
99
114
|
source: string;
|
|
100
115
|
getUniforms: GetUniformsFunc;
|
|
116
|
+
bindingAssignments: {moduleName: string; name: string; group: number; location: number}[];
|
|
117
|
+
bindingTable: ShaderBindingDebugRow[];
|
|
101
118
|
} {
|
|
102
119
|
const modules = getShaderModuleDependencies(options.modules || []);
|
|
120
|
+
const {source, bindingAssignments} = assembleShaderWGSL(options.platformInfo, {
|
|
121
|
+
...options,
|
|
122
|
+
source: options.source,
|
|
123
|
+
stage: 'vertex',
|
|
124
|
+
modules
|
|
125
|
+
});
|
|
103
126
|
|
|
104
127
|
return {
|
|
105
|
-
source
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
modules
|
|
110
|
-
}),
|
|
111
|
-
getUniforms: assembleGetUniforms(modules)
|
|
128
|
+
source,
|
|
129
|
+
getUniforms: assembleGetUniforms(modules),
|
|
130
|
+
bindingAssignments,
|
|
131
|
+
bindingTable: getShaderBindingDebugRowsFromWGSL(source, bindingAssignments)
|
|
112
132
|
};
|
|
113
133
|
}
|
|
114
134
|
|
|
@@ -155,7 +175,10 @@ export function assembleGLSLShaderPair(
|
|
|
155
175
|
* @param options
|
|
156
176
|
* @returns
|
|
157
177
|
*/
|
|
158
|
-
export function assembleShaderWGSL(
|
|
178
|
+
export function assembleShaderWGSL(
|
|
179
|
+
platformInfo: PlatformInfo,
|
|
180
|
+
options: AssembleStageOptions
|
|
181
|
+
): {source: string; bindingAssignments: WGSLBindingAssignment[]} {
|
|
159
182
|
const {
|
|
160
183
|
// id,
|
|
161
184
|
source,
|
|
@@ -226,12 +249,29 @@ export function assembleShaderWGSL(platformInfo: PlatformInfo, options: Assemble
|
|
|
226
249
|
|
|
227
250
|
// TODO - hack until shadertool modules support WebGPU
|
|
228
251
|
const modulesToInject = modules;
|
|
252
|
+
const usedBindingsByGroup = getUsedBindingsByGroupFromApplicationWGSL(coreSource);
|
|
253
|
+
const reservedBindingKeysByGroup = reserveRegisteredModuleBindings(
|
|
254
|
+
modulesToInject,
|
|
255
|
+
options._bindingRegistry,
|
|
256
|
+
usedBindingsByGroup
|
|
257
|
+
);
|
|
258
|
+
const bindingAssignments: WGSLBindingAssignment[] = [];
|
|
229
259
|
|
|
230
260
|
for (const module of modulesToInject) {
|
|
231
261
|
if (log) {
|
|
232
262
|
checkShaderModuleDeprecations(module, coreSource, log);
|
|
233
263
|
}
|
|
234
|
-
const
|
|
264
|
+
const relocation = relocateWGSLModuleBindings(
|
|
265
|
+
getShaderModuleSource(module, 'wgsl', log),
|
|
266
|
+
module,
|
|
267
|
+
{
|
|
268
|
+
usedBindingsByGroup,
|
|
269
|
+
bindingRegistry: options._bindingRegistry,
|
|
270
|
+
reservedBindingKeysByGroup
|
|
271
|
+
}
|
|
272
|
+
);
|
|
273
|
+
bindingAssignments.push(...relocation.bindingAssignments);
|
|
274
|
+
const moduleSource = relocation.source;
|
|
235
275
|
// Add the module source, and a #define that declares it presence
|
|
236
276
|
assembledSource += moduleSource;
|
|
237
277
|
|
|
@@ -256,6 +296,7 @@ export function assembleShaderWGSL(platformInfo: PlatformInfo, options: Assemble
|
|
|
256
296
|
assembledSource = injectShader(assembledSource, stage, declInjections);
|
|
257
297
|
|
|
258
298
|
assembledSource += getShaderHooks(hookFunctionMap[stage], hookInjections);
|
|
299
|
+
assembledSource += formatWGSLBindingAssignmentComments(bindingAssignments);
|
|
259
300
|
|
|
260
301
|
// Add the version directive and actual source of this shader
|
|
261
302
|
assembledSource += coreSource;
|
|
@@ -263,7 +304,9 @@ export function assembleShaderWGSL(platformInfo: PlatformInfo, options: Assemble
|
|
|
263
304
|
// Apply any requested shader injections
|
|
264
305
|
assembledSource = injectShader(assembledSource, stage, mainInjections);
|
|
265
306
|
|
|
266
|
-
|
|
307
|
+
assertNoUnresolvedAutoBindings(assembledSource);
|
|
308
|
+
|
|
309
|
+
return {source: assembledSource, bindingAssignments};
|
|
267
310
|
}
|
|
268
311
|
|
|
269
312
|
/**
|
|
@@ -379,7 +422,7 @@ ${getApplicationDefines(allDefines)}
|
|
|
379
422
|
if (log) {
|
|
380
423
|
checkShaderModuleDeprecations(module, coreSource, log);
|
|
381
424
|
}
|
|
382
|
-
const moduleSource = getShaderModuleSource(module, stage);
|
|
425
|
+
const moduleSource = getShaderModuleSource(module, stage, log);
|
|
383
426
|
// Add the module source, and a #define that declares it presence
|
|
384
427
|
assembledSource += moduleSource;
|
|
385
428
|
|
|
@@ -476,7 +519,8 @@ function getApplicationDefines(defines: Record<string, boolean> = {}): string {
|
|
|
476
519
|
/** Extracts the source code chunk for the specified shader type from the named shader module */
|
|
477
520
|
export function getShaderModuleSource(
|
|
478
521
|
module: ShaderModule,
|
|
479
|
-
stage: 'vertex' | 'fragment' | 'wgsl'
|
|
522
|
+
stage: 'vertex' | 'fragment' | 'wgsl',
|
|
523
|
+
log?: any
|
|
480
524
|
): string {
|
|
481
525
|
let moduleSource;
|
|
482
526
|
switch (stage) {
|
|
@@ -496,6 +540,9 @@ export function getShaderModuleSource(
|
|
|
496
540
|
if (!module.name) {
|
|
497
541
|
throw new Error('Shader module must have a name');
|
|
498
542
|
}
|
|
543
|
+
|
|
544
|
+
validateShaderModuleUniformLayout(module, stage, {log});
|
|
545
|
+
|
|
499
546
|
const moduleName = module.name.toUpperCase().replace(/[^0-9a-z]/gi, '_');
|
|
500
547
|
let source = `\
|
|
501
548
|
// ----- MODULE ${module.name} ---------------
|
|
@@ -508,6 +555,324 @@ export function getShaderModuleSource(
|
|
|
508
555
|
return source;
|
|
509
556
|
}
|
|
510
557
|
|
|
558
|
+
type BindingRelocationContext = {
|
|
559
|
+
usedBindingsByGroup: Map<number, Set<number>>;
|
|
560
|
+
bindingRegistry?: Map<string, number>;
|
|
561
|
+
reservedBindingKeysByGroup: Map<number, Map<number, string>>;
|
|
562
|
+
};
|
|
563
|
+
|
|
564
|
+
type WGSLBindingAssignment = {
|
|
565
|
+
moduleName: string;
|
|
566
|
+
name: string;
|
|
567
|
+
group: number;
|
|
568
|
+
location: number;
|
|
569
|
+
};
|
|
570
|
+
|
|
571
|
+
type WGSLRelocationState = {
|
|
572
|
+
sawSupportedBindingDeclaration: boolean;
|
|
573
|
+
nextHintedBindingLocation: number | null;
|
|
574
|
+
};
|
|
575
|
+
|
|
576
|
+
type WGSLRelocationParams = {
|
|
577
|
+
isBindingFirst: boolean;
|
|
578
|
+
module: ShaderModule;
|
|
579
|
+
context: BindingRelocationContext;
|
|
580
|
+
bindingAssignments: WGSLBindingAssignment[];
|
|
581
|
+
relocationState: WGSLRelocationState;
|
|
582
|
+
};
|
|
583
|
+
|
|
584
|
+
function getUsedBindingsByGroupFromApplicationWGSL(source: string): Map<number, Set<number>> {
|
|
585
|
+
const usedBindingsByGroup = new Map<number, Set<number>>();
|
|
586
|
+
|
|
587
|
+
for (const regex of WGSL_BINDING_DECLARATION_REGEXES) {
|
|
588
|
+
regex.lastIndex = 0;
|
|
589
|
+
let match: RegExpExecArray | null;
|
|
590
|
+
while ((match = regex.exec(source))) {
|
|
591
|
+
const isBindingFirst = regex === WGSL_BINDING_DECLARATION_REGEXES[0];
|
|
592
|
+
const location = Number(match[isBindingFirst ? 1 : 2]);
|
|
593
|
+
const group = Number(match[isBindingFirst ? 2 : 1]);
|
|
594
|
+
const name = match[4];
|
|
595
|
+
|
|
596
|
+
validateApplicationWGSLBinding(group, location, name);
|
|
597
|
+
registerUsedBindingLocation(
|
|
598
|
+
usedBindingsByGroup,
|
|
599
|
+
group,
|
|
600
|
+
location,
|
|
601
|
+
`application binding "${name}"`
|
|
602
|
+
);
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
return usedBindingsByGroup;
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
function relocateWGSLModuleBindings(
|
|
610
|
+
moduleSource: string,
|
|
611
|
+
module: ShaderModule,
|
|
612
|
+
context: BindingRelocationContext
|
|
613
|
+
): {source: string; bindingAssignments: WGSLBindingAssignment[]} {
|
|
614
|
+
const bindingAssignments: WGSLBindingAssignment[] = [];
|
|
615
|
+
const relocationState: WGSLRelocationState = {
|
|
616
|
+
sawSupportedBindingDeclaration: false,
|
|
617
|
+
nextHintedBindingLocation:
|
|
618
|
+
typeof module.firstBindingSlot === 'number' ? module.firstBindingSlot : null
|
|
619
|
+
};
|
|
620
|
+
|
|
621
|
+
let relocatedSource = relocateWGSLModuleBindingsWithRegex(
|
|
622
|
+
moduleSource,
|
|
623
|
+
MODULE_WGSL_BINDING_DECLARATION_REGEXES[0],
|
|
624
|
+
{isBindingFirst: true, module, context, bindingAssignments, relocationState}
|
|
625
|
+
);
|
|
626
|
+
relocatedSource = relocateWGSLModuleBindingsWithRegex(
|
|
627
|
+
relocatedSource,
|
|
628
|
+
MODULE_WGSL_BINDING_DECLARATION_REGEXES[1],
|
|
629
|
+
{isBindingFirst: false, module, context, bindingAssignments, relocationState}
|
|
630
|
+
);
|
|
631
|
+
|
|
632
|
+
if (moduleSource.includes('@binding(auto)') && !relocationState.sawSupportedBindingDeclaration) {
|
|
633
|
+
throw new Error(
|
|
634
|
+
`Unsupported @binding(auto) declaration form in module "${module.name}". ` +
|
|
635
|
+
'Use "@group(N) @binding(auto) var ..." or "@binding(auto) @group(N) var ..." on a single line.'
|
|
636
|
+
);
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
return {source: relocatedSource, bindingAssignments};
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
function relocateWGSLModuleBindingsWithRegex(
|
|
643
|
+
source: string,
|
|
644
|
+
regex: RegExp,
|
|
645
|
+
params: WGSLRelocationParams
|
|
646
|
+
): string {
|
|
647
|
+
return source.replace(regex, (...replaceArguments) =>
|
|
648
|
+
relocateWGSLModuleBindingMatch(replaceArguments, params)
|
|
649
|
+
);
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
function relocateWGSLModuleBindingMatch(
|
|
653
|
+
replaceArguments: unknown[],
|
|
654
|
+
params: WGSLRelocationParams
|
|
655
|
+
): string {
|
|
656
|
+
const {isBindingFirst, module, context, bindingAssignments, relocationState} = params;
|
|
657
|
+
relocationState.sawSupportedBindingDeclaration = true;
|
|
658
|
+
|
|
659
|
+
const match = replaceArguments[0] as string;
|
|
660
|
+
const bindingToken = replaceArguments[isBindingFirst ? 1 : 2] as string;
|
|
661
|
+
const groupToken = replaceArguments[isBindingFirst ? 2 : 1] as string;
|
|
662
|
+
const name = replaceArguments[4] as string;
|
|
663
|
+
const group = Number(groupToken);
|
|
664
|
+
|
|
665
|
+
if (bindingToken === 'auto') {
|
|
666
|
+
const registryKey = getBindingRegistryKey(group, module.name, name);
|
|
667
|
+
const registryLocation = context.bindingRegistry?.get(registryKey);
|
|
668
|
+
const location =
|
|
669
|
+
registryLocation !== undefined
|
|
670
|
+
? registryLocation
|
|
671
|
+
: relocationState.nextHintedBindingLocation === null
|
|
672
|
+
? allocateAutoBindingLocation(group, context.usedBindingsByGroup)
|
|
673
|
+
: allocateAutoBindingLocation(
|
|
674
|
+
group,
|
|
675
|
+
context.usedBindingsByGroup,
|
|
676
|
+
relocationState.nextHintedBindingLocation
|
|
677
|
+
);
|
|
678
|
+
validateModuleWGSLBinding(module.name, group, location, name);
|
|
679
|
+
if (
|
|
680
|
+
registryLocation !== undefined &&
|
|
681
|
+
claimReservedBindingLocation(context.reservedBindingKeysByGroup, group, location, registryKey)
|
|
682
|
+
) {
|
|
683
|
+
bindingAssignments.push({moduleName: module.name, name, group, location});
|
|
684
|
+
return match.replace(/@binding\(\s*auto\s*\)/, `@binding(${location})`);
|
|
685
|
+
}
|
|
686
|
+
registerUsedBindingLocation(
|
|
687
|
+
context.usedBindingsByGroup,
|
|
688
|
+
group,
|
|
689
|
+
location,
|
|
690
|
+
`module "${module.name}" binding "${name}"`
|
|
691
|
+
);
|
|
692
|
+
context.bindingRegistry?.set(registryKey, location);
|
|
693
|
+
bindingAssignments.push({moduleName: module.name, name, group, location});
|
|
694
|
+
if (relocationState.nextHintedBindingLocation !== null && registryLocation === undefined) {
|
|
695
|
+
relocationState.nextHintedBindingLocation = location + 1;
|
|
696
|
+
}
|
|
697
|
+
return match.replace(/@binding\(\s*auto\s*\)/, `@binding(${location})`);
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
const location = Number(bindingToken);
|
|
701
|
+
validateModuleWGSLBinding(module.name, group, location, name);
|
|
702
|
+
registerUsedBindingLocation(
|
|
703
|
+
context.usedBindingsByGroup,
|
|
704
|
+
group,
|
|
705
|
+
location,
|
|
706
|
+
`module "${module.name}" binding "${name}"`
|
|
707
|
+
);
|
|
708
|
+
bindingAssignments.push({moduleName: module.name, name, group, location});
|
|
709
|
+
return match;
|
|
710
|
+
}
|
|
711
|
+
|
|
712
|
+
function reserveRegisteredModuleBindings(
|
|
713
|
+
modules: ShaderModule[],
|
|
714
|
+
bindingRegistry: Map<string, number> | undefined,
|
|
715
|
+
usedBindingsByGroup: Map<number, Set<number>>
|
|
716
|
+
): Map<number, Map<number, string>> {
|
|
717
|
+
const reservedBindingKeysByGroup = new Map<number, Map<number, string>>();
|
|
718
|
+
if (!bindingRegistry) {
|
|
719
|
+
return reservedBindingKeysByGroup;
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
for (const module of modules) {
|
|
723
|
+
for (const binding of getModuleWGSLBindingDeclarations(module)) {
|
|
724
|
+
const registryKey = getBindingRegistryKey(binding.group, module.name, binding.name);
|
|
725
|
+
const location = bindingRegistry.get(registryKey);
|
|
726
|
+
if (location !== undefined) {
|
|
727
|
+
const reservedBindingKeys =
|
|
728
|
+
reservedBindingKeysByGroup.get(binding.group) || new Map<number, string>();
|
|
729
|
+
const existingReservation = reservedBindingKeys.get(location);
|
|
730
|
+
if (existingReservation && existingReservation !== registryKey) {
|
|
731
|
+
throw new Error(
|
|
732
|
+
`Duplicate WGSL binding reservation for modules "${existingReservation}" and "${registryKey}": group ${binding.group}, binding ${location}.`
|
|
733
|
+
);
|
|
734
|
+
}
|
|
735
|
+
|
|
736
|
+
registerUsedBindingLocation(
|
|
737
|
+
usedBindingsByGroup,
|
|
738
|
+
binding.group,
|
|
739
|
+
location,
|
|
740
|
+
`registered module binding "${registryKey}"`
|
|
741
|
+
);
|
|
742
|
+
reservedBindingKeys.set(location, registryKey);
|
|
743
|
+
reservedBindingKeysByGroup.set(binding.group, reservedBindingKeys);
|
|
744
|
+
}
|
|
745
|
+
}
|
|
746
|
+
}
|
|
747
|
+
|
|
748
|
+
return reservedBindingKeysByGroup;
|
|
749
|
+
}
|
|
750
|
+
|
|
751
|
+
function claimReservedBindingLocation(
|
|
752
|
+
reservedBindingKeysByGroup: Map<number, Map<number, string>>,
|
|
753
|
+
group: number,
|
|
754
|
+
location: number,
|
|
755
|
+
registryKey: string
|
|
756
|
+
): boolean {
|
|
757
|
+
const reservedBindingKeys = reservedBindingKeysByGroup.get(group);
|
|
758
|
+
if (!reservedBindingKeys) {
|
|
759
|
+
return false;
|
|
760
|
+
}
|
|
761
|
+
|
|
762
|
+
const reservedKey = reservedBindingKeys.get(location);
|
|
763
|
+
if (!reservedKey) {
|
|
764
|
+
return false;
|
|
765
|
+
}
|
|
766
|
+
if (reservedKey !== registryKey) {
|
|
767
|
+
throw new Error(
|
|
768
|
+
`Registered module binding "${registryKey}" collided with "${reservedKey}": group ${group}, binding ${location}.`
|
|
769
|
+
);
|
|
770
|
+
}
|
|
771
|
+
return true;
|
|
772
|
+
}
|
|
773
|
+
|
|
774
|
+
function getModuleWGSLBindingDeclarations(module: ShaderModule): {name: string; group: number}[] {
|
|
775
|
+
const declarations: {name: string; group: number}[] = [];
|
|
776
|
+
const moduleSource = module.source || '';
|
|
777
|
+
|
|
778
|
+
for (const regex of MODULE_WGSL_BINDING_DECLARATION_REGEXES) {
|
|
779
|
+
regex.lastIndex = 0;
|
|
780
|
+
let match: RegExpExecArray | null;
|
|
781
|
+
while ((match = regex.exec(moduleSource))) {
|
|
782
|
+
const isBindingFirst = regex === MODULE_WGSL_BINDING_DECLARATION_REGEXES[0];
|
|
783
|
+
declarations.push({
|
|
784
|
+
name: match[4],
|
|
785
|
+
group: Number(match[isBindingFirst ? 2 : 1])
|
|
786
|
+
});
|
|
787
|
+
}
|
|
788
|
+
}
|
|
789
|
+
|
|
790
|
+
return declarations;
|
|
791
|
+
}
|
|
792
|
+
|
|
793
|
+
function validateApplicationWGSLBinding(group: number, location: number, name: string): void {
|
|
794
|
+
if (group === 0 && location >= RESERVED_APPLICATION_GROUP_0_BINDING_LIMIT) {
|
|
795
|
+
throw new Error(
|
|
796
|
+
`Application binding "${name}" in group 0 uses reserved binding ${location}. ` +
|
|
797
|
+
`Application-owned explicit group-0 bindings must stay below ${RESERVED_APPLICATION_GROUP_0_BINDING_LIMIT}.`
|
|
798
|
+
);
|
|
799
|
+
}
|
|
800
|
+
}
|
|
801
|
+
|
|
802
|
+
function validateModuleWGSLBinding(
|
|
803
|
+
moduleName: string,
|
|
804
|
+
group: number,
|
|
805
|
+
location: number,
|
|
806
|
+
name: string
|
|
807
|
+
): void {
|
|
808
|
+
if (group === 0 && location < RESERVED_APPLICATION_GROUP_0_BINDING_LIMIT) {
|
|
809
|
+
throw new Error(
|
|
810
|
+
`Module "${moduleName}" binding "${name}" in group 0 uses reserved application binding ${location}. ` +
|
|
811
|
+
`Module-owned explicit group-0 bindings must be ${RESERVED_APPLICATION_GROUP_0_BINDING_LIMIT} or higher.`
|
|
812
|
+
);
|
|
813
|
+
}
|
|
814
|
+
}
|
|
815
|
+
|
|
816
|
+
function registerUsedBindingLocation(
|
|
817
|
+
usedBindingsByGroup: Map<number, Set<number>>,
|
|
818
|
+
group: number,
|
|
819
|
+
location: number,
|
|
820
|
+
label: string
|
|
821
|
+
): void {
|
|
822
|
+
const usedBindings = usedBindingsByGroup.get(group) || new Set<number>();
|
|
823
|
+
if (usedBindings.has(location)) {
|
|
824
|
+
throw new Error(
|
|
825
|
+
`Duplicate WGSL binding assignment for ${label}: group ${group}, binding ${location}.`
|
|
826
|
+
);
|
|
827
|
+
}
|
|
828
|
+
usedBindings.add(location);
|
|
829
|
+
usedBindingsByGroup.set(group, usedBindings);
|
|
830
|
+
}
|
|
831
|
+
|
|
832
|
+
function allocateAutoBindingLocation(
|
|
833
|
+
group: number,
|
|
834
|
+
usedBindingsByGroup: Map<number, Set<number>>,
|
|
835
|
+
preferredBindingLocation?: number
|
|
836
|
+
): number {
|
|
837
|
+
const usedBindings = usedBindingsByGroup.get(group) || new Set<number>();
|
|
838
|
+
let nextBinding =
|
|
839
|
+
preferredBindingLocation ??
|
|
840
|
+
(group === 0
|
|
841
|
+
? RESERVED_APPLICATION_GROUP_0_BINDING_LIMIT
|
|
842
|
+
: usedBindings.size > 0
|
|
843
|
+
? Math.max(...usedBindings) + 1
|
|
844
|
+
: 0);
|
|
845
|
+
|
|
846
|
+
while (usedBindings.has(nextBinding)) {
|
|
847
|
+
nextBinding++;
|
|
848
|
+
}
|
|
849
|
+
|
|
850
|
+
return nextBinding;
|
|
851
|
+
}
|
|
852
|
+
|
|
853
|
+
function assertNoUnresolvedAutoBindings(source: string): void {
|
|
854
|
+
if (/@binding\(\s*auto\s*\)/.test(source)) {
|
|
855
|
+
throw new Error('Unresolved @binding(auto) remained in assembled WGSL source.');
|
|
856
|
+
}
|
|
857
|
+
}
|
|
858
|
+
|
|
859
|
+
function formatWGSLBindingAssignmentComments(bindingAssignments: WGSLBindingAssignment[]): string {
|
|
860
|
+
if (bindingAssignments.length === 0) {
|
|
861
|
+
return '';
|
|
862
|
+
}
|
|
863
|
+
|
|
864
|
+
let source = '// ----- MODULE WGSL BINDING ASSIGNMENTS ---------------\n';
|
|
865
|
+
for (const bindingAssignment of bindingAssignments) {
|
|
866
|
+
source += `// ${bindingAssignment.moduleName}.${bindingAssignment.name} -> @group(${bindingAssignment.group}) @binding(${bindingAssignment.location})\n`;
|
|
867
|
+
}
|
|
868
|
+
source += '\n';
|
|
869
|
+
return source;
|
|
870
|
+
}
|
|
871
|
+
|
|
872
|
+
function getBindingRegistryKey(group: number, moduleName: string, bindingName: string): string {
|
|
873
|
+
return `${group}:${moduleName}:${bindingName}`;
|
|
874
|
+
}
|
|
875
|
+
|
|
511
876
|
/*
|
|
512
877
|
function getHookFunctions(
|
|
513
878
|
hookFunctions: Record<string, HookFunction>,
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
// luma.gl
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
// Copyright (c) vis.gl contributors
|
|
4
|
+
|
|
5
|
+
type ShaderBindingAssignment = {
|
|
6
|
+
moduleName: string;
|
|
7
|
+
name: string;
|
|
8
|
+
group: number;
|
|
9
|
+
location: number;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
const WGSL_BINDING_DEBUG_REGEXES = [
|
|
13
|
+
/@binding\(\s*(\d+)\s*\)\s*@group\(\s*(\d+)\s*\)\s*var(?:<([^>]+)>)?\s+([A-Za-z_][A-Za-z0-9_]*)\s*:\s*([^;]+);/g,
|
|
14
|
+
/@group\(\s*(\d+)\s*\)\s*@binding\(\s*(\d+)\s*\)\s*var(?:<([^>]+)>)?\s+([A-Za-z_][A-Za-z0-9_]*)\s*:\s*([^;]+);/g
|
|
15
|
+
] as const;
|
|
16
|
+
|
|
17
|
+
/** One debug row describing a WGSL binding in the assembled shader source. */
|
|
18
|
+
export type ShaderBindingDebugRow = {
|
|
19
|
+
/** Binding name as declared in WGSL. */
|
|
20
|
+
name: string;
|
|
21
|
+
/** Bind-group index. */
|
|
22
|
+
group: number;
|
|
23
|
+
/** Binding slot within the bind group. */
|
|
24
|
+
binding: number;
|
|
25
|
+
/** Resource kind inferred from the WGSL declaration. */
|
|
26
|
+
kind:
|
|
27
|
+
| 'uniform'
|
|
28
|
+
| 'storage'
|
|
29
|
+
| 'read-only-storage'
|
|
30
|
+
| 'texture'
|
|
31
|
+
| 'sampler'
|
|
32
|
+
| 'storage-texture'
|
|
33
|
+
| 'unknown';
|
|
34
|
+
/** Whether the binding came from application WGSL or a shader module. */
|
|
35
|
+
owner: 'application' | 'module';
|
|
36
|
+
/** Shader module name when the binding was contributed by a module. */
|
|
37
|
+
moduleName?: string;
|
|
38
|
+
/** Full WGSL resource type text from the declaration. */
|
|
39
|
+
resourceType?: string;
|
|
40
|
+
/** WGSL access mode when cheaply available. */
|
|
41
|
+
access?: string;
|
|
42
|
+
/** Texture view dimension when cheaply available. */
|
|
43
|
+
viewDimension?: string;
|
|
44
|
+
/** Texture sample type when cheaply available. */
|
|
45
|
+
sampleType?: string;
|
|
46
|
+
/** Sampler kind when cheaply available. */
|
|
47
|
+
samplerKind?: string;
|
|
48
|
+
/** Whether the texture is multisampled when cheaply available. */
|
|
49
|
+
multisampled?: boolean;
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
/** Builds a stable, table-friendly binding summary from assembled WGSL source. */
|
|
53
|
+
export function getShaderBindingDebugRowsFromWGSL(
|
|
54
|
+
source: string,
|
|
55
|
+
bindingAssignments: ShaderBindingAssignment[] = []
|
|
56
|
+
): ShaderBindingDebugRow[] {
|
|
57
|
+
const assignmentMap = new Map<string, string>();
|
|
58
|
+
for (const bindingAssignment of bindingAssignments) {
|
|
59
|
+
assignmentMap.set(
|
|
60
|
+
getBindingAssignmentKey(
|
|
61
|
+
bindingAssignment.name,
|
|
62
|
+
bindingAssignment.group,
|
|
63
|
+
bindingAssignment.location
|
|
64
|
+
),
|
|
65
|
+
bindingAssignment.moduleName
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const rows: ShaderBindingDebugRow[] = [];
|
|
70
|
+
for (const regex of WGSL_BINDING_DEBUG_REGEXES) {
|
|
71
|
+
regex.lastIndex = 0;
|
|
72
|
+
let match: RegExpExecArray | null;
|
|
73
|
+
while ((match = regex.exec(source))) {
|
|
74
|
+
const isBindingFirst = regex === WGSL_BINDING_DEBUG_REGEXES[0];
|
|
75
|
+
const binding = Number(match[isBindingFirst ? 1 : 2]);
|
|
76
|
+
const group = Number(match[isBindingFirst ? 2 : 1]);
|
|
77
|
+
const accessDeclaration = match[3]?.trim();
|
|
78
|
+
const name = match[4];
|
|
79
|
+
const resourceType = match[5].trim();
|
|
80
|
+
const moduleName = assignmentMap.get(getBindingAssignmentKey(name, group, binding));
|
|
81
|
+
|
|
82
|
+
rows.push(
|
|
83
|
+
normalizeShaderBindingDebugRow({
|
|
84
|
+
name,
|
|
85
|
+
group,
|
|
86
|
+
binding,
|
|
87
|
+
owner: moduleName ? 'module' : 'application',
|
|
88
|
+
moduleName,
|
|
89
|
+
accessDeclaration,
|
|
90
|
+
resourceType
|
|
91
|
+
})
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
return rows.sort((left, right) => {
|
|
97
|
+
if (left.group !== right.group) {
|
|
98
|
+
return left.group - right.group;
|
|
99
|
+
}
|
|
100
|
+
if (left.binding !== right.binding) {
|
|
101
|
+
return left.binding - right.binding;
|
|
102
|
+
}
|
|
103
|
+
return left.name.localeCompare(right.name);
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function normalizeShaderBindingDebugRow(row: {
|
|
108
|
+
name: string;
|
|
109
|
+
group: number;
|
|
110
|
+
binding: number;
|
|
111
|
+
owner: 'application' | 'module';
|
|
112
|
+
moduleName?: string;
|
|
113
|
+
accessDeclaration?: string;
|
|
114
|
+
resourceType: string;
|
|
115
|
+
}): ShaderBindingDebugRow {
|
|
116
|
+
const baseRow: ShaderBindingDebugRow = {
|
|
117
|
+
name: row.name,
|
|
118
|
+
group: row.group,
|
|
119
|
+
binding: row.binding,
|
|
120
|
+
owner: row.owner,
|
|
121
|
+
kind: 'unknown',
|
|
122
|
+
moduleName: row.moduleName,
|
|
123
|
+
resourceType: row.resourceType
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
if (row.accessDeclaration) {
|
|
127
|
+
const access = row.accessDeclaration.split(',').map(value => value.trim());
|
|
128
|
+
if (access[0] === 'uniform') {
|
|
129
|
+
return {...baseRow, kind: 'uniform', access: 'uniform'};
|
|
130
|
+
}
|
|
131
|
+
if (access[0] === 'storage') {
|
|
132
|
+
const storageAccess = access[1] || 'read_write';
|
|
133
|
+
return {
|
|
134
|
+
...baseRow,
|
|
135
|
+
kind: storageAccess === 'read' ? 'read-only-storage' : 'storage',
|
|
136
|
+
access: storageAccess
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
if (row.resourceType === 'sampler' || row.resourceType === 'sampler_comparison') {
|
|
142
|
+
return {
|
|
143
|
+
...baseRow,
|
|
144
|
+
kind: 'sampler',
|
|
145
|
+
samplerKind: row.resourceType === 'sampler_comparison' ? 'comparison' : 'filtering'
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
if (row.resourceType.startsWith('texture_storage_')) {
|
|
150
|
+
return {
|
|
151
|
+
...baseRow,
|
|
152
|
+
kind: 'storage-texture',
|
|
153
|
+
access: getStorageTextureAccess(row.resourceType),
|
|
154
|
+
viewDimension: getTextureViewDimension(row.resourceType)
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
if (row.resourceType.startsWith('texture_')) {
|
|
159
|
+
return {
|
|
160
|
+
...baseRow,
|
|
161
|
+
kind: 'texture',
|
|
162
|
+
viewDimension: getTextureViewDimension(row.resourceType),
|
|
163
|
+
sampleType: getTextureSampleType(row.resourceType),
|
|
164
|
+
multisampled: row.resourceType.startsWith('texture_multisampled_')
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
return baseRow;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
function getBindingAssignmentKey(name: string, group: number, binding: number): string {
|
|
172
|
+
return `${group}:${binding}:${name}`;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
function getTextureViewDimension(resourceType: string): string | undefined {
|
|
176
|
+
if (resourceType.includes('cube_array')) {
|
|
177
|
+
return 'cube-array';
|
|
178
|
+
}
|
|
179
|
+
if (resourceType.includes('2d_array')) {
|
|
180
|
+
return '2d-array';
|
|
181
|
+
}
|
|
182
|
+
if (resourceType.includes('cube')) {
|
|
183
|
+
return 'cube';
|
|
184
|
+
}
|
|
185
|
+
if (resourceType.includes('3d')) {
|
|
186
|
+
return '3d';
|
|
187
|
+
}
|
|
188
|
+
if (resourceType.includes('2d')) {
|
|
189
|
+
return '2d';
|
|
190
|
+
}
|
|
191
|
+
if (resourceType.includes('1d')) {
|
|
192
|
+
return '1d';
|
|
193
|
+
}
|
|
194
|
+
return undefined;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
function getTextureSampleType(resourceType: string): string | undefined {
|
|
198
|
+
if (resourceType.startsWith('texture_depth_')) {
|
|
199
|
+
return 'depth';
|
|
200
|
+
}
|
|
201
|
+
if (resourceType.includes('<i32>')) {
|
|
202
|
+
return 'sint';
|
|
203
|
+
}
|
|
204
|
+
if (resourceType.includes('<u32>')) {
|
|
205
|
+
return 'uint';
|
|
206
|
+
}
|
|
207
|
+
if (resourceType.includes('<f32>')) {
|
|
208
|
+
return 'float';
|
|
209
|
+
}
|
|
210
|
+
return undefined;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
function getStorageTextureAccess(resourceType: string): string | undefined {
|
|
214
|
+
const match = /,\s*([A-Za-z_][A-Za-z0-9_]*)\s*>$/.exec(resourceType);
|
|
215
|
+
return match?.[1];
|
|
216
|
+
}
|