@motion-core/motion-gpu 0.5.0 → 0.6.0
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/core/compute-bindgroup-cache.d.ts +13 -0
- package/dist/core/compute-bindgroup-cache.d.ts.map +1 -0
- package/dist/core/compute-bindgroup-cache.js +45 -0
- package/dist/core/compute-bindgroup-cache.js.map +1 -0
- package/dist/core/compute-shader.d.ts +48 -0
- package/dist/core/compute-shader.d.ts.map +1 -1
- package/dist/core/compute-shader.js +34 -1
- package/dist/core/compute-shader.js.map +1 -1
- package/dist/core/error-diagnostics.d.ts +8 -1
- package/dist/core/error-diagnostics.d.ts.map +1 -1
- package/dist/core/error-diagnostics.js +7 -3
- package/dist/core/error-diagnostics.js.map +1 -1
- package/dist/core/error-report.d.ts.map +1 -1
- package/dist/core/error-report.js +19 -1
- package/dist/core/error-report.js.map +1 -1
- package/dist/core/material.d.ts.map +1 -1
- package/dist/core/material.js +2 -1
- package/dist/core/material.js.map +1 -1
- package/dist/core/renderer.d.ts.map +1 -1
- package/dist/core/renderer.js +150 -85
- package/dist/core/renderer.js.map +1 -1
- package/dist/core/runtime-loop.d.ts.map +1 -1
- package/dist/core/runtime-loop.js +26 -14
- package/dist/core/runtime-loop.js.map +1 -1
- package/dist/core/shader.d.ts +7 -2
- package/dist/core/shader.d.ts.map +1 -1
- package/dist/core/shader.js +1 -0
- package/dist/core/shader.js.map +1 -1
- package/dist/core/textures.d.ts +4 -0
- package/dist/core/textures.d.ts.map +1 -1
- package/dist/core/textures.js +2 -1
- package/dist/core/textures.js.map +1 -1
- package/dist/core/types.d.ts +1 -1
- package/dist/core/types.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/lib/core/compute-bindgroup-cache.ts +73 -0
- package/src/lib/core/compute-shader.ts +86 -0
- package/src/lib/core/error-diagnostics.ts +29 -4
- package/src/lib/core/error-report.ts +26 -1
- package/src/lib/core/material.ts +2 -1
- package/src/lib/core/renderer.ts +198 -92
- package/src/lib/core/runtime-loop.ts +37 -16
- package/src/lib/core/shader.ts +13 -2
- package/src/lib/core/textures.ts +6 -1
- package/src/lib/core/types.ts +1 -1
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/// <reference types="@webgpu/types" />
|
|
2
|
+
export interface ComputeStorageBindGroupCacheRequest {
|
|
3
|
+
topologyKey: string;
|
|
4
|
+
layoutEntries: GPUBindGroupLayoutEntry[];
|
|
5
|
+
bindGroupEntries: GPUBindGroupEntry[];
|
|
6
|
+
resourceRefs: readonly unknown[];
|
|
7
|
+
}
|
|
8
|
+
export interface ComputeStorageBindGroupCache {
|
|
9
|
+
getOrCreate: (request: ComputeStorageBindGroupCacheRequest) => GPUBindGroup | null;
|
|
10
|
+
reset: () => void;
|
|
11
|
+
}
|
|
12
|
+
export declare function createComputeStorageBindGroupCache(device: GPUDevice): ComputeStorageBindGroupCache;
|
|
13
|
+
//# sourceMappingURL=compute-bindgroup-cache.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compute-bindgroup-cache.d.ts","sourceRoot":"","sources":["../../src/lib/core/compute-bindgroup-cache.ts"],"names":[],"mappings":";AAAA,MAAM,WAAW,mCAAmC;IACnD,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,uBAAuB,EAAE,CAAC;IACzC,gBAAgB,EAAE,iBAAiB,EAAE,CAAC;IACtC,YAAY,EAAE,SAAS,OAAO,EAAE,CAAC;CACjC;AAED,MAAM,WAAW,4BAA4B;IAC5C,WAAW,EAAE,CAAC,OAAO,EAAE,mCAAmC,KAAK,YAAY,GAAG,IAAI,CAAC;IACnF,KAAK,EAAE,MAAM,IAAI,CAAC;CAClB;AAgBD,wBAAgB,kCAAkC,CACjD,MAAM,EAAE,SAAS,GACf,4BAA4B,CA4C9B"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
//#region src/lib/core/compute-bindgroup-cache.ts
|
|
2
|
+
function equalResourceRefs(previous, next) {
|
|
3
|
+
if (previous.length !== next.length) return false;
|
|
4
|
+
for (let index = 0; index < previous.length; index += 1) if (!Object.is(previous[index], next[index])) return false;
|
|
5
|
+
return true;
|
|
6
|
+
}
|
|
7
|
+
function createComputeStorageBindGroupCache(device) {
|
|
8
|
+
let cachedTopologyKey = null;
|
|
9
|
+
let cachedLayout = null;
|
|
10
|
+
let cachedBindGroup = null;
|
|
11
|
+
let cachedResourceRefs = [];
|
|
12
|
+
const reset = () => {
|
|
13
|
+
cachedTopologyKey = null;
|
|
14
|
+
cachedLayout = null;
|
|
15
|
+
cachedBindGroup = null;
|
|
16
|
+
cachedResourceRefs = [];
|
|
17
|
+
};
|
|
18
|
+
return {
|
|
19
|
+
getOrCreate(request) {
|
|
20
|
+
if (request.layoutEntries.length === 0) {
|
|
21
|
+
reset();
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
if (cachedTopologyKey !== request.topologyKey) {
|
|
25
|
+
cachedTopologyKey = request.topologyKey;
|
|
26
|
+
cachedLayout = device.createBindGroupLayout({ entries: request.layoutEntries });
|
|
27
|
+
cachedBindGroup = null;
|
|
28
|
+
cachedResourceRefs = [];
|
|
29
|
+
}
|
|
30
|
+
if (!cachedLayout) throw new Error("Compute storage bind group cache is missing a layout.");
|
|
31
|
+
if (cachedBindGroup && equalResourceRefs(cachedResourceRefs, request.resourceRefs)) return cachedBindGroup;
|
|
32
|
+
cachedBindGroup = device.createBindGroup({
|
|
33
|
+
layout: cachedLayout,
|
|
34
|
+
entries: request.bindGroupEntries
|
|
35
|
+
});
|
|
36
|
+
cachedResourceRefs = [...request.resourceRefs];
|
|
37
|
+
return cachedBindGroup;
|
|
38
|
+
},
|
|
39
|
+
reset
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
//#endregion
|
|
43
|
+
export { createComputeStorageBindGroupCache };
|
|
44
|
+
|
|
45
|
+
//# sourceMappingURL=compute-bindgroup-cache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compute-bindgroup-cache.js","names":[],"sources":["../../src/lib/core/compute-bindgroup-cache.ts"],"sourcesContent":["export interface ComputeStorageBindGroupCacheRequest {\n\ttopologyKey: string;\n\tlayoutEntries: GPUBindGroupLayoutEntry[];\n\tbindGroupEntries: GPUBindGroupEntry[];\n\tresourceRefs: readonly unknown[];\n}\n\nexport interface ComputeStorageBindGroupCache {\n\tgetOrCreate: (request: ComputeStorageBindGroupCacheRequest) => GPUBindGroup | null;\n\treset: () => void;\n}\n\nfunction equalResourceRefs(previous: readonly unknown[], next: readonly unknown[]): boolean {\n\tif (previous.length !== next.length) {\n\t\treturn false;\n\t}\n\n\tfor (let index = 0; index < previous.length; index += 1) {\n\t\tif (!Object.is(previous[index], next[index])) {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\treturn true;\n}\n\nexport function createComputeStorageBindGroupCache(\n\tdevice: GPUDevice\n): ComputeStorageBindGroupCache {\n\tlet cachedTopologyKey: string | null = null;\n\tlet cachedLayout: GPUBindGroupLayout | null = null;\n\tlet cachedBindGroup: GPUBindGroup | null = null;\n\tlet cachedResourceRefs: readonly unknown[] = [];\n\n\tconst reset = (): void => {\n\t\tcachedTopologyKey = null;\n\t\tcachedLayout = null;\n\t\tcachedBindGroup = null;\n\t\tcachedResourceRefs = [];\n\t};\n\n\treturn {\n\t\tgetOrCreate(request) {\n\t\t\tif (request.layoutEntries.length === 0) {\n\t\t\t\treset();\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\tif (cachedTopologyKey !== request.topologyKey) {\n\t\t\t\tcachedTopologyKey = request.topologyKey;\n\t\t\t\tcachedLayout = device.createBindGroupLayout({ entries: request.layoutEntries });\n\t\t\t\tcachedBindGroup = null;\n\t\t\t\tcachedResourceRefs = [];\n\t\t\t}\n\n\t\t\tif (!cachedLayout) {\n\t\t\t\tthrow new Error('Compute storage bind group cache is missing a layout.');\n\t\t\t}\n\n\t\t\tif (cachedBindGroup && equalResourceRefs(cachedResourceRefs, request.resourceRefs)) {\n\t\t\t\treturn cachedBindGroup;\n\t\t\t}\n\n\t\t\tcachedBindGroup = device.createBindGroup({\n\t\t\t\tlayout: cachedLayout,\n\t\t\t\tentries: request.bindGroupEntries\n\t\t\t});\n\t\t\tcachedResourceRefs = [...request.resourceRefs];\n\t\t\treturn cachedBindGroup;\n\t\t},\n\t\treset\n\t};\n}\n"],"mappings":";AAYA,SAAS,kBAAkB,UAA8B,MAAmC;AAC3F,KAAI,SAAS,WAAW,KAAK,OAC5B,QAAO;AAGR,MAAK,IAAI,QAAQ,GAAG,QAAQ,SAAS,QAAQ,SAAS,EACrD,KAAI,CAAC,OAAO,GAAG,SAAS,QAAQ,KAAK,OAAO,CAC3C,QAAO;AAIT,QAAO;;AAGR,SAAgB,mCACf,QAC+B;CAC/B,IAAI,oBAAmC;CACvC,IAAI,eAA0C;CAC9C,IAAI,kBAAuC;CAC3C,IAAI,qBAAyC,EAAE;CAE/C,MAAM,cAAoB;AACzB,sBAAoB;AACpB,iBAAe;AACf,oBAAkB;AAClB,uBAAqB,EAAE;;AAGxB,QAAO;EACN,YAAY,SAAS;AACpB,OAAI,QAAQ,cAAc,WAAW,GAAG;AACvC,WAAO;AACP,WAAO;;AAGR,OAAI,sBAAsB,QAAQ,aAAa;AAC9C,wBAAoB,QAAQ;AAC5B,mBAAe,OAAO,sBAAsB,EAAE,SAAS,QAAQ,eAAe,CAAC;AAC/E,sBAAkB;AAClB,yBAAqB,EAAE;;AAGxB,OAAI,CAAC,aACJ,OAAM,IAAI,MAAM,wDAAwD;AAGzE,OAAI,mBAAmB,kBAAkB,oBAAoB,QAAQ,aAAa,CACjF,QAAO;AAGR,qBAAkB,OAAO,gBAAgB;IACxC,QAAQ;IACR,SAAS,QAAQ;IACjB,CAAC;AACF,wBAAqB,CAAC,GAAG,QAAQ,aAAa;AAC9C,UAAO;;EAER;EACA"}
|
|
@@ -65,6 +65,24 @@ export declare function buildPingPongComputeShaderSource(options: {
|
|
|
65
65
|
target: string;
|
|
66
66
|
targetFormat: GPUTextureFormat;
|
|
67
67
|
}): string;
|
|
68
|
+
/**
|
|
69
|
+
* Source location for generated compute shader lines.
|
|
70
|
+
*/
|
|
71
|
+
export interface ComputeShaderSourceLocation {
|
|
72
|
+
kind: 'compute';
|
|
73
|
+
line: number;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* 1-based line map from generated compute WGSL to user compute source.
|
|
77
|
+
*/
|
|
78
|
+
export type ComputeShaderLineMap = Array<ComputeShaderSourceLocation | null>;
|
|
79
|
+
/**
|
|
80
|
+
* Result of compute shader source generation with line mapping metadata.
|
|
81
|
+
*/
|
|
82
|
+
export interface BuiltComputeShaderSource {
|
|
83
|
+
code: string;
|
|
84
|
+
lineMap: ComputeShaderLineMap;
|
|
85
|
+
}
|
|
68
86
|
/**
|
|
69
87
|
* Assembles full compute shader WGSL with preamble.
|
|
70
88
|
*
|
|
@@ -84,4 +102,34 @@ export declare function buildComputeShaderSource(options: {
|
|
|
84
102
|
format: GPUTextureFormat;
|
|
85
103
|
}>;
|
|
86
104
|
}): string;
|
|
105
|
+
/**
|
|
106
|
+
* Assembles full compute shader WGSL with source line mapping metadata.
|
|
107
|
+
*/
|
|
108
|
+
export declare function buildComputeShaderSourceWithMap(options: {
|
|
109
|
+
compute: string;
|
|
110
|
+
uniformLayout: UniformLayout;
|
|
111
|
+
storageBufferKeys: string[];
|
|
112
|
+
storageBufferDefinitions: Record<string, {
|
|
113
|
+
type: StorageBufferType;
|
|
114
|
+
access: StorageBufferAccess;
|
|
115
|
+
}>;
|
|
116
|
+
storageTextureKeys: string[];
|
|
117
|
+
storageTextureDefinitions: Record<string, {
|
|
118
|
+
format: GPUTextureFormat;
|
|
119
|
+
}>;
|
|
120
|
+
}): BuiltComputeShaderSource;
|
|
121
|
+
/**
|
|
122
|
+
* Assembles ping-pong compute shader WGSL with source line mapping metadata.
|
|
123
|
+
*/
|
|
124
|
+
export declare function buildPingPongComputeShaderSourceWithMap(options: {
|
|
125
|
+
compute: string;
|
|
126
|
+
uniformLayout: UniformLayout;
|
|
127
|
+
storageBufferKeys: string[];
|
|
128
|
+
storageBufferDefinitions: Record<string, {
|
|
129
|
+
type: StorageBufferType;
|
|
130
|
+
access: StorageBufferAccess;
|
|
131
|
+
}>;
|
|
132
|
+
target: string;
|
|
133
|
+
targetFormat: GPUTextureFormat;
|
|
134
|
+
}): BuiltComputeShaderSource;
|
|
87
135
|
//# sourceMappingURL=compute-shader.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compute-shader.d.ts","sourceRoot":"","sources":["../../src/lib/core/compute-shader.ts"],"names":[],"mappings":";AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAExF;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,QAA+D,CAAC;AA+DnG;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAc3D;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAc9E;AA2BD;;;;;;;GAOG;AACH,wBAAgB,iCAAiC,CAChD,iBAAiB,EAAE,MAAM,EAAE,EAC3B,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE;IAAE,IAAI,EAAE,iBAAiB,CAAC;IAAC,MAAM,EAAE,mBAAmB,CAAA;CAAE,CAAC,EACrF,UAAU,EAAE,MAAM,GAChB,MAAM,CAyBR;AAED;;;;;;;GAOG;AACH,wBAAgB,kCAAkC,CACjD,kBAAkB,EAAE,MAAM,EAAE,EAC5B,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE;IAAE,MAAM,EAAE,gBAAgB,CAAA;CAAE,CAAC,EACzD,UAAU,EAAE,MAAM,GAChB,MAAM,CAwBR;AAED;;GAEG;AACH,wBAAgB,8BAA8B,CAAC,MAAM,EAAE,gBAAgB,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,CAS9F;AAED;;;;;;GAMG;AACH,wBAAgB,gCAAgC,CAAC,OAAO,EAAE;IACzD,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,aAAa,CAAC;IAC7B,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B,wBAAwB,EAAE,MAAM,CAC/B,MAAM,EACN;QAAE,IAAI,EAAE,iBAAiB,CAAC;QAAC,MAAM,EAAE,mBAAmB,CAAA;KAAE,CACxD,CAAC;IACF,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,gBAAgB,CAAC;CAC/B,GAAG,MAAM,CA8BT;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CAAC,OAAO,EAAE;IACjD,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,aAAa,CAAC;IAC7B,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B,wBAAwB,EAAE,MAAM,CAC/B,MAAM,EACN;QAAE,IAAI,EAAE,iBAAiB,CAAC;QAAC,MAAM,EAAE,mBAAmB,CAAA;KAAE,CACxD,CAAC;IACF,kBAAkB,EAAE,MAAM,EAAE,CAAC;IAC7B,yBAAyB,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,MAAM,EAAE,gBAAgB,CAAA;KAAE,CAAC,CAAC;CACxE,GAAG,MAAM,CA8BT"}
|
|
1
|
+
{"version":3,"file":"compute-shader.d.ts","sourceRoot":"","sources":["../../src/lib/core/compute-shader.ts"],"names":[],"mappings":";AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAExF;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,QAA+D,CAAC;AA+DnG;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAc3D;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAc9E;AA2BD;;;;;;;GAOG;AACH,wBAAgB,iCAAiC,CAChD,iBAAiB,EAAE,MAAM,EAAE,EAC3B,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE;IAAE,IAAI,EAAE,iBAAiB,CAAC;IAAC,MAAM,EAAE,mBAAmB,CAAA;CAAE,CAAC,EACrF,UAAU,EAAE,MAAM,GAChB,MAAM,CAyBR;AAED;;;;;;;GAOG;AACH,wBAAgB,kCAAkC,CACjD,kBAAkB,EAAE,MAAM,EAAE,EAC5B,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE;IAAE,MAAM,EAAE,gBAAgB,CAAA;CAAE,CAAC,EACzD,UAAU,EAAE,MAAM,GAChB,MAAM,CAwBR;AAED;;GAEG;AACH,wBAAgB,8BAA8B,CAAC,MAAM,EAAE,gBAAgB,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,CAS9F;AAED;;;;;;GAMG;AACH,wBAAgB,gCAAgC,CAAC,OAAO,EAAE;IACzD,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,aAAa,CAAC;IAC7B,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B,wBAAwB,EAAE,MAAM,CAC/B,MAAM,EACN;QAAE,IAAI,EAAE,iBAAiB,CAAC;QAAC,MAAM,EAAE,mBAAmB,CAAA;KAAE,CACxD,CAAC;IACF,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,gBAAgB,CAAC;CAC/B,GAAG,MAAM,CA8BT;AAED;;GAEG;AACH,MAAM,WAAW,2BAA2B;IAC3C,IAAI,EAAE,SAAS,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;CACb;AAED;;GAEG;AACH,MAAM,MAAM,oBAAoB,GAAG,KAAK,CAAC,2BAA2B,GAAG,IAAI,CAAC,CAAC;AAE7E;;GAEG;AACH,MAAM,WAAW,wBAAwB;IACxC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,oBAAoB,CAAC;CAC9B;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CAAC,OAAO,EAAE;IACjD,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,aAAa,CAAC;IAC7B,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B,wBAAwB,EAAE,MAAM,CAC/B,MAAM,EACN;QAAE,IAAI,EAAE,iBAAiB,CAAC;QAAC,MAAM,EAAE,mBAAmB,CAAA;KAAE,CACxD,CAAC;IACF,kBAAkB,EAAE,MAAM,EAAE,CAAC;IAC7B,yBAAyB,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,MAAM,EAAE,gBAAgB,CAAA;KAAE,CAAC,CAAC;CACxE,GAAG,MAAM,CA8BT;AAyBD;;GAEG;AACH,wBAAgB,+BAA+B,CAAC,OAAO,EAAE;IACxD,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,aAAa,CAAC;IAC7B,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B,wBAAwB,EAAE,MAAM,CAC/B,MAAM,EACN;QAAE,IAAI,EAAE,iBAAiB,CAAC;QAAC,MAAM,EAAE,mBAAmB,CAAA;KAAE,CACxD,CAAC;IACF,kBAAkB,EAAE,MAAM,EAAE,CAAC;IAC7B,yBAAyB,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,MAAM,EAAE,gBAAgB,CAAA;KAAE,CAAC,CAAC;CACxE,GAAG,wBAAwB,CAM3B;AAED;;GAEG;AACH,wBAAgB,uCAAuC,CAAC,OAAO,EAAE;IAChE,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,aAAa,CAAC;IAC7B,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B,wBAAwB,EAAE,MAAM,CAC/B,MAAM,EACN;QAAE,IAAI,EAAE,iBAAiB,CAAC;QAAC,MAAM,EAAE,mBAAmB,CAAA;KAAE,CACxD,CAAC;IACF,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,gBAAgB,CAAC;CAC/B,GAAG,wBAAwB,CAM3B"}
|
|
@@ -199,7 +199,40 @@ ${storageTextureBindings ? "\n" + storageTextureBindings : ""}
|
|
|
199
199
|
${options.compute}
|
|
200
200
|
`;
|
|
201
201
|
}
|
|
202
|
+
function buildComputeLineMap(generatedCode, userComputeSource) {
|
|
203
|
+
const lineCount = generatedCode.split("\n").length;
|
|
204
|
+
const lineMap = new Array(lineCount + 1).fill(null);
|
|
205
|
+
const computeStartIndex = generatedCode.indexOf(userComputeSource);
|
|
206
|
+
if (computeStartIndex === -1) return lineMap;
|
|
207
|
+
const computeStartLine = generatedCode.slice(0, computeStartIndex).split("\n").length;
|
|
208
|
+
const computeLineCount = userComputeSource.split("\n").length;
|
|
209
|
+
for (let line = 0; line < computeLineCount; line += 1) lineMap[computeStartLine + line] = {
|
|
210
|
+
kind: "compute",
|
|
211
|
+
line: line + 1
|
|
212
|
+
};
|
|
213
|
+
return lineMap;
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* Assembles full compute shader WGSL with source line mapping metadata.
|
|
217
|
+
*/
|
|
218
|
+
function buildComputeShaderSourceWithMap(options) {
|
|
219
|
+
const code = buildComputeShaderSource(options);
|
|
220
|
+
return {
|
|
221
|
+
code,
|
|
222
|
+
lineMap: buildComputeLineMap(code, options.compute)
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* Assembles ping-pong compute shader WGSL with source line mapping metadata.
|
|
227
|
+
*/
|
|
228
|
+
function buildPingPongComputeShaderSourceWithMap(options) {
|
|
229
|
+
const code = buildPingPongComputeShaderSource(options);
|
|
230
|
+
return {
|
|
231
|
+
code,
|
|
232
|
+
lineMap: buildComputeLineMap(code, options.compute)
|
|
233
|
+
};
|
|
234
|
+
}
|
|
202
235
|
//#endregion
|
|
203
|
-
export { COMPUTE_ENTRY_CONTRACT, assertComputeContract, buildComputeShaderSource, buildComputeStorageBufferBindings, buildComputeStorageTextureBindings, buildPingPongComputeShaderSource, extractWorkgroupSize, storageTextureSampleScalarType };
|
|
236
|
+
export { COMPUTE_ENTRY_CONTRACT, assertComputeContract, buildComputeShaderSource, buildComputeShaderSourceWithMap, buildComputeStorageBufferBindings, buildComputeStorageTextureBindings, buildPingPongComputeShaderSource, buildPingPongComputeShaderSourceWithMap, extractWorkgroupSize, storageTextureSampleScalarType };
|
|
204
237
|
|
|
205
238
|
//# sourceMappingURL=compute-shader.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compute-shader.js","names":[],"sources":["../../src/lib/core/compute-shader.ts"],"sourcesContent":["import type { StorageBufferAccess, StorageBufferType, UniformLayout } from './types.js';\n\n/**\n * Regex contract for compute entrypoint.\n * Matches: @compute @workgroup_size(...) fn compute(\n * with @builtin(global_invocation_id) parameter.\n */\nexport const COMPUTE_ENTRY_CONTRACT = /@compute\\s+@workgroup_size\\s*\\([^)]+\\)\\s*fn\\s+compute\\s*\\(/;\n\n/**\n * Regex to extract @workgroup_size values.\n */\nconst WORKGROUP_SIZE_PATTERN =\n\t/@workgroup_size\\s*\\(\\s*(\\d+)(?:\\s*,\\s*(\\d+))?(?:\\s*,\\s*(\\d+))?\\s*\\)/;\n\n/**\n * Regex to verify @builtin(global_invocation_id) parameter.\n */\nconst GLOBAL_INVOCATION_ID_PATTERN = /@builtin\\s*\\(\\s*global_invocation_id\\s*\\)/;\nconst WORKGROUP_DIMENSION_MIN = 1;\nconst WORKGROUP_DIMENSION_MAX = 65535;\n\nfunction extractComputeParamList(compute: string): string | null {\n\tconst computeFnIndex = compute.indexOf('fn compute');\n\tif (computeFnIndex === -1) {\n\t\treturn null;\n\t}\n\n\tconst openParenIndex = compute.indexOf('(', computeFnIndex);\n\tif (openParenIndex === -1) {\n\t\treturn null;\n\t}\n\n\tlet depth = 0;\n\tfor (let index = openParenIndex; index < compute.length; index += 1) {\n\t\tconst char = compute[index];\n\t\tif (char === '(') {\n\t\t\tdepth += 1;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (char === ')') {\n\t\t\tdepth -= 1;\n\t\t\tif (depth === 0) {\n\t\t\t\treturn compute.slice(openParenIndex + 1, index);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn null;\n}\n\nfunction assertWorkgroupDimension(value: number): void {\n\tif (\n\t\t!Number.isFinite(value) ||\n\t\t!Number.isInteger(value) ||\n\t\tvalue < WORKGROUP_DIMENSION_MIN ||\n\t\tvalue > WORKGROUP_DIMENSION_MAX\n\t) {\n\t\tthrow new Error(\n\t\t\t`@workgroup_size dimensions must be integers in range ${WORKGROUP_DIMENSION_MIN}-${WORKGROUP_DIMENSION_MAX}, got ${value}.`\n\t\t);\n\t}\n}\n\n/**\n * Default uniform field used when no custom uniforms are provided in compute.\n */\nconst DEFAULT_UNIFORM_FIELD = 'motiongpu_unused: vec4f,';\n\n/**\n * Validates compute shader user code matches the compute contract.\n *\n * @param compute - User compute shader WGSL source.\n * @throws {Error} When shader does not match the compute contract.\n */\nexport function assertComputeContract(compute: string): void {\n\tif (!COMPUTE_ENTRY_CONTRACT.test(compute)) {\n\t\tthrow new Error(\n\t\t\t'Compute shader must declare `@compute @workgroup_size(...) fn compute(...)`. ' +\n\t\t\t\t'Ensure the function is named `compute` and includes @compute and @workgroup_size annotations.'\n\t\t);\n\t}\n\n\tconst params = extractComputeParamList(compute);\n\tif (!params || !GLOBAL_INVOCATION_ID_PATTERN.test(params)) {\n\t\tthrow new Error('Compute shader must include a `@builtin(global_invocation_id)` parameter.');\n\t}\n\n\textractWorkgroupSize(compute);\n}\n\n/**\n * Extracts @workgroup_size values from WGSL compute shader.\n *\n * @param compute - Validated compute shader source.\n * @returns Tuple [x, y, z] with defaults of 1 for omitted dimensions.\n */\nexport function extractWorkgroupSize(compute: string): [number, number, number] {\n\tconst match = compute.match(WORKGROUP_SIZE_PATTERN);\n\tif (!match) {\n\t\tthrow new Error('Could not extract @workgroup_size from compute shader source.');\n\t}\n\n\tconst x = Number.parseInt(match[1] ?? '1', 10);\n\tconst y = Number.parseInt(match[2] ?? '1', 10);\n\tconst z = Number.parseInt(match[3] ?? '1', 10);\n\tassertWorkgroupDimension(x);\n\tassertWorkgroupDimension(y);\n\tassertWorkgroupDimension(z);\n\n\treturn [x, y, z];\n}\n\n/**\n * Maps StorageBufferAccess to WGSL var qualifier.\n */\nfunction toWgslAccessMode(access: StorageBufferAccess): string {\n\tswitch (access) {\n\t\tcase 'read':\n\t\t\treturn 'read';\n\t\tcase 'read-write':\n\t\t\treturn 'read_write';\n\t\tdefault:\n\t\t\tthrow new Error(`Unsupported storage buffer access mode \"${String(access)}\".`);\n\t}\n}\n\n/**\n * Builds WGSL struct fields for uniforms used in compute shader preamble.\n */\nfunction buildUniformStructForCompute(layout: UniformLayout): string {\n\tif (layout.entries.length === 0) {\n\t\treturn DEFAULT_UNIFORM_FIELD;\n\t}\n\n\treturn layout.entries.map((entry) => `${entry.name}: ${entry.type},`).join('\\n\\t');\n}\n\n/**\n * Builds storage buffer binding declarations for compute shader.\n *\n * @param storageBufferKeys - Sorted buffer keys.\n * @param definitions - Type/access definitions per key.\n * @param groupIndex - Bind group index for storage buffers.\n * @returns WGSL binding declaration string.\n */\nexport function buildComputeStorageBufferBindings(\n\tstorageBufferKeys: string[],\n\tdefinitions: Record<string, { type: StorageBufferType; access: StorageBufferAccess }>,\n\tgroupIndex: number\n): string {\n\tif (storageBufferKeys.length === 0) {\n\t\treturn '';\n\t}\n\n\tconst declarations: string[] = [];\n\n\tfor (let index = 0; index < storageBufferKeys.length; index += 1) {\n\t\tconst key = storageBufferKeys[index];\n\t\tif (key === undefined) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst definition = definitions[key];\n\t\tif (!definition) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst accessMode = toWgslAccessMode(definition.access);\n\t\tdeclarations.push(\n\t\t\t`@group(${groupIndex}) @binding(${index}) var<storage, ${accessMode}> ${key}: ${definition.type};`\n\t\t);\n\t}\n\n\treturn declarations.join('\\n');\n}\n\n/**\n * Builds storage texture binding declarations for compute shader.\n *\n * @param storageTextureKeys - Sorted storage texture keys.\n * @param definitions - Format definitions per key.\n * @param groupIndex - Bind group index for storage textures.\n * @returns WGSL binding declaration string.\n */\nexport function buildComputeStorageTextureBindings(\n\tstorageTextureKeys: string[],\n\tdefinitions: Record<string, { format: GPUTextureFormat }>,\n\tgroupIndex: number\n): string {\n\tif (storageTextureKeys.length === 0) {\n\t\treturn '';\n\t}\n\n\tconst declarations: string[] = [];\n\n\tfor (let index = 0; index < storageTextureKeys.length; index += 1) {\n\t\tconst key = storageTextureKeys[index];\n\t\tif (key === undefined) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst definition = definitions[key];\n\t\tif (!definition) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tdeclarations.push(\n\t\t\t`@group(${groupIndex}) @binding(${index}) var ${key}: texture_storage_2d<${definition.format}, write>;`\n\t\t);\n\t}\n\n\treturn declarations.join('\\n');\n}\n\n/**\n * Maps storage texture format to sampled texture scalar type for `texture_2d<T>`.\n */\nexport function storageTextureSampleScalarType(format: GPUTextureFormat): 'f32' | 'u32' | 'i32' {\n\tconst normalized = String(format).toLowerCase();\n\tif (normalized.endsWith('uint')) {\n\t\treturn 'u32';\n\t}\n\tif (normalized.endsWith('sint')) {\n\t\treturn 'i32';\n\t}\n\treturn 'f32';\n}\n\n/**\n * Assembles compute shader WGSL for ping-pong workflows.\n *\n * Exposes two generated bindings under group(2):\n * - `${target}A`: sampled read texture (`texture_2d<T>`)\n * - `${target}B`: storage write texture (`texture_storage_2d<format, write>`)\n */\nexport function buildPingPongComputeShaderSource(options: {\n\tcompute: string;\n\tuniformLayout: UniformLayout;\n\tstorageBufferKeys: string[];\n\tstorageBufferDefinitions: Record<\n\t\tstring,\n\t\t{ type: StorageBufferType; access: StorageBufferAccess }\n\t>;\n\ttarget: string;\n\ttargetFormat: GPUTextureFormat;\n}): string {\n\tconst uniformFields = buildUniformStructForCompute(options.uniformLayout);\n\tconst storageBufferBindings = buildComputeStorageBufferBindings(\n\t\toptions.storageBufferKeys,\n\t\toptions.storageBufferDefinitions,\n\t\t1\n\t);\n\tconst sampledType = storageTextureSampleScalarType(options.targetFormat);\n\tconst pingPongTextureBindings = [\n\t\t`@group(2) @binding(0) var ${options.target}A: texture_2d<${sampledType}>;`,\n\t\t`@group(2) @binding(1) var ${options.target}B: texture_storage_2d<${options.targetFormat}, write>;`\n\t].join('\\n');\n\n\treturn `struct MotionGPUFrame {\n\ttime: f32,\n\tdelta: f32,\n\tresolution: vec2f,\n};\n\nstruct MotionGPUUniforms {\n\t${uniformFields}\n};\n\n@group(0) @binding(0) var<uniform> motiongpuFrame: MotionGPUFrame;\n@group(0) @binding(1) var<uniform> motiongpuUniforms: MotionGPUUniforms;\n${storageBufferBindings ? '\\n' + storageBufferBindings : ''}\n${pingPongTextureBindings ? '\\n' + pingPongTextureBindings : ''}\n\n${options.compute}\n`;\n}\n\n/**\n * Assembles full compute shader WGSL with preamble.\n *\n * @param options - Compute shader build options.\n * @returns Complete WGSL source for compute stage.\n */\nexport function buildComputeShaderSource(options: {\n\tcompute: string;\n\tuniformLayout: UniformLayout;\n\tstorageBufferKeys: string[];\n\tstorageBufferDefinitions: Record<\n\t\tstring,\n\t\t{ type: StorageBufferType; access: StorageBufferAccess }\n\t>;\n\tstorageTextureKeys: string[];\n\tstorageTextureDefinitions: Record<string, { format: GPUTextureFormat }>;\n}): string {\n\tconst uniformFields = buildUniformStructForCompute(options.uniformLayout);\n\tconst storageBufferBindings = buildComputeStorageBufferBindings(\n\t\toptions.storageBufferKeys,\n\t\toptions.storageBufferDefinitions,\n\t\t1\n\t);\n\tconst storageTextureBindings = buildComputeStorageTextureBindings(\n\t\toptions.storageTextureKeys,\n\t\toptions.storageTextureDefinitions,\n\t\t2\n\t);\n\n\treturn `struct MotionGPUFrame {\n\ttime: f32,\n\tdelta: f32,\n\tresolution: vec2f,\n};\n\nstruct MotionGPUUniforms {\n\t${uniformFields}\n};\n\n@group(0) @binding(0) var<uniform> motiongpuFrame: MotionGPUFrame;\n@group(0) @binding(1) var<uniform> motiongpuUniforms: MotionGPUUniforms;\n${storageBufferBindings ? '\\n' + storageBufferBindings : ''}\n${storageTextureBindings ? '\\n' + storageTextureBindings : ''}\n\n${options.compute}\n`;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"compute-shader.js","names":[],"sources":["../../src/lib/core/compute-shader.ts"],"sourcesContent":["import type { StorageBufferAccess, StorageBufferType, UniformLayout } from './types.js';\n\n/**\n * Regex contract for compute entrypoint.\n * Matches: @compute @workgroup_size(...) fn compute(\n * with @builtin(global_invocation_id) parameter.\n */\nexport const COMPUTE_ENTRY_CONTRACT = /@compute\\s+@workgroup_size\\s*\\([^)]+\\)\\s*fn\\s+compute\\s*\\(/;\n\n/**\n * Regex to extract @workgroup_size values.\n */\nconst WORKGROUP_SIZE_PATTERN =\n\t/@workgroup_size\\s*\\(\\s*(\\d+)(?:\\s*,\\s*(\\d+))?(?:\\s*,\\s*(\\d+))?\\s*\\)/;\n\n/**\n * Regex to verify @builtin(global_invocation_id) parameter.\n */\nconst GLOBAL_INVOCATION_ID_PATTERN = /@builtin\\s*\\(\\s*global_invocation_id\\s*\\)/;\nconst WORKGROUP_DIMENSION_MIN = 1;\nconst WORKGROUP_DIMENSION_MAX = 65535;\n\nfunction extractComputeParamList(compute: string): string | null {\n\tconst computeFnIndex = compute.indexOf('fn compute');\n\tif (computeFnIndex === -1) {\n\t\treturn null;\n\t}\n\n\tconst openParenIndex = compute.indexOf('(', computeFnIndex);\n\tif (openParenIndex === -1) {\n\t\treturn null;\n\t}\n\n\tlet depth = 0;\n\tfor (let index = openParenIndex; index < compute.length; index += 1) {\n\t\tconst char = compute[index];\n\t\tif (char === '(') {\n\t\t\tdepth += 1;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (char === ')') {\n\t\t\tdepth -= 1;\n\t\t\tif (depth === 0) {\n\t\t\t\treturn compute.slice(openParenIndex + 1, index);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn null;\n}\n\nfunction assertWorkgroupDimension(value: number): void {\n\tif (\n\t\t!Number.isFinite(value) ||\n\t\t!Number.isInteger(value) ||\n\t\tvalue < WORKGROUP_DIMENSION_MIN ||\n\t\tvalue > WORKGROUP_DIMENSION_MAX\n\t) {\n\t\tthrow new Error(\n\t\t\t`@workgroup_size dimensions must be integers in range ${WORKGROUP_DIMENSION_MIN}-${WORKGROUP_DIMENSION_MAX}, got ${value}.`\n\t\t);\n\t}\n}\n\n/**\n * Default uniform field used when no custom uniforms are provided in compute.\n */\nconst DEFAULT_UNIFORM_FIELD = 'motiongpu_unused: vec4f,';\n\n/**\n * Validates compute shader user code matches the compute contract.\n *\n * @param compute - User compute shader WGSL source.\n * @throws {Error} When shader does not match the compute contract.\n */\nexport function assertComputeContract(compute: string): void {\n\tif (!COMPUTE_ENTRY_CONTRACT.test(compute)) {\n\t\tthrow new Error(\n\t\t\t'Compute shader must declare `@compute @workgroup_size(...) fn compute(...)`. ' +\n\t\t\t\t'Ensure the function is named `compute` and includes @compute and @workgroup_size annotations.'\n\t\t);\n\t}\n\n\tconst params = extractComputeParamList(compute);\n\tif (!params || !GLOBAL_INVOCATION_ID_PATTERN.test(params)) {\n\t\tthrow new Error('Compute shader must include a `@builtin(global_invocation_id)` parameter.');\n\t}\n\n\textractWorkgroupSize(compute);\n}\n\n/**\n * Extracts @workgroup_size values from WGSL compute shader.\n *\n * @param compute - Validated compute shader source.\n * @returns Tuple [x, y, z] with defaults of 1 for omitted dimensions.\n */\nexport function extractWorkgroupSize(compute: string): [number, number, number] {\n\tconst match = compute.match(WORKGROUP_SIZE_PATTERN);\n\tif (!match) {\n\t\tthrow new Error('Could not extract @workgroup_size from compute shader source.');\n\t}\n\n\tconst x = Number.parseInt(match[1] ?? '1', 10);\n\tconst y = Number.parseInt(match[2] ?? '1', 10);\n\tconst z = Number.parseInt(match[3] ?? '1', 10);\n\tassertWorkgroupDimension(x);\n\tassertWorkgroupDimension(y);\n\tassertWorkgroupDimension(z);\n\n\treturn [x, y, z];\n}\n\n/**\n * Maps StorageBufferAccess to WGSL var qualifier.\n */\nfunction toWgslAccessMode(access: StorageBufferAccess): string {\n\tswitch (access) {\n\t\tcase 'read':\n\t\t\treturn 'read';\n\t\tcase 'read-write':\n\t\t\treturn 'read_write';\n\t\tdefault:\n\t\t\tthrow new Error(`Unsupported storage buffer access mode \"${String(access)}\".`);\n\t}\n}\n\n/**\n * Builds WGSL struct fields for uniforms used in compute shader preamble.\n */\nfunction buildUniformStructForCompute(layout: UniformLayout): string {\n\tif (layout.entries.length === 0) {\n\t\treturn DEFAULT_UNIFORM_FIELD;\n\t}\n\n\treturn layout.entries.map((entry) => `${entry.name}: ${entry.type},`).join('\\n\\t');\n}\n\n/**\n * Builds storage buffer binding declarations for compute shader.\n *\n * @param storageBufferKeys - Sorted buffer keys.\n * @param definitions - Type/access definitions per key.\n * @param groupIndex - Bind group index for storage buffers.\n * @returns WGSL binding declaration string.\n */\nexport function buildComputeStorageBufferBindings(\n\tstorageBufferKeys: string[],\n\tdefinitions: Record<string, { type: StorageBufferType; access: StorageBufferAccess }>,\n\tgroupIndex: number\n): string {\n\tif (storageBufferKeys.length === 0) {\n\t\treturn '';\n\t}\n\n\tconst declarations: string[] = [];\n\n\tfor (let index = 0; index < storageBufferKeys.length; index += 1) {\n\t\tconst key = storageBufferKeys[index];\n\t\tif (key === undefined) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst definition = definitions[key];\n\t\tif (!definition) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst accessMode = toWgslAccessMode(definition.access);\n\t\tdeclarations.push(\n\t\t\t`@group(${groupIndex}) @binding(${index}) var<storage, ${accessMode}> ${key}: ${definition.type};`\n\t\t);\n\t}\n\n\treturn declarations.join('\\n');\n}\n\n/**\n * Builds storage texture binding declarations for compute shader.\n *\n * @param storageTextureKeys - Sorted storage texture keys.\n * @param definitions - Format definitions per key.\n * @param groupIndex - Bind group index for storage textures.\n * @returns WGSL binding declaration string.\n */\nexport function buildComputeStorageTextureBindings(\n\tstorageTextureKeys: string[],\n\tdefinitions: Record<string, { format: GPUTextureFormat }>,\n\tgroupIndex: number\n): string {\n\tif (storageTextureKeys.length === 0) {\n\t\treturn '';\n\t}\n\n\tconst declarations: string[] = [];\n\n\tfor (let index = 0; index < storageTextureKeys.length; index += 1) {\n\t\tconst key = storageTextureKeys[index];\n\t\tif (key === undefined) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst definition = definitions[key];\n\t\tif (!definition) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tdeclarations.push(\n\t\t\t`@group(${groupIndex}) @binding(${index}) var ${key}: texture_storage_2d<${definition.format}, write>;`\n\t\t);\n\t}\n\n\treturn declarations.join('\\n');\n}\n\n/**\n * Maps storage texture format to sampled texture scalar type for `texture_2d<T>`.\n */\nexport function storageTextureSampleScalarType(format: GPUTextureFormat): 'f32' | 'u32' | 'i32' {\n\tconst normalized = String(format).toLowerCase();\n\tif (normalized.endsWith('uint')) {\n\t\treturn 'u32';\n\t}\n\tif (normalized.endsWith('sint')) {\n\t\treturn 'i32';\n\t}\n\treturn 'f32';\n}\n\n/**\n * Assembles compute shader WGSL for ping-pong workflows.\n *\n * Exposes two generated bindings under group(2):\n * - `${target}A`: sampled read texture (`texture_2d<T>`)\n * - `${target}B`: storage write texture (`texture_storage_2d<format, write>`)\n */\nexport function buildPingPongComputeShaderSource(options: {\n\tcompute: string;\n\tuniformLayout: UniformLayout;\n\tstorageBufferKeys: string[];\n\tstorageBufferDefinitions: Record<\n\t\tstring,\n\t\t{ type: StorageBufferType; access: StorageBufferAccess }\n\t>;\n\ttarget: string;\n\ttargetFormat: GPUTextureFormat;\n}): string {\n\tconst uniformFields = buildUniformStructForCompute(options.uniformLayout);\n\tconst storageBufferBindings = buildComputeStorageBufferBindings(\n\t\toptions.storageBufferKeys,\n\t\toptions.storageBufferDefinitions,\n\t\t1\n\t);\n\tconst sampledType = storageTextureSampleScalarType(options.targetFormat);\n\tconst pingPongTextureBindings = [\n\t\t`@group(2) @binding(0) var ${options.target}A: texture_2d<${sampledType}>;`,\n\t\t`@group(2) @binding(1) var ${options.target}B: texture_storage_2d<${options.targetFormat}, write>;`\n\t].join('\\n');\n\n\treturn `struct MotionGPUFrame {\n\ttime: f32,\n\tdelta: f32,\n\tresolution: vec2f,\n};\n\nstruct MotionGPUUniforms {\n\t${uniformFields}\n};\n\n@group(0) @binding(0) var<uniform> motiongpuFrame: MotionGPUFrame;\n@group(0) @binding(1) var<uniform> motiongpuUniforms: MotionGPUUniforms;\n${storageBufferBindings ? '\\n' + storageBufferBindings : ''}\n${pingPongTextureBindings ? '\\n' + pingPongTextureBindings : ''}\n\n${options.compute}\n`;\n}\n\n/**\n * Source location for generated compute shader lines.\n */\nexport interface ComputeShaderSourceLocation {\n\tkind: 'compute';\n\tline: number;\n}\n\n/**\n * 1-based line map from generated compute WGSL to user compute source.\n */\nexport type ComputeShaderLineMap = Array<ComputeShaderSourceLocation | null>;\n\n/**\n * Result of compute shader source generation with line mapping metadata.\n */\nexport interface BuiltComputeShaderSource {\n\tcode: string;\n\tlineMap: ComputeShaderLineMap;\n}\n\n/**\n * Assembles full compute shader WGSL with preamble.\n *\n * @param options - Compute shader build options.\n * @returns Complete WGSL source for compute stage.\n */\nexport function buildComputeShaderSource(options: {\n\tcompute: string;\n\tuniformLayout: UniformLayout;\n\tstorageBufferKeys: string[];\n\tstorageBufferDefinitions: Record<\n\t\tstring,\n\t\t{ type: StorageBufferType; access: StorageBufferAccess }\n\t>;\n\tstorageTextureKeys: string[];\n\tstorageTextureDefinitions: Record<string, { format: GPUTextureFormat }>;\n}): string {\n\tconst uniformFields = buildUniformStructForCompute(options.uniformLayout);\n\tconst storageBufferBindings = buildComputeStorageBufferBindings(\n\t\toptions.storageBufferKeys,\n\t\toptions.storageBufferDefinitions,\n\t\t1\n\t);\n\tconst storageTextureBindings = buildComputeStorageTextureBindings(\n\t\toptions.storageTextureKeys,\n\t\toptions.storageTextureDefinitions,\n\t\t2\n\t);\n\n\treturn `struct MotionGPUFrame {\n\ttime: f32,\n\tdelta: f32,\n\tresolution: vec2f,\n};\n\nstruct MotionGPUUniforms {\n\t${uniformFields}\n};\n\n@group(0) @binding(0) var<uniform> motiongpuFrame: MotionGPUFrame;\n@group(0) @binding(1) var<uniform> motiongpuUniforms: MotionGPUUniforms;\n${storageBufferBindings ? '\\n' + storageBufferBindings : ''}\n${storageTextureBindings ? '\\n' + storageTextureBindings : ''}\n\n${options.compute}\n`;\n}\n\nfunction buildComputeLineMap(\n\tgeneratedCode: string,\n\tuserComputeSource: string\n): ComputeShaderLineMap {\n\tconst lineCount = generatedCode.split('\\n').length;\n\tconst lineMap: ComputeShaderLineMap = new Array(lineCount + 1).fill(null);\n\tconst computeStartIndex = generatedCode.indexOf(userComputeSource);\n\tif (computeStartIndex === -1) {\n\t\treturn lineMap;\n\t}\n\n\tconst computeStartLine = generatedCode.slice(0, computeStartIndex).split('\\n').length;\n\tconst computeLineCount = userComputeSource.split('\\n').length;\n\tfor (let line = 0; line < computeLineCount; line += 1) {\n\t\tlineMap[computeStartLine + line] = {\n\t\t\tkind: 'compute',\n\t\t\tline: line + 1\n\t\t};\n\t}\n\n\treturn lineMap;\n}\n\n/**\n * Assembles full compute shader WGSL with source line mapping metadata.\n */\nexport function buildComputeShaderSourceWithMap(options: {\n\tcompute: string;\n\tuniformLayout: UniformLayout;\n\tstorageBufferKeys: string[];\n\tstorageBufferDefinitions: Record<\n\t\tstring,\n\t\t{ type: StorageBufferType; access: StorageBufferAccess }\n\t>;\n\tstorageTextureKeys: string[];\n\tstorageTextureDefinitions: Record<string, { format: GPUTextureFormat }>;\n}): BuiltComputeShaderSource {\n\tconst code = buildComputeShaderSource(options);\n\treturn {\n\t\tcode,\n\t\tlineMap: buildComputeLineMap(code, options.compute)\n\t};\n}\n\n/**\n * Assembles ping-pong compute shader WGSL with source line mapping metadata.\n */\nexport function buildPingPongComputeShaderSourceWithMap(options: {\n\tcompute: string;\n\tuniformLayout: UniformLayout;\n\tstorageBufferKeys: string[];\n\tstorageBufferDefinitions: Record<\n\t\tstring,\n\t\t{ type: StorageBufferType; access: StorageBufferAccess }\n\t>;\n\ttarget: string;\n\ttargetFormat: GPUTextureFormat;\n}): BuiltComputeShaderSource {\n\tconst code = buildPingPongComputeShaderSource(options);\n\treturn {\n\t\tcode,\n\t\tlineMap: buildComputeLineMap(code, options.compute)\n\t};\n}\n"],"mappings":"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"}
|
|
@@ -9,6 +9,11 @@ export interface MaterialSourceMetadata {
|
|
|
9
9
|
column?: number;
|
|
10
10
|
functionName?: string;
|
|
11
11
|
}
|
|
12
|
+
export interface ComputeSourceLocation {
|
|
13
|
+
kind: 'compute';
|
|
14
|
+
line: number;
|
|
15
|
+
}
|
|
16
|
+
export type ShaderSourceLocation = MaterialSourceLocation | ComputeSourceLocation;
|
|
12
17
|
/**
|
|
13
18
|
* One WGSL compiler diagnostic enriched with source-location metadata.
|
|
14
19
|
*/
|
|
@@ -17,7 +22,7 @@ export interface ShaderCompilationDiagnostic {
|
|
|
17
22
|
message: string;
|
|
18
23
|
linePos?: number;
|
|
19
24
|
lineLength?: number;
|
|
20
|
-
sourceLocation:
|
|
25
|
+
sourceLocation: ShaderSourceLocation | null;
|
|
21
26
|
}
|
|
22
27
|
/**
|
|
23
28
|
* Runtime context snapshot captured for shader compilation diagnostics.
|
|
@@ -37,8 +42,10 @@ export interface ShaderCompilationRuntimeContext {
|
|
|
37
42
|
*/
|
|
38
43
|
export interface ShaderCompilationDiagnosticsPayload {
|
|
39
44
|
kind: 'shader-compilation';
|
|
45
|
+
shaderStage?: 'fragment' | 'compute';
|
|
40
46
|
diagnostics: ShaderCompilationDiagnostic[];
|
|
41
47
|
fragmentSource: string;
|
|
48
|
+
computeSource?: string;
|
|
42
49
|
includeSources: Record<string, string>;
|
|
43
50
|
defineBlockSource?: string;
|
|
44
51
|
materialSource: MaterialSourceMetadata | null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"error-diagnostics.d.ts","sourceRoot":"","sources":["../../src/lib/core/error-diagnostics.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAEvE;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACtC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;GAEG;AACH,MAAM,WAAW,2BAA2B;IAC3C,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,
|
|
1
|
+
{"version":3,"file":"error-diagnostics.d.ts","sourceRoot":"","sources":["../../src/lib/core/error-diagnostics.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAEvE;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACtC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,qBAAqB;IACrC,IAAI,EAAE,SAAS,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;CACb;AAED,MAAM,MAAM,oBAAoB,GAAG,sBAAsB,GAAG,qBAAqB,CAAC;AAElF;;GAEG;AACH,MAAM,WAAW,2BAA2B;IAC3C,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,oBAAoB,GAAG,IAAI,CAAC;CAC5C;AAED;;GAEG;AACH,MAAM,WAAW,+BAA+B;IAC/C,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,SAAS,CAAC,EAAE;QACX,SAAS,EAAE,MAAM,CAAC;QAClB,gBAAgB,EAAE,MAAM,CAAC;QACzB,MAAM,EAAE,MAAM,EAAE,CAAC;QACjB,OAAO,EAAE,MAAM,EAAE,CAAC;KAClB,CAAC;IACF,mBAAmB,EAAE,MAAM,EAAE,CAAC;CAC9B;AAED;;GAEG;AACH,MAAM,WAAW,mCAAmC;IACnD,IAAI,EAAE,oBAAoB,CAAC;IAC3B,WAAW,CAAC,EAAE,UAAU,GAAG,SAAS,CAAC;IACrC,WAAW,EAAE,2BAA2B,EAAE,CAAC;IAC3C,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACvC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,cAAc,EAAE,sBAAsB,GAAG,IAAI,CAAC;IAC9C,cAAc,CAAC,EAAE,+BAA+B,CAAC;CACjD;AAkHD;;GAEG;AACH,wBAAgB,kCAAkC,CACjD,KAAK,EAAE,KAAK,EACZ,OAAO,EAAE,mCAAmC,GAC1C,KAAK,CAGP;AAED;;GAEG;AACH,wBAAgB,+BAA+B,CAC9C,KAAK,EAAE,OAAO,GACZ,mCAAmC,GAAG,IAAI,CAwE5C"}
|
|
@@ -9,12 +9,12 @@ function isMaterialSourceMetadata(value) {
|
|
|
9
9
|
if (record.column !== void 0 && typeof record.column !== "number") return false;
|
|
10
10
|
return true;
|
|
11
11
|
}
|
|
12
|
-
function
|
|
12
|
+
function isShaderSourceLocation(value) {
|
|
13
13
|
if (value === null) return true;
|
|
14
14
|
if (typeof value !== "object") return false;
|
|
15
15
|
const record = value;
|
|
16
16
|
const kind = record.kind;
|
|
17
|
-
if (kind !== "fragment" && kind !== "include" && kind !== "define") return false;
|
|
17
|
+
if (kind !== "fragment" && kind !== "include" && kind !== "define" && kind !== "compute") return false;
|
|
18
18
|
return typeof record.line === "number";
|
|
19
19
|
}
|
|
20
20
|
function isShaderCompilationDiagnostic(value) {
|
|
@@ -24,7 +24,7 @@ function isShaderCompilationDiagnostic(value) {
|
|
|
24
24
|
if (typeof record.message !== "string") return false;
|
|
25
25
|
if (record.linePos !== void 0 && typeof record.linePos !== "number") return false;
|
|
26
26
|
if (record.lineLength !== void 0 && typeof record.lineLength !== "number") return false;
|
|
27
|
-
if (!
|
|
27
|
+
if (!isShaderSourceLocation(record.sourceLocation)) return false;
|
|
28
28
|
return true;
|
|
29
29
|
}
|
|
30
30
|
function isStringArray(value) {
|
|
@@ -60,8 +60,10 @@ function getShaderCompilationDiagnostics(error) {
|
|
|
60
60
|
if (payload === null || typeof payload !== "object") return null;
|
|
61
61
|
const record = payload;
|
|
62
62
|
if (record.kind !== "shader-compilation") return null;
|
|
63
|
+
if (record.shaderStage !== void 0 && record.shaderStage !== "fragment" && record.shaderStage !== "compute") return null;
|
|
63
64
|
if (!Array.isArray(record.diagnostics) || !record.diagnostics.every(isShaderCompilationDiagnostic)) return null;
|
|
64
65
|
if (typeof record.fragmentSource !== "string") return null;
|
|
66
|
+
if (record.computeSource !== void 0 && typeof record.computeSource !== "string") return null;
|
|
65
67
|
if (record.defineBlockSource !== void 0 && typeof record.defineBlockSource !== "string") return null;
|
|
66
68
|
if (record.includeSources === null || typeof record.includeSources !== "object") return null;
|
|
67
69
|
const includeSources = record.includeSources;
|
|
@@ -70,8 +72,10 @@ function getShaderCompilationDiagnostics(error) {
|
|
|
70
72
|
if (record.runtimeContext !== void 0 && !isShaderCompilationRuntimeContext(record.runtimeContext)) return null;
|
|
71
73
|
return {
|
|
72
74
|
kind: "shader-compilation",
|
|
75
|
+
...record.shaderStage !== void 0 ? { shaderStage: record.shaderStage } : {},
|
|
73
76
|
diagnostics: record.diagnostics,
|
|
74
77
|
fragmentSource: record.fragmentSource,
|
|
78
|
+
...record.computeSource !== void 0 ? { computeSource: record.computeSource } : {},
|
|
75
79
|
includeSources,
|
|
76
80
|
...record.defineBlockSource !== void 0 ? { defineBlockSource: record.defineBlockSource } : {},
|
|
77
81
|
materialSource: record.materialSource ?? null,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"error-diagnostics.js","names":[],"sources":["../../src/lib/core/error-diagnostics.ts"],"sourcesContent":["import type { MaterialSourceLocation } from './material-preprocess.js';\n\n/**\n * Source metadata for material declaration callsite.\n */\nexport interface MaterialSourceMetadata {\n\tcomponent?: string;\n\tfile?: string;\n\tline?: number;\n\tcolumn?: number;\n\tfunctionName?: string;\n}\n\n/**\n * One WGSL compiler diagnostic enriched with source-location metadata.\n */\nexport interface ShaderCompilationDiagnostic {\n\tgeneratedLine: number;\n\tmessage: string;\n\tlinePos?: number;\n\tlineLength?: number;\n\tsourceLocation: MaterialSourceLocation | null;\n}\n\n/**\n * Runtime context snapshot captured for shader compilation diagnostics.\n */\nexport interface ShaderCompilationRuntimeContext {\n\tmaterialSignature?: string;\n\tpassGraph?: {\n\t\tpassCount: number;\n\t\tenabledPassCount: number;\n\t\tinputs: string[];\n\t\toutputs: string[];\n\t};\n\tactiveRenderTargets: string[];\n}\n\n/**\n * Structured payload attached to WGSL compilation errors.\n */\nexport interface ShaderCompilationDiagnosticsPayload {\n\tkind: 'shader-compilation';\n\tdiagnostics: ShaderCompilationDiagnostic[];\n\tfragmentSource: string;\n\tincludeSources: Record<string, string>;\n\tdefineBlockSource?: string;\n\tmaterialSource: MaterialSourceMetadata | null;\n\truntimeContext?: ShaderCompilationRuntimeContext;\n}\n\ntype MotionGPUErrorWithDiagnostics = Error & {\n\tmotiongpuDiagnostics?: unknown;\n};\n\nfunction isMaterialSourceMetadata(value: unknown): value is MaterialSourceMetadata {\n\tif (value === null || typeof value !== 'object') {\n\t\treturn false;\n\t}\n\n\tconst record = value as Record<string, unknown>;\n\tif (record.component !== undefined && typeof record.component !== 'string') {\n\t\treturn false;\n\t}\n\tif (record.file !== undefined && typeof record.file !== 'string') {\n\t\treturn false;\n\t}\n\tif (record.functionName !== undefined && typeof record.functionName !== 'string') {\n\t\treturn false;\n\t}\n\tif (record.line !== undefined && typeof record.line !== 'number') {\n\t\treturn false;\n\t}\n\tif (record.column !== undefined && typeof record.column !== 'number') {\n\t\treturn false;\n\t}\n\n\treturn true;\n}\n\nfunction isMaterialSourceLocation(value: unknown): value is MaterialSourceLocation | null {\n\tif (value === null) {\n\t\treturn true;\n\t}\n\n\tif (typeof value !== 'object') {\n\t\treturn false;\n\t}\n\n\tconst record = value as Record<string, unknown>;\n\tconst kind = record.kind;\n\tif (kind !== 'fragment' && kind !== 'include' && kind !== 'define') {\n\t\treturn false;\n\t}\n\n\treturn typeof record.line === 'number';\n}\n\nfunction isShaderCompilationDiagnostic(value: unknown): value is ShaderCompilationDiagnostic {\n\tif (value === null || typeof value !== 'object') {\n\t\treturn false;\n\t}\n\n\tconst record = value as Record<string, unknown>;\n\tif (typeof record.generatedLine !== 'number') {\n\t\treturn false;\n\t}\n\tif (typeof record.message !== 'string') {\n\t\treturn false;\n\t}\n\tif (record.linePos !== undefined && typeof record.linePos !== 'number') {\n\t\treturn false;\n\t}\n\tif (record.lineLength !== undefined && typeof record.lineLength !== 'number') {\n\t\treturn false;\n\t}\n\tif (!isMaterialSourceLocation(record.sourceLocation)) {\n\t\treturn false;\n\t}\n\n\treturn true;\n}\n\nfunction isStringArray(value: unknown): value is string[] {\n\treturn Array.isArray(value) && value.every((entry) => typeof entry === 'string');\n}\n\nfunction isShaderCompilationRuntimeContext(\n\tvalue: unknown\n): value is ShaderCompilationRuntimeContext {\n\tif (value === null || typeof value !== 'object') {\n\t\treturn false;\n\t}\n\n\tconst record = value as Record<string, unknown>;\n\tif (record.materialSignature !== undefined && typeof record.materialSignature !== 'string') {\n\t\treturn false;\n\t}\n\tif (!isStringArray(record.activeRenderTargets)) {\n\t\treturn false;\n\t}\n\tconst passGraph = record.passGraph;\n\tif (passGraph === undefined) {\n\t\treturn true;\n\t}\n\tif (passGraph === null || typeof passGraph !== 'object') {\n\t\treturn false;\n\t}\n\n\tconst passGraphRecord = passGraph as Record<string, unknown>;\n\tif (typeof passGraphRecord.passCount !== 'number') {\n\t\treturn false;\n\t}\n\tif (typeof passGraphRecord.enabledPassCount !== 'number') {\n\t\treturn false;\n\t}\n\tif (!isStringArray(passGraphRecord.inputs) || !isStringArray(passGraphRecord.outputs)) {\n\t\treturn false;\n\t}\n\n\treturn true;\n}\n\n/**\n * Attaches structured diagnostics payload to an Error.\n */\nexport function attachShaderCompilationDiagnostics(\n\terror: Error,\n\tpayload: ShaderCompilationDiagnosticsPayload\n): Error {\n\t(error as MotionGPUErrorWithDiagnostics).motiongpuDiagnostics = payload;\n\treturn error;\n}\n\n/**\n * Extracts structured diagnostics payload from unknown error value.\n */\nexport function getShaderCompilationDiagnostics(\n\terror: unknown\n): ShaderCompilationDiagnosticsPayload | null {\n\tif (!(error instanceof Error)) {\n\t\treturn null;\n\t}\n\n\tconst payload = (error as MotionGPUErrorWithDiagnostics).motiongpuDiagnostics;\n\tif (payload === null || typeof payload !== 'object') {\n\t\treturn null;\n\t}\n\n\tconst record = payload as Record<string, unknown>;\n\tif (record.kind !== 'shader-compilation') {\n\t\treturn null;\n\t}\n\tif (\n\t\t!Array.isArray(record.diagnostics) ||\n\t\t!record.diagnostics.every(isShaderCompilationDiagnostic)\n\t) {\n\t\treturn null;\n\t}\n\tif (typeof record.fragmentSource !== 'string') {\n\t\treturn null;\n\t}\n\tif (record.defineBlockSource !== undefined && typeof record.defineBlockSource !== 'string') {\n\t\treturn null;\n\t}\n\tif (record.includeSources === null || typeof record.includeSources !== 'object') {\n\t\treturn null;\n\t}\n\tconst includeSources = record.includeSources as Record<string, unknown>;\n\tif (Object.values(includeSources).some((value) => typeof value !== 'string')) {\n\t\treturn null;\n\t}\n\tif (record.materialSource !== null && !isMaterialSourceMetadata(record.materialSource)) {\n\t\treturn null;\n\t}\n\tif (\n\t\trecord.runtimeContext !== undefined &&\n\t\t!isShaderCompilationRuntimeContext(record.runtimeContext)\n\t) {\n\t\treturn null;\n\t}\n\n\treturn {\n\t\tkind: 'shader-compilation',\n\t\tdiagnostics: record.diagnostics as ShaderCompilationDiagnostic[],\n\t\tfragmentSource: record.fragmentSource,\n\t\tincludeSources: includeSources as Record<string, string>,\n\t\t...(record.defineBlockSource !== undefined\n\t\t\t? { defineBlockSource: record.defineBlockSource as string }\n\t\t\t: {}),\n\t\tmaterialSource: (record.materialSource ?? null) as MaterialSourceMetadata | null,\n\t\t...(record.runtimeContext !== undefined\n\t\t\t? { runtimeContext: record.runtimeContext as ShaderCompilationRuntimeContext }\n\t\t\t: {})\n\t};\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"error-diagnostics.js","names":[],"sources":["../../src/lib/core/error-diagnostics.ts"],"sourcesContent":["import type { MaterialSourceLocation } from './material-preprocess.js';\n\n/**\n * Source metadata for material declaration callsite.\n */\nexport interface MaterialSourceMetadata {\n\tcomponent?: string;\n\tfile?: string;\n\tline?: number;\n\tcolumn?: number;\n\tfunctionName?: string;\n}\n\nexport interface ComputeSourceLocation {\n\tkind: 'compute';\n\tline: number;\n}\n\nexport type ShaderSourceLocation = MaterialSourceLocation | ComputeSourceLocation;\n\n/**\n * One WGSL compiler diagnostic enriched with source-location metadata.\n */\nexport interface ShaderCompilationDiagnostic {\n\tgeneratedLine: number;\n\tmessage: string;\n\tlinePos?: number;\n\tlineLength?: number;\n\tsourceLocation: ShaderSourceLocation | null;\n}\n\n/**\n * Runtime context snapshot captured for shader compilation diagnostics.\n */\nexport interface ShaderCompilationRuntimeContext {\n\tmaterialSignature?: string;\n\tpassGraph?: {\n\t\tpassCount: number;\n\t\tenabledPassCount: number;\n\t\tinputs: string[];\n\t\toutputs: string[];\n\t};\n\tactiveRenderTargets: string[];\n}\n\n/**\n * Structured payload attached to WGSL compilation errors.\n */\nexport interface ShaderCompilationDiagnosticsPayload {\n\tkind: 'shader-compilation';\n\tshaderStage?: 'fragment' | 'compute';\n\tdiagnostics: ShaderCompilationDiagnostic[];\n\tfragmentSource: string;\n\tcomputeSource?: string;\n\tincludeSources: Record<string, string>;\n\tdefineBlockSource?: string;\n\tmaterialSource: MaterialSourceMetadata | null;\n\truntimeContext?: ShaderCompilationRuntimeContext;\n}\n\ntype MotionGPUErrorWithDiagnostics = Error & {\n\tmotiongpuDiagnostics?: unknown;\n};\n\nfunction isMaterialSourceMetadata(value: unknown): value is MaterialSourceMetadata {\n\tif (value === null || typeof value !== 'object') {\n\t\treturn false;\n\t}\n\n\tconst record = value as Record<string, unknown>;\n\tif (record.component !== undefined && typeof record.component !== 'string') {\n\t\treturn false;\n\t}\n\tif (record.file !== undefined && typeof record.file !== 'string') {\n\t\treturn false;\n\t}\n\tif (record.functionName !== undefined && typeof record.functionName !== 'string') {\n\t\treturn false;\n\t}\n\tif (record.line !== undefined && typeof record.line !== 'number') {\n\t\treturn false;\n\t}\n\tif (record.column !== undefined && typeof record.column !== 'number') {\n\t\treturn false;\n\t}\n\n\treturn true;\n}\n\nfunction isShaderSourceLocation(value: unknown): value is ShaderSourceLocation | null {\n\tif (value === null) {\n\t\treturn true;\n\t}\n\n\tif (typeof value !== 'object') {\n\t\treturn false;\n\t}\n\n\tconst record = value as Record<string, unknown>;\n\tconst kind = record.kind;\n\tif (kind !== 'fragment' && kind !== 'include' && kind !== 'define' && kind !== 'compute') {\n\t\treturn false;\n\t}\n\n\treturn typeof record.line === 'number';\n}\n\nfunction isShaderCompilationDiagnostic(value: unknown): value is ShaderCompilationDiagnostic {\n\tif (value === null || typeof value !== 'object') {\n\t\treturn false;\n\t}\n\n\tconst record = value as Record<string, unknown>;\n\tif (typeof record.generatedLine !== 'number') {\n\t\treturn false;\n\t}\n\tif (typeof record.message !== 'string') {\n\t\treturn false;\n\t}\n\tif (record.linePos !== undefined && typeof record.linePos !== 'number') {\n\t\treturn false;\n\t}\n\tif (record.lineLength !== undefined && typeof record.lineLength !== 'number') {\n\t\treturn false;\n\t}\n\tif (!isShaderSourceLocation(record.sourceLocation)) {\n\t\treturn false;\n\t}\n\n\treturn true;\n}\n\nfunction isStringArray(value: unknown): value is string[] {\n\treturn Array.isArray(value) && value.every((entry) => typeof entry === 'string');\n}\n\nfunction isShaderCompilationRuntimeContext(\n\tvalue: unknown\n): value is ShaderCompilationRuntimeContext {\n\tif (value === null || typeof value !== 'object') {\n\t\treturn false;\n\t}\n\n\tconst record = value as Record<string, unknown>;\n\tif (record.materialSignature !== undefined && typeof record.materialSignature !== 'string') {\n\t\treturn false;\n\t}\n\tif (!isStringArray(record.activeRenderTargets)) {\n\t\treturn false;\n\t}\n\tconst passGraph = record.passGraph;\n\tif (passGraph === undefined) {\n\t\treturn true;\n\t}\n\tif (passGraph === null || typeof passGraph !== 'object') {\n\t\treturn false;\n\t}\n\n\tconst passGraphRecord = passGraph as Record<string, unknown>;\n\tif (typeof passGraphRecord.passCount !== 'number') {\n\t\treturn false;\n\t}\n\tif (typeof passGraphRecord.enabledPassCount !== 'number') {\n\t\treturn false;\n\t}\n\tif (!isStringArray(passGraphRecord.inputs) || !isStringArray(passGraphRecord.outputs)) {\n\t\treturn false;\n\t}\n\n\treturn true;\n}\n\n/**\n * Attaches structured diagnostics payload to an Error.\n */\nexport function attachShaderCompilationDiagnostics(\n\terror: Error,\n\tpayload: ShaderCompilationDiagnosticsPayload\n): Error {\n\t(error as MotionGPUErrorWithDiagnostics).motiongpuDiagnostics = payload;\n\treturn error;\n}\n\n/**\n * Extracts structured diagnostics payload from unknown error value.\n */\nexport function getShaderCompilationDiagnostics(\n\terror: unknown\n): ShaderCompilationDiagnosticsPayload | null {\n\tif (!(error instanceof Error)) {\n\t\treturn null;\n\t}\n\n\tconst payload = (error as MotionGPUErrorWithDiagnostics).motiongpuDiagnostics;\n\tif (payload === null || typeof payload !== 'object') {\n\t\treturn null;\n\t}\n\n\tconst record = payload as Record<string, unknown>;\n\tif (record.kind !== 'shader-compilation') {\n\t\treturn null;\n\t}\n\tif (\n\t\trecord.shaderStage !== undefined &&\n\t\trecord.shaderStage !== 'fragment' &&\n\t\trecord.shaderStage !== 'compute'\n\t) {\n\t\treturn null;\n\t}\n\tif (\n\t\t!Array.isArray(record.diagnostics) ||\n\t\t!record.diagnostics.every(isShaderCompilationDiagnostic)\n\t) {\n\t\treturn null;\n\t}\n\tif (typeof record.fragmentSource !== 'string') {\n\t\treturn null;\n\t}\n\tif (record.computeSource !== undefined && typeof record.computeSource !== 'string') {\n\t\treturn null;\n\t}\n\tif (record.defineBlockSource !== undefined && typeof record.defineBlockSource !== 'string') {\n\t\treturn null;\n\t}\n\tif (record.includeSources === null || typeof record.includeSources !== 'object') {\n\t\treturn null;\n\t}\n\tconst includeSources = record.includeSources as Record<string, unknown>;\n\tif (Object.values(includeSources).some((value) => typeof value !== 'string')) {\n\t\treturn null;\n\t}\n\tif (record.materialSource !== null && !isMaterialSourceMetadata(record.materialSource)) {\n\t\treturn null;\n\t}\n\tif (\n\t\trecord.runtimeContext !== undefined &&\n\t\t!isShaderCompilationRuntimeContext(record.runtimeContext)\n\t) {\n\t\treturn null;\n\t}\n\n\treturn {\n\t\tkind: 'shader-compilation',\n\t\t...(record.shaderStage !== undefined\n\t\t\t? { shaderStage: record.shaderStage as 'fragment' | 'compute' }\n\t\t\t: {}),\n\t\tdiagnostics: record.diagnostics as ShaderCompilationDiagnostic[],\n\t\tfragmentSource: record.fragmentSource,\n\t\t...(record.computeSource !== undefined\n\t\t\t? { computeSource: record.computeSource as string }\n\t\t\t: {}),\n\t\tincludeSources: includeSources as Record<string, string>,\n\t\t...(record.defineBlockSource !== undefined\n\t\t\t? { defineBlockSource: record.defineBlockSource as string }\n\t\t\t: {}),\n\t\tmaterialSource: (record.materialSource ?? null) as MaterialSourceMetadata | null,\n\t\t...(record.runtimeContext !== undefined\n\t\t\t? { runtimeContext: record.runtimeContext as ShaderCompilationRuntimeContext }\n\t\t\t: {})\n\t};\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"error-report.d.ts","sourceRoot":"","sources":["../../src/lib/core/error-report.ts"],"names":[],"mappings":"AAMA;;GAEG;AACH,MAAM,MAAM,mBAAmB,GAAG,gBAAgB,GAAG,QAAQ,CAAC;AAE9D;;GAEG;AACH,MAAM,MAAM,kBAAkB,GAC3B,oBAAoB,GACpB,4BAA4B,GAC5B,4BAA4B,GAC5B,yBAAyB,GACzB,4BAA4B,GAC5B,oBAAoB,GACpB,yBAAyB,GACzB,qBAAqB,GACrB,0BAA0B,GAC1B,uBAAuB,GACvB,8BAA8B,GAC9B,4BAA4B,GAC5B,sBAAsB,GACtB,gCAAgC,GAChC,uBAAuB,GACvB,wBAAwB,GACxB,4BAA4B,GAC5B,yBAAyB,GACzB,4BAA4B,GAC5B,0BAA0B,GAC1B,yBAAyB,CAAC;AAE7B;;GAEG;AACH,MAAM,MAAM,sBAAsB,GAAG,OAAO,GAAG,OAAO,CAAC;AAEvD;;GAEG;AACH,MAAM,WAAW,wBAAwB;IACxC,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,OAAO,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACpC,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,wBAAwB,EAAE,CAAC;CACpC;AAED;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACrC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,SAAS,CAAC,EAAE;QACX,SAAS,EAAE,MAAM,CAAC;QAClB,gBAAgB,EAAE,MAAM,CAAC;QACzB,MAAM,EAAE,MAAM,EAAE,CAAC;QACjB,OAAO,EAAE,MAAM,EAAE,CAAC;KAClB,CAAC;IACF,mBAAmB,EAAE,MAAM,EAAE,CAAC;CAC9B;AAED;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACpC;;OAEG;IACH,IAAI,EAAE,kBAAkB,CAAC;IACzB;;OAEG;IACH,QAAQ,EAAE,sBAAsB,CAAC;IACjC;;OAEG;IACH,WAAW,EAAE,OAAO,CAAC;IACrB;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,OAAO,EAAE,MAAM,CAAC;IAChB;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;IACb;;OAEG;IACH,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB;;OAEG;IACH,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB;;OAEG;IACH,UAAU,EAAE,MAAM,CAAC;IACnB;;OAEG;IACH,KAAK,EAAE,mBAAmB,CAAC;IAC3B;;OAEG;IACH,MAAM,EAAE,oBAAoB,GAAG,IAAI,CAAC;IACpC;;OAEG;IACH,OAAO,EAAE,qBAAqB,GAAG,IAAI,CAAC;CACtC;
|
|
1
|
+
{"version":3,"file":"error-report.d.ts","sourceRoot":"","sources":["../../src/lib/core/error-report.ts"],"names":[],"mappings":"AAMA;;GAEG;AACH,MAAM,MAAM,mBAAmB,GAAG,gBAAgB,GAAG,QAAQ,CAAC;AAE9D;;GAEG;AACH,MAAM,MAAM,kBAAkB,GAC3B,oBAAoB,GACpB,4BAA4B,GAC5B,4BAA4B,GAC5B,yBAAyB,GACzB,4BAA4B,GAC5B,oBAAoB,GACpB,yBAAyB,GACzB,qBAAqB,GACrB,0BAA0B,GAC1B,uBAAuB,GACvB,8BAA8B,GAC9B,4BAA4B,GAC5B,sBAAsB,GACtB,gCAAgC,GAChC,uBAAuB,GACvB,wBAAwB,GACxB,4BAA4B,GAC5B,yBAAyB,GACzB,4BAA4B,GAC5B,0BAA0B,GAC1B,yBAAyB,CAAC;AAE7B;;GAEG;AACH,MAAM,MAAM,sBAAsB,GAAG,OAAO,GAAG,OAAO,CAAC;AAEvD;;GAEG;AACH,MAAM,WAAW,wBAAwB;IACxC,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,OAAO,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACpC,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,wBAAwB,EAAE,CAAC;CACpC;AAED;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACrC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,SAAS,CAAC,EAAE;QACX,SAAS,EAAE,MAAM,CAAC;QAClB,gBAAgB,EAAE,MAAM,CAAC;QACzB,MAAM,EAAE,MAAM,EAAE,CAAC;QACjB,OAAO,EAAE,MAAM,EAAE,CAAC;KAClB,CAAC;IACF,mBAAmB,EAAE,MAAM,EAAE,CAAC;CAC9B;AAED;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACpC;;OAEG;IACH,IAAI,EAAE,kBAAkB,CAAC;IACzB;;OAEG;IACH,QAAQ,EAAE,sBAAsB,CAAC;IACjC;;OAEG;IACH,WAAW,EAAE,OAAO,CAAC;IACrB;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,OAAO,EAAE,MAAM,CAAC;IAChB;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;IACb;;OAEG;IACH,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB;;OAEG;IACH,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB;;OAEG;IACH,UAAU,EAAE,MAAM,CAAC;IACnB;;OAEG;IACH,KAAK,EAAE,mBAAmB,CAAC;IAC3B;;OAEG;IACH,MAAM,EAAE,oBAAoB,GAAG,IAAI,CAAC;IACpC;;OAEG;IACH,OAAO,EAAE,qBAAqB,GAAG,IAAI,CAAC;CACtC;AAiXD;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CACrC,KAAK,EAAE,OAAO,EACd,KAAK,EAAE,mBAAmB,GACxB,oBAAoB,CAoDtB"}
|
|
@@ -55,6 +55,17 @@ function buildSourceFromDiagnostics(error) {
|
|
|
55
55
|
snippet: toSnippet(includeSource, location.line)
|
|
56
56
|
};
|
|
57
57
|
}
|
|
58
|
+
if (location.kind === "compute") {
|
|
59
|
+
const computeSource = diagnostics.computeSource ?? diagnostics.fragmentSource;
|
|
60
|
+
const component = "Compute shader";
|
|
61
|
+
return {
|
|
62
|
+
component,
|
|
63
|
+
location: `${component} (${formatShaderSourceLocation(location) ?? `compute line ${location.line}`})`,
|
|
64
|
+
line: location.line,
|
|
65
|
+
...column !== void 0 ? { column } : {},
|
|
66
|
+
snippet: toSnippet(computeSource, location.line)
|
|
67
|
+
};
|
|
68
|
+
}
|
|
58
69
|
const defineName = location.define ?? "unknown";
|
|
59
70
|
const defineLine = Math.max(1, location.line);
|
|
60
71
|
const component = `#define ${defineName}`;
|
|
@@ -241,7 +252,14 @@ function toMotionGPUErrorReport(error, phase) {
|
|
|
241
252
|
const message = shaderDiagnostics && shaderDiagnostics.diagnostics[0] ? formatDiagnosticMessage(shaderDiagnostics.diagnostics[0]) : defaultMessage;
|
|
242
253
|
const details = shaderDiagnostics ? shaderDiagnostics.diagnostics.slice(1).map((entry) => formatDiagnosticMessage(entry)) : defaultDetails;
|
|
243
254
|
const stack = error instanceof Error && error.stack ? splitLines(error.stack).filter((line) => line !== message) : [];
|
|
244
|
-
|
|
255
|
+
let classification = classifyErrorMessage(rawMessage);
|
|
256
|
+
if (shaderDiagnostics?.shaderStage === "compute" && classification.code === "WGSL_COMPILATION_FAILED") classification = {
|
|
257
|
+
code: "COMPUTE_COMPILATION_FAILED",
|
|
258
|
+
severity: "error",
|
|
259
|
+
recoverable: true,
|
|
260
|
+
title: "Compute shader compilation failed",
|
|
261
|
+
hint: "Check WGSL compute shader sources below and verify storage bindings."
|
|
262
|
+
};
|
|
245
263
|
return {
|
|
246
264
|
code: classification.code,
|
|
247
265
|
severity: classification.severity,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"error-report.js","names":[],"sources":["../../src/lib/core/error-report.ts"],"sourcesContent":["import {\n\tgetShaderCompilationDiagnostics,\n\ttype ShaderCompilationDiagnostic\n} from './error-diagnostics.js';\nimport { formatShaderSourceLocation } from './shader.js';\n\n/**\n * Runtime phase in which an error occurred.\n */\nexport type MotionGPUErrorPhase = 'initialization' | 'render';\n\n/**\n * Stable machine-readable error category code.\n */\nexport type MotionGPUErrorCode =\n\t| 'WEBGPU_UNAVAILABLE'\n\t| 'WEBGPU_ADAPTER_UNAVAILABLE'\n\t| 'WEBGPU_CONTEXT_UNAVAILABLE'\n\t| 'WGSL_COMPILATION_FAILED'\n\t| 'MATERIAL_PREPROCESS_FAILED'\n\t| 'WEBGPU_DEVICE_LOST'\n\t| 'WEBGPU_UNCAPTURED_ERROR'\n\t| 'BIND_GROUP_MISMATCH'\n\t| 'RUNTIME_RESOURCE_MISSING'\n\t| 'UNIFORM_VALUE_INVALID'\n\t| 'STORAGE_BUFFER_OUT_OF_BOUNDS'\n\t| 'STORAGE_BUFFER_READ_FAILED'\n\t| 'RENDER_GRAPH_INVALID'\n\t| 'PINGPONG_CONFIGURATION_INVALID'\n\t| 'TEXTURE_USAGE_INVALID'\n\t| 'TEXTURE_REQUEST_FAILED'\n\t| 'TEXTURE_DECODE_UNAVAILABLE'\n\t| 'TEXTURE_REQUEST_ABORTED'\n\t| 'COMPUTE_COMPILATION_FAILED'\n\t| 'COMPUTE_CONTRACT_INVALID'\n\t| 'MOTIONGPU_RUNTIME_ERROR';\n\n/**\n * Severity level for user-facing diagnostics.\n */\nexport type MotionGPUErrorSeverity = 'error' | 'fatal';\n\n/**\n * One source-code line displayed in diagnostics snippet.\n */\nexport interface MotionGPUErrorSourceLine {\n\tnumber: number;\n\tcode: string;\n\thighlight: boolean;\n}\n\n/**\n * Structured source context displayed for shader compilation errors.\n */\nexport interface MotionGPUErrorSource {\n\tcomponent: string;\n\tlocation: string;\n\tline: number;\n\tcolumn?: number;\n\tsnippet: MotionGPUErrorSourceLine[];\n}\n\n/**\n * Optional runtime context captured with diagnostics payload.\n */\nexport interface MotionGPUErrorContext {\n\tmaterialSignature?: string;\n\tpassGraph?: {\n\t\tpassCount: number;\n\t\tenabledPassCount: number;\n\t\tinputs: string[];\n\t\toutputs: string[];\n\t};\n\tactiveRenderTargets: string[];\n}\n\n/**\n * Structured error payload used by UI diagnostics.\n */\nexport interface MotionGPUErrorReport {\n\t/**\n\t * Stable machine-readable category code.\n\t */\n\tcode: MotionGPUErrorCode;\n\t/**\n\t * Severity level used by diagnostics UIs and telemetry.\n\t */\n\tseverity: MotionGPUErrorSeverity;\n\t/**\n\t * Whether runtime may recover without full renderer re-creation.\n\t */\n\trecoverable: boolean;\n\t/**\n\t * Short category title.\n\t */\n\ttitle: string;\n\t/**\n\t * Primary human-readable message.\n\t */\n\tmessage: string;\n\t/**\n\t * Suggested remediation hint.\n\t */\n\thint: string;\n\t/**\n\t * Additional parsed details (for example WGSL line errors).\n\t */\n\tdetails: string[];\n\t/**\n\t * Stack trace lines when available.\n\t */\n\tstack: string[];\n\t/**\n\t * Original unmodified message.\n\t */\n\trawMessage: string;\n\t/**\n\t * Runtime phase where the error occurred.\n\t */\n\tphase: MotionGPUErrorPhase;\n\t/**\n\t * Optional source context for shader-related diagnostics.\n\t */\n\tsource: MotionGPUErrorSource | null;\n\t/**\n\t * Optional runtime context snapshot (material/pass graph/render targets).\n\t */\n\tcontext: MotionGPUErrorContext | null;\n}\n\n/**\n * Splits multi-line values into trimmed non-empty lines.\n */\nfunction splitLines(value: string): string[] {\n\treturn value\n\t\t.split('\\n')\n\t\t.map((line) => line.trim())\n\t\t.filter((line) => line.length > 0);\n}\n\nfunction toDisplayName(path: string): string {\n\tconst normalized = path.split(/[?#]/)[0] ?? path;\n\tconst chunks = normalized.split(/[\\\\/]/);\n\tconst last = chunks[chunks.length - 1];\n\treturn last && last.length > 0 ? last : path;\n}\n\nfunction toSnippet(source: string, line: number, radius = 3): MotionGPUErrorSourceLine[] {\n\tconst lines = source.replace(/\\r\\n?/g, '\\n').split('\\n');\n\tif (lines.length === 0) {\n\t\treturn [];\n\t}\n\n\tconst targetLine = Math.min(Math.max(1, line), lines.length);\n\tconst start = Math.max(1, targetLine - radius);\n\tconst end = Math.min(lines.length, targetLine + radius);\n\tconst snippet: MotionGPUErrorSourceLine[] = [];\n\n\tfor (let index = start; index <= end; index += 1) {\n\t\tsnippet.push({\n\t\t\tnumber: index,\n\t\t\tcode: lines[index - 1] ?? '',\n\t\t\thighlight: index === targetLine\n\t\t});\n\t}\n\n\treturn snippet;\n}\n\nfunction buildSourceFromDiagnostics(error: unknown): MotionGPUErrorSource | null {\n\tconst diagnostics = getShaderCompilationDiagnostics(error);\n\tif (!diagnostics || diagnostics.diagnostics.length === 0) {\n\t\treturn null;\n\t}\n\n\tconst primary = diagnostics.diagnostics.find((entry) => entry.sourceLocation !== null);\n\tif (!primary?.sourceLocation) {\n\t\treturn null;\n\t}\n\n\tconst location = primary.sourceLocation;\n\tconst column = primary.linePos && primary.linePos > 0 ? primary.linePos : undefined;\n\n\tif (location.kind === 'fragment') {\n\t\tconst component =\n\t\t\tdiagnostics.materialSource?.component ??\n\t\t\t(diagnostics.materialSource?.file\n\t\t\t\t? toDisplayName(diagnostics.materialSource.file)\n\t\t\t\t: 'User shader fragment');\n\t\tconst locationLabel = formatShaderSourceLocation(location) ?? `fragment line ${location.line}`;\n\t\treturn {\n\t\t\tcomponent,\n\t\t\tlocation: `${component} (${locationLabel})`,\n\t\t\tline: location.line,\n\t\t\t...(column !== undefined ? { column } : {}),\n\t\t\tsnippet: toSnippet(diagnostics.fragmentSource, location.line)\n\t\t};\n\t}\n\n\tif (location.kind === 'include') {\n\t\tconst includeName = location.include ?? 'unknown';\n\t\tconst includeSource = diagnostics.includeSources[includeName] ?? '';\n\t\tconst component = `#include <${includeName}>`;\n\t\tconst locationLabel = formatShaderSourceLocation(location) ?? `include <${includeName}>`;\n\t\treturn {\n\t\t\tcomponent,\n\t\t\tlocation: `${component} (${locationLabel})`,\n\t\t\tline: location.line,\n\t\t\t...(column !== undefined ? { column } : {}),\n\t\t\tsnippet: toSnippet(includeSource, location.line)\n\t\t};\n\t}\n\n\tconst defineName = location.define ?? 'unknown';\n\tconst defineLine = Math.max(1, location.line);\n\tconst component = `#define ${defineName}`;\n\tconst locationLabel =\n\t\tformatShaderSourceLocation(location) ?? `define \"${defineName}\" line ${defineLine}`;\n\treturn {\n\t\tcomponent,\n\t\tlocation: `${component} (${locationLabel})`,\n\t\tline: defineLine,\n\t\t...(column !== undefined ? { column } : {}),\n\t\tsnippet: toSnippet(diagnostics.defineBlockSource ?? '', defineLine, 2)\n\t};\n}\n\nfunction formatDiagnosticMessage(entry: ShaderCompilationDiagnostic): string {\n\tconst sourceLabel = formatShaderSourceLocation(entry.sourceLocation);\n\tconst generatedLineLabel =\n\t\tentry.generatedLine > 0 ? `generated WGSL line ${entry.generatedLine}` : null;\n\tconst labels = [sourceLabel, generatedLineLabel].filter((value) => Boolean(value));\n\tif (labels.length === 0) {\n\t\treturn entry.message;\n\t}\n\n\treturn `[${labels.join(' | ')}] ${entry.message}`;\n}\n\n/**\n * Maps known WebGPU/WGSL error patterns to a user-facing title and hint.\n */\nfunction classifyErrorMessage(\n\tmessage: string\n): Pick<MotionGPUErrorReport, 'code' | 'severity' | 'recoverable' | 'title' | 'hint'> {\n\tif (message.includes('WebGPU is not available in this browser')) {\n\t\treturn {\n\t\t\tcode: 'WEBGPU_UNAVAILABLE',\n\t\t\tseverity: 'fatal',\n\t\t\trecoverable: false,\n\t\t\ttitle: 'WebGPU unavailable',\n\t\t\thint: 'Use a browser with WebGPU enabled (latest Chrome/Edge/Safari TP) and secure context.'\n\t\t};\n\t}\n\n\tif (message.includes('Unable to acquire WebGPU adapter')) {\n\t\treturn {\n\t\t\tcode: 'WEBGPU_ADAPTER_UNAVAILABLE',\n\t\t\tseverity: 'fatal',\n\t\t\trecoverable: false,\n\t\t\ttitle: 'WebGPU adapter unavailable',\n\t\t\thint: 'GPU adapter request failed. Check browser permissions, flags and device support.'\n\t\t};\n\t}\n\n\tif (message.includes('Canvas does not support webgpu context')) {\n\t\treturn {\n\t\t\tcode: 'WEBGPU_CONTEXT_UNAVAILABLE',\n\t\t\tseverity: 'error',\n\t\t\trecoverable: true,\n\t\t\ttitle: 'Canvas cannot create WebGPU context',\n\t\t\thint: 'Make sure this canvas is attached to DOM and not using an unsupported context option.'\n\t\t};\n\t}\n\n\tif (message.includes('WGSL compilation failed')) {\n\t\treturn {\n\t\t\tcode: 'WGSL_COMPILATION_FAILED',\n\t\t\tseverity: 'error',\n\t\t\trecoverable: true,\n\t\t\ttitle: 'WGSL compilation failed',\n\t\t\thint: 'Check WGSL line numbers below and verify struct/binding/function signatures.'\n\t\t};\n\t}\n\n\tif (\n\t\tmessage.includes('Invalid include directive in fragment shader.') ||\n\t\tmessage.includes('Unknown include \"') ||\n\t\tmessage.includes('Circular include detected for \"') ||\n\t\tmessage.includes('Invalid define value for \"') ||\n\t\tmessage.includes('Invalid include \"')\n\t) {\n\t\treturn {\n\t\t\tcode: 'MATERIAL_PREPROCESS_FAILED',\n\t\t\tseverity: 'error',\n\t\t\trecoverable: true,\n\t\t\ttitle: 'Material preprocess failed',\n\t\t\thint: 'Validate #include keys, define values and include expansion order before retrying.'\n\t\t};\n\t}\n\n\tif (message.includes('Compute shader compilation failed')) {\n\t\treturn {\n\t\t\tcode: 'COMPUTE_COMPILATION_FAILED',\n\t\t\tseverity: 'error',\n\t\t\trecoverable: true,\n\t\t\ttitle: 'Compute shader compilation failed',\n\t\t\thint: 'Check WGSL compute shader sources below and verify storage bindings.'\n\t\t};\n\t}\n\n\tif (\n\t\tmessage.includes(\n\t\t\t'Compute shader must declare `@compute @workgroup_size(...) fn compute(...)`.'\n\t\t) ||\n\t\tmessage.includes('Compute shader must include a `@builtin(global_invocation_id)` parameter.') ||\n\t\tmessage.includes('Could not extract @workgroup_size from compute shader source.') ||\n\t\tmessage.includes('@workgroup_size dimensions must be integers in range') ||\n\t\tmessage.includes('Unsupported storage buffer access mode \"')\n\t) {\n\t\treturn {\n\t\t\tcode: 'COMPUTE_CONTRACT_INVALID',\n\t\t\tseverity: 'error',\n\t\t\trecoverable: true,\n\t\t\ttitle: 'Compute contract is invalid',\n\t\t\thint: 'Ensure compute shader contract (@compute, @workgroup_size, global_invocation_id, storage access) is valid.'\n\t\t};\n\t}\n\n\tif (message.includes('WebGPU device lost') || message.includes('Device Lost')) {\n\t\treturn {\n\t\t\tcode: 'WEBGPU_DEVICE_LOST',\n\t\t\tseverity: 'fatal',\n\t\t\trecoverable: false,\n\t\t\ttitle: 'WebGPU device lost',\n\t\t\thint: 'GPU device/context was lost. Recreate the renderer and check OS/GPU stability.'\n\t\t};\n\t}\n\n\tif (message.includes('WebGPU uncaptured error')) {\n\t\treturn {\n\t\t\tcode: 'WEBGPU_UNCAPTURED_ERROR',\n\t\t\tseverity: 'error',\n\t\t\trecoverable: true,\n\t\t\ttitle: 'WebGPU uncaptured error',\n\t\t\thint: 'A GPU command failed asynchronously. Review details and validate resource/state usage.'\n\t\t};\n\t}\n\n\tif (message.includes('CreateBindGroup') || message.includes('bind group layout')) {\n\t\treturn {\n\t\t\tcode: 'BIND_GROUP_MISMATCH',\n\t\t\tseverity: 'error',\n\t\t\trecoverable: true,\n\t\t\ttitle: 'Bind group mismatch',\n\t\t\thint: 'Bindings in shader and runtime resources are out of sync. Verify uniforms/textures layout.'\n\t\t};\n\t}\n\n\tif (message.includes('Storage buffer \"') && message.includes('write out of bounds:')) {\n\t\treturn {\n\t\t\tcode: 'STORAGE_BUFFER_OUT_OF_BOUNDS',\n\t\t\tseverity: 'error',\n\t\t\trecoverable: true,\n\t\t\ttitle: 'Storage buffer write out of bounds',\n\t\t\thint: 'Ensure offset + write byte length does not exceed declared storage buffer size.'\n\t\t};\n\t}\n\n\tif (\n\t\tmessage.includes('Cannot read storage buffer \"') ||\n\t\tmessage.includes('Cannot read storage buffer: GPU device unavailable.') ||\n\t\tmessage.includes('not allocated on GPU.')\n\t) {\n\t\treturn {\n\t\t\tcode: 'STORAGE_BUFFER_READ_FAILED',\n\t\t\tseverity: 'error',\n\t\t\trecoverable: true,\n\t\t\ttitle: 'Storage buffer read failed',\n\t\t\thint: 'Readbacks require an initialized renderer, allocated GPU buffer and active device.'\n\t\t};\n\t}\n\n\tif (\n\t\tmessage.includes('Unknown uniform \"') ||\n\t\tmessage.includes('Unknown uniform type for \"') ||\n\t\tmessage.includes('Unknown texture \"') ||\n\t\tmessage.includes('Unknown storage buffer \"') ||\n\t\tmessage.includes('Missing definition for storage buffer \"') ||\n\t\tmessage.includes('Missing texture definition for \"') ||\n\t\t(message.includes('Storage buffer \"') && message.includes('\" not allocated.')) ||\n\t\t(message.includes('Storage texture \"') && message.includes('\" not allocated.'))\n\t) {\n\t\treturn {\n\t\t\tcode: 'RUNTIME_RESOURCE_MISSING',\n\t\t\tseverity: 'error',\n\t\t\trecoverable: true,\n\t\t\ttitle: 'Runtime resource binding failed',\n\t\t\thint: 'Check material declarations and runtime keys for uniforms, textures and storage resources.'\n\t\t};\n\t}\n\n\tif (message.includes('Uniform ') && message.includes(' value must')) {\n\t\treturn {\n\t\t\tcode: 'UNIFORM_VALUE_INVALID',\n\t\t\tseverity: 'error',\n\t\t\trecoverable: true,\n\t\t\ttitle: 'Uniform value is invalid',\n\t\t\thint: 'Provide finite values with tuple/matrix sizes matching the uniform type.'\n\t\t};\n\t}\n\n\tif (\n\t\tmessage.includes('Render pass #') ||\n\t\tmessage.includes('Render graph references unknown runtime target')\n\t) {\n\t\treturn {\n\t\t\tcode: 'RENDER_GRAPH_INVALID',\n\t\t\tseverity: 'error',\n\t\t\trecoverable: true,\n\t\t\ttitle: 'Render graph configuration is invalid',\n\t\t\thint: 'Verify pass inputs/outputs, declared render targets and execution order.'\n\t\t};\n\t}\n\n\tif (message.includes('PingPongComputePass must provide a target texture key.')) {\n\t\treturn {\n\t\t\tcode: 'PINGPONG_CONFIGURATION_INVALID',\n\t\t\tseverity: 'error',\n\t\t\trecoverable: true,\n\t\t\ttitle: 'Ping-pong compute pass is misconfigured',\n\t\t\thint: 'Configure a valid target texture key for PingPongComputePass.'\n\t\t};\n\t}\n\n\tif (message.includes('Destination texture needs to have CopyDst')) {\n\t\treturn {\n\t\t\tcode: 'TEXTURE_USAGE_INVALID',\n\t\t\tseverity: 'error',\n\t\t\trecoverable: true,\n\t\t\ttitle: 'Invalid texture usage flags',\n\t\t\thint: 'Texture used as upload destination must include CopyDst (and often RenderAttachment).'\n\t\t};\n\t}\n\n\tif (message.includes('Texture request failed')) {\n\t\treturn {\n\t\t\tcode: 'TEXTURE_REQUEST_FAILED',\n\t\t\tseverity: 'error',\n\t\t\trecoverable: true,\n\t\t\ttitle: 'Texture request failed',\n\t\t\thint: 'Verify texture URL, CORS policy and response status before retrying.'\n\t\t};\n\t}\n\n\tif (message.includes('createImageBitmap is not available in this runtime')) {\n\t\treturn {\n\t\t\tcode: 'TEXTURE_DECODE_UNAVAILABLE',\n\t\t\tseverity: 'fatal',\n\t\t\trecoverable: false,\n\t\t\ttitle: 'Texture decode unavailable',\n\t\t\thint: 'Runtime lacks createImageBitmap support. Use a browser/runtime with image bitmap decoding.'\n\t\t};\n\t}\n\n\tif (message.toLowerCase().includes('texture request was aborted')) {\n\t\treturn {\n\t\t\tcode: 'TEXTURE_REQUEST_ABORTED',\n\t\t\tseverity: 'error',\n\t\t\trecoverable: true,\n\t\t\ttitle: 'Texture request aborted',\n\t\t\thint: 'Texture load was cancelled. Retry the request when source inputs stabilize.'\n\t\t};\n\t}\n\n\treturn {\n\t\tcode: 'MOTIONGPU_RUNTIME_ERROR',\n\t\tseverity: 'error',\n\t\trecoverable: true,\n\t\ttitle: 'MotionGPU render error',\n\t\thint: 'Review technical details below. If issue persists, isolate shader/uniform/texture changes.'\n\t};\n}\n\n/**\n * Converts unknown errors to a consistent, display-ready error report.\n *\n * @param error - Unknown thrown value.\n * @param phase - Phase during which error occurred.\n * @returns Normalized error report.\n */\nexport function toMotionGPUErrorReport(\n\terror: unknown,\n\tphase: MotionGPUErrorPhase\n): MotionGPUErrorReport {\n\tconst shaderDiagnostics = getShaderCompilationDiagnostics(error);\n\tconst rawMessage =\n\t\terror instanceof Error\n\t\t\t? error.message\n\t\t\t: typeof error === 'string'\n\t\t\t\t? error\n\t\t\t\t: 'Unknown FragCanvas error';\n\tconst rawLines = splitLines(rawMessage);\n\tconst defaultMessage = rawLines[0] ?? rawMessage;\n\tconst defaultDetails = rawLines.slice(1);\n\tconst source = buildSourceFromDiagnostics(error);\n\tconst context = shaderDiagnostics?.runtimeContext ?? null;\n\tconst message =\n\t\tshaderDiagnostics && shaderDiagnostics.diagnostics[0]\n\t\t\t? formatDiagnosticMessage(shaderDiagnostics.diagnostics[0])\n\t\t\t: defaultMessage;\n\tconst details = shaderDiagnostics\n\t\t? shaderDiagnostics.diagnostics.slice(1).map((entry) => formatDiagnosticMessage(entry))\n\t\t: defaultDetails;\n\tconst stack =\n\t\terror instanceof Error && error.stack\n\t\t\t? splitLines(error.stack).filter((line) => line !== message)\n\t\t\t: [];\n\tconst classification = classifyErrorMessage(rawMessage);\n\n\treturn {\n\t\tcode: classification.code,\n\t\tseverity: classification.severity,\n\t\trecoverable: classification.recoverable,\n\t\ttitle: classification.title,\n\t\tmessage,\n\t\thint: classification.hint,\n\t\tdetails,\n\t\tstack,\n\t\trawMessage,\n\t\tphase,\n\t\tsource,\n\t\tcontext\n\t};\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"error-report.js","names":[],"sources":["../../src/lib/core/error-report.ts"],"sourcesContent":["import {\n\tgetShaderCompilationDiagnostics,\n\ttype ShaderCompilationDiagnostic\n} from './error-diagnostics.js';\nimport { formatShaderSourceLocation } from './shader.js';\n\n/**\n * Runtime phase in which an error occurred.\n */\nexport type MotionGPUErrorPhase = 'initialization' | 'render';\n\n/**\n * Stable machine-readable error category code.\n */\nexport type MotionGPUErrorCode =\n\t| 'WEBGPU_UNAVAILABLE'\n\t| 'WEBGPU_ADAPTER_UNAVAILABLE'\n\t| 'WEBGPU_CONTEXT_UNAVAILABLE'\n\t| 'WGSL_COMPILATION_FAILED'\n\t| 'MATERIAL_PREPROCESS_FAILED'\n\t| 'WEBGPU_DEVICE_LOST'\n\t| 'WEBGPU_UNCAPTURED_ERROR'\n\t| 'BIND_GROUP_MISMATCH'\n\t| 'RUNTIME_RESOURCE_MISSING'\n\t| 'UNIFORM_VALUE_INVALID'\n\t| 'STORAGE_BUFFER_OUT_OF_BOUNDS'\n\t| 'STORAGE_BUFFER_READ_FAILED'\n\t| 'RENDER_GRAPH_INVALID'\n\t| 'PINGPONG_CONFIGURATION_INVALID'\n\t| 'TEXTURE_USAGE_INVALID'\n\t| 'TEXTURE_REQUEST_FAILED'\n\t| 'TEXTURE_DECODE_UNAVAILABLE'\n\t| 'TEXTURE_REQUEST_ABORTED'\n\t| 'COMPUTE_COMPILATION_FAILED'\n\t| 'COMPUTE_CONTRACT_INVALID'\n\t| 'MOTIONGPU_RUNTIME_ERROR';\n\n/**\n * Severity level for user-facing diagnostics.\n */\nexport type MotionGPUErrorSeverity = 'error' | 'fatal';\n\n/**\n * One source-code line displayed in diagnostics snippet.\n */\nexport interface MotionGPUErrorSourceLine {\n\tnumber: number;\n\tcode: string;\n\thighlight: boolean;\n}\n\n/**\n * Structured source context displayed for shader compilation errors.\n */\nexport interface MotionGPUErrorSource {\n\tcomponent: string;\n\tlocation: string;\n\tline: number;\n\tcolumn?: number;\n\tsnippet: MotionGPUErrorSourceLine[];\n}\n\n/**\n * Optional runtime context captured with diagnostics payload.\n */\nexport interface MotionGPUErrorContext {\n\tmaterialSignature?: string;\n\tpassGraph?: {\n\t\tpassCount: number;\n\t\tenabledPassCount: number;\n\t\tinputs: string[];\n\t\toutputs: string[];\n\t};\n\tactiveRenderTargets: string[];\n}\n\n/**\n * Structured error payload used by UI diagnostics.\n */\nexport interface MotionGPUErrorReport {\n\t/**\n\t * Stable machine-readable category code.\n\t */\n\tcode: MotionGPUErrorCode;\n\t/**\n\t * Severity level used by diagnostics UIs and telemetry.\n\t */\n\tseverity: MotionGPUErrorSeverity;\n\t/**\n\t * Whether runtime may recover without full renderer re-creation.\n\t */\n\trecoverable: boolean;\n\t/**\n\t * Short category title.\n\t */\n\ttitle: string;\n\t/**\n\t * Primary human-readable message.\n\t */\n\tmessage: string;\n\t/**\n\t * Suggested remediation hint.\n\t */\n\thint: string;\n\t/**\n\t * Additional parsed details (for example WGSL line errors).\n\t */\n\tdetails: string[];\n\t/**\n\t * Stack trace lines when available.\n\t */\n\tstack: string[];\n\t/**\n\t * Original unmodified message.\n\t */\n\trawMessage: string;\n\t/**\n\t * Runtime phase where the error occurred.\n\t */\n\tphase: MotionGPUErrorPhase;\n\t/**\n\t * Optional source context for shader-related diagnostics.\n\t */\n\tsource: MotionGPUErrorSource | null;\n\t/**\n\t * Optional runtime context snapshot (material/pass graph/render targets).\n\t */\n\tcontext: MotionGPUErrorContext | null;\n}\n\n/**\n * Splits multi-line values into trimmed non-empty lines.\n */\nfunction splitLines(value: string): string[] {\n\treturn value\n\t\t.split('\\n')\n\t\t.map((line) => line.trim())\n\t\t.filter((line) => line.length > 0);\n}\n\nfunction toDisplayName(path: string): string {\n\tconst normalized = path.split(/[?#]/)[0] ?? path;\n\tconst chunks = normalized.split(/[\\\\/]/);\n\tconst last = chunks[chunks.length - 1];\n\treturn last && last.length > 0 ? last : path;\n}\n\nfunction toSnippet(source: string, line: number, radius = 3): MotionGPUErrorSourceLine[] {\n\tconst lines = source.replace(/\\r\\n?/g, '\\n').split('\\n');\n\tif (lines.length === 0) {\n\t\treturn [];\n\t}\n\n\tconst targetLine = Math.min(Math.max(1, line), lines.length);\n\tconst start = Math.max(1, targetLine - radius);\n\tconst end = Math.min(lines.length, targetLine + radius);\n\tconst snippet: MotionGPUErrorSourceLine[] = [];\n\n\tfor (let index = start; index <= end; index += 1) {\n\t\tsnippet.push({\n\t\t\tnumber: index,\n\t\t\tcode: lines[index - 1] ?? '',\n\t\t\thighlight: index === targetLine\n\t\t});\n\t}\n\n\treturn snippet;\n}\n\nfunction buildSourceFromDiagnostics(error: unknown): MotionGPUErrorSource | null {\n\tconst diagnostics = getShaderCompilationDiagnostics(error);\n\tif (!diagnostics || diagnostics.diagnostics.length === 0) {\n\t\treturn null;\n\t}\n\n\tconst primary = diagnostics.diagnostics.find((entry) => entry.sourceLocation !== null);\n\tif (!primary?.sourceLocation) {\n\t\treturn null;\n\t}\n\n\tconst location = primary.sourceLocation;\n\tconst column = primary.linePos && primary.linePos > 0 ? primary.linePos : undefined;\n\n\tif (location.kind === 'fragment') {\n\t\tconst component =\n\t\t\tdiagnostics.materialSource?.component ??\n\t\t\t(diagnostics.materialSource?.file\n\t\t\t\t? toDisplayName(diagnostics.materialSource.file)\n\t\t\t\t: 'User shader fragment');\n\t\tconst locationLabel = formatShaderSourceLocation(location) ?? `fragment line ${location.line}`;\n\t\treturn {\n\t\t\tcomponent,\n\t\t\tlocation: `${component} (${locationLabel})`,\n\t\t\tline: location.line,\n\t\t\t...(column !== undefined ? { column } : {}),\n\t\t\tsnippet: toSnippet(diagnostics.fragmentSource, location.line)\n\t\t};\n\t}\n\n\tif (location.kind === 'include') {\n\t\tconst includeName = location.include ?? 'unknown';\n\t\tconst includeSource = diagnostics.includeSources[includeName] ?? '';\n\t\tconst component = `#include <${includeName}>`;\n\t\tconst locationLabel = formatShaderSourceLocation(location) ?? `include <${includeName}>`;\n\t\treturn {\n\t\t\tcomponent,\n\t\t\tlocation: `${component} (${locationLabel})`,\n\t\t\tline: location.line,\n\t\t\t...(column !== undefined ? { column } : {}),\n\t\t\tsnippet: toSnippet(includeSource, location.line)\n\t\t};\n\t}\n\n\tif (location.kind === 'compute') {\n\t\tconst computeSource = diagnostics.computeSource ?? diagnostics.fragmentSource;\n\t\tconst component = 'Compute shader';\n\t\tconst locationLabel = formatShaderSourceLocation(location) ?? `compute line ${location.line}`;\n\t\treturn {\n\t\t\tcomponent,\n\t\t\tlocation: `${component} (${locationLabel})`,\n\t\t\tline: location.line,\n\t\t\t...(column !== undefined ? { column } : {}),\n\t\t\tsnippet: toSnippet(computeSource, location.line)\n\t\t};\n\t}\n\n\tconst defineName = location.define ?? 'unknown';\n\tconst defineLine = Math.max(1, location.line);\n\tconst component = `#define ${defineName}`;\n\tconst locationLabel =\n\t\tformatShaderSourceLocation(location) ?? `define \"${defineName}\" line ${defineLine}`;\n\treturn {\n\t\tcomponent,\n\t\tlocation: `${component} (${locationLabel})`,\n\t\tline: defineLine,\n\t\t...(column !== undefined ? { column } : {}),\n\t\tsnippet: toSnippet(diagnostics.defineBlockSource ?? '', defineLine, 2)\n\t};\n}\n\nfunction formatDiagnosticMessage(entry: ShaderCompilationDiagnostic): string {\n\tconst sourceLabel = formatShaderSourceLocation(entry.sourceLocation);\n\tconst generatedLineLabel =\n\t\tentry.generatedLine > 0 ? `generated WGSL line ${entry.generatedLine}` : null;\n\tconst labels = [sourceLabel, generatedLineLabel].filter((value) => Boolean(value));\n\tif (labels.length === 0) {\n\t\treturn entry.message;\n\t}\n\n\treturn `[${labels.join(' | ')}] ${entry.message}`;\n}\n\n/**\n * Maps known WebGPU/WGSL error patterns to a user-facing title and hint.\n */\nfunction classifyErrorMessage(\n\tmessage: string\n): Pick<MotionGPUErrorReport, 'code' | 'severity' | 'recoverable' | 'title' | 'hint'> {\n\tif (message.includes('WebGPU is not available in this browser')) {\n\t\treturn {\n\t\t\tcode: 'WEBGPU_UNAVAILABLE',\n\t\t\tseverity: 'fatal',\n\t\t\trecoverable: false,\n\t\t\ttitle: 'WebGPU unavailable',\n\t\t\thint: 'Use a browser with WebGPU enabled (latest Chrome/Edge/Safari TP) and secure context.'\n\t\t};\n\t}\n\n\tif (message.includes('Unable to acquire WebGPU adapter')) {\n\t\treturn {\n\t\t\tcode: 'WEBGPU_ADAPTER_UNAVAILABLE',\n\t\t\tseverity: 'fatal',\n\t\t\trecoverable: false,\n\t\t\ttitle: 'WebGPU adapter unavailable',\n\t\t\thint: 'GPU adapter request failed. Check browser permissions, flags and device support.'\n\t\t};\n\t}\n\n\tif (message.includes('Canvas does not support webgpu context')) {\n\t\treturn {\n\t\t\tcode: 'WEBGPU_CONTEXT_UNAVAILABLE',\n\t\t\tseverity: 'error',\n\t\t\trecoverable: true,\n\t\t\ttitle: 'Canvas cannot create WebGPU context',\n\t\t\thint: 'Make sure this canvas is attached to DOM and not using an unsupported context option.'\n\t\t};\n\t}\n\n\tif (message.includes('WGSL compilation failed')) {\n\t\treturn {\n\t\t\tcode: 'WGSL_COMPILATION_FAILED',\n\t\t\tseverity: 'error',\n\t\t\trecoverable: true,\n\t\t\ttitle: 'WGSL compilation failed',\n\t\t\thint: 'Check WGSL line numbers below and verify struct/binding/function signatures.'\n\t\t};\n\t}\n\n\tif (\n\t\tmessage.includes('Invalid include directive in fragment shader.') ||\n\t\tmessage.includes('Unknown include \"') ||\n\t\tmessage.includes('Circular include detected for \"') ||\n\t\tmessage.includes('Invalid define value for \"') ||\n\t\tmessage.includes('Invalid include \"')\n\t) {\n\t\treturn {\n\t\t\tcode: 'MATERIAL_PREPROCESS_FAILED',\n\t\t\tseverity: 'error',\n\t\t\trecoverable: true,\n\t\t\ttitle: 'Material preprocess failed',\n\t\t\thint: 'Validate #include keys, define values and include expansion order before retrying.'\n\t\t};\n\t}\n\n\tif (message.includes('Compute shader compilation failed')) {\n\t\treturn {\n\t\t\tcode: 'COMPUTE_COMPILATION_FAILED',\n\t\t\tseverity: 'error',\n\t\t\trecoverable: true,\n\t\t\ttitle: 'Compute shader compilation failed',\n\t\t\thint: 'Check WGSL compute shader sources below and verify storage bindings.'\n\t\t};\n\t}\n\n\tif (\n\t\tmessage.includes(\n\t\t\t'Compute shader must declare `@compute @workgroup_size(...) fn compute(...)`.'\n\t\t) ||\n\t\tmessage.includes('Compute shader must include a `@builtin(global_invocation_id)` parameter.') ||\n\t\tmessage.includes('Could not extract @workgroup_size from compute shader source.') ||\n\t\tmessage.includes('@workgroup_size dimensions must be integers in range') ||\n\t\tmessage.includes('Unsupported storage buffer access mode \"')\n\t) {\n\t\treturn {\n\t\t\tcode: 'COMPUTE_CONTRACT_INVALID',\n\t\t\tseverity: 'error',\n\t\t\trecoverable: true,\n\t\t\ttitle: 'Compute contract is invalid',\n\t\t\thint: 'Ensure compute shader contract (@compute, @workgroup_size, global_invocation_id, storage access) is valid.'\n\t\t};\n\t}\n\n\tif (message.includes('WebGPU device lost') || message.includes('Device Lost')) {\n\t\treturn {\n\t\t\tcode: 'WEBGPU_DEVICE_LOST',\n\t\t\tseverity: 'fatal',\n\t\t\trecoverable: false,\n\t\t\ttitle: 'WebGPU device lost',\n\t\t\thint: 'GPU device/context was lost. Recreate the renderer and check OS/GPU stability.'\n\t\t};\n\t}\n\n\tif (message.includes('WebGPU uncaptured error')) {\n\t\treturn {\n\t\t\tcode: 'WEBGPU_UNCAPTURED_ERROR',\n\t\t\tseverity: 'error',\n\t\t\trecoverable: true,\n\t\t\ttitle: 'WebGPU uncaptured error',\n\t\t\thint: 'A GPU command failed asynchronously. Review details and validate resource/state usage.'\n\t\t};\n\t}\n\n\tif (message.includes('CreateBindGroup') || message.includes('bind group layout')) {\n\t\treturn {\n\t\t\tcode: 'BIND_GROUP_MISMATCH',\n\t\t\tseverity: 'error',\n\t\t\trecoverable: true,\n\t\t\ttitle: 'Bind group mismatch',\n\t\t\thint: 'Bindings in shader and runtime resources are out of sync. Verify uniforms/textures layout.'\n\t\t};\n\t}\n\n\tif (message.includes('Storage buffer \"') && message.includes('write out of bounds:')) {\n\t\treturn {\n\t\t\tcode: 'STORAGE_BUFFER_OUT_OF_BOUNDS',\n\t\t\tseverity: 'error',\n\t\t\trecoverable: true,\n\t\t\ttitle: 'Storage buffer write out of bounds',\n\t\t\thint: 'Ensure offset + write byte length does not exceed declared storage buffer size.'\n\t\t};\n\t}\n\n\tif (\n\t\tmessage.includes('Cannot read storage buffer \"') ||\n\t\tmessage.includes('Cannot read storage buffer: GPU device unavailable.') ||\n\t\tmessage.includes('not allocated on GPU.')\n\t) {\n\t\treturn {\n\t\t\tcode: 'STORAGE_BUFFER_READ_FAILED',\n\t\t\tseverity: 'error',\n\t\t\trecoverable: true,\n\t\t\ttitle: 'Storage buffer read failed',\n\t\t\thint: 'Readbacks require an initialized renderer, allocated GPU buffer and active device.'\n\t\t};\n\t}\n\n\tif (\n\t\tmessage.includes('Unknown uniform \"') ||\n\t\tmessage.includes('Unknown uniform type for \"') ||\n\t\tmessage.includes('Unknown texture \"') ||\n\t\tmessage.includes('Unknown storage buffer \"') ||\n\t\tmessage.includes('Missing definition for storage buffer \"') ||\n\t\tmessage.includes('Missing texture definition for \"') ||\n\t\t(message.includes('Storage buffer \"') && message.includes('\" not allocated.')) ||\n\t\t(message.includes('Storage texture \"') && message.includes('\" not allocated.'))\n\t) {\n\t\treturn {\n\t\t\tcode: 'RUNTIME_RESOURCE_MISSING',\n\t\t\tseverity: 'error',\n\t\t\trecoverable: true,\n\t\t\ttitle: 'Runtime resource binding failed',\n\t\t\thint: 'Check material declarations and runtime keys for uniforms, textures and storage resources.'\n\t\t};\n\t}\n\n\tif (message.includes('Uniform ') && message.includes(' value must')) {\n\t\treturn {\n\t\t\tcode: 'UNIFORM_VALUE_INVALID',\n\t\t\tseverity: 'error',\n\t\t\trecoverable: true,\n\t\t\ttitle: 'Uniform value is invalid',\n\t\t\thint: 'Provide finite values with tuple/matrix sizes matching the uniform type.'\n\t\t};\n\t}\n\n\tif (\n\t\tmessage.includes('Render pass #') ||\n\t\tmessage.includes('Render graph references unknown runtime target')\n\t) {\n\t\treturn {\n\t\t\tcode: 'RENDER_GRAPH_INVALID',\n\t\t\tseverity: 'error',\n\t\t\trecoverable: true,\n\t\t\ttitle: 'Render graph configuration is invalid',\n\t\t\thint: 'Verify pass inputs/outputs, declared render targets and execution order.'\n\t\t};\n\t}\n\n\tif (message.includes('PingPongComputePass must provide a target texture key.')) {\n\t\treturn {\n\t\t\tcode: 'PINGPONG_CONFIGURATION_INVALID',\n\t\t\tseverity: 'error',\n\t\t\trecoverable: true,\n\t\t\ttitle: 'Ping-pong compute pass is misconfigured',\n\t\t\thint: 'Configure a valid target texture key for PingPongComputePass.'\n\t\t};\n\t}\n\n\tif (message.includes('Destination texture needs to have CopyDst')) {\n\t\treturn {\n\t\t\tcode: 'TEXTURE_USAGE_INVALID',\n\t\t\tseverity: 'error',\n\t\t\trecoverable: true,\n\t\t\ttitle: 'Invalid texture usage flags',\n\t\t\thint: 'Texture used as upload destination must include CopyDst (and often RenderAttachment).'\n\t\t};\n\t}\n\n\tif (message.includes('Texture request failed')) {\n\t\treturn {\n\t\t\tcode: 'TEXTURE_REQUEST_FAILED',\n\t\t\tseverity: 'error',\n\t\t\trecoverable: true,\n\t\t\ttitle: 'Texture request failed',\n\t\t\thint: 'Verify texture URL, CORS policy and response status before retrying.'\n\t\t};\n\t}\n\n\tif (message.includes('createImageBitmap is not available in this runtime')) {\n\t\treturn {\n\t\t\tcode: 'TEXTURE_DECODE_UNAVAILABLE',\n\t\t\tseverity: 'fatal',\n\t\t\trecoverable: false,\n\t\t\ttitle: 'Texture decode unavailable',\n\t\t\thint: 'Runtime lacks createImageBitmap support. Use a browser/runtime with image bitmap decoding.'\n\t\t};\n\t}\n\n\tif (message.toLowerCase().includes('texture request was aborted')) {\n\t\treturn {\n\t\t\tcode: 'TEXTURE_REQUEST_ABORTED',\n\t\t\tseverity: 'error',\n\t\t\trecoverable: true,\n\t\t\ttitle: 'Texture request aborted',\n\t\t\thint: 'Texture load was cancelled. Retry the request when source inputs stabilize.'\n\t\t};\n\t}\n\n\treturn {\n\t\tcode: 'MOTIONGPU_RUNTIME_ERROR',\n\t\tseverity: 'error',\n\t\trecoverable: true,\n\t\ttitle: 'MotionGPU render error',\n\t\thint: 'Review technical details below. If issue persists, isolate shader/uniform/texture changes.'\n\t};\n}\n\n/**\n * Converts unknown errors to a consistent, display-ready error report.\n *\n * @param error - Unknown thrown value.\n * @param phase - Phase during which error occurred.\n * @returns Normalized error report.\n */\nexport function toMotionGPUErrorReport(\n\terror: unknown,\n\tphase: MotionGPUErrorPhase\n): MotionGPUErrorReport {\n\tconst shaderDiagnostics = getShaderCompilationDiagnostics(error);\n\tconst rawMessage =\n\t\terror instanceof Error\n\t\t\t? error.message\n\t\t\t: typeof error === 'string'\n\t\t\t\t? error\n\t\t\t\t: 'Unknown FragCanvas error';\n\tconst rawLines = splitLines(rawMessage);\n\tconst defaultMessage = rawLines[0] ?? rawMessage;\n\tconst defaultDetails = rawLines.slice(1);\n\tconst source = buildSourceFromDiagnostics(error);\n\tconst context = shaderDiagnostics?.runtimeContext ?? null;\n\tconst message =\n\t\tshaderDiagnostics && shaderDiagnostics.diagnostics[0]\n\t\t\t? formatDiagnosticMessage(shaderDiagnostics.diagnostics[0])\n\t\t\t: defaultMessage;\n\tconst details = shaderDiagnostics\n\t\t? shaderDiagnostics.diagnostics.slice(1).map((entry) => formatDiagnosticMessage(entry))\n\t\t: defaultDetails;\n\tconst stack =\n\t\terror instanceof Error && error.stack\n\t\t\t? splitLines(error.stack).filter((line) => line !== message)\n\t\t\t: [];\n\tlet classification = classifyErrorMessage(rawMessage);\n\tif (\n\t\tshaderDiagnostics?.shaderStage === 'compute' &&\n\t\tclassification.code === 'WGSL_COMPILATION_FAILED'\n\t) {\n\t\tclassification = {\n\t\t\tcode: 'COMPUTE_COMPILATION_FAILED',\n\t\t\tseverity: 'error',\n\t\t\trecoverable: true,\n\t\t\ttitle: 'Compute shader compilation failed',\n\t\t\thint: 'Check WGSL compute shader sources below and verify storage bindings.'\n\t\t};\n\t}\n\n\treturn {\n\t\tcode: classification.code,\n\t\tseverity: classification.severity,\n\t\trecoverable: classification.recoverable,\n\t\ttitle: classification.title,\n\t\tmessage,\n\t\thint: classification.hint,\n\t\tdetails,\n\t\tstack,\n\t\trawMessage,\n\t\tphase,\n\t\tsource,\n\t\tcontext\n\t};\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"material.d.ts","sourceRoot":"","sources":["../../src/lib/core/material.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;AACrE,OAAO,EAIN,oBAAoB,EACpB,MAAM,eAAe,CAAC;AACvB,OAAO,EAKN,KAAK,eAAe,EAEpB,MAAM,0BAA0B,CAAC;AAElC,OAAO,KAAK,EAEX,0BAA0B,EAG1B,oBAAoB,EAGpB,UAAU,EAEV,MAAM,YAAY,CAAC;AAEpB;;GAEG;AACH,MAAM,MAAM,wBAAwB,GACjC;IACA;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;IACb;;OAEG;IACH,KAAK,EAAE,OAAO,CAAC;CACd,GACD;IACA;;OAEG;IACH,IAAI,EAAE,KAAK,GAAG,KAAK,GAAG,KAAK,CAAC;IAC5B;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;CACb,CAAC;AAEL;;GAEG;AACH,MAAM,MAAM,mBAAmB,GAAG,OAAO,GAAG,MAAM,GAAG,wBAAwB,CAAC;AAE9E;;GAEG;AACH,MAAM,MAAM,eAAe,CAAC,IAAI,SAAS,MAAM,GAAG,MAAM,IAAI,MAAM,CAAC,IAAI,EAAE,mBAAmB,CAAC,CAAC;AAE9F;;GAEG;AACH,MAAM,MAAM,gBAAgB,CAAC,IAAI,SAAS,MAAM,GAAG,MAAM,IAAI,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;AAElF;;GAEG;AACH,MAAM,WAAW,iBAAiB,CACjC,WAAW,SAAS,MAAM,GAAG,MAAM,EACnC,WAAW,SAAS,MAAM,GAAG,MAAM,EACnC,UAAU,SAAS,MAAM,GAAG,MAAM,EAClC,WAAW,SAAS,MAAM,GAAG,MAAM,EACnC,iBAAiB,SAAS,MAAM,GAAG,MAAM;IAEzC;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAC;IACjB;;OAEG;IACH,QAAQ,CAAC,EAAE,UAAU,CAAC,WAAW,CAAC,CAAC;IACnC;;OAEG;IACH,QAAQ,CAAC,EAAE,oBAAoB,CAAC,WAAW,CAAC,CAAC;IAC7C;;OAEG;IACH,OAAO,CAAC,EAAE,eAAe,CAAC,UAAU,CAAC,CAAC;IACtC;;OAEG;IACH,QAAQ,CAAC,EAAE,gBAAgB,CAAC,WAAW,CAAC,CAAC;IACzC;;OAEG;IACH,cAAc,CAAC,EAAE,0BAA0B,CAAC,iBAAiB,CAAC,CAAC;CAC/D;AAED;;GAEG;AACH,MAAM,WAAW,YAAY,CAC5B,WAAW,SAAS,MAAM,GAAG,MAAM,EACnC,WAAW,SAAS,MAAM,GAAG,MAAM,EACnC,UAAU,SAAS,MAAM,GAAG,MAAM,EAClC,WAAW,SAAS,MAAM,GAAG,MAAM,EACnC,iBAAiB,SAAS,MAAM,GAAG,MAAM;IAEzC;;OAEG;IACH,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B;;OAEG;IACH,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC,CAAC;IACrD;;OAEG;IACH,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC,oBAAoB,CAAC,WAAW,CAAC,CAAC,CAAC;IAC/D;;OAEG;IACH,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,eAAe,CAAC,UAAU,CAAC,CAAC,CAAC;IACxD;;OAEG;IACH,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC,gBAAgB,CAAC,WAAW,CAAC,CAAC,CAAC;IAC3D;;OAEG;IACH,QAAQ,CAAC,cAAc,EAAE,QAAQ,CAAC,0BAA0B,CAAC,iBAAiB,CAAC,CAAC,CAAC;CACjF;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB,CAChC,WAAW,SAAS,MAAM,GAAG,MAAM,EACnC,WAAW,SAAS,MAAM,GAAG,MAAM,EACnC,WAAW,SAAS,MAAM,GAAG,MAAM,EACnC,iBAAiB,SAAS,MAAM,GAAG,MAAM;IAEzC;;OAEG;IACH,YAAY,EAAE,MAAM,CAAC;IACrB;;OAEG;IACH,eAAe,EAAE,eAAe,CAAC;IACjC;;OAEG;IACH,QAAQ,EAAE,UAAU,CAAC,WAAW,CAAC,CAAC;IAClC;;OAEG;IACH,QAAQ,EAAE,oBAAoB,CAAC,WAAW,CAAC,CAAC;IAC5C;;OAEG;IACH,aAAa,EAAE,UAAU,CAAC,OAAO,oBAAoB,CAAC,CAAC;IACvD;;OAEG;IACH,WAAW,EAAE,WAAW,EAAE,CAAC;IAC3B;;OAEG;IACH,SAAS,EAAE,MAAM,CAAC;IAClB;;OAEG;IACH,cAAc,EAAE,MAAM,CAAC;IACvB;;OAEG;IACH,cAAc,EAAE,gBAAgB,CAAC,WAAW,CAAC,CAAC;IAC9C;;OAEG;IACH,iBAAiB,EAAE,MAAM,CAAC;IAC1B;;OAEG;IACH,MAAM,EAAE,QAAQ,CAAC,sBAAsB,CAAC,GAAG,IAAI,CAAC;IAChD;;OAEG;IACH,iBAAiB,EAAE,iBAAiB,EAAE,CAAC;IACvC;;OAEG;IACH,kBAAkB,EAAE,WAAW,EAAE,CAAC;CAClC;
|
|
1
|
+
{"version":3,"file":"material.d.ts","sourceRoot":"","sources":["../../src/lib/core/material.ts"],"names":[],"mappings":"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"}
|
package/dist/core/material.js
CHANGED
|
@@ -203,7 +203,8 @@ function buildTextureConfigSignature(textures, textureKeys) {
|
|
|
203
203
|
normalized.anisotropy,
|
|
204
204
|
normalized.filter,
|
|
205
205
|
normalized.addressModeU,
|
|
206
|
-
normalized.addressModeV
|
|
206
|
+
normalized.addressModeV,
|
|
207
|
+
normalized.fragmentVisible ? "1" : "0"
|
|
207
208
|
].join(":");
|
|
208
209
|
}
|
|
209
210
|
return signature;
|