@luma.gl/shaders 10.0.0-alpha.5 → 10.0.0-alpha.7
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/LICENSE +38 -0
- package/dist/dist.dev.js +159 -127
- package/dist/dist.min.js +110 -105
- package/dist/glsl.cjs.map +1 -1
- package/dist/index.cjs.map +2 -2
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/lib/glsl-shader-assembler.cjs +1 -1
- package/dist/lib/glsl-shader-assembler.js +1 -1
- package/dist/lib/glsl-shader-assembler.js.map +1 -1
- package/dist/lib/preprocessor/preprocessor.cjs +21 -0
- package/dist/lib/preprocessor/preprocessor.js +21 -0
- package/dist/lib/preprocessor/preprocessor.js.map +1 -1
- package/dist/lib/shader-assembly/assemble-glsl-shaders.cjs +11 -19
- package/dist/lib/shader-assembly/assemble-glsl-shaders.d.ts +2 -2
- package/dist/lib/shader-assembly/assemble-glsl-shaders.d.ts.map +1 -1
- package/dist/lib/shader-assembly/assemble-glsl-shaders.js +12 -20
- package/dist/lib/shader-assembly/assemble-glsl-shaders.js.map +1 -1
- package/dist/lib/shader-assembly/assemble-wgsl-shaders.cjs +6 -6
- package/dist/lib/shader-assembly/assemble-wgsl-shaders.js +7 -7
- package/dist/lib/shader-assembly/assemble-wgsl-shaders.js.map +1 -1
- package/dist/lib/shader-assembly/shader-assembly-types.d.ts +7 -7
- package/dist/lib/shader-assembly/shader-assembly-types.d.ts.map +1 -1
- package/dist/lib/shader-assembly/shader-hooks.cjs +4 -1
- package/dist/lib/shader-assembly/shader-hooks.d.ts.map +1 -1
- package/dist/lib/shader-assembly/shader-hooks.js +4 -1
- package/dist/lib/shader-assembly/shader-hooks.js.map +1 -1
- package/dist/lib/shader-assembly/shader-injections.d.ts +2 -0
- package/dist/lib/shader-assembly/shader-injections.d.ts.map +1 -1
- package/dist/lib/shader-assembly/shader-injections.js.map +1 -1
- package/dist/lib/shader-assembly/shader-plugin-varyings.cjs +39 -22
- package/dist/lib/shader-assembly/shader-plugin-varyings.d.ts +5 -5
- package/dist/lib/shader-assembly/shader-plugin-varyings.d.ts.map +1 -1
- package/dist/lib/shader-assembly/shader-plugin-varyings.js +45 -19
- package/dist/lib/shader-assembly/shader-plugin-varyings.js.map +1 -1
- package/dist/lib/shader-generator/glsl/generate-glsl.d.ts +1 -1
- package/dist/lib/shader-generator/glsl/generate-glsl.d.ts.map +1 -1
- package/dist/lib/shader-generator/wgsl/generate-wgsl.d.ts +1 -1
- package/dist/lib/shader-generator/wgsl/generate-wgsl.d.ts.map +1 -1
- package/dist/lib/shader-plugin.cjs +44 -30
- package/dist/lib/shader-plugin.d.ts +33 -32
- package/dist/lib/shader-plugin.d.ts.map +1 -1
- package/dist/lib/shader-plugin.js +49 -31
- package/dist/lib/shader-plugin.js.map +1 -1
- package/dist/lib/wgsl-shader-assembler.cjs +1 -1
- package/dist/lib/wgsl-shader-assembler.js +1 -1
- package/dist/lib/wgsl-shader-assembler.js.map +1 -1
- package/dist/modules/engine/clip/clip.cjs +18 -30
- package/dist/modules/engine/clip/clip.d.ts.map +1 -1
- package/dist/modules/engine/clip/clip.js +19 -31
- package/dist/modules/engine/clip/clip.js.map +1 -1
- package/dist/modules/engine/filter/filter.cjs +9 -18
- package/dist/modules/engine/filter/filter.d.ts.map +1 -1
- package/dist/modules/engine/filter/filter.js +9 -18
- package/dist/modules/engine/filter/filter.js.map +1 -1
- package/dist/modules/math/fp64/fp64.cjs +1 -1
- package/dist/modules/math/fp64/fp64.d.ts +1 -1
- package/dist/modules/math/fp64/fp64.d.ts.map +1 -1
- package/dist/modules/math/fp64/fp64.js +1 -1
- package/dist/modules/math/fp64/fp64.js.map +1 -1
- package/dist/types.cjs +27 -16
- package/dist/types.d.ts +7 -7
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +2 -7
- package/dist/types.js.map +1 -1
- package/dist/wgsl.cjs +20 -4
- package/dist/wgsl.cjs.map +1 -1
- package/dist/wgsl.d.ts +1 -1
- package/dist/wgsl.d.ts.map +1 -1
- package/dist/wgsl.js +1 -1
- package/dist/wgsl.js.map +1 -1
- package/package.json +3 -3
- package/src/index.ts +3 -4
- package/src/lib/glsl-shader-assembler.ts +1 -1
- package/src/lib/preprocessor/preprocessor.ts +25 -0
- package/src/lib/shader-assembly/assemble-glsl-shaders.ts +17 -22
- package/src/lib/shader-assembly/assemble-wgsl-shaders.ts +8 -8
- package/src/lib/shader-assembly/shader-assembly-types.ts +7 -7
- package/src/lib/shader-assembly/shader-hooks.ts +6 -1
- package/src/lib/shader-assembly/shader-injections.ts +2 -0
- package/src/lib/shader-assembly/shader-plugin-varyings.ts +58 -27
- package/src/lib/shader-generator/glsl/generate-glsl.ts +1 -1
- package/src/lib/shader-generator/wgsl/generate-wgsl.ts +1 -1
- package/src/lib/shader-module/shader-module-dependencies.ts +1 -1
- package/src/lib/shader-plugin.ts +75 -68
- package/src/lib/wgsl-shader-assembler.ts +1 -1
- package/src/modules/engine/clip/clip.ts +19 -31
- package/src/modules/engine/filter/filter.ts +9 -18
- package/src/modules/math/fp64/fp64.ts +1 -1
- package/src/types.ts +75 -7
- package/src/wgsl.ts +12 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@luma.gl/shaders",
|
|
3
|
-
"version": "10.0.0-alpha.
|
|
3
|
+
"version": "10.0.0-alpha.7",
|
|
4
4
|
"description": "Shader module system for luma.gl",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -61,7 +61,7 @@
|
|
|
61
61
|
"prepublishOnly": "npm run build-minified-bundle && npm run build-dev-bundle"
|
|
62
62
|
},
|
|
63
63
|
"dependencies": {
|
|
64
|
-
"@math.gl/core": "~5.0.0-beta.
|
|
64
|
+
"@math.gl/core": "~5.0.0-beta.2"
|
|
65
65
|
},
|
|
66
|
-
"gitHead": "
|
|
66
|
+
"gitHead": "e3979f06848a6d04547ac7a26f844212ba569806"
|
|
67
67
|
}
|
package/src/index.ts
CHANGED
|
@@ -20,13 +20,12 @@ export {
|
|
|
20
20
|
export type {ShaderModule} from './lib/shader-module/shader-module';
|
|
21
21
|
export type {
|
|
22
22
|
ResolvedShaderPlugins,
|
|
23
|
-
|
|
23
|
+
ResolvedShaderPluginInterStageVariable,
|
|
24
24
|
ShaderPlugin,
|
|
25
25
|
ShaderPluginInjection,
|
|
26
26
|
ShaderPluginInjectionTarget,
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
ShaderPluginVariant
|
|
27
|
+
ShaderPluginInterStageVariable,
|
|
28
|
+
ShaderPluginInterStageVariableInterpolation
|
|
30
29
|
} from './lib/shader-plugin';
|
|
31
30
|
export type {
|
|
32
31
|
ShaderPass,
|
|
@@ -23,7 +23,7 @@ export class GLSLShaderAssembler extends ShaderAssembler {
|
|
|
23
23
|
modules: ShaderModule[];
|
|
24
24
|
} {
|
|
25
25
|
const modules = this._getModuleList(props.modules); // Combine with default modules
|
|
26
|
-
const hookFunctions = this._hookFunctions
|
|
26
|
+
const hookFunctions = [...this._hookFunctions, ...(props.hookFunctions || [])];
|
|
27
27
|
const vertex = this._transpileShader(props, modules, props.vs, 'vertex');
|
|
28
28
|
const fragment = this._transpileShader(props, modules, props.fs, 'fragment');
|
|
29
29
|
const assembled = assembleGLSLShaderPair({
|
|
@@ -104,6 +104,31 @@ function evaluateIfExpression(
|
|
|
104
104
|
return false;
|
|
105
105
|
}
|
|
106
106
|
|
|
107
|
+
const operandPattern = '(?:[A-Za-z_][A-Za-z0-9_]*|[+-]?\\d+(?:\\.\\d+)?)';
|
|
108
|
+
const comparison = trimmedExpression.match(
|
|
109
|
+
new RegExp(`^(${operandPattern})\\s*(==|!=|<=|>=|<|>)\\s*(${operandPattern})$`)
|
|
110
|
+
);
|
|
111
|
+
if (comparison) {
|
|
112
|
+
const resolveOperand = (operand: string) =>
|
|
113
|
+
/^[A-Za-z_]/.test(operand) ? Number(defines[operand] ?? 0) : Number(operand);
|
|
114
|
+
const left = resolveOperand(comparison[1]);
|
|
115
|
+
const right = resolveOperand(comparison[3]);
|
|
116
|
+
switch (comparison[2]) {
|
|
117
|
+
case '==':
|
|
118
|
+
return left === right;
|
|
119
|
+
case '!=':
|
|
120
|
+
return left !== right;
|
|
121
|
+
case '<=':
|
|
122
|
+
return left <= right;
|
|
123
|
+
case '>=':
|
|
124
|
+
return left >= right;
|
|
125
|
+
case '<':
|
|
126
|
+
return left < right;
|
|
127
|
+
case '>':
|
|
128
|
+
return left > right;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
107
132
|
const negatedDefineMatch = trimmedExpression.match(new RegExp(`^!\\s*${DEFINE_NAME_PATTERN}$`));
|
|
108
133
|
if (negatedDefineMatch) {
|
|
109
134
|
return !Boolean(defines[negatedDefineMatch[1]]);
|
|
@@ -24,12 +24,12 @@ import {
|
|
|
24
24
|
} from './shader-hooks';
|
|
25
25
|
import {type ShaderInjection, injectShader} from './shader-injections';
|
|
26
26
|
import {type AttributeShaderType} from '../../types';
|
|
27
|
-
import {type
|
|
27
|
+
import {type ResolvedShaderPluginInterStageVariable} from '../shader-plugin';
|
|
28
28
|
import {assert} from '../utils/assert';
|
|
29
29
|
import {getShaderInfo} from '../glsl-utils/get-shader-info';
|
|
30
30
|
import {getPlatformShaderDefines} from './platform-defines';
|
|
31
31
|
import {getShaderPluginVertexInputDeclarationsGLSL} from './shader-plugin-vertex-inputs';
|
|
32
|
-
import {
|
|
32
|
+
import {assembleShaderPluginInterStageVariablesGLSL} from './shader-plugin-varyings';
|
|
33
33
|
import {transpileGLSLShader} from '../shader-transpiler/transpile-glsl-shader';
|
|
34
34
|
import {warnIfGLSLUniformBlocksAreNotStd140} from '../shader-module/shader-module-uniform-layout';
|
|
35
35
|
|
|
@@ -97,7 +97,7 @@ export function assembleShaderGLSL(
|
|
|
97
97
|
inject?: Record<string, string | ShaderInjection>;
|
|
98
98
|
pluginInjections?: Record<string, ShaderInjection[]>;
|
|
99
99
|
pluginVertexInputs?: Record<string, AttributeShaderType>;
|
|
100
|
-
|
|
100
|
+
pluginInterStageVariables?: Record<string, ResolvedShaderPluginInterStageVariable>;
|
|
101
101
|
prologue?: boolean;
|
|
102
102
|
log?: ShaderAssemblyLog;
|
|
103
103
|
}
|
|
@@ -112,7 +112,7 @@ export function assembleShaderGLSL(
|
|
|
112
112
|
inject = {},
|
|
113
113
|
pluginInjections = {},
|
|
114
114
|
pluginVertexInputs = {},
|
|
115
|
-
|
|
115
|
+
pluginInterStageVariables = {},
|
|
116
116
|
prologue = true,
|
|
117
117
|
log
|
|
118
118
|
} = options;
|
|
@@ -181,36 +181,31 @@ ${getApplicationDefines(allDefines)}
|
|
|
181
181
|
const name = match[3];
|
|
182
182
|
if (hash) {
|
|
183
183
|
if (name === 'decl') {
|
|
184
|
-
declInjections[key] = [injection];
|
|
184
|
+
declInjections[key] = [...(declInjections[key] || []), injection];
|
|
185
185
|
} else {
|
|
186
|
-
mainInjections[key] = [injection];
|
|
186
|
+
mainInjections[key] = [...(mainInjections[key] || []), injection];
|
|
187
187
|
}
|
|
188
188
|
} else {
|
|
189
|
-
hookInjections[key] = [injection];
|
|
189
|
+
hookInjections[key] = [...(hookInjections[key] || []), injection];
|
|
190
190
|
}
|
|
191
191
|
} else {
|
|
192
192
|
// Regex injection
|
|
193
|
-
mainInjections[key] = [injection];
|
|
193
|
+
mainInjections[key] = [...(mainInjections[key] || []), injection];
|
|
194
194
|
}
|
|
195
195
|
}
|
|
196
|
+
// Module helpers may access plugin inputs and varyings. GLSL requires these
|
|
197
|
+
// interface declarations before the helpers, unlike ordinary #decl injections.
|
|
196
198
|
if (stage === 'vertex') {
|
|
197
199
|
const declarations = getShaderPluginVertexInputDeclarationsGLSL(coreSource, pluginVertexInputs);
|
|
198
|
-
if (declarations) {
|
|
199
|
-
declInjections['vs:#decl'] = declInjections['vs:#decl'] || [];
|
|
200
|
-
declInjections['vs:#decl'].push({
|
|
201
|
-
injection: declarations,
|
|
202
|
-
order: Number.MIN_SAFE_INTEGER
|
|
203
|
-
});
|
|
204
|
-
}
|
|
200
|
+
if (declarations) assembledSource += `${declarations}\n`;
|
|
205
201
|
}
|
|
206
|
-
const pluginVaryingAssembly =
|
|
202
|
+
const pluginVaryingAssembly = assembleShaderPluginInterStageVariablesGLSL(
|
|
203
|
+
coreSource,
|
|
204
|
+
stage,
|
|
205
|
+
pluginInterStageVariables
|
|
206
|
+
);
|
|
207
207
|
if (pluginVaryingAssembly.declarations) {
|
|
208
|
-
|
|
209
|
-
declInjections[declarationTarget] = declInjections[declarationTarget] || [];
|
|
210
|
-
declInjections[declarationTarget].push({
|
|
211
|
-
injection: pluginVaryingAssembly.declarations,
|
|
212
|
-
order: Number.MIN_SAFE_INTEGER
|
|
213
|
-
});
|
|
208
|
+
assembledSource += `${pluginVaryingAssembly.declarations}\n`;
|
|
214
209
|
}
|
|
215
210
|
if (pluginVaryingAssembly.initialization) {
|
|
216
211
|
mainInjections['vs:#main-start'] = mainInjections['vs:#main-start'] || [];
|
|
@@ -26,7 +26,7 @@ import {PlatformInfo} from './platform-info';
|
|
|
26
26
|
import {assert} from '../utils/assert';
|
|
27
27
|
import {preprocess} from '../preprocessor/preprocessor';
|
|
28
28
|
import {assembleShaderPluginVertexInputsWGSL} from './shader-plugin-vertex-inputs';
|
|
29
|
-
import {
|
|
29
|
+
import {assembleShaderPluginInterStageVariablesWGSL} from './shader-plugin-varyings';
|
|
30
30
|
import {
|
|
31
31
|
normalizeShaderHooks,
|
|
32
32
|
validateShaderHookInjections,
|
|
@@ -113,7 +113,7 @@ export function assembleShaderWGSL(
|
|
|
113
113
|
inject = {},
|
|
114
114
|
pluginInjections = {},
|
|
115
115
|
pluginVertexInputs = {},
|
|
116
|
-
|
|
116
|
+
pluginInterStageVariables = {},
|
|
117
117
|
vertexEntryPoint = 'vertexMain',
|
|
118
118
|
fragmentEntryPoint = 'fragmentMain',
|
|
119
119
|
log
|
|
@@ -130,11 +130,11 @@ export function assembleShaderWGSL(
|
|
|
130
130
|
vertexEntryPoint,
|
|
131
131
|
pluginVertexInputs
|
|
132
132
|
);
|
|
133
|
-
const pluginVaryingAssembly =
|
|
133
|
+
const pluginVaryingAssembly = assembleShaderPluginInterStageVariablesWGSL(
|
|
134
134
|
pluginVertexInputAssembly.source,
|
|
135
135
|
vertexEntryPoint,
|
|
136
136
|
fragmentEntryPoint,
|
|
137
|
-
|
|
137
|
+
pluginInterStageVariables
|
|
138
138
|
);
|
|
139
139
|
const coreSource = pluginVaryingAssembly.source;
|
|
140
140
|
|
|
@@ -177,16 +177,16 @@ export function assembleShaderWGSL(
|
|
|
177
177
|
const name = match[3];
|
|
178
178
|
if (hash) {
|
|
179
179
|
if (name === 'decl') {
|
|
180
|
-
declInjections[key] = [injection];
|
|
180
|
+
declInjections[key] = [...(declInjections[key] || []), injection];
|
|
181
181
|
} else {
|
|
182
|
-
mainInjections[key] = [injection];
|
|
182
|
+
mainInjections[key] = [...(mainInjections[key] || []), injection];
|
|
183
183
|
}
|
|
184
184
|
} else {
|
|
185
|
-
hookInjections[key] = [injection];
|
|
185
|
+
hookInjections[key] = [...(hookInjections[key] || []), injection];
|
|
186
186
|
}
|
|
187
187
|
} else {
|
|
188
188
|
// Regex injection
|
|
189
|
-
mainInjections[key] = [injection];
|
|
189
|
+
mainInjections[key] = [...(mainInjections[key] || []), injection];
|
|
190
190
|
}
|
|
191
191
|
}
|
|
192
192
|
appendGeneratedVertexInputInjections(
|
|
@@ -7,7 +7,7 @@ import {type ShaderModule} from '../shader-module/shader-module';
|
|
|
7
7
|
import {type ShaderHook} from './shader-hooks';
|
|
8
8
|
import {type ShaderInjection} from './shader-injections';
|
|
9
9
|
import {type AttributeShaderType} from '../../types';
|
|
10
|
-
import {type
|
|
10
|
+
import {type ResolvedShaderPluginInterStageVariable} from '../shader-plugin';
|
|
11
11
|
|
|
12
12
|
export type ShaderAssemblyLog = {
|
|
13
13
|
deprecated?: (...args: unknown[]) => () => unknown;
|
|
@@ -44,7 +44,7 @@ export type AssembleShaderOptions = {
|
|
|
44
44
|
defines?: Record<string, boolean | number>;
|
|
45
45
|
/** GLSL only: Overrides to be injected. In WGSL these are supplied during Pipeline creation time */
|
|
46
46
|
constants?: Record<string, number>;
|
|
47
|
-
/**
|
|
47
|
+
/** Per-call hooks, appended after registered assembler hooks; matching names override for this call. */
|
|
48
48
|
hookFunctions?: readonly (ShaderHook | string)[];
|
|
49
49
|
/** Code injections */
|
|
50
50
|
inject?: Record<string, string | ShaderInjection>;
|
|
@@ -52,8 +52,8 @@ export type AssembleShaderOptions = {
|
|
|
52
52
|
pluginInjections?: Record<string, ShaderInjection[]>;
|
|
53
53
|
/** Vertex inputs contributed by ShaderPlugin descriptors. */
|
|
54
54
|
pluginVertexInputs?: Record<string, AttributeShaderType>;
|
|
55
|
-
/**
|
|
56
|
-
|
|
55
|
+
/** Inter-stage variables contributed by ShaderPlugin descriptors. */
|
|
56
|
+
pluginInterStageVariables?: Record<string, ResolvedShaderPluginInterStageVariable>;
|
|
57
57
|
/** WGSL vertex entry point selected by the render pipeline. */
|
|
58
58
|
vertexEntryPoint?: string;
|
|
59
59
|
/** Whether WGSL interface scanning should include vertex attributes. */
|
|
@@ -78,7 +78,7 @@ export type AssembleStageOptions = {
|
|
|
78
78
|
defines?: Record<string, boolean | number>;
|
|
79
79
|
/** GLSL only: Overrides to be injected. In WGSL these are supplied during Pipeline creation time */
|
|
80
80
|
constants?: Record<string, number>;
|
|
81
|
-
/**
|
|
81
|
+
/** Per-call hooks, appended after registered assembler hooks; matching names override for this call. */
|
|
82
82
|
hookFunctions?: readonly (ShaderHook | string)[];
|
|
83
83
|
/** Code injections */
|
|
84
84
|
inject?: Record<string, string | ShaderInjection>;
|
|
@@ -86,8 +86,8 @@ export type AssembleStageOptions = {
|
|
|
86
86
|
pluginInjections?: Record<string, ShaderInjection[]>;
|
|
87
87
|
/** Vertex inputs contributed by ShaderPlugin descriptors. */
|
|
88
88
|
pluginVertexInputs?: Record<string, AttributeShaderType>;
|
|
89
|
-
/**
|
|
90
|
-
|
|
89
|
+
/** Inter-stage variables contributed by ShaderPlugin descriptors. */
|
|
90
|
+
pluginInterStageVariables?: Record<string, ResolvedShaderPluginInterStageVariable>;
|
|
91
91
|
/** WGSL vertex entry point selected by the render pipeline. */
|
|
92
92
|
vertexEntryPoint?: string;
|
|
93
93
|
/** WGSL fragment entry point selected by the render pipeline. */
|
|
@@ -106,7 +106,12 @@ export function validateShaderHookInjections(
|
|
|
106
106
|
|
|
107
107
|
if (!isShaderHookRegistered(registry, hookName)) {
|
|
108
108
|
// The injection targets a hook that was not declared for this stage.
|
|
109
|
-
|
|
109
|
+
const pluginNames = [
|
|
110
|
+
...new Set(hookInjections[hookName].map(injection => injection.pluginName).filter(Boolean))
|
|
111
|
+
];
|
|
112
|
+
throw new Error(
|
|
113
|
+
`Unknown shader hook ${hookName}${pluginNames.length ? ` (plugins: ${pluginNames.join(', ')})` : ''}`
|
|
114
|
+
);
|
|
110
115
|
}
|
|
111
116
|
}
|
|
112
117
|
}
|
|
@@ -21,6 +21,8 @@ export const DECLARATION_INJECT_MARKER = '__LUMA_INJECT_DECLARATIONS__';
|
|
|
21
21
|
*
|
|
22
22
|
*/
|
|
23
23
|
export type ShaderInjection = {
|
|
24
|
+
/** Plugin responsible for this injection, when supplied by a ShaderPlugin. */
|
|
25
|
+
pluginName?: string;
|
|
24
26
|
injection: string;
|
|
25
27
|
order: number;
|
|
26
28
|
};
|
|
@@ -3,10 +3,11 @@
|
|
|
3
3
|
// SPDX-FileCopyrightText: Copyright (c) vis.gl contributors
|
|
4
4
|
|
|
5
5
|
import {shaderTypeDecoder} from '../../types';
|
|
6
|
-
import type {
|
|
6
|
+
import type {ResolvedShaderPluginInterStageVariable} from '../shader-plugin';
|
|
7
7
|
import {getGLSLAttributeType} from './shader-plugin-vertex-inputs';
|
|
8
|
+
import {maskWGSLComments} from './wgsl-binding-scan';
|
|
8
9
|
|
|
9
|
-
export type
|
|
10
|
+
export type ShaderPluginInterStageVariableAssembly = {
|
|
10
11
|
source: string;
|
|
11
12
|
declarations: string;
|
|
12
13
|
vertexInitialization: string;
|
|
@@ -14,14 +15,14 @@ export type ShaderPluginVaryingAssembly = {
|
|
|
14
15
|
};
|
|
15
16
|
|
|
16
17
|
/** Generate one stage of the GLSL interface contributed by shader plugins. */
|
|
17
|
-
export function
|
|
18
|
+
export function assembleShaderPluginInterStageVariablesGLSL(
|
|
18
19
|
source: string,
|
|
19
20
|
stage: 'vertex' | 'fragment',
|
|
20
|
-
|
|
21
|
+
interStageVariables: Record<string, ResolvedShaderPluginInterStageVariable>
|
|
21
22
|
): {declarations: string; initialization: string} {
|
|
22
23
|
const declarations: string[] = [];
|
|
23
24
|
const initialization: string[] = [];
|
|
24
|
-
for (const [name, varying] of Object.entries(
|
|
25
|
+
for (const [name, varying] of Object.entries(interStageVariables)) {
|
|
25
26
|
assertGLSLVaryingIsNew(source, name);
|
|
26
27
|
const qualifier = varying.interpolation === 'flat' ? 'flat ' : '';
|
|
27
28
|
const direction = stage === 'vertex' ? 'out' : 'in';
|
|
@@ -33,14 +34,14 @@ export function assembleShaderPluginVaryingsGLSL(
|
|
|
33
34
|
return {declarations: declarations.join('\n'), initialization: initialization.join('\n')};
|
|
34
35
|
}
|
|
35
36
|
|
|
36
|
-
/** Add plugin
|
|
37
|
-
export function
|
|
37
|
+
/** Add plugin interStageVariables to selected WGSL vertex and fragment entry points. */
|
|
38
|
+
export function assembleShaderPluginInterStageVariablesWGSL(
|
|
38
39
|
source: string,
|
|
39
40
|
vertexEntryPoint: string,
|
|
40
41
|
fragmentEntryPoint: string,
|
|
41
|
-
|
|
42
|
-
):
|
|
43
|
-
const entries = Object.entries(
|
|
42
|
+
interStageVariables: Record<string, ResolvedShaderPluginInterStageVariable>
|
|
43
|
+
): ShaderPluginInterStageVariableAssembly {
|
|
44
|
+
const entries = Object.entries(interStageVariables);
|
|
44
45
|
if (entries.length === 0) {
|
|
45
46
|
return {
|
|
46
47
|
source,
|
|
@@ -56,19 +57,23 @@ export function assembleShaderPluginVaryingsWGSL(
|
|
|
56
57
|
let fragmentFunction = getWGSLFunctionRange(transformedSource, fragmentEntryPoint, 'fragment');
|
|
57
58
|
const fragmentInput = getWGSLFragmentStructInput(transformedSource, fragmentFunction);
|
|
58
59
|
const vertexOutputStruct = getWGSLStructRange(transformedSource, vertexOutputType);
|
|
59
|
-
const fragmentInputStruct =
|
|
60
|
+
const fragmentInputStruct = fragmentInput
|
|
61
|
+
? getWGSLStructRange(transformedSource, fragmentInput.type)
|
|
62
|
+
: null;
|
|
60
63
|
|
|
61
64
|
const interfaceNames = new Set([
|
|
62
65
|
...getWGSLDeclaredNames(vertexFunction.parameters),
|
|
63
66
|
...getWGSLDeclaredNames(vertexOutputStruct.body),
|
|
64
67
|
...getWGSLDeclaredNames(fragmentFunction.parameters),
|
|
65
|
-
...getWGSLDeclaredNames(fragmentInputStruct
|
|
68
|
+
...getWGSLDeclaredNames(fragmentInputStruct?.body || '')
|
|
66
69
|
]);
|
|
67
70
|
const usedLocations = new Set([
|
|
68
71
|
...getWGSLLocations(vertexOutputStruct.body),
|
|
69
|
-
...getWGSLLocations(fragmentInputStruct
|
|
72
|
+
...getWGSLLocations(fragmentInputStruct?.body || ''),
|
|
73
|
+
...getWGSLLocations(fragmentFunction.parameters)
|
|
70
74
|
]);
|
|
71
75
|
const fields: string[] = [];
|
|
76
|
+
const fragmentParameters: string[] = [];
|
|
72
77
|
const declarations: string[] = [];
|
|
73
78
|
const vertexInitialization: string[] = [];
|
|
74
79
|
const fragmentInitialization: string[] = [];
|
|
@@ -85,7 +90,20 @@ export function assembleShaderPluginVaryingsWGSL(
|
|
|
85
90
|
fields.push(` @location(${location})${interpolation} ${name}: ${varying.type},`);
|
|
86
91
|
declarations.push(`var<private> ${name}: ${varying.type};`);
|
|
87
92
|
vertexInitialization.push(`${name} = ${getWGSLZeroValue(varying.type)};`);
|
|
88
|
-
|
|
93
|
+
if (fragmentInput) {
|
|
94
|
+
fragmentInitialization.push(`${name} = ${fragmentInput.name}.${name};`);
|
|
95
|
+
} else {
|
|
96
|
+
const parameterName = `_luma_${name}`;
|
|
97
|
+
if (interfaceNames.has(parameterName)) {
|
|
98
|
+
throw new Error(
|
|
99
|
+
`ShaderPlugin varying "${name}" conflicts with a generated fragment parameter`
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
fragmentParameters.push(
|
|
103
|
+
`@location(${location})${interpolation} ${parameterName}: ${varying.type}`
|
|
104
|
+
);
|
|
105
|
+
fragmentInitialization.push(`${name} = ${parameterName};`);
|
|
106
|
+
}
|
|
89
107
|
}
|
|
90
108
|
|
|
91
109
|
assertWGSLStructConstructorsAreLocal(
|
|
@@ -108,7 +126,7 @@ export function assembleShaderPluginVaryingsWGSL(
|
|
|
108
126
|
);
|
|
109
127
|
|
|
110
128
|
const structNames =
|
|
111
|
-
vertexOutputType === fragmentInput.type
|
|
129
|
+
!fragmentInput || vertexOutputType === fragmentInput.type
|
|
112
130
|
? [vertexOutputType]
|
|
113
131
|
: [vertexOutputType, fragmentInput.type];
|
|
114
132
|
const structInsertions = structNames
|
|
@@ -122,9 +140,20 @@ export function assembleShaderPluginVaryingsWGSL(
|
|
|
122
140
|
}
|
|
123
141
|
|
|
124
142
|
fragmentFunction = getWGSLFunctionRange(transformedSource, fragmentEntryPoint, 'fragment');
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
143
|
+
if (fragmentParameters.length) {
|
|
144
|
+
let parameters = fragmentFunction.parameters;
|
|
145
|
+
const parameterTokens = maskWGSLComments(parameters).trimEnd();
|
|
146
|
+
if (parameterTokens.trim() && !parameterTokens.endsWith(',')) {
|
|
147
|
+
const insertionIndex = parameterTokens.length;
|
|
148
|
+
parameters = `${parameters.slice(0, insertionIndex)},${parameters.slice(insertionIndex)}`;
|
|
149
|
+
}
|
|
150
|
+
transformedSource =
|
|
151
|
+
transformedSource.slice(0, fragmentFunction.openParenthesis + 1) +
|
|
152
|
+
parameters +
|
|
153
|
+
'\n ' +
|
|
154
|
+
fragmentParameters.join(',\n ') +
|
|
155
|
+
'\n' +
|
|
156
|
+
transformedSource.slice(fragmentFunction.closeParenthesis);
|
|
128
157
|
}
|
|
129
158
|
|
|
130
159
|
return {
|
|
@@ -157,7 +186,9 @@ function getWGSLFunctionRange(
|
|
|
157
186
|
const functionPattern = new RegExp(`\\bfn\\s+${escapeRegExp(entryPoint)}\\s*\\(`, 'g');
|
|
158
187
|
const match = functionPattern.exec(source);
|
|
159
188
|
if (!match) {
|
|
160
|
-
throw new Error(
|
|
189
|
+
throw new Error(
|
|
190
|
+
`ShaderPlugin interStageVariables require WGSL ${stage} entry point "${entryPoint}"`
|
|
191
|
+
);
|
|
161
192
|
}
|
|
162
193
|
const openParenthesis = source.indexOf('(', match.index);
|
|
163
194
|
const closeParenthesis = findMatchingDelimiter(source, openParenthesis, '(', ')');
|
|
@@ -180,7 +211,7 @@ function getWGSLNamedReturnType(source: string, functionRange: WGSLFunctionRange
|
|
|
180
211
|
const match = /->\s*([A-Za-z_][\w]*)\s*$/.exec(resultSource.trim());
|
|
181
212
|
if (!match || getWGSLStructRangeOrNull(source, match[1]) === null) {
|
|
182
213
|
throw new Error(
|
|
183
|
-
'ShaderPlugin
|
|
214
|
+
'ShaderPlugin interStageVariables require the WGSL vertex entry point to return a named struct'
|
|
184
215
|
);
|
|
185
216
|
}
|
|
186
217
|
return match[1];
|
|
@@ -189,9 +220,9 @@ function getWGSLNamedReturnType(source: string, functionRange: WGSLFunctionRange
|
|
|
189
220
|
function getWGSLFragmentStructInput(
|
|
190
221
|
source: string,
|
|
191
222
|
functionRange: WGSLFunctionRange
|
|
192
|
-
): {name: string; type: string} {
|
|
223
|
+
): {name: string; type: string} | null {
|
|
193
224
|
const candidates: {name: string; type: string}[] = [];
|
|
194
|
-
for (const parameter of splitTopLevel(functionRange.parameters, ',')) {
|
|
225
|
+
for (const parameter of splitTopLevel(maskWGSLComments(functionRange.parameters), ',')) {
|
|
195
226
|
const match =
|
|
196
227
|
/(?:@[A-Za-z_][\w]*(?:\([^)]*\))?\s*)*([A-Za-z_][\w]*)\s*:\s*([A-Za-z_][\w]*)\s*$/.exec(
|
|
197
228
|
parameter.trim()
|
|
@@ -200,12 +231,12 @@ function getWGSLFragmentStructInput(
|
|
|
200
231
|
candidates.push({name: match[1], type: match[2]});
|
|
201
232
|
}
|
|
202
233
|
}
|
|
203
|
-
if (candidates.length
|
|
234
|
+
if (candidates.length > 1) {
|
|
204
235
|
throw new Error(
|
|
205
|
-
`ShaderPlugin
|
|
236
|
+
`ShaderPlugin interStageVariables require exactly one named WGSL fragment input struct; found ${candidates.length}`
|
|
206
237
|
);
|
|
207
238
|
}
|
|
208
|
-
return candidates[0];
|
|
239
|
+
return candidates[0] || null;
|
|
209
240
|
}
|
|
210
241
|
|
|
211
242
|
function getWGSLStructRange(source: string, structName: string): WGSLStructRange {
|
|
@@ -440,13 +471,13 @@ function getFirstUnusedLocation(usedLocations: Set<number>): number {
|
|
|
440
471
|
return location;
|
|
441
472
|
}
|
|
442
473
|
|
|
443
|
-
function getGLSLZeroValue(type:
|
|
474
|
+
function getGLSLZeroValue(type: ResolvedShaderPluginInterStageVariable['type']): string {
|
|
444
475
|
const {primitiveType, components} = shaderTypeDecoder.getAttributeShaderTypeInfo(type);
|
|
445
476
|
const scalar = primitiveType === 'u32' ? '0u' : primitiveType === 'i32' ? '0' : '0.0';
|
|
446
477
|
return components === 1 ? scalar : `${getGLSLAttributeType(type)}(${scalar})`;
|
|
447
478
|
}
|
|
448
479
|
|
|
449
|
-
function getWGSLZeroValue(type:
|
|
480
|
+
function getWGSLZeroValue(type: ResolvedShaderPluginInterStageVariable['type']): string {
|
|
450
481
|
const {primitiveType, components} = shaderTypeDecoder.getAttributeShaderTypeInfo(type);
|
|
451
482
|
const scalar = `${primitiveType}(0)`;
|
|
452
483
|
return components === 1 ? scalar : `${type}(${scalar})`;
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// SPDX-FileCopyrightText: Copyright (c) vis.gl contributors
|
|
4
4
|
|
|
5
5
|
import {UniformFormat} from '../../../types';
|
|
6
|
-
import {ShaderModule} from '
|
|
6
|
+
import {ShaderModule} from '../../shader-module/shader-module';
|
|
7
7
|
import {capitalize} from '../utils/capitalize';
|
|
8
8
|
|
|
9
9
|
export type GLSLGenerationOptions = {
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// SPDX-License-Identifier: MIT
|
|
3
3
|
// SPDX-FileCopyrightText: Copyright (c) vis.gl contributors
|
|
4
4
|
|
|
5
|
-
import {ShaderModule} from '
|
|
5
|
+
import {ShaderModule} from '../../shader-module/shader-module';
|
|
6
6
|
import {capitalize} from '../utils/capitalize';
|
|
7
7
|
|
|
8
8
|
export type WGSLGenerationOptions = {
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
import {ShaderModule, initializeShaderModules} from './shader-module';
|
|
6
6
|
import {assert} from '../utils/assert';
|
|
7
7
|
|
|
8
|
-
// import type {ShaderModule} from '
|
|
8
|
+
// import type {ShaderModule} from './shader-module';
|
|
9
9
|
|
|
10
10
|
type AbstractModule = {
|
|
11
11
|
name: string;
|