@luma.gl/shadertools 9.3.6 → 9.4.0-alpha.1
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 +6555 -2373
- package/dist/dist.min.js +2984 -237
- package/dist/index.cjs +4356 -268
- package/dist/index.cjs.map +4 -4
- package/dist/index.d.ts +13 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -1
- package/dist/index.js.map +1 -1
- package/dist/lib/preprocessor/preprocessor.d.ts +11 -1
- package/dist/lib/preprocessor/preprocessor.d.ts.map +1 -1
- package/dist/lib/preprocessor/preprocessor.js +47 -2
- package/dist/lib/preprocessor/preprocessor.js.map +1 -1
- package/dist/lib/shader-assembler.d.ts +10 -10
- package/dist/lib/shader-assembler.d.ts.map +1 -1
- package/dist/lib/shader-assembler.js +36 -20
- package/dist/lib/shader-assembler.js.map +1 -1
- package/dist/lib/shader-assembly/assemble-shaders.d.ts +28 -7
- package/dist/lib/shader-assembly/assemble-shaders.d.ts.map +1 -1
- package/dist/lib/shader-assembly/assemble-shaders.js +133 -15
- package/dist/lib/shader-assembly/assemble-shaders.js.map +1 -1
- package/dist/lib/shader-assembly/platform-info.d.ts +2 -0
- package/dist/lib/shader-assembly/platform-info.d.ts.map +1 -1
- package/dist/lib/shader-assembly/shader-hooks.d.ts +1 -1
- package/dist/lib/shader-assembly/shader-hooks.d.ts.map +1 -1
- package/dist/lib/shader-assembly/shader-hooks.js +6 -3
- package/dist/lib/shader-assembly/shader-hooks.js.map +1 -1
- package/dist/lib/shader-assembly/shader-injections.d.ts +4 -1
- package/dist/lib/shader-assembly/shader-injections.d.ts.map +1 -1
- package/dist/lib/shader-assembly/shader-injections.js +68 -11
- package/dist/lib/shader-assembly/shader-injections.js.map +1 -1
- package/dist/lib/shader-assembly/shader-plugin-varyings.d.ts +15 -0
- package/dist/lib/shader-assembly/shader-plugin-varyings.d.ts.map +1 -0
- package/dist/lib/shader-assembly/shader-plugin-varyings.js +412 -0
- package/dist/lib/shader-assembly/shader-plugin-varyings.js.map +1 -0
- package/dist/lib/shader-assembly/shader-plugin-vertex-inputs.d.ts +12 -0
- package/dist/lib/shader-assembly/shader-plugin-vertex-inputs.d.ts.map +1 -0
- package/dist/lib/shader-assembly/shader-plugin-vertex-inputs.js +237 -0
- package/dist/lib/shader-assembly/shader-plugin-vertex-inputs.js.map +1 -0
- package/dist/lib/shader-module/shader-module.d.ts +3 -0
- 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/shader-module/shader-pass-pipeline.d.ts +14 -0
- package/dist/lib/shader-module/shader-pass-pipeline.d.ts.map +1 -0
- package/dist/lib/shader-module/shader-pass-pipeline.js +5 -0
- package/dist/lib/shader-module/shader-pass-pipeline.js.map +1 -0
- package/dist/lib/shader-module/shader-pass.d.ts +21 -4
- package/dist/lib/shader-module/shader-pass.d.ts.map +1 -1
- package/dist/lib/shader-plugin.d.ts +68 -0
- package/dist/lib/shader-plugin.d.ts.map +1 -0
- package/dist/lib/shader-plugin.js +98 -0
- package/dist/lib/shader-plugin.js.map +1 -0
- package/dist/lib/utils/assert.js +1 -1
- package/dist/lib/utils/assert.js.map +1 -1
- package/dist/modules/color/float-colors.d.ts +111 -5
- package/dist/modules/color/float-colors.d.ts.map +1 -1
- package/dist/modules/color/float-colors.js +200 -34
- package/dist/modules/color/float-colors.js.map +1 -1
- package/dist/modules/engine/clip/clip.d.ts +12 -0
- package/dist/modules/engine/clip/clip.d.ts.map +1 -0
- package/dist/modules/engine/clip/clip.js +129 -0
- package/dist/modules/engine/clip/clip.js.map +1 -0
- package/dist/modules/engine/filter/filter.d.ts +12 -0
- package/dist/modules/engine/filter/filter.d.ts.map +1 -0
- package/dist/modules/engine/filter/filter.js +88 -0
- package/dist/modules/engine/filter/filter.js.map +1 -0
- package/dist/modules/geospatial/dggs/dggs-wgsl.d.ts +3 -0
- package/dist/modules/geospatial/dggs/dggs-wgsl.d.ts.map +1 -0
- package/dist/modules/geospatial/dggs/dggs-wgsl.js +1892 -0
- package/dist/modules/geospatial/dggs/dggs-wgsl.js.map +1 -0
- package/dist/modules/geospatial/dggs/dggs.d.ts +6 -0
- package/dist/modules/geospatial/dggs/dggs.d.ts.map +1 -0
- package/dist/modules/geospatial/dggs/dggs.js +10 -0
- package/dist/modules/geospatial/dggs/dggs.js.map +1 -0
- package/dist/modules/lighting/water-material/water-material.d.ts +28 -0
- package/dist/modules/lighting/water-material/water-material.d.ts.map +1 -0
- package/dist/modules/lighting/water-material/water-material.js +179 -0
- package/dist/modules/lighting/water-material/water-material.js.map +1 -0
- package/dist/modules/lighting/water-material/water-shaders-glsl.d.ts +3 -0
- package/dist/modules/lighting/water-material/water-shaders-glsl.d.ts.map +1 -0
- package/dist/modules/lighting/water-material/water-shaders-glsl.js +232 -0
- package/dist/modules/lighting/water-material/water-shaders-glsl.js.map +1 -0
- package/dist/modules/lighting/water-material/water-shaders-wgsl.d.ts +2 -0
- package/dist/modules/lighting/water-material/water-shaders-wgsl.d.ts.map +1 -0
- package/dist/modules/lighting/water-material/water-shaders-wgsl.js +230 -0
- package/dist/modules/lighting/water-material/water-shaders-wgsl.js.map +1 -0
- package/dist/modules/math/fp64/fp64-arithmetic-wgsl.d.ts +2 -1
- package/dist/modules/math/fp64/fp64-arithmetic-wgsl.d.ts.map +1 -1
- package/dist/modules/math/fp64/fp64-arithmetic-wgsl.js +268 -0
- package/dist/modules/math/fp64/fp64-arithmetic-wgsl.js.map +1 -1
- package/package.json +2 -2
- package/src/index.ts +50 -3
- package/src/lib/preprocessor/preprocessor.ts +68 -3
- package/src/lib/shader-assembler.ts +49 -20
- package/src/lib/shader-assembly/assemble-shaders.ts +242 -30
- package/src/lib/shader-assembly/platform-info.ts +2 -0
- package/src/lib/shader-assembly/shader-hooks.ts +7 -3
- package/src/lib/shader-assembly/shader-injections.ts +96 -11
- package/src/lib/shader-assembly/shader-plugin-varyings.ts +524 -0
- package/src/lib/shader-assembly/shader-plugin-vertex-inputs.ts +279 -0
- package/src/lib/shader-module/shader-module.ts +3 -0
- package/src/lib/shader-module/shader-pass-pipeline.ts +19 -0
- package/src/lib/shader-module/shader-pass.ts +29 -4
- package/src/lib/shader-plugin.ts +214 -0
- package/src/lib/utils/assert.ts +1 -1
- package/src/modules/color/float-colors.ts +272 -37
- package/src/modules/engine/clip/clip.ts +149 -0
- package/src/modules/engine/filter/filter.ts +107 -0
- package/src/modules/geospatial/dggs/dggs-wgsl.ts +1892 -0
- package/src/modules/geospatial/dggs/dggs.ts +12 -0
- package/src/modules/lighting/water-material/water-material.ts +234 -0
- package/src/modules/lighting/water-material/water-shaders-glsl.ts +233 -0
- package/src/modules/lighting/water-material/water-shaders-wgsl.ts +230 -0
- package/src/modules/math/fp64/fp64-arithmetic-wgsl.ts +268 -0
|
@@ -18,6 +18,17 @@ import {ShaderHook, normalizeShaderHooks, getShaderHooks} from './shader-hooks';
|
|
|
18
18
|
import {assert} from '../utils/assert';
|
|
19
19
|
import {getShaderInfo} from '../glsl-utils/get-shader-info';
|
|
20
20
|
import {getShaderBindingDebugRowsFromWGSL, type ShaderBindingDebugRow} from './wgsl-binding-debug';
|
|
21
|
+
import {preprocess} from '../preprocessor/preprocessor';
|
|
22
|
+
import type {AttributeShaderType} from '@luma.gl/core';
|
|
23
|
+
import type {ResolvedShaderPluginVarying} from '../shader-plugin';
|
|
24
|
+
import {
|
|
25
|
+
assembleShaderPluginVertexInputsWGSL,
|
|
26
|
+
getShaderPluginVertexInputDeclarationsGLSL
|
|
27
|
+
} from './shader-plugin-vertex-inputs';
|
|
28
|
+
import {
|
|
29
|
+
assembleShaderPluginVaryingsGLSL,
|
|
30
|
+
assembleShaderPluginVaryingsWGSL
|
|
31
|
+
} from './shader-plugin-varyings';
|
|
21
32
|
import {
|
|
22
33
|
MODULE_WGSL_BINDING_DECLARATION_REGEXES,
|
|
23
34
|
WGSL_BINDING_DECLARATION_REGEXES,
|
|
@@ -40,9 +51,7 @@ const FRAGMENT_SHADER_PROLOGUE = /* glsl */ `\
|
|
|
40
51
|
precision highp float;
|
|
41
52
|
`;
|
|
42
53
|
|
|
43
|
-
/**
|
|
44
|
-
* Options for `ShaderAssembler.assembleShaders()`
|
|
45
|
-
*/
|
|
54
|
+
/** Props accepted by `ShaderAssembler` assembly methods. */
|
|
46
55
|
export type AssembleShaderProps = AssembleShaderOptions & {
|
|
47
56
|
platformInfo: PlatformInfo;
|
|
48
57
|
/** WGSL: single shader source. */
|
|
@@ -53,6 +62,7 @@ export type AssembleShaderProps = AssembleShaderOptions & {
|
|
|
53
62
|
fs?: string | null;
|
|
54
63
|
};
|
|
55
64
|
|
|
65
|
+
/** Shared shader assembly options. */
|
|
56
66
|
export type AssembleShaderOptions = {
|
|
57
67
|
/** information about the platform (which shader language & version, extensions etc.) */
|
|
58
68
|
platformInfo: PlatformInfo;
|
|
@@ -60,14 +70,24 @@ export type AssembleShaderOptions = {
|
|
|
60
70
|
id?: string;
|
|
61
71
|
/** Modules to be injected */
|
|
62
72
|
modules?: ShaderModule[];
|
|
63
|
-
/**
|
|
64
|
-
defines?: Record<string, boolean>;
|
|
73
|
+
/** Boolean or numeric preprocessor defines evaluated before shader assembly. */
|
|
74
|
+
defines?: Record<string, boolean | number>;
|
|
65
75
|
/** GLSL only: Overrides to be injected. In WGSL these are supplied during Pipeline creation time */
|
|
66
76
|
constants?: Record<string, number>;
|
|
67
77
|
/** Hook functions */
|
|
68
78
|
hookFunctions?: (ShaderHook | string)[];
|
|
69
79
|
/** Code injections */
|
|
70
80
|
inject?: Record<string, string | ShaderInjection>;
|
|
81
|
+
/** Ordered code injections contributed by ShaderPlugin descriptors. */
|
|
82
|
+
pluginInjections?: Record<string, ShaderInjection[]>;
|
|
83
|
+
/** Vertex inputs contributed by ShaderPlugin descriptors. */
|
|
84
|
+
pluginVertexInputs?: Record<string, AttributeShaderType>;
|
|
85
|
+
/** Cross-stage varyings contributed by ShaderPlugin descriptors. */
|
|
86
|
+
pluginVaryings?: Record<string, ResolvedShaderPluginVarying>;
|
|
87
|
+
/** WGSL vertex entry point selected by the render pipeline. */
|
|
88
|
+
vertexEntryPoint?: string;
|
|
89
|
+
/** WGSL fragment entry point selected by the render pipeline. */
|
|
90
|
+
fragmentEntryPoint?: string;
|
|
71
91
|
/** Whether to inject prologue */
|
|
72
92
|
prologue?: boolean;
|
|
73
93
|
/** logger object */
|
|
@@ -82,14 +102,24 @@ type AssembleStageOptions = {
|
|
|
82
102
|
stage: 'vertex' | 'fragment';
|
|
83
103
|
/** Modules to be injected */
|
|
84
104
|
modules: any[];
|
|
85
|
-
/**
|
|
86
|
-
defines?: Record<string, boolean>;
|
|
105
|
+
/** Boolean or numeric preprocessor defines evaluated before shader assembly. */
|
|
106
|
+
defines?: Record<string, boolean | number>;
|
|
87
107
|
/** GLSL only: Overrides to be injected. In WGSL these are supplied during Pipeline creation time */
|
|
88
108
|
constants?: Record<string, number>;
|
|
89
109
|
/** Hook functions */
|
|
90
110
|
hookFunctions?: (ShaderHook | string)[];
|
|
91
111
|
/** Code injections */
|
|
92
112
|
inject?: Record<string, string | ShaderInjection>;
|
|
113
|
+
/** Ordered code injections contributed by ShaderPlugin descriptors. */
|
|
114
|
+
pluginInjections?: Record<string, ShaderInjection[]>;
|
|
115
|
+
/** Vertex inputs contributed by ShaderPlugin descriptors. */
|
|
116
|
+
pluginVertexInputs?: Record<string, AttributeShaderType>;
|
|
117
|
+
/** Cross-stage varyings contributed by ShaderPlugin descriptors. */
|
|
118
|
+
pluginVaryings?: Record<string, ResolvedShaderPluginVarying>;
|
|
119
|
+
/** WGSL vertex entry point selected by the render pipeline. */
|
|
120
|
+
vertexEntryPoint?: string;
|
|
121
|
+
/** WGSL fragment entry point selected by the render pipeline. */
|
|
122
|
+
fragmentEntryPoint?: string;
|
|
93
123
|
/** Whether to inject prologue */
|
|
94
124
|
prologue?: boolean;
|
|
95
125
|
/** logger object */
|
|
@@ -190,8 +220,14 @@ export function assembleShaderWGSL(
|
|
|
190
220
|
stage,
|
|
191
221
|
modules,
|
|
192
222
|
// defines = {},
|
|
223
|
+
defines = {},
|
|
193
224
|
hookFunctions = [],
|
|
194
225
|
inject = {},
|
|
226
|
+
pluginInjections = {},
|
|
227
|
+
pluginVertexInputs = {},
|
|
228
|
+
pluginVaryings = {},
|
|
229
|
+
vertexEntryPoint = 'vertexMain',
|
|
230
|
+
fragmentEntryPoint = 'fragmentMain',
|
|
195
231
|
log
|
|
196
232
|
} = options;
|
|
197
233
|
|
|
@@ -200,7 +236,19 @@ export function assembleShaderWGSL(
|
|
|
200
236
|
// const isVertex = type === 'vs';
|
|
201
237
|
// const sourceLines = source.split('\n');
|
|
202
238
|
|
|
203
|
-
const
|
|
239
|
+
const preprocessedSource = preprocess(source, {defines});
|
|
240
|
+
const pluginVertexInputAssembly = assembleShaderPluginVertexInputsWGSL(
|
|
241
|
+
preprocessedSource,
|
|
242
|
+
vertexEntryPoint,
|
|
243
|
+
pluginVertexInputs
|
|
244
|
+
);
|
|
245
|
+
const pluginVaryingAssembly = assembleShaderPluginVaryingsWGSL(
|
|
246
|
+
pluginVertexInputAssembly.source,
|
|
247
|
+
vertexEntryPoint,
|
|
248
|
+
fragmentEntryPoint,
|
|
249
|
+
pluginVaryings
|
|
250
|
+
);
|
|
251
|
+
const coreSource = pluginVaryingAssembly.source;
|
|
204
252
|
|
|
205
253
|
// Combine Module and Application Defines
|
|
206
254
|
// const allDefines = {};
|
|
@@ -230,6 +278,8 @@ export function assembleShaderWGSL(
|
|
|
230
278
|
const declInjections: Record<string, ShaderInjection[]> = {};
|
|
231
279
|
const mainInjections: Record<string, ShaderInjection[]> = {};
|
|
232
280
|
|
|
281
|
+
appendInjections(pluginInjections, hookInjections, declInjections, mainInjections);
|
|
282
|
+
|
|
233
283
|
for (const key in inject) {
|
|
234
284
|
const injection =
|
|
235
285
|
typeof inject[key] === 'string' ? {injection: inject[key], order: 0} : inject[key];
|
|
@@ -251,6 +301,13 @@ export function assembleShaderWGSL(
|
|
|
251
301
|
mainInjections[key] = [injection as any];
|
|
252
302
|
}
|
|
253
303
|
}
|
|
304
|
+
appendGeneratedVertexInputInjections(
|
|
305
|
+
pluginVertexInputAssembly.declarations,
|
|
306
|
+
pluginVertexInputAssembly.initialization,
|
|
307
|
+
declInjections,
|
|
308
|
+
mainInjections
|
|
309
|
+
);
|
|
310
|
+
appendGeneratedVaryingInjections(pluginVaryingAssembly, declInjections, mainInjections);
|
|
254
311
|
|
|
255
312
|
// TODO - hack until shadertool modules support WebGPU
|
|
256
313
|
const modulesToInject = modules;
|
|
@@ -261,7 +318,8 @@ export function assembleShaderWGSL(
|
|
|
261
318
|
const reservedBindingKeysByGroup = reserveRegisteredModuleBindings(
|
|
262
319
|
modulesToInject,
|
|
263
320
|
options._bindingRegistry,
|
|
264
|
-
usedBindingsByGroup
|
|
321
|
+
usedBindingsByGroup,
|
|
322
|
+
defines
|
|
265
323
|
);
|
|
266
324
|
const bindingAssignments: WGSLBindingAssignment[] = [];
|
|
267
325
|
|
|
@@ -269,21 +327,20 @@ export function assembleShaderWGSL(
|
|
|
269
327
|
if (log) {
|
|
270
328
|
checkShaderModuleDeprecations(module, coreSource, log);
|
|
271
329
|
}
|
|
272
|
-
const
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
);
|
|
330
|
+
const preprocessedModuleSource = preprocess(getShaderModuleSource(module, 'wgsl', log), {
|
|
331
|
+
defines
|
|
332
|
+
});
|
|
333
|
+
const relocation = relocateWGSLModuleBindings(preprocessedModuleSource, module, {
|
|
334
|
+
usedBindingsByGroup,
|
|
335
|
+
bindingRegistry: options._bindingRegistry,
|
|
336
|
+
reservedBindingKeysByGroup
|
|
337
|
+
});
|
|
281
338
|
bindingAssignments.push(...relocation.bindingAssignments);
|
|
282
|
-
const
|
|
339
|
+
const relocatedModuleSource = relocation.source;
|
|
283
340
|
// Add the module source, and a #define that declares it presence
|
|
284
|
-
assembledSource +=
|
|
341
|
+
assembledSource += relocatedModuleSource;
|
|
285
342
|
|
|
286
|
-
const injections = module
|
|
343
|
+
const injections = getWGSLModuleInjections(module);
|
|
287
344
|
for (const key in injections) {
|
|
288
345
|
const match = /^(v|f)s:#([\w-]+)$/.exec(key);
|
|
289
346
|
if (match) {
|
|
@@ -301,16 +358,26 @@ export function assembleShaderWGSL(
|
|
|
301
358
|
// For injectShader
|
|
302
359
|
assembledSource += INJECT_SHADER_DECLARATIONS;
|
|
303
360
|
|
|
304
|
-
assembledSource = injectShader(
|
|
361
|
+
assembledSource = injectShader(
|
|
362
|
+
assembledSource,
|
|
363
|
+
stage,
|
|
364
|
+
getWGSLDeclarationInjections(declInjections),
|
|
365
|
+
false,
|
|
366
|
+
'wgsl',
|
|
367
|
+
{vertex: vertexEntryPoint, fragment: fragmentEntryPoint}
|
|
368
|
+
);
|
|
305
369
|
|
|
306
|
-
assembledSource +=
|
|
370
|
+
assembledSource += getWGSLShaderHooks(hookFunctionMap, hookInjections);
|
|
307
371
|
assembledSource += formatWGSLBindingAssignmentComments(bindingAssignments);
|
|
308
372
|
|
|
309
373
|
// Add the version directive and actual source of this shader
|
|
310
374
|
assembledSource += applicationRelocation.source;
|
|
311
375
|
|
|
312
376
|
// Apply any requested shader injections
|
|
313
|
-
assembledSource = injectShader(assembledSource, stage, mainInjections
|
|
377
|
+
assembledSource = injectShader(assembledSource, stage, mainInjections, false, 'wgsl', {
|
|
378
|
+
vertex: vertexEntryPoint,
|
|
379
|
+
fragment: fragmentEntryPoint
|
|
380
|
+
});
|
|
314
381
|
|
|
315
382
|
assertNoUnresolvedAutoBindings(assembledSource);
|
|
316
383
|
|
|
@@ -332,9 +399,12 @@ function assembleShaderGLSL(
|
|
|
332
399
|
language?: 'glsl' | 'wgsl';
|
|
333
400
|
stage: 'vertex' | 'fragment';
|
|
334
401
|
modules: ShaderModule[];
|
|
335
|
-
defines?: Record<string, boolean>;
|
|
402
|
+
defines?: Record<string, boolean | number>;
|
|
336
403
|
hookFunctions?: any[];
|
|
337
404
|
inject?: Record<string, string | ShaderInjection>;
|
|
405
|
+
pluginInjections?: Record<string, ShaderInjection[]>;
|
|
406
|
+
pluginVertexInputs?: Record<string, AttributeShaderType>;
|
|
407
|
+
pluginVaryings?: Record<string, ResolvedShaderPluginVarying>;
|
|
338
408
|
prologue?: boolean;
|
|
339
409
|
log?: any;
|
|
340
410
|
}
|
|
@@ -347,6 +417,9 @@ function assembleShaderGLSL(
|
|
|
347
417
|
defines = {},
|
|
348
418
|
hookFunctions = [],
|
|
349
419
|
inject = {},
|
|
420
|
+
pluginInjections = {},
|
|
421
|
+
pluginVertexInputs = {},
|
|
422
|
+
pluginVaryings = {},
|
|
350
423
|
prologue = true,
|
|
351
424
|
log
|
|
352
425
|
} = options;
|
|
@@ -404,6 +477,8 @@ ${getApplicationDefines(allDefines)}
|
|
|
404
477
|
const declInjections: Record<string, ShaderInjection[]> = {};
|
|
405
478
|
const mainInjections: Record<string, ShaderInjection[]> = {};
|
|
406
479
|
|
|
480
|
+
appendInjections(pluginInjections, hookInjections, declInjections, mainInjections);
|
|
481
|
+
|
|
407
482
|
for (const key in inject) {
|
|
408
483
|
const injection: ShaderInjection =
|
|
409
484
|
typeof inject[key] === 'string' ? {injection: inject[key], order: 0} : inject[key];
|
|
@@ -425,6 +500,32 @@ ${getApplicationDefines(allDefines)}
|
|
|
425
500
|
mainInjections[key] = [injection];
|
|
426
501
|
}
|
|
427
502
|
}
|
|
503
|
+
if (stage === 'vertex') {
|
|
504
|
+
const declarations = getShaderPluginVertexInputDeclarationsGLSL(coreSource, pluginVertexInputs);
|
|
505
|
+
if (declarations) {
|
|
506
|
+
declInjections['vs:#decl'] = declInjections['vs:#decl'] || [];
|
|
507
|
+
declInjections['vs:#decl'].push({
|
|
508
|
+
injection: declarations,
|
|
509
|
+
order: Number.MIN_SAFE_INTEGER
|
|
510
|
+
});
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
const pluginVaryingAssembly = assembleShaderPluginVaryingsGLSL(coreSource, stage, pluginVaryings);
|
|
514
|
+
if (pluginVaryingAssembly.declarations) {
|
|
515
|
+
const declarationTarget = stage === 'vertex' ? 'vs:#decl' : 'fs:#decl';
|
|
516
|
+
declInjections[declarationTarget] = declInjections[declarationTarget] || [];
|
|
517
|
+
declInjections[declarationTarget].push({
|
|
518
|
+
injection: pluginVaryingAssembly.declarations,
|
|
519
|
+
order: Number.MIN_SAFE_INTEGER
|
|
520
|
+
});
|
|
521
|
+
}
|
|
522
|
+
if (pluginVaryingAssembly.initialization) {
|
|
523
|
+
mainInjections['vs:#main-start'] = mainInjections['vs:#main-start'] || [];
|
|
524
|
+
mainInjections['vs:#main-start'].push({
|
|
525
|
+
injection: pluginVaryingAssembly.initialization,
|
|
526
|
+
order: Number.MIN_SAFE_INTEGER
|
|
527
|
+
});
|
|
528
|
+
}
|
|
428
529
|
|
|
429
530
|
for (const module of modules) {
|
|
430
531
|
if (log) {
|
|
@@ -496,6 +597,113 @@ export function assembleGetUniforms(modules: ShaderModule[]) {
|
|
|
496
597
|
};
|
|
497
598
|
}
|
|
498
599
|
|
|
600
|
+
function appendInjections(
|
|
601
|
+
injections: Record<string, ShaderInjection[]>,
|
|
602
|
+
hookInjections: Record<string, ShaderInjection[]>,
|
|
603
|
+
declInjections: Record<string, ShaderInjection[]>,
|
|
604
|
+
mainInjections: Record<string, ShaderInjection[]>
|
|
605
|
+
): void {
|
|
606
|
+
for (const key in injections) {
|
|
607
|
+
const match = /^(v|f)s:(#)?([\w-]+)$/.exec(key);
|
|
608
|
+
if (match) {
|
|
609
|
+
const hash = match[2];
|
|
610
|
+
const name = match[3];
|
|
611
|
+
const injectionType = hash
|
|
612
|
+
? name === 'decl'
|
|
613
|
+
? declInjections
|
|
614
|
+
: mainInjections
|
|
615
|
+
: hookInjections;
|
|
616
|
+
injectionType[key] = injectionType[key] || [];
|
|
617
|
+
injectionType[key].push(...injections[key]);
|
|
618
|
+
} else {
|
|
619
|
+
mainInjections[key] = mainInjections[key] || [];
|
|
620
|
+
mainInjections[key].push(...injections[key]);
|
|
621
|
+
}
|
|
622
|
+
}
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
function appendGeneratedVertexInputInjections(
|
|
626
|
+
declarations: string,
|
|
627
|
+
initialization: string,
|
|
628
|
+
declarationInjections: Record<string, ShaderInjection[]>,
|
|
629
|
+
mainInjections: Record<string, ShaderInjection[]>
|
|
630
|
+
): void {
|
|
631
|
+
if (declarations) {
|
|
632
|
+
declarationInjections['vs:#decl'] = declarationInjections['vs:#decl'] || [];
|
|
633
|
+
declarationInjections['vs:#decl'].push({
|
|
634
|
+
injection: declarations,
|
|
635
|
+
order: Number.MIN_SAFE_INTEGER
|
|
636
|
+
});
|
|
637
|
+
}
|
|
638
|
+
if (initialization) {
|
|
639
|
+
mainInjections['vs:#main-start'] = mainInjections['vs:#main-start'] || [];
|
|
640
|
+
mainInjections['vs:#main-start'].push({
|
|
641
|
+
injection: initialization,
|
|
642
|
+
order: Number.MIN_SAFE_INTEGER
|
|
643
|
+
});
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
function appendGeneratedVaryingInjections(
|
|
648
|
+
assembly: {
|
|
649
|
+
declarations: string;
|
|
650
|
+
vertexInitialization: string;
|
|
651
|
+
fragmentInitialization: string;
|
|
652
|
+
},
|
|
653
|
+
declarationInjections: Record<string, ShaderInjection[]>,
|
|
654
|
+
mainInjections: Record<string, ShaderInjection[]>
|
|
655
|
+
): void {
|
|
656
|
+
if (assembly.declarations) {
|
|
657
|
+
declarationInjections['vs:#decl'] = declarationInjections['vs:#decl'] || [];
|
|
658
|
+
declarationInjections['vs:#decl'].push({
|
|
659
|
+
injection: assembly.declarations,
|
|
660
|
+
order: Number.MIN_SAFE_INTEGER
|
|
661
|
+
});
|
|
662
|
+
}
|
|
663
|
+
if (assembly.vertexInitialization) {
|
|
664
|
+
mainInjections['vs:#main-start'] = mainInjections['vs:#main-start'] || [];
|
|
665
|
+
mainInjections['vs:#main-start'].push({
|
|
666
|
+
injection: assembly.vertexInitialization,
|
|
667
|
+
order: Number.MIN_SAFE_INTEGER
|
|
668
|
+
});
|
|
669
|
+
}
|
|
670
|
+
if (assembly.fragmentInitialization) {
|
|
671
|
+
mainInjections['fs:#main-start'] = mainInjections['fs:#main-start'] || [];
|
|
672
|
+
mainInjections['fs:#main-start'].push({
|
|
673
|
+
injection: assembly.fragmentInitialization,
|
|
674
|
+
order: Number.MIN_SAFE_INTEGER
|
|
675
|
+
});
|
|
676
|
+
}
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
function getWGSLModuleInjections(module: ShaderModule): Record<string, ShaderInjection> {
|
|
680
|
+
return {
|
|
681
|
+
...(module.instance?.normalizedInjections.vertex || {}),
|
|
682
|
+
...(module.instance?.normalizedInjections.fragment || {})
|
|
683
|
+
};
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
function getWGSLDeclarationInjections(
|
|
687
|
+
declarationInjections: Record<string, ShaderInjection[]>
|
|
688
|
+
): Record<string, ShaderInjection[]> {
|
|
689
|
+
const unifiedDeclarations = [
|
|
690
|
+
...(declarationInjections['vs:#decl'] || []),
|
|
691
|
+
...(declarationInjections['fs:#decl'] || [])
|
|
692
|
+
];
|
|
693
|
+
|
|
694
|
+
return unifiedDeclarations.length ? {'vs:#decl': unifiedDeclarations} : {};
|
|
695
|
+
}
|
|
696
|
+
|
|
697
|
+
function getWGSLShaderHooks(
|
|
698
|
+
hookFunctionMap: ReturnType<typeof normalizeShaderHooks>,
|
|
699
|
+
hookInjections: Record<string, ShaderInjection[]>
|
|
700
|
+
): string {
|
|
701
|
+
return (
|
|
702
|
+
getShaderHooks(hookFunctionMap.vertex, hookInjections, 'wgsl') +
|
|
703
|
+
getShaderHooks(hookFunctionMap.fragment, hookInjections, 'wgsl')
|
|
704
|
+
);
|
|
705
|
+
}
|
|
706
|
+
|
|
499
707
|
/**
|
|
500
708
|
* NOTE: Removed as id injection defeated caching of shaders
|
|
501
709
|
*
|
|
@@ -517,7 +725,7 @@ export function assembleGetUniforms(modules: ShaderModule[]) {
|
|
|
517
725
|
*/
|
|
518
726
|
|
|
519
727
|
/** Generates application defines from an object of key value pairs */
|
|
520
|
-
function getApplicationDefines(defines: Record<string, boolean> = {}): string {
|
|
728
|
+
function getApplicationDefines(defines: Record<string, boolean | number> = {}): string {
|
|
521
729
|
let sourceText = '';
|
|
522
730
|
for (const define in defines) {
|
|
523
731
|
const value = defines[define];
|
|
@@ -784,7 +992,8 @@ function relocateWGSLApplicationBindingMatch(
|
|
|
784
992
|
function reserveRegisteredModuleBindings(
|
|
785
993
|
modules: ShaderModule[],
|
|
786
994
|
bindingRegistry: Map<string, number> | undefined,
|
|
787
|
-
usedBindingsByGroup: Map<number, Set<number
|
|
995
|
+
usedBindingsByGroup: Map<number, Set<number>>,
|
|
996
|
+
defines: Record<string, boolean | number>
|
|
788
997
|
): Map<number, Map<number, string>> {
|
|
789
998
|
const reservedBindingKeysByGroup = new Map<number, Map<number, string>>();
|
|
790
999
|
if (!bindingRegistry) {
|
|
@@ -792,7 +1001,7 @@ function reserveRegisteredModuleBindings(
|
|
|
792
1001
|
}
|
|
793
1002
|
|
|
794
1003
|
for (const module of modules) {
|
|
795
|
-
for (const binding of getModuleWGSLBindingDeclarations(module)) {
|
|
1004
|
+
for (const binding of getModuleWGSLBindingDeclarations(module, defines)) {
|
|
796
1005
|
const registryKey = getBindingRegistryKey(binding.group, module.name, binding.name);
|
|
797
1006
|
const location = bindingRegistry.get(registryKey);
|
|
798
1007
|
if (location !== undefined) {
|
|
@@ -843,9 +1052,12 @@ function claimReservedBindingLocation(
|
|
|
843
1052
|
return true;
|
|
844
1053
|
}
|
|
845
1054
|
|
|
846
|
-
function getModuleWGSLBindingDeclarations(
|
|
1055
|
+
function getModuleWGSLBindingDeclarations(
|
|
1056
|
+
module: ShaderModule,
|
|
1057
|
+
defines: Record<string, boolean | number>
|
|
1058
|
+
): {name: string; group: number}[] {
|
|
847
1059
|
const declarations: {name: string; group: number}[] = [];
|
|
848
|
-
const moduleSource = module.source || '';
|
|
1060
|
+
const moduleSource = preprocess(module.source || '', {defines});
|
|
849
1061
|
|
|
850
1062
|
for (const match of getWGSLBindingDeclarationMatches(
|
|
851
1063
|
moduleSource,
|
|
@@ -16,6 +16,8 @@ export type PlatformInfo = {
|
|
|
16
16
|
shaderLanguageVersion: 100 | 300;
|
|
17
17
|
/** string identifying current GPU */
|
|
18
18
|
gpu: string;
|
|
19
|
+
/** Device limits exposed to shader preprocessing decisions such as platform capability defines. */
|
|
20
|
+
limits?: Record<string, number | undefined>;
|
|
19
21
|
/** Feature strings for feature detection */
|
|
20
22
|
features: Set<string>;
|
|
21
23
|
};
|
|
@@ -39,12 +39,14 @@ export type ShaderHooks = {
|
|
|
39
39
|
/** Generate hook source code */
|
|
40
40
|
export function getShaderHooks(
|
|
41
41
|
hookFunctions: Record<string, ShaderHook>,
|
|
42
|
-
hookInjections: Record<string, ShaderInjection[]
|
|
42
|
+
hookInjections: Record<string, ShaderInjection[]>,
|
|
43
|
+
shaderLanguage: 'glsl' | 'wgsl' = 'glsl'
|
|
43
44
|
): string {
|
|
44
45
|
let result = '';
|
|
45
46
|
for (const hookName in hookFunctions) {
|
|
46
47
|
const hookFunction = hookFunctions[hookName];
|
|
47
|
-
|
|
48
|
+
const functionPrefix = shaderLanguage === 'wgsl' ? 'fn' : 'void';
|
|
49
|
+
result += `${functionPrefix} ${hookFunction.signature} {\n`;
|
|
48
50
|
if (hookFunction.header) {
|
|
49
51
|
result += ` ${hookFunction.header}`;
|
|
50
52
|
}
|
|
@@ -82,7 +84,9 @@ export function normalizeShaderHooks(hookFunctions: (string | ShaderHook)[]): Sh
|
|
|
82
84
|
hook = hookFunction;
|
|
83
85
|
}
|
|
84
86
|
hook = hook.trim();
|
|
85
|
-
const
|
|
87
|
+
const stageSeparatorIndex = hook.indexOf(':');
|
|
88
|
+
const shaderStage = hook.slice(0, stageSeparatorIndex);
|
|
89
|
+
const signature = hook.slice(stageSeparatorIndex + 1);
|
|
86
90
|
const name = hook.replace(/\(.+/, '');
|
|
87
91
|
const normalizedHook: ShaderHook = Object.assign(opts, {signature});
|
|
88
92
|
switch (shaderStage) {
|
|
@@ -83,7 +83,9 @@ export function injectShader(
|
|
|
83
83
|
source: string,
|
|
84
84
|
stage: 'vertex' | 'fragment',
|
|
85
85
|
inject: Record<string, ShaderInjection[]>,
|
|
86
|
-
injectStandardStubs = false
|
|
86
|
+
injectStandardStubs = false,
|
|
87
|
+
language: 'glsl' | 'wgsl' = 'glsl',
|
|
88
|
+
entryPoints: {vertex?: string; fragment?: string} = {}
|
|
87
89
|
): string {
|
|
88
90
|
const isVertex = stage === 'vertex';
|
|
89
91
|
|
|
@@ -98,38 +100,56 @@ export function injectShader(
|
|
|
98
100
|
switch (key) {
|
|
99
101
|
// declarations are injected before the main function
|
|
100
102
|
case 'vs:#decl':
|
|
101
|
-
if (isVertex) {
|
|
103
|
+
if (language === 'wgsl' || isVertex) {
|
|
102
104
|
source = source.replace(DECLARATION_INJECT_MARKER, fragmentString);
|
|
103
105
|
}
|
|
104
106
|
break;
|
|
105
107
|
// inject code at the beginning of the main function
|
|
106
108
|
case 'vs:#main-start':
|
|
107
|
-
if (isVertex) {
|
|
108
|
-
source =
|
|
109
|
+
if (language === 'wgsl' || isVertex) {
|
|
110
|
+
source =
|
|
111
|
+
language === 'wgsl'
|
|
112
|
+
? injectWGSLStageMain(source, 'vertex', fragmentString, 'start', entryPoints.vertex)
|
|
113
|
+
: source.replace(REGEX_START_OF_MAIN, (match: string) => match + fragmentString);
|
|
109
114
|
}
|
|
110
115
|
break;
|
|
111
116
|
// inject code at the end of main function
|
|
112
117
|
case 'vs:#main-end':
|
|
113
|
-
if (isVertex) {
|
|
114
|
-
source =
|
|
118
|
+
if (language === 'wgsl' || isVertex) {
|
|
119
|
+
source =
|
|
120
|
+
language === 'wgsl'
|
|
121
|
+
? injectWGSLStageMain(source, 'vertex', fragmentString, 'end', entryPoints.vertex)
|
|
122
|
+
: source.replace(REGEX_END_OF_MAIN, (match: string) => fragmentString + match);
|
|
115
123
|
}
|
|
116
124
|
break;
|
|
117
125
|
// declarations are injected before the main function
|
|
118
126
|
case 'fs:#decl':
|
|
119
|
-
if (!isVertex) {
|
|
127
|
+
if (language === 'wgsl' || !isVertex) {
|
|
120
128
|
source = source.replace(DECLARATION_INJECT_MARKER, fragmentString);
|
|
121
129
|
}
|
|
122
130
|
break;
|
|
123
131
|
// inject code at the beginning of the main function
|
|
124
132
|
case 'fs:#main-start':
|
|
125
|
-
if (!isVertex) {
|
|
126
|
-
source =
|
|
133
|
+
if (language === 'wgsl' || !isVertex) {
|
|
134
|
+
source =
|
|
135
|
+
language === 'wgsl'
|
|
136
|
+
? injectWGSLStageMain(
|
|
137
|
+
source,
|
|
138
|
+
'fragment',
|
|
139
|
+
fragmentString,
|
|
140
|
+
'start',
|
|
141
|
+
entryPoints.fragment
|
|
142
|
+
)
|
|
143
|
+
: source.replace(REGEX_START_OF_MAIN, (match: string) => match + fragmentString);
|
|
127
144
|
}
|
|
128
145
|
break;
|
|
129
146
|
// inject code at the end of main function
|
|
130
147
|
case 'fs:#main-end':
|
|
131
|
-
if (!isVertex) {
|
|
132
|
-
source =
|
|
148
|
+
if (language === 'wgsl' || !isVertex) {
|
|
149
|
+
source =
|
|
150
|
+
language === 'wgsl'
|
|
151
|
+
? injectWGSLStageMain(source, 'fragment', fragmentString, 'end', entryPoints.fragment)
|
|
152
|
+
: source.replace(REGEX_END_OF_MAIN, (match: string) => fragmentString + match);
|
|
133
153
|
}
|
|
134
154
|
break;
|
|
135
155
|
|
|
@@ -163,3 +183,68 @@ export function combineInjects(injects: any[]): Record<string, string> {
|
|
|
163
183
|
});
|
|
164
184
|
return result;
|
|
165
185
|
}
|
|
186
|
+
|
|
187
|
+
function injectWGSLStageMain(
|
|
188
|
+
source: string,
|
|
189
|
+
stage: 'vertex' | 'fragment',
|
|
190
|
+
fragmentString: string,
|
|
191
|
+
position: 'start' | 'end',
|
|
192
|
+
entryPoint?: string
|
|
193
|
+
): string {
|
|
194
|
+
const bodyRange = getWGSLStageFunctionBodyRange(source, stage, entryPoint);
|
|
195
|
+
if (!bodyRange) {
|
|
196
|
+
return source;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
if (position === 'start') {
|
|
200
|
+
const insertionIndex = bodyRange.openBraceIndex + 1;
|
|
201
|
+
return `${source.slice(0, insertionIndex)}\n${fragmentString}${source.slice(insertionIndex)}`;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
return `${source.slice(0, bodyRange.closeBraceIndex)}${fragmentString}${source.slice(
|
|
205
|
+
bodyRange.closeBraceIndex
|
|
206
|
+
)}`;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
function getWGSLStageFunctionBodyRange(
|
|
210
|
+
source: string,
|
|
211
|
+
stage: 'vertex' | 'fragment',
|
|
212
|
+
entryPoint?: string
|
|
213
|
+
): {openBraceIndex: number; closeBraceIndex: number} | null {
|
|
214
|
+
const stageAttribute = stage === 'vertex' ? '@vertex' : '@fragment';
|
|
215
|
+
const stageIndex = source.indexOf(stageAttribute);
|
|
216
|
+
if (stageIndex < 0) {
|
|
217
|
+
return null;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
const functionIndex = entryPoint
|
|
221
|
+
? source.search(new RegExp(`\\bfn\\s+${escapeRegExp(entryPoint)}\\s*\\(`))
|
|
222
|
+
: source.indexOf('fn', stageIndex);
|
|
223
|
+
if (functionIndex < 0) {
|
|
224
|
+
return null;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
const openBraceIndex = source.indexOf('{', functionIndex);
|
|
228
|
+
if (openBraceIndex < 0) {
|
|
229
|
+
return null;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
let braceDepth = 0;
|
|
233
|
+
for (let index = openBraceIndex; index < source.length; index++) {
|
|
234
|
+
const character = source[index];
|
|
235
|
+
if (character === '{') {
|
|
236
|
+
braceDepth++;
|
|
237
|
+
} else if (character === '}') {
|
|
238
|
+
braceDepth--;
|
|
239
|
+
if (braceDepth === 0) {
|
|
240
|
+
return {openBraceIndex, closeBraceIndex: index};
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
return null;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
function escapeRegExp(value: string): string {
|
|
249
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
250
|
+
}
|